twitterで画像のツイートのみ取得する

#はじめに
私はTwitterで育児漫画を読むことが多いのですが、
漫画以外のツイートもタイムラインに表示されると鬱陶しいので、
漫画（＝画像）のツイートのみをTwitter APIを使って取得します。

#処理フロー
1.自分がフォローしているユーザーを取得（Twitter API）
2.各ユーザーのタイムラインを取得（Twitter API）
3.ツイート内容から画像有無を判定
4.画像があるものをいいね＆リツイート（Twitter API）

こうすると自分のタイムラインを表示すれば、画像のツイートのみをまとめて閲覧できます。

#実装
##Twitter APIの認証
API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRETは以下のサイトを参考に取得しました。
[2020年度版 Twitter API利用申請の例文からAPIキーの取得まで詳しく解説](https://www.itti.jp/web-direction/how-to-apply-for-twitter-api/)

```python:
twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
```

##1.自分がフォローしているユーザーを取得
まず自分がフォローしているユーザーのユーザー名（正確にはscreen name）を取得します。
エンドポイントは https://api.twitter.com/1.1/friends/list.json を使用します。
最大200人がAPIの制限のようです。
引数のscreen_nameには自分のscreen_nameを指定します。
（他の人のscreen nameでも取得はできます）

```python:get_follow_screen_name
def get_follow_screen_name(screen_name):
    # 空のリストを用意
    follow_list = []

    # 認証
    twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
    # 取得エンドポイント
    url = "https://api.twitter.com/1.1/friends/list.json"
    # パラメータ
    params = {"screen_name": screen_name, "count": 200}

    # リクエスト
    res = twitter.get(url, params=params)

    if res.status_code == 200:
        result_json = json.loads(res.text)
        # リストにフォロー者を追加
        for i in range(0, len(result_json["users"]), 1):
            follow_list.append(result_json["users"][i]["screen_name"])
        # リストを返す
        return follow_list
    else:
        return None
```

##2.各ユーザーのタイムラインを取得
1で取得した各ユーザーのscreen_nameを使用し、タイムラインを取得してJSON形式で返します。
今回は最新のツイートが欲しいので、count=1としています。

```python:get_user_timeline
def get_user_timeline(screen_name):
    # 認証処理
    twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
    # タイムライン取得エンドポイント
    url = "https://api.twitter.com/1.1/statuses/user_timeline.json"
    # パラメータ
    params = {
        "count": 1,
        "screen_name": screen_name,
        "include_entities": True,
        "exclude_replies": False,
        "include_rts": False,
    }

    # レスポンスからタイムラインリストを取得
    res = twitter.get(url, params=params)

    if res.status_code == 200:
        return json.loads(res.text)
    else:
        return None
```

##3.ツイート内容から画像有無を判定
まず2で保存したJSONファイルを以下のクラスにします。

```python:
class Tweet:
    def __init__(self, json_file):
        self.created_at = json_file[0]["created_at"]
        self.tweet_id = json_file[0]["id"]
        self.text = json_file[0]["text"]
        self.user_name = json_file[0]["user"]["name"]
        self.user_screen_name = json_file[0]["user"]["screen_name"]
        self.user_mention = json_file[0]["entities"]["user_mentions"]
        self.image_urls_list = []

        # 添付ファイルがある場合
        if "extended_entities" in json_file[0]:
            self.media_number = len(json_file[0]["extended_entities"]["media"])
            self.content_type = json_file[0]["extended_entities"]["media"][0]["type"]

            for i in range(0, self.media_number, 1):
                self.image_urls_list.append(
                    json_file[0]["extended_entities"]["media"][i]["media_url"]
                )

        else:
            self.media_number = 0
            self.content_type = ""
```
self.media_number = len(json_file[0]["extended_entities"]["media"])を見て
画像が投稿されているかを見分けます。

```python:is_content_type
def is_content_type(obj_tweet, expect_type):
    if obj_tweet.content_type == expect_type:
        return True
    else:
        return False
```


##4.画像があるものをいいね＆リツイート
画像が投稿されていた場合、以下のようにAPIをたたいていいねとリツイートを行います。
いずれもツイートIDを指定するだけでいいです。

```python:push_favorite
def push_favorite(tweet_id):
    # 認証
    twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

    # リクエスト
    url = "https://api.twitter.com/1.1/favorites/create.json"
    params = {"id": tweet_id}
    req = twitter.post(url, params=params)
    req_json = json.loads(req.text)

    if req.status_code == 200:
        return True
    # すでにいいね済の場合
    elif req.status_code == 403 and req_json["errors"][0]["code"] == 139:
        return True
    else:
        return False
```

```python:retweet
def retweet(tweetId):
    twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
    url = "https://api.twitter.com/1.1/statuses/retweet/%d.json" % tweetId
    res = twitter.post(url)
    res_json = json.loads(res.text)

    if res.status_code == 200:
        return True
    # すでにリツイート済
    elif res.status_code == 403 and res_json["errors"][0]["code"] == 327:
        return True
    else:
        return False
```