天然パーマです。

IRC HTTP Stream (仮) for YAPC::Asia 2009

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" );
    }
}