のみまくし日記

毎日が文化祭の前日、そんな環境っていいですよね。この日記は未来の自分へのメッセージです。

2005年04月28日 ()

影舞に登録されたらIRCで告知

会社の作業依頼で影舞使っているんですが、本日中な依頼を、登録されて気が付かないことが有るので、IRCですぐに教えてくれるbotが欲しいナーと思いました。

影舞からどうやってIRC botに通知するかってのでちょっと迷った。定期的に見に行くのも良いけど、出来ればリアルタイムが良い。というわけで、POE使って、ごにょごにょっと出来ないかなーと。

POE::Component::IRCPOE::Component::Server::HTTPをつかって HTTP Serverな機能を備えたIRCbotを作りました。

HTTP ServerはどんなURLで来ても1ピクセルの画像を出力するだけな単純な仕組みです。

影舞のデータの格納先はDBにしておきます。

影舞の登録完了のHTMLで

/kagemai/resource/ja/template/_default/add_message.rhtml
/kagemai/resource/ja/template/_default/new_report.rhtml
<img src="http://localhost:8888/<%= report.id %>" />

見たいにしておいて、POEで作ったHTTP Serverに通知。HTTP Server ではリクエストされたURLをみれれば、影舞のレポート番号がわかるので、DBに直接聞きに行くと。いった感じ。かなり適当だけど、コードを晒してみます。

#!/usr/bin/perl
# =========================================================================
# BTSからIMGタグアクセスでIRCに告知
#
# =========================================================================
use strict;
use POE qw(
    Component::Server::HTTP
    Component::IRC
    Component::TSTP
);
use POE::Sugar::Args;
use HTTP::Status;
use Jcode;
use LWP::Simple;

use BTS::Data::Report;

# -------------------------------------------------------------------------
# 設定
#
# -------------------------------------------------------------------------
our @CHANNEL = (
    '#BTS',
);
our $NICK     = 'BTS';
our $USERNAME = 'kagemai';
our $IRCNAME  = 'kagemai';
our $SERVER   = 'localhost';
our $PORT     = '6667';


# -------------------------------------------------------------------------
# main
#
# -------------------------------------------------------------------------
POE::Component::TSTP->create(); # Ctrl-Z をトラップする
POE::Component::IRC->new("irc");
POE::Component::Server::HTTP->new(
    Alias => 'httpd',
    Port => 8888,
    ContentHandler => {'/' => \&http_handler},
    Headers => { Server => 'My Server' },
);

POE::Session->create(
    inline_states => {
        _start   => \&setup_service,
        _stop    => \&shutdown_service,
        # _default => \&_debug,
    },
);
$poe_kernel->run;


# -------------------------------------------------------------------------
# デバッグ
#
# -------------------------------------------------------------------------
sub _debug {
    my ( $event, $args ) = @_[ ARG0 .. $#_ ];
    print "unhandled $event\n";

    my $arg_number = 0;
    foreach (@$args) {
        print "  ARG$arg_number = ";
        if ( ref($_) eq 'ARRAY' ) {
            print "$_ = [", join ( ", ", @$_ ), "]\n";
        }
        else {
            print "'$_'\n";
        }
        $arg_number++;
    }
    return 0;    # Don't handle signals.
}


# -------------------------------------------------------------------------
# start, stop
#
# -------------------------------------------------------------------------
sub setup_service { 
    my $poe = sweet_args;

    $poe->kernel->alias_set("btsbot");

    # IRC botのセットアップ
    $poe->kernel->post( irc => register => qw(all) );
    $poe->kernel->post( irc => connect => {
            Nick     => $NICK,
            Username => $USERNAME,
            Ircname  => $IRCNAME,
            Server   => $SERVER,
            Port     => $PORT
        }
    );
}

sub shutdown_service { }

# -------------------------------------------------------------------------
# IRC接続
#
# -------------------------------------------------------------------------
sub on_connect {
    my $poe = sweet_args;

    for my $v (@CHANNEL) {
        $poe->kernel->post(irc => join => jis($v));
    }
}

# -------------------------------------------------------------------------
# 文字コードの変換
#
# -------------------------------------------------------------------------
sub jis {
    return Jcode->new(shift, 'euc')->jis;
}   

sub euc {
    return Jcode->new(shift, 'jis')->euc;
}

# -------------------------------------------------------------------------
# HTTPアクセスでBTSの更新を通知が来る
#
# -------------------------------------------------------------------------
sub http_handler {
    my ($request, $response) = @_;

    send_message($request->uri);

    # http://nais.to/~yto/clog/2004-12-08-4.html
    my $content = "\x47\x49\x46\x38\x39\x61\x01".
    "\x00\x01\x00\x80\xff\x00\xff\xff\xff\x00\x00\x00\x21\xf9".
    "\x04\x01\x00\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01".
    "\x00\x00\x02\x02\x44\x01\x00\x3b";

    $response->code(RC_OK);
    $response->push_header('Content-type', 'text/gif');
    $response->push_header('Pragma', 'no-cache');
    $response->push_header('Cache-Control', 'no-cache');
    $response->content($content);

    return RC_OK;
}

# -------------------------------------------------------------------------
# BTSの情報をメッセージ送信
#
# -------------------------------------------------------------------------
sub send_message {
    my $request_uri = shift;

    my ($report_id,) = ($request_uri =~ /(\d+)$/);

    #
    # 影舞のからデータ取ってくる
    #
    my $report = BTS::Data::Report->retrieve($report_id);

    POE::Kernel->call(
        irc => privmsg => '#BTS' => jis(sprintf"%s(%s)",
            $report->title,
            $report->status
        )
    );
    POE::Kernel->call(
        irc => privmsg => '#BTS' => jis(sprintf"%s >%s",
            $report->url,
            $report->assigned
        )
    );
}

BTS::Data::Report ってのは影舞で使っているテーブルをClass::DBIを使って定義しておいたヤツ。

参考にしたのは

ここら辺へんです。

Perl 仕事 posted by takefumi | この日記へリンク | コメント(0) | トラックバック(0)

この日記へのトラックバック

この日記へのコメント