hubotのbotスクリプトはcoffeescriptで書かれていて、ところどころ非同期動作となり初心者には難しく感じた。ある程度勉強してそれなりにかけるようになったが、複雑な処理をやらせようとするといつも私は壁に当たってしまう。めんどくさくなったので使い慣れたperlで書くことにした。
perlで書くといってもircとの接続部分はhubotを使うのでperlを起動し結果をircに渡す最低限の箇所だけcoffeescriptで書き、あとはperlで実装する方式を採用する。
実際、やってみたがあっさりできた。DB連携でき文字化けもせず今のところ問題ない。
やり方を公開しとく。
1.まず最初にやるのは本ブログで紹介したirc.coffeeの文字化け対策。詳細は
こちら。
2.次にbotをircに接続するため、以下の内容で
~/tools/hubot/node_modules/hubot-scripts/src/scripts/tellme.coffeeを作成。
# tellme.coffee
module.exports = (robot) ->
robot.hear /^(tellme_del|tellme_add|tellme)(\ | ).+/i, (msg) ->
cmd = "~/tools/hubot/perl/dbbot.pl "+escape('tellme')+" "+ escape(msg.match[0])
exec = require('child_process').exec
exec cmd, (err,stdout,stderr) ->
msg.send stdout
3.runbot.shで上記スクリプトが読み込まれるよう
~/tools/hubot/hubot-scripts.jsonに以下青字を追加
["redis-brain.coffee", "shipit.coffee", "tellme.coffee"]
4.perlスクリプトを以下内容で~/tools/hubot/perl/dbbot.plに作成。mysqlのアカウントとパスワードは環境により修正要!
#!/usr/bin/perl
use utf8;
use DBI;
use Encode;
use URI::Escape;
exit if($#ARGV < 1);
$maxcnt=5; # 最大表示レコード数
$tbl=uri_unescape(decode("utf-8",$ARGV[0]));
$tbl=~s/%u([0-9a-fA-F]{4})/pack("U",hex($1))/ego;
$str=uri_unescape(decode("utf-8",$ARGV[1]));
$str=~s/%u([0-9a-fA-F]{4})/pack("U",hex($1))/ego;
$str=~s/\ /\ /g;$pos=index($str,' ');
exit if($pos == -1);
$exeid=substr($str,0,$pos);$key=substr($str,$pos+1);$exeid=~tr/A-Z/a-z/;
if($exeid =~ /.+_add$/){
$pos=index($key,' ');
if($pos == -1){print "内容がないよぅ\n";exit;}
$val=substr($key,$pos+1);$key=substr($key,0,$pos);
}
if($key eq "help"||$key eq "?"||$key eq "?"){
$exeid =~ tr/A-Za-z//;
print "■".$exeid."マクロの使い方\n";
print "\t登録・・・『 ".$exeid."_add <key> <val> 』\n";
print "\t削除・・・『 ".$exeid."_del <key> 』\n";
print "\t参照<完全一致>・・・『 ".$exeid." <key> 』\n";
print "\t参照<部分一致>・・・『 ".$exeid." %<key>% 』\n";
print "\t参照<前方一致>・・・『 ".$exeid." <key>% 』\n";
print "\t参照<後方一致>・・・『 ".$exeid." %<key> 』\n";
print " ※情報が複数ある場合は最大".$maxcnt."つまで表示する\n";
exit;
}
if($exeid =~/.+_add/ || $exeid =~ /.+_del/){
$dbh=DBI->connect('DBI:mysql:hubot', 'root', 'root');
$dbh->do("set names utf8");
$sql='SELECT * FROM `'.$tbl.'` WHERE `key` = '.$dbh->quote($key);%rows=();
$sth=$dbh->prepare($sql);$sth->execute;
while ($row = $sth->fetchrow_hashref()){$rows{$row->{key}}=$row->{val};}
$sth->finish;
if(scalar(keys(%rows)) == 0){
if($exeid =~ /.+_del/){
$dbh->disconnect;print "そんなキーワードないよ!!\n";exit;
}
$sql='INSERT INTO `hubot`.`'.$tbl.'` (`key`, `val`) VALUES ('.
$dbh->quote($key).', '.$dbh->quote($val).');';
$val="追加しました!!";
}
else{
if($exeid =~ /.+_del/){
$sql='DELETE FROM `hubot`.`'.$tbl.'` WHERE `'.$tbl.'`.`key` = '.
$dbh->quote($key).';';
$val="削除しました!!";
}
else{
$sql='UPDATE `hubot`.`'.$tbl.'` SET `val` = '.$dbh->quote($val).
' WHERE `'.$tbl.'`.`key` = '.$dbh->quote($key).';';
$val="更新しました!! 旧->".decode("utf-8",$rows{encode("utf-8",$key)});
}
}
$sth=$dbh->prepare($sql);$sth->execute;
if($sth->err){print "ERROR! ".$sth->errstr."\n";}else{print $val."\n";}
$sth->finish;$dbh->disconnect;
}
else{
$dbh=DBI->connect('DBI:mysql:hubot', 'root', 'root');
$dbh->do("set names utf8");
if($key =~ /.*%.*/){$ope="LIKE";}else{$ope="=";}
$sql='SELECT * FROM `'.$tbl.'` WHERE `key` '.$ope.' '.$dbh->quote($key);
$sth=$dbh->prepare($sql);$sth->execute;%rows=();
while ($row = $sth->fetchrow_hashref()){$rows{$row->{key}}=$row->{val};}
$sth->finish;$dbh->disconnect;
if(scalar(keys(%rows)) == 0){print "そんなキーワードないですよ!!\n";exit;}
foreach $key(keys(%rows)){
print "%u0016".$key."%u000f ".$rows{$key}."\n" if($ope eq "LIKE");
print $rows{$key}."\n" if($ope eq "=");
$maxcnt--;last if($maxcnt < 1);
}
print "・・・以下省略。ほかにもあるよ!!\n" if(scalar(keys(%rows)) > 5)
}
5.DB準備。
(1)MySqlインストール
(2)DB作成。名前は「hubot」
(3)テーブル作成。名前は「tellme」。カラム数は2
(4)テーブルの構造設定。
1カラム目:名前「key」データ型「char」長さ「255」照合順序「utf8-bin」
2カラム目:名前「val」データ型「char」長さ「255」照合順序「utf8-bin」
これで準備完了。cd ~/tools/hubot ; ./runbot.shで起動するとmybot君がチャットに登場する。
使い方は、
tellme_add キーワード 内容
でDBに情報登録
tellme キーワード
でDBの情報をチャットに出力
tellme_del キーワード
でDBのレコードを削除
ちなみに、tellme.coffeeの robot.hearの行を
robot.hear /^(なんとか_del|なんとか_add|なんとか)(\ | ).+/i, (msg) ->
にかえると、「なんとか」でbotが反応するようになる。
また
cmd = "~/tools/hubot/perl/dbbot.pl "+escape('tellme')+" "+ escape(msg.match[0])
のtellmeを「なんとか」にかえるとテーブル名「なんとか」でDB登録参照するようになる。
高橋 順子
技術評論社
売り上げランキング: 81,545