YAPC::Asia の会場では、無線LANがあるがしかし、IRCのポートは空いていないようだ。 そこで、80番ポート、HTTP つなぎっぱの Stream(?) で IRCの発言を垂れ流すものがあれば苦労しないなと思い、 Plack + AnyEvent でなんとなくスクリプトを作ってみた。 というか、昨日の tokuhirom / miyagawa セッションでのデモを Async な Plack をみていじりたくなったw 一応動くっぽいので、稼働させている。
$ curl http://yapc-stream.pulpsite.net
とかやれば垂れ流れてきます。 が、接続時間の問題とかで途切れたり、複数クライアントの接続があった時にどの程度まで 耐えれるか不明。 とりあえず、ソース張っておきます。 ためしに、講堂の左側にあるスクリーンで映してくれたりすると嬉しいのだが、安定してないので なんともいえない。AnyEvent のドキュメント、読み込んでなくて見よう見まねなので、 おかしなところあると思うのでつっこみ歓迎です。
#!/usr/bin/perl use strict; use Plack::Loader; use AnyEvent; use AnyEvent::IRC::Client; use DateTime; my $channel = shift; my $nick = 'irc_stream'; my $impl = Plack::Loader->load( 'AnyEvent', port => 8080 ); my $writer; my $cv = AnyEvent->condvar; my $pc = AnyEvent::IRC::Client->new; $cv->begin; $pc->reg_cb( connect => sub { my ( $pc, $err ) = @_; if ( defined $err ) { warn "Couldn't connect to server: $err\n"; } }, registered => sub { my ($self) = @_; warn "join $channel\n"; $pc->enable_ping(60); }, disconnect => sub { warn "disconnected: $_[1]!\n"; }, irc_notice => sub { http_write( @_ ); }, irc_privmsg => sub { http_write ( @_ ); } ); $pc->send_srv( "JOIN", $channel ); $pc->connect( "irc.freenode.net", 6667, { nick => $nick, user => $nick, real => $nick } ); $cv->end; $impl->run( sub { my ( $env, $start_response ) = @_; $writer = $start_response->( 200, [ 'Content-Type' => 'text/plain' ] ); $writer->write("IRC HTTP Stream!\n"); return []; } ); warn "start server port: $impl->{port}\n"; $impl->run_loop; sub http_write { my ( $name, $msg ) = @_; if ( $msg->{params}->[1] && $msg->{prefix} =~ /([^!]+)/ ) { my $nick = $1; my $text = $msg->{params}->[1]; my $now = DateTime->now( time_zone => 'Asia/Tokyo' ); $writer->write( $now->hms(':') . " $nick: $text\n" ); } }