「知ってた?」と言われてもプラグイン作者(僕です)が書いていないのだから、ほとんどの人は知らないと思いますが。
さて、凄過ぎて誰も使っていないプラグインであるGianismですが、「twitterにポストする」という便利な関数があることを以前書きました。で、それ以外のAPIも実は利用できるので、そのことについて書きます。
twitterボットで特定の時間になにかをするのは以前紹介した方法でできますが、何か質問すると答えてくれる「人工無能」みたいなものもつくるとなると、ちょっと工夫が必要です。
基本的な流れはこんな感じですかね。
- 自分宛のメンションを定期的に取得する
- そのうち、自分が目的とするツイートかどうかを判断する
- 該当するツイートの場合、そのツイートに対してメンションを送る
では、この方法について紹介しましょう。Gianismを有効にしており、なおかつtwitterの設定が済んでいることを前提とします。
事例: 破滅サロン
破滅サロンは破滅派のオフィスで、無目的スペースとして同人諸氏に解放しているのですが、まだ3人ぐらいしか来ていません…… で、今回は破滅派のtwitterアカウントに対して「破滅サロン開いてますか?」と質問すると、空き状況を教えてくれるという仕組みにしましょう。
@takahashifumiki はい。17時13分現在、1人います。誰がいるかはサイトでわかります。 http://t.co/Z2uGAOwDwL
— 破滅派@文フリ京都う-10 (@hametuha) October 14, 2014
さて、2分に一回(別に毎分でもいいとは思いますが)メンションを取得するので、WordPressに備え付けのWP Cronという機能を使います。デフォルトで一番短いのが毎時間なので、スケジュールを追加します。
add_action('cron_schedules', function($schedules){ $schedules['hametu_salon_bot'] = array( 'interval' => 120, // 120秒=2分 'display' => '2分毎にメンションがないかチェック' ); return $schedules; });
続いて、イベントを登録します。
add_action('init', function(){ if( !wp_next_scheduled('hametu_salon_bot') ){ wp_schedule_event(current_time('timestamp', true), 'hametu_salon_bot', 'hametu_salon_bot'); } });
これで、指定した時間にhametu_salon_bot
アクションが実行されるので、そこにフックをかけます。
add_action('hametu_salon_bot', 'hs_get_mentions');
これで2分に一回hs_get_mentions
が実行されます。あとは、hs_get_mentions
の中身を定義するだけなのですが、その前にGianismを利用してTwitter REST APIを利用する際の基本を学んでおきます。
- GianismはTwitterOAuthというライブラリを利用している
- 管理画面での設定が済んでいる場合、
get_instance
メソッドで認証が完了しているインスタンスが手に入る - APIを呼ぶための
call_api
というメソッドがある
要するに、get_instance
をして、call_api
をやればいいわけですね。名前空間を使っているので、あまりPHPに慣れていない人は「えっ?」となるかもしれませんが、自分で0から実装するよりは楽なんじゃないかなーと思います。
/** * APIリクエスを送り、レスポンスを返す * * APIの種類はtwitterのドキュメントを見ること * * @see https://dev.twitter.com/docs/api/1.1 * @param string $endpoint APIのURL。スラッシュからはじめないこと 'statuses/user_timeline' * @param array $params ドキュメントにあるParametersのこと。 * @param string $method GET または POST デフォルトはGET * @param \TwitterOAuth $oauth 指定しない場合は管理画面で設定されたアカウント * @return \stdClass|mixed たぶんJSONオブジェクト */ public function call_api($endpoint, array $params, $method = 'GET', \TwitterOAuth $oauth = null){ // 実装は https://github.com/fumikito/Gianism/blob/master/app/service/twitter.php を見てね }
メンションの取得(statuses/mentions_timeline)もステータスの更新(statuses/update)もAPIにドキュメントがあるので、こちらのパラメータを指定すれば動きます。
function hs_get_mentions(){ if( !class_exists('Gianism\\Service\\Twitter') || !($twitter = \Gianism\Service\Twitter::get_instance())){ // Gianismのtwitterが取れなかったら終わり。 // この部分は難しいので、そのうち直します。 return false; } // 1回に取得する件数を指定 $params = array( 'count' => 200, ); // 最後に取得したIDがあれば、それ以降を取る if( $last_id = (int)get_option('salon_bot_since_id', 0) ){ $params['since_id'] = $last_id; } // メンションを取得 $mentions = $twitter->call_api('statuses/mentions_timeline', $params); if( $mentions ){ // 現在チェックインしている人数を取得。 // これは破滅サロン独自の関数です。 if( $users = hametu_user_list() ){ $reply = sprintf('はい。%s現在、%d人います。誰がいるかはサイトでわかります。', date_i18n('H時i分'), count($users)); }else{ $reply = sprintf('すいません。%s現在、誰もいません......', date_i18n('H時i分')); } $current_latest_id = false; foreach( $mentions as $mention ){ // 新しい順で来るので、一番新しいIDを次回以降のために保存しておく if( !$current_latest_id ){ $current_latest_id = $mention->id; update_option('salon_bot_since_id', $current_latest_id ); } // メンションが質問を含むか調べる if( false !== strpos($mention->text, '破滅サロン’) && preg_match('/(あいて|やって|開いて|誰かい|だれかい)(ますか|ます|る|ません|ませんか|ない)[??]?/u', $mention->text) ){ // 質問の回答分を作成 $reply = "@{$user_name} {$reply} ".home_url(); // メンションへのリプライとして投稿する $result = $twitter->call_api('statuses/update', array( 'status' => $reply, 'in_reply_to_status_id' => $status_id, ), 'POST'); } } } }
あとはCronがちゃんと毎分起動するようにした方がいいですかね。アクセスがそんなにないサイトでは、crontabで毎分起動して方がいいかもしれません(参考:WordPress の wp-cron.php を無効にする)
ちなみに、破滅サロンでの実装はこれと違うので、詳しくはGithubのソースを見てください。
まとめ
さて、今回のやり方で単なる定期更新とは異なるボットが作れることがわかったと思います。
twitterはその性質上、たくさんの人目に触れるので、リプライへの自動返信がユニークで、質問者本人以外がサイトを見たくなるような(=導線として有効な)仕組みを考えるといいんじゃないでしょうか。
診断メーカー的なものとかはすでにあるので、自分のサイトのコンテンツと絡めて色々やると面白いんじゃないかと思います。
また、もっと進んだ使い方として、メンションなどの受動的なものではなく、タイムライン全体を探してなんらかのアクションを起こすというのがありえます。
ただし、その場合はNLP(自然言語処理)などでがんばらないといけないので、「プラグインでボットを作れるからなんだっつーんだよ」と思うぐらい大変そうですけど。終わり。
[429] [429] Client error: `POST https://webservices.amazon.co.jp/paapi5/getitems` resulted in a `429 Too Many Requests` response: {"__type":"com.amazon.paapi5#TooManyRequestsException","Errors":[{"Code":"TooManyRequests","Message":"The request was de (truncated...)