北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

CoroでコールバックなしのIRC bot

GUIのイベントを拾ったり、IRCクライアントのように登録したコールバックが何度も呼ばれるパターンでは、return型の関数にするのは難しいと思います。

while でループさせるような作りにしたらできそうですけど、それがわかりやすいかどうか。

Coro::AnyEventでフロントエンドをコールバックを使わずに書くComments

やっつけ仕事で一応やってみましたが・・・。特にIRC::Clientで、while内でイベントの種類で分岐しまくる作りとなる辺り、なんか逆行してる感がw

Twitter::Streamの方はいい感じだと思います*1。発生するイベントが1個だと、コールバックが何度も呼ばれるライブラリでもうまくCoroにあいますね。

package main;
use strict;
use warnings;
use Coro;
use Encode;
use utf8;

my $channel = $ARGV[0];
my $c = MyCoro::IRC::Client->new;
$c->reg_watcher('connect');
$c->reg_watcher('registered');
$c->reg_watcher('publicmsg');

$c->ae_irc->connect( 
  "irc.nara.wide.ad.jp", 6663, { nick => 'hiratara_bot' }
);
$c->ae_irc->send_srv( "JOIN", $channel );

async{
	while(my $ev = $c->next){
		if( $ev->{event} eq 'publicmsg'){
			$c->ae_irc->send_chan( 
				$channel, "NOTICE", $channel, 
				$ev->{args}[2]{params}[1]
			);
		}else{
			warn $ev->{event};
		};
	}
};

my $twitter = MyCoro::Twitter::Stream->new(
    username => $ARGV[1],
    password => $ARGV[2],
    method   => 'filter',
    track    => '#food',
);

async{
	while(my $tweet = $twitter->next){
		$c->ae_irc->send_chan(
			$channel, "NOTICE", $channel,
			encode_utf8( "$tweet->{user}{screen_name}: $tweet->{text}" )
		);
	}
};

schedule;

ライブラリ側も含めた全体は、こちらのgistで。


*1:ただ、エラー処理これじゃ駄目(dieじゃ落ちない)んで調べなきゃ><