我使用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
宝石,我认为这是有道理的,但我在找出构建事物的最佳方法时遇到了一些麻烦。我的问题包括......
ruby_events
个侦听器附加到哪里感到有点困惑 - 它只是扩展了Object,所以它并没有明确如何实现它。Bot
是一个模块,所以我不能只从其中一个插件调用Bot.send_data
来发送数据 - 我如何与其中一个插件的EM连接进行交互?我完全接受任何建筑修订或其他宝石的建议,使我正在努力做的事情也更容易。
答案 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。