使用EventMachine的Ruby TCP“bot” - 实现命令调度程序

时间:2011-09-29 05:44:57

标签: ruby events bots eventmachine

我使用EventMachine制作了一个基本的TCP客户端。代码:

# run.rb
EventMachine::run do
  EventMachine::connect $config_host, $config_port, Bot
end

# bot.rb
module Bot
  def post_init
    # log us in and do any other spinup.
    sleep(1)
    send_data $config_login + "\n"
    EventMachine.add_periodic_timer($config_keepalive_duration) { send_data $config_keepalive_str + "\n" }
    @valid_command =  /^<#{$config_passphrase}:([^>:]+):(#\d+)>(.*)$/
  end

  def receive_data(data)
    if(ma = @valid_command.match(data))
      command, user, args = ma[1,3]
      args.strip!
      command.downcase!
      p "Received: #{command}, #{user}, #{args}"
      # and.. here we handle the command.
    end
  end
end

这一切都很有效。基本思想是它应该连接,监听特殊格式的命令,并执行命令;在执行命令时,可能会有任意数量的“动作”导致客户端发送各种数据。

但是,对于我的下一招,我需要添加实际处理Bot收到的命令的功能。

我想使用动态事件监听器库或类似的东西来做这件事;即,我有任意数量的插件可以注册以侦听特定命令并从bot.rb获得回调。 (最后,我希望能够在不重新启动机器人的情况下重新加载这些插件。)

我看过ruby_events宝石,我认为这是有道理的,但我在找出构建事物的最佳方法时遇到了一些麻烦。我的问题包括......

  1. 我对将ruby_events个侦听器附加到哪里感到有点困惑 - 它只是扩展了Object,所以它并没有明确如何实现它。
  2. Bot是一个模块,所以我不能只从其中一个插件调用Bot.send_data来发送数据 - 我如何与其中一个插件的EM连接进行交互?
  3. 我完全接受任何建筑修订或其他宝石的建议,使我正在努力做的事情也更容易。

1 个答案:

答案 0 :(得分:2)

我不确定你要做什么,但在EM中这样做的一个常见模式是将命令处理程序定义为回调。那么命令逻辑可以从Bot模块本身推出,它只处理基本套接字通信和命令解析。想想Web服务器如何分派给应用程序 - Web服务器不执行任务,只是调度。

例如像

这样的东西
EM::run do 

  bot = EM::connect $config_host, $config_port, Bot

  bot.on_command_1 do |user, *args|
     # handle command_1 in a block
  end

  # or if you want to modularize it, something like this
  # where Command2Handler = lambda {|user, *args| #... }
  bot.on_command_2(&Command2Handler)

end

那么你只需要在你的Bot中实现#on_command_1#on_command_2等,这只是将procs存储到实例变量的问题;然后在您从receive_data解析传递的命令后调用它们。

生产中的一个好的,非常易读的例子是TwitterStream