[PHP] 曜日や時間でつぶやく内容が変わるTwitter botをPHP+TwistOAuthで作ってみた

web
2017.09.06
重複エラーについて追記しました。

1時間に1回つぶやき、曜日や時間により内容が変化する簡単なTwitter botをPHPで作ってみた。
チンアナゴbot
ちんあなごがなにごとかつぶやきます。

環境

  • 【サーバ】 さくらインターネット
  • 【言語】 PHP5.4

事前準備

Twitter App

まずはTwitter Appに登録する必要があります。
詳しく書いているページが多くあるので、方法はググッてください。
Twitter App 作成 – Google 検索

  • Consumer Key (API Key)
  • Consumer Secret (API Secret)
  • Access Token
  • Access Token Secret

登録できたら、この4つをメモしておきましょう。

TwistOAuth

次にTwistOAuthというライブラリを準備します。
https://github.com/mpyw/TwistOAuth
このページのsrcディレクトリ内にあるTwistOAuth.pharを保存しておきます。

PHPの準備

ディレクトリ構成

  • twitter-bot.php
  • default.txt
  • TwistOAuth.phar

最低限必要なのはこの3ファイルです。
ツイートを投稿するPHPのtwitter-bot.php、つぶやきリストのdefault.txtを新規に作成し、ダウンロードしてきたTwistOAuth.pharと同じ階層にまとめておきます。

つぶやきリストを作成

ニュッ
ニュルン
ノロリ
ニュルリ
サッ

default.txtに、つぶやきたい文章をまとめます。1行が1ツイートとして使用されます。
つぶやきはなるべく多く用意しておいたほうが、重複エラー(後述)が避けられます。

つぶやきリストからランダムにつぶやくPHP

//エラーメッセージをメールで送る関数
function errorMail($error) {
  mb_language("Japanese");
  mb_internal_encoding("UTF-8");
  $to      = "送信先メールアドレス";
  $subject = "Twitter botにエラーが発生しました";
  $message = $error;
  $headers = "From: 送信元メールアドレス" . "rn";
  mb_send_mail($to, $subject, $message, $headers);
}

//テキストをシャッフルして返す関数
function tweetShuffle($tweetList, $recentTweets) {
  shuffle($tweetList); //シャッフル
  $tweet = rtrim($tweetList[0]); //文末のスペースを削除
  foreach ( $recentTweets as $key => $val ) {
    // 渡された直近n件のツイート文面を配列に入れる
    $tweetArray[] = $recentTweets[$key]->text;
  }
  if( in_array($tweet, $tweetArray) ) {
    // ツイートしようとしている文面と、直近n件のツイート文面を比較して一致したら再度シャッフル
    $tweet = tweetShuffle($tweetList, $recentTweets);
  }
  return $tweet; //結果を返す
}

// TwistOAuthの読み込み
require_once('TwistOAuth.phar');

// Twitterユーザー名(@なし)
$screenName = "ユーザー名";
// 認証キー類
$consumerKey = "CKCKCKCKCKCKCKCKCKCKCKCKCKCKCKCK";
$consumerSecret = "CSCSCSCSCSCSCSCSCSCSCSCSCSCSCSCSCS";
$accessToken = "ATATATATATATATATATATATATATATATATAT";
$accessTokenSecret = "ATSATSATSATSATSATSATSATSATSATSATSATSATSATS";
//コンストラクタ認証
try {
  $oauth = new TwistOAuth($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret);
} catch(TwistException $e) {
  $error = $e->getMessage();
  errorMail($error);
}

//デフォルトのツイートリストを設定
$tweetList = file('default.txt');

//直近ツイート10件を読み込む
$param = array('screen_name' => $screenName, 'count' => '10');
try {
  $recentTweets = $oauth->get('statuses/user_timeline', $param);
} catch (TwistException $e) {
  $error = $e->getMessage();
  errorMail($error);
}

if( $recentTweets ) {
  // リストをシャッフル関数に渡してシャッフル
  $tweet = tweetShuffle($tweetList, $recentTweets);

  //つぶやく
  try {
    // POSTする
    $status = $oauth->post('statuses/update', ['status' => $tweet ]);
    // 結果をダンプ
    var_dump($status);
  } catch (TwistException $e) {
    //エラーをメール送信
    errorMail("[{$e->getCode()}] {$e->getMessage()}", $tweet);
  }
}

twitter-bot.phpにこのように書きます。
$consumer_key$consumer_secret$access_token$access_token_secretは先程取得したもの。

シャッフルしているとはいえ、結構な頻度で前回や前々回のツイートとかぶることがあります。
かぶった場合403 Status is a duplicate.が返ってきてつぶやけないので、対策を入れました。
//直近ツイート10件を読み込むのところで、直近5件を取得し、’tweetShuffle()’へ渡しています。
$paramcountの値を任意の数に変えることで、最大200件まで取得できます。
‘tweetShuffle()’は、直近10件のツイートと現在ツイートしようとしている文面を比較し、一致したら再度シャッフルを回しています。
2017.09.06追記: 直近10件までチェックしているという情報があったので、5件から10件に増やしました。

また、CRONの自動実行ではエラーが発生してもエラーコードが確認出来ないので、エラー時はメールが送られるようにしました。
errorMail()内のメールアドレスを任意のものに変更してください。

曜日や時間によりつぶやく内容を変える

ただリストからつぶやくだけでは単調なbotになってしまうので、曜日や時間によって変化をつけてみます。
曜日・時間別につぶやきリストを作成しておきます。

#

こんな感じで。ファイル名は自分が分かりやすければなんでもだいじょうぶです。

先程のコードの$tweetList = file('default.txt');の下に以下を書き足します。

date_default_timezone_set('Asia/Tokyo'); //タイムゾーンをアジア・東京に設定
$week = (int)date("w"); //週を取得 (日=0,月=1…の数値)
$hour = (int)date("H"); //時間を取得 (0-23の数値)

// 指定時間は配列に入れておく
$morning = array(6,7); //6時と7時
$lunch = array(12,13); //12時と13時
$snack = array(15); //15時
$nigth = array(18,19); //18時と19時
$midnight = array(0,1); //0時と1時

if( in_array($hour, $morning, true) ) {
  //$morning = 6時と7時
  if( $week == 1 ) {
    $tweetlist = file('monday_morning.txt');
  } else {
    $tweetlist = file('morning.txt');
  }
} elseif( in_array($hour, $lunch, true) ) {
  //$lunch = 12時と13時
  $tweetlist = file('lunch.txt');
}

1行目はタイムゾーンの設定。環境によっては必要ないかも。
$weekは現在の曜日の数値。日曜は0、月曜は1…土曜は6となります。
$hourは現在時間の数値。24時間表記です。

つぶやく内容を変更する時間は配列化しておきます。
$morning = array(6,7);は6時と7時となります。

if文の条件は、in_array()の引数に$hour(現在時間)と指定時間を入れます。
in_array()は、第1引数の値が第2引数内に含まれているかをチェックし、Booleanで返します。
今回は先に時間で条件分岐し、その中で曜日で再度分岐させていますが、場合によっては逆のほうが楽かもです。
if文内で$tweetlistにそれぞれ指定したいファイルを入れておきます。

これで曜日や時間によって読み込むテキストファイルを変えて、ツイートに変化が出ました。
しかしこんなアナログな方法でいいんだろうか…?
もっといい方法があればコメントやTwitter等で教えてくださいませ。

  • TwistOAuth.phar
  • twitter-bot.php
  • default.txt
  • 時間別つぶやきリスト.txt

これらをサーバーにアップしておきましょう。
アップしたあと、ファイルのパーミッションをチェックして、実行権限がなければ付与します。

CRON

ここからはさくらサーバー側での作業です。
CRONという指定したスクリプトを定期実行してくれるコマンドを使用します。
さくらインターネットサーバコントロールパネル
さくらインターネットのコントロールパネルにログインします。

#

左のサイドバーからCRONの設定へ飛びます。

#

CRON 設定一覧の中の>> 新規項目の追加をクリック

#

実行コマンドcd /home/さくらのアカウント名/www/アップしたディレクトリ名; /usr/local/bin/php twitter-bot.phpと入れます。
これはコマンドであり、PHPファイルまでのフルパスではないことに注意。
ぱっと見フルパスに見えるので、ここでつまずく人が多いとかなんとか…。

実行日時は、いつこのコマンドが実行されるかを指定します。
毎月、毎日、毎時、毎分を指定したい場合は*(アスタリスク)を入れます(さくらは毎分の指定ができないようです)

今回は1時間に一回つぶやきたいので、月、日、時、分をそれぞれ***0としました。
この時、例えば深夜帯はツイートを停止したいのであれば時を0,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23などとすれば、1-5時はコマンドが実行されません。

連投規制について

ツイート: 1日に2,400件。1日のツイート投稿リミットは、さらに30分間隔の細かいリミットに分かれます。リツイートもツイートとしてカウントされます。

Twitterリミット (API、ツイート投稿、およびフォロー)
TwitterAPIでは、1日2,400件、30分間隔の未公表数によるリミットがあるようです。
1分間に3件連投してみたところ、3時間ほど規制されました。
投稿テストで規制されてはモチベーションが保てません。お気をつけください。

TwistOAuthが非推奨な件について

ここまでやっておいて、TwistOAuthが非推奨になっていることに気づきました。
現在はcowitterというライブラリが推奨されています。
cowitter

が、ただちに使えなくなるとか危険性があるわけではなさそうなので、今回はこのままでいいかな。

参考

自動ランダムツイートするTwitter BOTをPHPとさくらインターネットで作る
TwistOAuthを使ってユーザータイムラインを取得する – Qiita