icyleaf/wechat-bot

View on GitHub
lib/wechat/bot/core.rb

Summary

Maintainability
A
1 hr
Test Coverage
require "wechat/bot/configuration"
require "wechat/bot/cached_list"
require "wechat/bot/contact_list"
require "wechat/bot/contact"
require "wechat/bot/logger"

require "wechat/bot/handler_list"
require "wechat/bot/handler"
require "wechat/bot/message"
require "wechat/bot/pattern"
require "wechat/bot/callback"

require "wechat/bot/http/adapter/js"
require "wechat/bot/http/adapter/xml"
require "wechat/bot/http/session"

require "logger"

module WeChat::Bot
  # 机器人的核心类
  class Core
    # 微信 API 客户端
    #
    # @return [Client]
    attr_reader :client

    # 当前登录用户信息
    #
    # @return [Contact]
    attr_reader :profile

    # 联系人列表
    #
    # @return [ContactList]
    attr_reader :contact_list

    # @return [Logger]
    attr_accessor :logger

    # @return [HandlerList]
    attr_reader :handlers

    # @return [Configuration]
    attr_reader :config

    # @return [Callback]
    # @api private
    attr_reader :callback

    def initialize(&block)
      # defaults_logger
      @logger = Logger.new(STDOUT, self)
      @config = Configuration.new
      @handlers = HandlerList.new
      @callback = Callback.new(self)

      @client = Client.new(self)
      @profile = Contact.new(self)
      @contact_list = ContactList.new(self)

      instance_eval(&block) if block_given?
    end

    # 消息触发器
    #
    # @param [String, Symbol, Integer] event
    # @param [Regexp, Pattern, String] regexp
    # @param [Array<Object>] args
    # @yieldparam [Array<String>]
    # @return [Handler]
    def on(event, regexp = //, *args, &block)
      event = event.to_s.to_sym

      pattern = case regexp
                when Pattern
                  regexp
                when Regexp
                  Pattern.new(nil, regexp, nil)
                else
                  if event == :ctcp
                    Pattern.generate(:ctcp, regexp)
                  else
                    Pattern.new(/^/, /#{Regexp.escape(regexp.to_s)}/, /$/)
                  end
                end

      handler = Handler.new(self, event, pattern, {args: args, execute_in_callback: true}, &block)
      @handlers.register(handler)

      handler
    end

    # 用于设置 WeChat::Bot 的配置
    # 默认无需配置,需要定制化 yield {Core#config} 进行配置
    #
    # @yieldparam [Struct] config
    # @return [void] 没有返回值
    def configure
      yield @config
    end

    # 运行机器人
    #
    # @return [void]
    def start
      @client.login
      @client.contacts

      @contact_list.each do |c|
        @logger.debug "Contact: #{c}"
      end

      while true
        break unless @client.logged? || @client.alive?
        sleep 1
      end
    rescue Interrupt => e
      message = "你使用 Ctrl + C 终止了运行"
      @logger.warn(message)
      @client.send_text(@config.fireman, "[告警] 意外下线\n#{message}\n#{e.backtrace.join("\n")}") if @client.logged? && @client.alive?
    rescue Exception => e
      message = e.message
      @logger.fatal(e)
      @client.send_text(@config.fireman, "[告警] 意外下线\n#{message}\n#{e.backtrace.join("\n")}") if @client.logged? && @client.alive?
    ensure
      @client.logout if @client.logged? && @client.alive?
    end

    # private

    # def defaults_logger
    #   @logger = Logger.new($stdout)
    #   @logger.formatter = proc do |severity, datetime, progname, msg|
    #     "#{severity}\t[#{datetime.strftime("%Y-%m-%d %H:%M:%S.%2N")}]: #{msg}\n"
    #   end
    # end
  end
end