Twitter API v1.1 で自動フォロー返し機能を実装する で紹介した自動フォロー返しコードを修正し、エラーに慎重に対処し安全に自動フォロー返しを行うバージョンを紹介します。

修正版コード

<?php
require __DIR__ . '/lib/twitteroauth/twitteroauth.php';

define('CONSUMER_KEY', 'your_consumer_key');
define('CONSUMER_SECRET', 'your_consumer_secret');
define('ACCESS_TOKEN', 'your_access_token');
define('ACCESS_TOKEN_SECRET', 'your_access_token_secret');

$toa = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);

$followers = $toa->get('followers/ids', array('cursor' => -1));
$friends   = $toa->get('friends/ids',   array('cursor' => -1));

if (!is_array($followers->ids) or !is_array($friends->ids)) exit;

$errorIds = file_exists('error.log') ? file_get_contents('error.log') : null;
$errCnt = 0;

foreach ($followers->ids as $i => $id)
{
    if (empty($friends->ids) or !in_array($id, $friends->ids))
    {
        if (!is_null($errorIds) and false !== strpos($errorIds, (string)$id)) continue;

        $ret = $toa->post('friendships/create', array('user_id' => $id));

        if (isset($ret->errors))
        {
            /*
               Error code:
                 34 : Sorry, that page does not exist
                 108: Cannot find specified user
                 130: Over capacity
                 131: Internal error
                 159: Sorry, this account has been suspended
                 160: You've already requested to follow USER_NAME
                 161: You are unable to follow more people at this time
            */
            if ($ret->errors[0]->code != 161 and $ret->errors[0]->code != 131 and $ret->errors[0]->code != 130)
            {
                $fh = fopen('error.log', 'a');
                fwrite($fh, "$id\n");
                fclose($fh);
            }

            $errCnt++;
            if ($errCnt >= 5) break;
        }
    }
}

修正点の解説

if (!is_array($followers->ids) or !is_array($friends->ids)) exit;

14 行目の処理を追加して、リストが取得できているか確認し、失敗していれば終了するようにしました。API のリミットに引っかかる等、何らかの理由で、フォロー/フォロワーのリスト取得に失敗する場合があるためです。

例えば極稀ですが、奇跡的に $followers (自分をフォローしているユーザ)は取得できても、$friends (自分がフォローしているユーザ)の取得に失敗することが起こり得ます。

この場合、以前のコードでは、$friends の取得に失敗しただけなのに、まだ誰もフォロー返ししていないということになり、$follower に対して、不要なフォロー返しを試みてしまいます。これは大変行儀の悪いことなので、14 行目の処理を追加しました。

次に、25 行目以降の箇所です。

        $ret = $toa->post('friendships/create', array('user_id' => $id));

        if (isset($ret->errors))
        {
            /*
               Error code:
                 34 : Sorry, that page does not exist
                 108: Cannot find specified user
                 130: Over capacity
                 131: Internal error
                 159: Sorry, this account has been suspended
                 160: You've already requested to follow USER_NAME
                 161: You are unable to follow more people at this time
            */
            if ($ret->errors[0]->code != 161 and $ret->errors[0]->code != 131 and $ret->errors[0]->code != 130)
            {
                $fh = fopen('error.log', 'a');
                fwrite($fh, "$id\n");
                fclose($fh);
            }

            $errCnt++;
            if ($errCnt >= 5) break;
        }

これは、25 行目のフォローリクエストで発生するエラーに対処するためのものです。

        $ret = $toa->post('friendships/create', array('user_id' => $id));

25 行目では、下記のエラーが発生する場合があります。

  • エラーコード 34:そのページは存在しません
  • エラーコード 108:ユーザが見つかりません
  • エラーコード 130:キャパを超えました
  • エラーコード 131:内部エラー
  • エラーコード 159:このアカウントはサスペンドされました
  • エラーコード 160:あなたはすでにフォローリクエストを行っています
    • 相手が非公開設定を行っていて、フォローリクエストを許可してもらえてない場合に発生
  • エラーコード 161:今はこれ以上フォローできません

これらのうち、エラーコード 130、131、161 以外は、エラーが発生したユーザ ID をファイル "error.log" に保存して、次回実行時にはこのログを参照して、同じユーザ ID に対してフォロークエストをしないようにします。

こうするのは、例えば、$toa->get('followers/ids', array('cursor' => -1)); で取得したリストの中に "エラーコード 108:ユーザが見つかりません" が発生するユーザ ID が入ってきてしまうからです。Twitter API は結構アバウトな動作をするようになっているのかよく分かりませんが、見つからないユーザ ID も返してくるので、このような対処をしています。

最後に、46 - 47 行目ですが、エラーが 5 回発生したら、安全のためループから抜けて処理を中断するようにしています。