Chatworkでbotを作る(2) - php で オウム返しbot


Chatwork botへ次のステップ

(1)でChatworkのルームにメッセージが書き込まれたら、設定したweebhookのURLが呼び出されるところまで確認できました。
この書き込まれたメッセージを、オウム返しで書き込んで返すようなbotのプログラムを作成します。

チャットワークAPIはREST形式でメッセージをやりとりし、エンドポイントURLに対してHTTP形式でパラメータを送ります。
データはHTTP形式ですが、エンドポイントURLはhttpsですので暗号化されて送信されます。

難しいことはとばして、出来るだけシンプルにAPIを使ってみます。

会議室の発言で受け取ったメッセージは

発言したメッセージをログファイルに出力しているので、[Webhook_event]のサブ配列は以下のように確認できています。

       [message_id] => 1017313389526647584
       [room_id] => 1234567
       [account_id] => 1234321
       [body] => おはよう!
       [send_time] => 1519019750
       [update_time] => 0

APIドキュメントでも、Webhookイベントオブジェクトの内容は同じであることも確認できます。

(1)で動作させたphpプログラムでは、

$receive['webhook_event']['body'];

に発言メッセージが入っているので、bot ではこの部分に対応して返信をすればいいのです。

発言と同じ内容を返信するbotプログラム

シンプルにプログラムを記述します。
Chatwork APIを呼び出すには、phpのcurlモジュールを使用しています。

bot.php
<?php

$raw = file_get_contents('php://input');
$receive = json_decode($raw, true);

$message = $receive['webhook_event']['body'];

$reply = array('body' => $message );

header('Content-type: application/json; charset=utf-8');

$cdata = curl_init();
curl_setopt($cdata, CURLOPT_URL, 'https://api.chatwork.com/v2/rooms/1234567/messages');
curl_setopt($cdata, CURLOPT_HTTPHEADER, array('X-ChatWorkToken: 342a5a5a5a5a5a5a5e4e4e4f7d2e'));
curl_setopt($cdata, CURLOPT_POSTFIELDS, http_build_query($reply, '', '&'));
curl_setopt($cdata, CURLOPT_POST, 1);
curl_setopt($cdata, CURLOPT_RETURNTRANSFER, 1);

$ret = curl_exec($cdata);
curl_close($data);

CURLOPT_URLには、webhook で設定したものと同じroomid(1234567)を設定します。
CURLOPT_HTTPHEADERにはAPI設定画面で生成した識別用のToken文字列を設定します。

bot実行!・・・あらら!

WEBサーバーにphpプログラムをアップロードします。
アップロードファイル名は(1)と同じくwebhook先の、chatwork.phpにします。
早速「こんばんは!」と発言しましょう。

「送信」ボタンを押して、botから同じメッセージが帰ってくるはずです・・・が、

メッセージは帰ってきました!・・・・ですが、bot からの挨拶が止まりません!!・・・緊急事態です!
ループしてメッセージが送出され続けています。

APIのリクエスト数は「5分あたり100回まで」と制限もされていますので、早く何とかしないと規約にも違反しています!

プログラムは正常です

ともかくWEBサーバのプロセスを止めるか、一度プログラム(chatwork.php)を削除してWEBサーバーでエラーを起こさせます。

原因はすぐに予想できました。

そうです、bot が返信したメッセージに対しても webhook が呼び出されるので、永遠にbotがメッセージを返し続けるのでしょう。

webhookで呼び出されたメッセージを返しているのですから、プログラムは正常です。

自分(bot)の発言には返信しない

これがいちばん簡単に実装できそうです。
発言者(account_id)が自分(bot)であれば返信せずプログラム終了させます。

bot.php
<?php

$raw = file_get_contents('php://input');
$receive = json_decode($raw, true);

if ($receive['webhook_event']['account_id'] == 1234567 ) exit();

$message = $receive['webhook_event']['body'];

$reply = array('body' => $message );

header('Content-type: application/json; charset=utf-8');

$cdata = curl_init();
curl_setopt($cdata, CURLOPT_URL, 'https://api.chatwork.com/v2/rooms/1234567/messages');
curl_setopt($cdata, CURLOPT_HTTPHEADER, array('X-ChatWorkToken: 342a5a5a5a5a5a5a5e4e4e4f7d2e'));
curl_setopt($cdata, CURLOPT_POSTFIELDS, http_build_query($reply, '', '&'));
curl_setopt($cdata, CURLOPT_POST, 1);
curl_setopt($cdata, CURLOPT_RETURNTRANSFER, 1);

$ret = curl_exec($cdata);
curl_close($data);

追加したのは1行。if文の部分です。

account_id はチャットワークIDではなく、数字です。
account_id は(1)でログに出力した際のファイルに記録確認しましょう。

コマンドラインのAPIでもaccount_idを確認できます。

curl -X GET -H "X-ChatWorkToken: 342a5a5a5a5a5a5a5e4e4e4f7d2e" "https://api.chatwork.com/v2/me"

完成


発言に対してオウム返しされています。
完成です。

あくまでも動作確認のスケルトン(骨組み)ですので、この先はbotとして返すメッセージを生成しないとならないですし、(1)で説明したようにwebhookの認証や各種例外処理も組み込まなくてはならないでしょう。

さらにチャットルームIDや発言者のアカウントID取得など、実運用には考慮しなくてはならない課題もまだまだありそうです。

chatwork API ドキュメント
http://developer.chatwork.com/ja/