2011-09-29 34 views
1

我使用EventMachine製作了一個基本的TCP客戶端。代碼:使用EventMachine的Ruby TCP「bot」 - 實現命令調度程序

# 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聽衆 - 它只是擴展對象,因此不會使它明顯如何實現它。
  2. Bot是一個模塊,所以我不能只從一個插件中調用Bot.send_data來發送數據 - 我怎樣才能從一個插件與EM連接進行交互?

我完全開放給任何建築修訂或其他寶石的建議,使我想做的事情也變得更容易。

回答

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 

,那麼你只需要實現#on_command_1#on_command_2,等你的機器人,這僅僅是一個存儲特效到實例瓦爾的事;然後一旦你從你的receive_data中解析出通過的命令,就會打電話給他們。

一個很好的,非常易讀的例子是TwitterStream