TwitterでBOTを作成してみた

#＜目的＞
##何がしたいか
1.TwitterAPIを利用して、自動的に投稿するBOTを作りたい。
2.特定の人のツイートをRTしたい。
3.フォローされたら自動的にフォロバしたい。

#＜準備＞
##TwitterAPI
新しくアカウントを取得して、電話番号認証を通して…APIの認証を通してください。
参考：https://qiita.com/kngsym2018/items/2524d21455aac111cdee

##CakePHP3
別になんでも良いですが、composerが使えて、TwitterAPIが利用できるフレームワーク

##TwitterOAuth
こちらを利用して、TwitterAPIの操作をします。
参考：http://atomicbox.tank.jp/website/cakephp/1290/

##cron
自動で動かすので、cronを利用します。
CakePHP3のShellを自動的に実行する感じです。

#<実装>
##設定
TwitterComponent.phpを作成しておいて、こちらを呼び出すようにします。
割とよく使う4項目は定数にしておきます。
<img width="642" alt="0129.png" src="https://qiita-image-store.s3.amazonaws.com/0/232174/fb71d98f-e2fa-6fd4-b8e5-0fef6a020547.png">
また、認証処理は毎回使いますので、ここに記載します。

```php:TwitterComponent.php
<?php
namespace App\Controller\Component;

use Cake\Controller\Component;
use Abraham\TwitterOAuth\TwitterOAuth; //twitter

class TwitterComponent extends Component
{
  // API
  // コンシューマキー 画像の①
  protected $TWITTER_CONSUMER_KEY = "";
  // コンシューマーシークレット 画像の②
  protected $TWITTER_CONSUMER_SECRET = "";

  // user
  // twitterアクセストークン 画像の③
  protected $TWITTER_ACCESS_TOKEN = "";
  // twitterアクセストークンシークレット 画像の④
  protected $TWITTER_ACCESS_TOKEN_SECRET = "";

    /**
     * 認証処理
     */
  public function twitterOAuth(){
      $access_token = $this->TWITTER_ACCESS_TOKEN;
      $access_token_secret = $this->TWITTER_ACCESS_TOKEN_SECRET;
      $consumer_key = $this->TWITTER_CONSUMER_KEY;
      $consumer_secret = $this->TWITTER_CONSUMER_SECRET;

      $connection = new TwitterOAuth($consumer_key, $consumer_secret, $access_token, $access_token_secret);
      return $connection;
  }
}
```

##自動投稿
・画像アップロード＆投稿
 
画像をアップロード＆投稿ための処理をまず作ります。
(img=サーバー内の画像を指定してください)
この方法で、imgを指定すれば画像付き投稿が実装できます。
画像は`media/upload`を、
投稿は`statuses/update`を利用します。
[参考：POST media/upload - 画像をアップロードする](https://syncer.jp/Web/API/Twitter/REST_API/POST/media/upload/)
[参考：POST statuses/update - ツイートを投稿する](https://syncer.jp/Web/API/Twitter/REST_API/POST/statuses/update/)

```php:setImgPost
public function setImgPost($str, $img=''){
      $connection = $this->twitterOAuth();

      if(!empty($img)) {
          $media = $connection->upload('media/upload', ['media' => $img]);
      }
      // ツイートの内容を設定
      $params = [
          'status' => "{$str}",
          'media_ids' => implode(',', [$media->media_id_string])
      ];

      $result = $connection->post("statuses/update", $params);

      return $result;
  }
```

これを動かすためのShellファイルを作成しましょう。
Shellは
`src/Shell/TwitterShell.php`
として作成します。

```php:TwitterShell.php
<?php
namespace App\Shell;

use Cake\Console\Shell;
use Cake\Controller\ComponentRegistry;
use App\Controller\Component\TwitterComponent;

class TwitterShell extends Shell
{
    public function main()
    {
        $word = 'test\n送信';
        $img = '/var/www/test/img/test.jpg';
        $result = $this->Twitter->setImgPost($word, $img);
    }
}
```

実行コマンドは
`bin/cake twitter`
となります。
画像付きで、このように表示されれば成功です。
<img width="511" alt="0129_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/232174/adff43dd-ef58-ba35-2b5b-68dec5e00187.png">

こちらをベースに、Databaseで文言を入れておいて、
その時間のデータを呼び出して、cronを設定しておけば自動で投稿することが可能になります。

cronには30分おきに実行するように…
`0,30 * * * * /var/www/cake3/bin/cake twitter`
とでもしておけば良いのでは無いでしょうか。
(`/var/www/cake3/bin/cake`の部分はご自身の環境に合わせてください)

##自動RT
・特定の投稿を取得する
次に、特定ユーザーの投稿を取得してRTする処理を作成します。
とりあえず、最新の10件を取得するfunctionを作成します。
screen_name=Twitterの「＠〜」となっている部分の@を外したものを指定してください。
`statuses/user_timeline`を利用します。
[参考：GET statuses/user_timeline - ユーザータイムラインを取得する](https://syncer.jp/Web/API/Twitter/REST_API/GET/statuses/user_timeline/)

```php:TwitterComponent.php
    public function getUserTimeline($screen_name, $count=10){
        $connection = $this->twitterOAuth();

        $content = $connection->get("statuses/user_timeline", array(
          "screen_name" => "{$screen_name}",
          "count" => "{$count}",
          "trim_user" => "true",
          "exclude_replies" => "true",
          "include_rts" => "false",
        ));

    return $content;
  }
```

これで最新の10件を取得することが可能になりました。


・投稿をRTする
リツイート処理を作成します。
getUserTimeline()で取得した$contentをループさせて取得できるidを元に実行します。
`statuses/retweet/{$id}`を利用します。
[参考：POST statuses/retweet/:id - リツイートを実行する](https://syncer.jp/Web/API/Twitter/REST_API/POST/statuses/retweet/id/)

```php:TwitterComponent.php
    public function retweet($id){
        $connection = $this->twitterOAuth();
        // リツイート
        $result = $connection->post("statuses/retweet/{$id}");
    }
```

実際の処理としてはこのような形になります。

```php:TwitterShell.php
    public function reTweet($userName=''){
        $result = $this->Twitter->getUserTimeline($userName);
        foreach ($result as $row) {
            // ここで既にRT済みかチェックを入れると良いかもしれません。
            $this->Twitter->retweet($row->id_str);
        }
    }
```

実行コマンドは(abcというユーザーの場合)
`bin/cake twitter reTweet abc`
となります。

##自動フォロー
・フォローする
フォローする処理を作成します。
ここのuser_idは対象ユーザーのユーザーIDなので、userInfoを取得してそのidを利用しています。

`friendships/create`を利用します。
[参考：POST friendships/create - フォローする](https://syncer.jp/Web/API/Twitter/REST_API/POST/friendships/create/)

```php:TwitterComponent.php
  public function setFollow($userInfo){
      // $userInfo->following = 1 フォローしている状態
      if(!empty($userInfo) && $userInfo->following != 1){
          $connection = $this->twitterOAuth();

          $params = [
              'user_id' => $userInfo->id,
          ];

          $result = $connection->post("friendships/create" ,$params);
      }
  }
```

userInfoの取得には、
`users/show`を利用しても良いですが、リツイートされた場合、フォローされた場合で一気に取得することも可能です。
[GET users/show - ユーザーを取得する](https://syncer.jp/Web/API/Twitter/REST_API/GET/users/show/)

・リツートされた場合
特定の投稿idからリツイートしたユーザーを一気に取得する方法です。
`statuses/retweets/{$id}`を利用します。
[GET statuses/retweets/:id - ツイートをRTしたユーザーをオブジェクトで取得する](https://syncer.jp/Web/API/Twitter/REST_API/GET/statuses/retweeters/id/)

```php:TwitterComponent.php
  public function getRetweetUser($id){
      $connection = $this->twitterOAuth();
      
      $result = $connection->get("statuses/retweets/{$id}");
      return $result;
  }
```


・フォローされている場合
フォロワー一覧を取得する形で取得します。
`followers/list`を利用します。
[参考：GET followers/list - フォロワーをオブジェクトの一覧で取得する](https://syncer.jp/Web/API/Twitter/REST_API/GET/followers/list/)

```php:TwitterComponent.php
    public function getFollowersList(){
        $connection = $this->twitterOAuth();
        // 自分のフォロワー最新200人を取得
        $result = $connection->get("followers/list",['count' => 200]);
        return $result;
    }
```

・自動フォロー
これらを組み合わせた自動フォローはこのようになります。

```php:TwitterShell.php
public function follow($screenName){
        //自分の投稿の最新3件を取得する
        $result = $this->Twitter->getUserTimeline($screenName,3);
        //リツイートしたユーザーをフォローする
        foreach($result as $row){
            $users = $this->Twitter->getRetweetUser($row->id_str);
            if(!empty($users)){
                foreach($users as $user){
                    $this->Twitter->setFollow($user->user);
                }
            }
        }

        //最新フォロワー200人を取得する
        $list = $this->Twitter->getFollowersList();
        if(!empty($list->users)){
            foreach($list->users as $user){
                $this->Twitter->setFollow($user);
            }
        }
    }
```

実行コマンドは(defというユーザーの場合)
`bin/cake twitter follow def`
となります。

#まとめ
TwitterAPIを利用すれば、自動投稿、自動RT、自動フォローなど色々なことができます。

ただし、短時間にフォローが増えすぎると認証画面に飛ばされて
「robotじゃないか？」と言われるので、放置しっぱなしは良く無いかもしれません。
(認証にはSMSが必要となります)

色々と試してみて、ご自身の目的にあったTwitterBOT作成してみてください。