nazolabo

フリーランスのWebエンジニアが近況や思ったことを発信しています。

rhacoでTwitterのBOTを作るチュートリアル

PHPでTwitterのBotを作ってみる - yuyarinの日記
rhacoで実装しようと思います。使用するrhacoはrev.2594(2008/1/21時点でのtrunk)です。

初期設定

※ 作業中は作業フォルダ以下の全てのフォルダ/ファイルのパーミッションを777(あるいはapacheが読み書きできる属性)にしておいてください。またブラウザ上で作業した際にできたファイルは通常ユーザ権限でアクセスできません。管理者権限で属性を変更する必要があります。(suexecとか windows環境なら気にしなくていいです)
適当な作業フォルダを作り、rhacoフォルダにあるsetup.php(管理画面)をそこにコピーし、それをブラウザから実行します。
最初にrhacoのライブラリのパスを聞かれるので、適当に指定します。
するといろいろ設定画面が出てきますが、とりあえず何も考えずにどこかの「生成」ボタンを押します。
作業フォルダにいろいろ追加されているのがわかると思います。
今回はTwitterにアクセスするので、拙作のTwitterAPIを使用します。
http://rhacolibs.googlecode.com/svn/trunk/network/services/TwitterAPI.php
からダウンロードし(必ず最新のものを使用してください)、作業フォルダのlibrary/network/services/以下に入れてください(library以下は空だと思うのでフォルダは自分で作ってください)。

データベース設定

重複して反応しないように、既読メッセージはデータベースに格納し、それをチェックするようにします。今回はMySQLを使用しますが、SQLiteでも構いません。
管理画面に入り、画面上部に並んでいるメニューから[編集]を選択します。
すると大きめのtextareaに以下のような記述があります。

<project rhacover="1.4.1" version="1.0.0" name="rhacobot" xmlns="http://rhaco.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://rhaco.org http://media.rhaco.org/project.xsd">
</project>

これを以下のように変更し、「更新」を押します。

<project rhacover="1.4.1" version="1.0.0" name="rhacobot" xmlns="http://rhaco.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://rhaco.org http://media.rhaco.org/project.xsd">
  <database name="twitterbot">
    <table name="deduped">
      <column name="id" type="integer" primary="true" />
    </table>
    <table name="keywords" admin="true">
      <column name="id" type="serial" primary="true" />
      <column name="keyword" type="string" size="255" require="true" />
    </table>
    <table name="replies" admin="true">
      <column name="id" type="serial" primary="true" />
      <column name="keyword_id" type="integer" reference="keywords.id" require="true" />
      <column name="reply" type="string" size="255" require="true" />
    </table>
  </database>
</project>

更新されたら、[setting]を選択します。最初と比べると「データベースの設定 [twitterbot]」という項目が追加されています。
ここに各自のデータベース設定を入力し、「生成」を押します。データベースが作成されていない場合は別途作成しておいてください。
さらに[exe]を選択します。「データベースの設定 [twitterbot]」という項目があるので、「テーブル作成」の「作成」を押します。これで上で指定した構造がtwitterbotデータベースに投入されます。

実装

作業フォルダにindex.phpというファイルを作り、以下のように記述します。

<?php
include_once("__init__.php");
Rhaco::import("generic.Flow");
Rhaco::import("network.services.TwitterAPI");

Rhaco::import("database.DbUtil");
Rhaco::import("database.model.Criteria");
Rhaco::import("abbr.Q");

Rhaco::import("model.Deduped");
Rhaco::import("model.Keywords");
Rhaco::import("model.Replies");

$login = "nazobot"; // BOTTwitterのID
$password = "pass"; // BOTTwitterのPassword

$flow = new Flow();
$twitter = new TwitterAPI($login, $password);
$db = new DbUtil(Deduped::connection());

$timelines = $twitter->status_friends_timeline();

foreach($timelines as $line) {
    // 重複チェック
    $c = new Criteria(Q::eq(Deduped::columnId(), $line['id']));
    $deduped = $db->get(new Deduped(), $c);
    if (!$deduped) {
        // 新規データなので発言を調べる
        $talk = $line['text'];
        if (strpos($talk, '@'.$login.' ') === 0) {
            // 自分に向けられた発言
            $len = strlen($talk);
            $at_len = strlen('@'.$login.' ');
            $command = substr($talk, $at_len, $len - $at_len);
            $command = html_entity_decode($command, ENT_QUOTES, 'UTF-8');
            
            // commandが一致するかを調べる
            $c = new Criteria(Q::eq(Keywords::columnKeyword(), $command));
            $keyword = $db->get(new Keywords(), $c);
            if ($keyword) {
                // 置換語があるかどうかを調べる
                $c = new Criteria(Q::eq(Replies::columnKeywordId(), $keyword->getId()));
                $replies = $db->select(new Replies(), $c);
                if (count($replies) > 0) {
                    $reply = $replies[rand() % count($replies)]; // ランダムで返答を決定
                    $twitter->status_update('@'.$line['user']['screen_name'].' '.$reply->getReply()); // 実際に発言する
                }
            }
        }
        
        // 重複にする
        $deduped = new Deduped();
        $deduped->setId($line['id']);
        $deduped->save();
    }
}

$flow->write("index.html");

さらにlibrary/model/Keywords.phpに以下の記述を追加します。

<?php
Rhaco::import("model.table.KeywordsTable");
class Keywords extends KeywordsTable{
    // ここから追加
    function toString() {
        return $this->getKeyword();
    }
    // ここまで追加
}

?>

resources/templates/index.htmlも作ります。

<html>
<head>
<meta http-equiv="Refresh" content="120;URL={$rhaco.url('index.php')}">
</head>
<body>
<p>120秒後に自動リロードされます。</p>
</body>
</html>

データの登録

発言するデータを登録します。
[db]を選択すると、「Keywords」「Replies」という二つの項目があります。Keywordsに反応する発言を、Repliesに返答を登録していきます。
試しに「Keyword」を選択し、「追加」で、「こんにちは」と入力して「保存」します。
次に「Replies」を選択し、「追加」で、「keyword_id」を「こんにちは」、「reply」を「今日はいい天気ですね!」にして「保存」します。
これで準備は完了です。

実行

ブラウザからindex.phpを開くと実行されます。
誰かが「@あなたの名前 こんにちは」と発言すると自動で「@対象 今日はいい天気ですね!」と返します。
ほっとくと自動リロードします。cronが使えるならそちらのほうがいいと思います。