Perl の IRC モジュールと言えば、ちょっと前まで Net::IRC だと思っていたが、久しく cpan でそいつをインストールしようとすると、
時代遅れだから POE::Component::IRC を使っちゃいなー ! “
と言われた。
イベントドリブンな IRC クライアントを書く為のモジュールで、PING/PONG の自動応答など、IRC セッションを裏で面倒見てくれる便利なモジュールらしい。
POE 自体、ネットワーク関係の疑似マルチスレッディング、同期通信など、カーネル側でサポートされそうな事をやってくれる便利なパッケージ。これを使うと、よ り環境に依存しないネットワークツールが作れる訳だ。
POE::Component::IRC の日本語ドキュメントもさくっと見つかった。
サンプルがついているので、ちょっと遊んでみる。ついでに、ホスト& IRC サーバともども、UTF-8 な日本語環境で利用する為の工夫もしてみた。
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Encode;
use POE qw(Component::IRC);
# IRC の接続設定
my $nickname = 'poepoe' . $$;
my $ircname = 'POE POE Bot';
my $ircserver = 'sasebo.ddo.jp';
my $port = 6665;
my @channels = ( '#alice' );
# 接続設定を渡して、オブジェクトを作成
my $irc = POE::Component::IRC->spawn(
nick => $nickname,
server => $ircserver,
port => $port,
ircname => $ircname,
) or die "Failed. $!";
# イベントハンドラを登録
POE::Session->create(
package_states => [
'main' => [ qw(_default _start irc_001 irc_public) ],
],
heap => {
irc => $irc
},
);
# 実行
$poe_kernel->run();
exit 0;
# 以下、イベント
# 接続
sub start {
my ($kernel,$heap) = @[KERNEL,HEAP];
my $irc_session = $heap->{irc}->session_id();
$kernel->post( $irc_session => register => 'all' );
$kernel->post( $irc_session => connect => { } );
undef;
}
# 接続完了 → チャンネルへ Join !
sub irc_001 {
my ($kernel,$sender) = @[KERNEL,SENDER];
my $poco_object = $sender->get_heap();
print "Connected to ", $poco_object->server_name(), "\n";
$kernel->post( $sender => join => $ ) for @channels;
undef;
}
# 発言時や状態が変わった時などに呼ばれるイベント。
# ここに自由な挙動を書く。
sub irc_public {
my ($kernel,$sender,$who,$where,$what) = @_[KERNEL,SENDER,ARG0,ARG1,ARG2];
my $nick = ( split /!/, $who )[0];
my $channel = $where->[0];
# 内部 Unicode 用に UTF8 フラグを付与
$what = Encode::decode("utf-8",$what);
if ( $what =~ /イ[カモ]/ ) {
# 本当は、BOT の発言は privmsg ではなく notice にするのがマナー。
$kernel->post( $sender => privmsg => $channel => "おいしいです、$nick。" );
}
# 茶筅に投げてみるテスト
if ( my ($rot13) = $what =~ /^! (.+)/ ) {
foreach my $line (echo '$rot13'|chasen -iw){
$kernel->post( $sender => notice => $channel => $line );
}
}
# 出力時には、UTF8 フラグを除去
$what = Encode::encode("utf-8",$what);
undef;
}
# 標準出力に動作ログを吐く
sub default {
my ($event, $args) = @[ARG0 .. $#_];
my @output = ( "$event: " );
foreach my $arg ( @$args ) {
if ( ref($arg) eq 'ARRAY' ) {
push( @output, "[" . join(" ,", @$arg ) . "]" );
} else {
push ( @output, "'$arg'" );
}
}
print STDOUT join ' ', @output, "\n";
return 0;
}
ソースも LOCALE も IRC サーバも UTF-8 だが、Perl の内部保持している文字列データは単純な Unicode なので、UTF-8 フラグを付けてから処理してやらなければならない。
上の例では、「イカ」とか「イモ」という発言があれば反応する。
参考ページ
※ 2020/07/02 度重なるブログ移転・ブログシステムのアップデートにより崩れた記事を校正。