IRCで発言を逃さない為に・・・

弊社では作業環境としてMacBookProを使用している人も多いのですが、ノートパソコンだとしばらくするとスリープになってしまい、ネットワークも切れるため、IRCサーバーからログアウトした状態になり、その間の発言ログは見る事ができない状態になります。

単にログを収集するbotを簡単に作れないかと思い調べてみました。

PHPにこだわらないのであればIRCproxyの「tiarra」等で上記の問題は対応でき、完璧なツールです、が今回はスルーです。(tiarraについてはカヤックさんのブログがとてもわかりやすかったです。)
stone を使って tiarra を SSL 化する方法

PEAR::Net_SmartIRC を使ってPHPで作る

PEARにてばっちりなIRC用のPHPクラスがあったのでこちらを使いました。

pear install Net_SmartIRC

とりあえず作成したPHPソースの全文です。
88. PEAR::Net_SmartIRCではじめるIRC Bot入門
を参考にしました。

logbot.php
[code]
<?php

include_once(‘Net/SmartIRC.php‘);

define(“LOG_PATH”, “/path/to/irc-logs.txt”); //ログの保存先
$irc_host = “localhost“; //IRCサーバー
$irc_port = “6667”; // IRCサーバーのポート
$irc_name = “bot“; // 名前
$irc_channel = “#hogehoge”; // チャンネル名

class mybot
{
function welcome(&$irc, &$data)
{
// welcome
$irc->message(SMARTIRC_TYPE_NOTICE, $data->channel, $data->nick.’さん : ようこそー。’);
}

        function url(&amp;$irc,&amp;$data)
{
preg_match_all('|http://\w+(?:-\w+)*(?:\.\w+(?:-\w+)*)+(?::\d+)?(?:[/\?][\w%&amp;=~\-\+/;\.\?]*(?:#[^]*)?)?|', $data-&gt;message, $match);
$url=$match[0][0];
$urldata = file_get_contents($url);
$urldata = mb_convert_encoding($urldata, "UTF-8", "auto" );
preg_match( "/<title>(.*?)/i", $urldata, $matches);
$irc-&gt;message(SMARTIRC_TYPE_NOTICE, $data-&gt;channel,$matches[1] . ' - ' . $url );
}
function getlog(&amp;$irc,&amp;$data)
{
$data-&gt;message;
$fp = fopen(LOG_PATH, "a+");
fwrite($fp, date("Y-m-d H:i:s") . ' - (' . $data-&gt;nick . ') - ' . "$data-&gt;message \n");
fclose($fp);
}

}

$bot = &new mybot();
$irc = &new Net_SmartIRC();
//$irc->setDebug(SMARTIRC_DEBUG_ALL);
$irc->setUseSockets(TRUE);
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, ‘(?:^|[\s ]+)*1;
$irc->listen();
$irc->disconnect();

[/code]

簡単な解説

詳細なドキュメントはこちらです。
http://pear.php.net/package/Net_SmartIRC/docs/latest/Net_SmartIRC/Net_SmartIRC_base.html

URLを含む発言があったら、そのページのタイトルを取得して発言させる

[code]
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, ‘(?:^|[\s ]+)((?:https?|ftp):\/\/[^\s ]+)’, $bot, ‘url’);
[/code]

これはログの保存とは関係ないですが・・・
registerActionhandlerの第一引数でSMARTIRC_TYPE_CHANNELを選ぶ事で発言を監視し、第二引数の正規表現にマッチした場合に特定の動作を行わせる事ができます。
上記の例だと発言にURLが含まれていた場合にmybotクラスのurl関数を実行します。
url関数はURLに接続してtitleタグを取得しNOTICEとしてIRCでタイトルとURLを発言します。
こんな感じになります ↓

ログを収集する

[code]
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, ‘.*’, $bot, ‘getlog’);
[/code]
こちらがメインのログを収集する処理。
さきほどと同じく発言を監視しますがすべての発言にマッチするような正規表現となっています。
今回はgetlog関数を実行し、時間と発言者と発言内容をファイルに書きだす処理になってます。

JOINしたユーザーにwelcomeメッセージをとばす

[code]
$irc->registerActionhandler(SMARTIRC_TYPE_JOIN, ‘.*’, $bot, ‘welcome’);
[/code]
こちらはお遊び。第一引数をSMARTIRC_TYPE_JOINとするとユーザーがJOINしてきた時になんらかの動作を行わせる事ができます。
今回はチャンネルにJOINしてきた方へbotは「ようこそー」と発言させています。

実行

バックグラウンドで実行しておきます。

php logbot.php &amp;

このときIRCサーバーに正常にログインし、指定されたチャンネルへbot君がJOINしていれば成功。

おまけ

あとは書き出されたログをPHPとかで表示してやればOKです。
ドキュメントルート以下におけばブラウザから参照できますね。

logview.php

[code]
<!DOCTYPE html>
<html lang=”ja”>
<head>
<meta content=”text/html; charset=utf-8” http-equiv=”Content-Type”>
<title>IRC Log
</head>
<body>
<p>

<?php
$lines = file(‘/path/to/irc-logs.txt’);
foreach ($lines as $line_num => $line) {
echo nl2br(htmlspecialchars($line));
}
?>

</p>
</body>
</html>
[/code]

*1:?:https?|ftp):\/\/[^\s ]+)’, $bot, ‘url’);
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, ‘.‘, $bot, ‘getlog’);
$irc->registerActionhandler(SMARTIRC_TYPE_JOIN, ‘.
‘, $bot, ‘welcome’);
$irc->connect($irc_host, $irc_port);
$irc->login($irc_name, $irc_name, 0, $irc_name, $irc_pass);
$irc->join(array($irc_channel