Twitter 画像付き自動投稿つくってみた【AWS Lambda】

## あらまし
素数の日（=yy/mm/dd のdd 部が素数）[^1]にその素数にちなんだ画像を自動ツイートする機能をAWS Lambda で作成しました。

[^1]:yyyymmdd の8桁が素数の場合を「素数の日」と呼ぶ流派もあるようです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">今日は23日です．素数の日おめでとう．<br> <a href="https://twitter.com/hashtag/pixelart?src=hash&amp;ref_src=twsrc%5Etfw">#pixelart</a> <a href="https://twitter.com/hashtag/LINE%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%97?src=hash&amp;ref_src=twsrc%5Etfw">#LINEスタンプ</a> <br> <a href="https://t.co/Ya7euC5jMG">https://t.co/Ya7euC5jMG</a> <a href="https://t.co/H4Vv8iSJTV">pic.twitter.com/H4Vv8iSJTV</a></p>&mdash; ｶﾉｺﾘﾝﾀﾛｳ(𝙼𝚎𝚗𝚘)@ShibuyaArtAwards展示(12-13th) (@RyntaloL) <a href="https://twitter.com/RyntaloL/status/1595162489708195840?ref_src=twsrc%5Etfw">November 22, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


殆ど以下の記事に記載されている通りに実装したので、関数作成前のTwitter API利用開始までの手順を備忘録としてメモ。

https://qiita.com/niwasawa/items/272d55b474980080f99c#amazon-cloudwatch-events-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B

## Twitter Developer Portal に登録

Twitter API を利用するために、以下のDeveloper Portal にアカウントを登録します。

https://developer.twitter.com/en/portal/dashboard

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/2f641aea-5e18-157a-abf9-332c7eeb3645.png)

APIを利用するTwitter アカウントで、事前に電話番号を登録しておかないといけなかった。こちらは登録していなかった場合のエラーメッセージ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/dd8a9d5a-20af-3056-566c-742cbe92f43f.png)

> There was a problem completing your request
User must have a verified phone number on file prior to submitting application.

電話番号の登録はTwitter のアカウント設定から実施。

その後Developer Potal に戻り、登録継続。
こちらでアプリ名を入力。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/b0ee47bb-8c75-c0b5-7771-9c8fb0e00b94.png)

事前に調べたところもっと大変そうだったのですが、この時点でAPI キー等が取得できました。
※後ほどアクセス権限をアップグレードするElevated Access のリクエストにて、英作文する必要がありました。後述。

## キーをSystem Manager のパラメータストアに登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/4187e753-3b90-8d30-be99-3bb6a11ac5aa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/0274ce34-d911-e435-8a1b-24be8591ba1b.png)

ユーザ毎のアクセストークンをTwitterDeveloper Dashboard から生成しておいて、こちらも同様に登録。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/bb4240d1-29c1-a14f-aa0d-68965f595db3.png)

初めに生成したらRead Only の権限だったので、Read and Write に設定して再生成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/cb6f0202-63cd-4f91-bc26-2b7feda8250f.png)

設定はUser authentication Settings から。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/3887e59e-9c14-0a95-5458-727fd4dc61a7.png)


## Lambda 関数の作成

Role はBasic Lambda Permissions で登録。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/bf5b1fa2-304e-58f0-11c3-96370865ae7e.png)

このRole はSystem Manager のパラメータストアを参照できるよう、権限を編集する必要があります。
こちらの記事を参考にしました。

https://dev.classmethod.jp/articles/sugano-039-ssm-paramstore-lambda/

Lambda 関数の中身は冒頭で張り付けた記事を参考にしています。再掲。

https://qiita.com/niwasawa/items/272d55b474980080f99c#amazon-cloudwatch-events-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B

## Developer Portal でAPI権限の拡張をリクエスト

Lambda 関数のテスト実行後、次のエラーが出る。

> You currently have Essential access which includes access to Twitter API v2 endpoints only.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/1e396275-096f-3dee-9c95-7f100ab0faee.png)

**テスト実行結果としてはSuccess と出ている**ので、ちょっと紛らわしい。

このエラーはAPIの利用権限が足りていないのが原因。
Twitter Developer の以下へアクセスし、Apply for Elevated のリクエストを送る。

https://developer.twitter.com/en/portal/products/elevated

ここで英文での利用用途の説明が必要。以下に回答を張り付けておきます。

* Q. How will you use the Twitter API or Twitter Data?

> I'm going to create TweetBot for a personal use. I will use AWS Lambda for deploying, and this will be triggered on a specific day by AWS CloudWatch. The purpose is to post an image related to some specific day, not for any businesses. 

* Q. Will your App use Tweet, Retweet, Like, Follow, or Direct Message functionality?

> I will use only a post method to post a Tweet with an image. I would not use Retweet, Like, Follow or Direct Message methods. 

その他の質問事項はスイッチをオフにして無回答。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/7aa83882-b5fc-aef8-b221-dad892aea576.png)

サブミット後、即承認される。

再度Lambda のテストを実行すると、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/e532af69-bbac-9534-b30a-d81c5df16cbd.png)

無事ツイートできていた。

## EventBridge (Cloudwatch Event) でLambda の実行トリガーを設定

毎月、素数の日の06時09分に発火するよう設定。
ただしEventBridge のCron 式はUTCなので9時間前の21時9分、日付も一日前で設定。ちょっとややこしい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/3a571848-0405-4a0a-fbd5-95be85e3a2aa.png)


## 追記：料金について

一か月運用してみたところ、無料利用枠に収まっていました。
コストに関わってくるリソースはEvent Bridge とLambda ですが、この通り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/12fb3bef-5960-f73e-18a9-fede455d6d55.png)


## まとめ

そんなわけで[拙Twitter アカウント](https://twitter.com/RyntaloL)では素数の日に*素敵*を*素数*と言い間違えた画像が自動投稿されるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/6ae6d45e-9227-5de5-af97-57af7cc85b24.png)

ちなみにこれらは元々LINEスタンプとして作成したもの。販売中です。

https://store.line.me/stickershop/product/20969693/ja

自動投稿の対象でない、31より大きな素数もあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/ab249632-acda-652a-a34a-beeb168df8ec.png)