JabberでBotを作る


JabberBotを作ってみた.まず,最小限の設定をDJabberdにしてみる.

<VHost jabber.foo.co.jp>
    S2S false
    RequireSSL no

    <Plugin DJabberd::Authen::AllowedUsers>
        Policy accept
        AllowedUsers mac win
    </Plugin>
    <Plugin DJabberd::Authen::StaticPassword>
        Password password
    </Plugin>

    <Plugin DJabberd::RosterStorage::SQLite>
        Database roster.sqlite
    </Plugin>
</VHost>

Psiを使ってmacアカウントでログオンできることを確認.次にBotを作り始める.最初に作ったのはこんな感じ.

#!/usr/local/bin/perl

use Bot::JabberBot;
use strict;

Bot::JabberBot->new(
    server   => 'jabber.foo.co.jp',
    port     => 5222,
    nick     => 'win',
    password => 'password',
    resource => 'bot'
)->run();

Psiでmacアカウントからwinをコンタクトリストに載せることができたので,ちゃんとwinアカウントでログオンできたらしい.でも,他には何も動かないつまらないスクリプト.というわけで,言われたことを繰り返すスクリプトにすると…,

#!/usr/local/bin/perl
use Bot::JabberBot;
use Bot::JabberBot::Plugin::Mine;
use strict;

Bot::JabberBot->new(
    server   => 'jabber.foo.co.jp',
    port     => 5222,
    nick     => 'win',
    password => 'password',
    resource => 'bot'
)->run();

Bot::JabberBot::saidを再定義することでBotを作ることになっていたので,Bot::JabberBot::Plugin::Mineというモジュールを作って,その中で定義することにした.参考にしたのは宮川さんの書いたプラグインの薦め記事.中身はこんな感じになる.

package Bot::JabberBot::Plugin::Mine;
use strict;

sub import {
    my $class = shift;
    *Bot::JabberBot::said = sub {
        my ( $self, $said ) = @_;
        return $said->{body};
      }
}

1;

これで,alphabetなメッセージなら返事を返すようになった.でも日本語メッセージを送るとBotスクリプトが異常終了してしまう.これはutf-8フラグが立ったままの文字列をsocketで送信しようとしたために起こっているらしい.そこでsocketに書き出す前にフラグを落とすモジュールを新たに作成した.

package Jabber::Connection::Plugin::Mine;
use Encode qw(_utf8_off);
use strict;

sub import {
    my $class = shift;
    *Jabber::Connection::_write = sub {
        my ( $self, $data ) = @_;
        _utf8_off($data);
        $self->_log("SEND: ".$data);
        $self->{socket}->send($data);
      }
}

1;

このモジュールを読み込むようにしたBotスクリプトはこんな感じになった

#!/usr/local/bin/perl
use Bot::JabberBot;
use Bot::JabberBot::Plugin::Mine;
use Jabber::Connection::Plugin::Mine;
use strict;

Bot::JabberBot->new(
    server   => 'jabber.foo.nttr.co.jp',
    port     => 5222,
    nick     => 'win',
    password => 'password',
    resource => 'bot'
)->run();

日本語でも異常終了しなくなった.めでたしめでたし.