POE::Component::IRC で遊ぶ

PerlのIRCモジュールと言えば、ちょっと前まで Net::IRCだと思っていたが、久しくcpanでそいつをインストールしようとすると、”時代遅れだからPOE::Component::IRCを使っちゃいなー ! ” と言われた。 イベントドリブンなIRCクライアントを書く為のモジュールで、PING/PONGの自動応答など、IRCセッションを裏で面倒見てくれる便利なモジュールらしい。POE自体、ネットワーク関係の疑似マルチスレッディング、同期通信など、カーネル側でサポートされそうな事をやってくれる便利なパッケージ。これを使うと、よ り環境に依存しないネットワークツールが作れる訳だ。

POE::Component::IRC の日本語ドキュメントもさくっと見つかった。

サンプルがついているので、ちょっと遊んでみる。ついでに、ホスト& IRCサーバともども、UTF-8な日本語環境で利用する為の工夫もしてみた。

[perl]

!/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;
}
[/perl]

ソースも LOCALE も IRC サーバも UTF-8 だが、Perl の内部保持している文字列データは単純な Unicode なので、UTF-8 フラグを付けてから処理してやらなければならない。 上の例では、「イカ」とか「イモ」という発言があれば反応する。

参考ページ

コメントを残す

メールアドレスが公開されることはありません。