Github Actions で Twitter の Bot を稼働できる件

こんにちは！ぬこすけです。

「[Github Actions で SEO 対策！サイトマップ作成を自動化！](https://qiita.com/nuko-suke/items/f397334c30817b22948c)」に続き Github Actions について 2 回目の投稿です!

https://qiita.com/nuko-suke/items/f397334c30817b22948c

あまり利用イメージはないかもしれませんが、実は **Github Actions で Twitter Bot を運用できちゃったりします**。

この記事では私が運営しているサイト「[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)」で実際にやっている Github Actions を使った Twitter Bot の運用について紹介します。

なお、もし Github Actions がわからない方は「[Github Actions で SEO 対策！サイトマップ作成を自動化！](https://qiita.com/nuko-suke/items/f397334c30817b22948c)」の「[Github Actions とは](https://qiita.com/nuko-suke/items/f397334c30817b22948c#github-actions-%E3%81%A8%E3%81%AF)」を見てもらえればと思います。

## どんな Twitter Bot?

[こいつ](https://mobile.twitter.com/nukoprogramming)です。
![nukopro_twitter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164159/8b908508-d6c9-c303-89fb-e04af5509593.png)
この猫型 Twitter Bot は 1 日に 2 回、こんな感じでおすすめの技術書を自動でツイートしてくれます。
![nukopro_tweet_example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164159/7bab1c88-0641-8ec1-2440-f35f16226e58.png)
この猫型 Twitter Bot の正体ですが、実は内部的には **Github Actions を使って動かしています**。

## Github Actions でどうやって Twitter Bot を動かしているの？

簡単です。 **Github Actions で Twitter Bot を動かすためのスクリプトを定期実行しているだけ** です。

スクリプトの実行内容としては簡単に次の 3 ステップになっています。

1. 技術書の情報を返却する API にリクエストして、技術書の情報をとってくる。
2. bitly の API にリクエストして短縮 URL を取得する。
3. Twitter の API を使ってツイート。

まず、技術書の情報を返却する API へリクエストし、ツイートする本のタイトルやカテゴリ（ Python や JavaScript など）の情報を取得します。

次に [bitly](https://bitly.com/) という URL を短縮してくれる API を使います。
ツイートには[全角140文字／半角280文字という文字数制限](https://news.mynavi.jp/article/20210907-1966765/#:~:text=%E7%9B%AE%E6%AC%A1%E3%82%92%E9%96%8B%E3%81%8F-,%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E3%81%A7%E3%81%8D%E3%82%8B%E6%96%87%E5%AD%97%E6%95%B0%E3%81%AF%E5%85%A8%E8%A7%92140%E6%96%87%E5%AD%97%EF%BC%8F%E5%8D%8A%E8%A7%92280%E6%96%87%E5%AD%97,%E6%96%87%E5%AD%97%E6%95%B0%E3%81%AE%E5%88%B6%E9%99%90%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82)があるため、次のような長ったらしい URL を短くします。

- 短縮前
  - https://nuko-programming.com/ranking/TypeScript/book/b060d6f2-1ed8-4d6e-89eb-2164386f5108
- 短縮後
  - https://t.co/65cHVBJeEw

最後に Twitter の API を使ってツイートします。
Twitter の API を使うために事前に認証情報を用意しておきます。
また、API へのリクエスト処理は自前で実装するのが大変なので、[twitter-api-v2](https://github.com/PLhery/node-twitter-api-v2)というライブラリを使います。

ここまで簡単な処理内容について説明しましたが、イメージとしては次のような JavaScript ファイルになります。

```js
import axios from 'axios';
import { TwitterApi } from 'twitter-api-v2';

// ツイッターの認証情報
const twitterCredentials = {
  appKey: process.env.TWITTER_APPKEY,
  appSecret: process.env.TWITTER_APPSECRET,
  accessToken: process.env.TWITTER_ACCESSTOKEN,
  accessSecret: process.env.TWITTER_ACCESSSECRET,
};

// twitter-api-v2 というライブラリを使ってツイッターの API を叩く
const twitterClient = new TwitterApi(twitterCredentials);

// bitly の認証情報
// bitly は URL 短縮サービス。ツイッターは文字数制限があるので重宝。
const bitlyAccessToken = process.env.BITLY_ACCESSTOKEN;

// ツイートする文言
const createText = (keyword, title, url) =>
  `${keyword}入門書ランキング1位⚡は「${title}」にゃ！\n#${keyword}\n#プログラミング初心者\n#駆け出しエンジニアと繋がりたい\n${url}`;

try {
  // Python や JavaScript など、技術書のカテゴリ一覧を取得。一覧のソートはランダム。
  const keywords = await axios.get(...);
  const keyword = keywords[0]
  // カテゴリをキーに技術書一覧取得。一覧のソートはランキング順。
  const books = await axios.get(...);
  // 1位の技術書
  const book = books[0];
  // URL短縮するため bitly にリクエスト
  const { data } = await axios.post(
    'https://api-ssl.bitly.com/v4/shorten',
    {
      long_url: `https://nuko-programming.com/ranking/${encodeURIComponent(keyword)}/book/${
        book.id
      }`,
    },
    {
      headers: {
        Authorization: `Bearer ${bitlyAccessToken}`,
        'Content-Type': 'application/json',
      },
    },
  );
  // ツイートする文言生成
  const text = createText(keyword, book.title, data.link);
  // ツイート
  twitterClient.v2.tweet(text);
} catch (e) {
  console.error(e);
  process.exit(1);
}
```

## Github Actions のファイル例

では Github Actions の yml ファイルはどうなっているのでしょうか？

サンプルとしては次のようになっています。

```yml
name: daily-tweet

on:
  schedule:
    - cron: '0 0 * * *'
    - cron: '0 9 * * *'

jobs:
  tweet:
    runs-on: ubuntu-latest
    timeout-minutes: 60
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: '16'
          cache: npm
      - name: Install Dependencies
        run: npm ci
      - name: Start API
        run: npm run start-gcp
      - name: Post Tweet
        run: npm run tweet
      - name: Stop API
        if: ${{ always() }}
        run: npm run end-gcp
```

`on.schedule.cron[]` で毎日 9 時と 18 時に定期実行しています（時間は UTC での指定なので注意）。

あとは、API サーバーは GCP 上に立てているので、ツイートする JavaScript のスクリプト実行前後に API サーバーを起動/停止するコマンドも用意しています。

このような Github Actions の yml ファイルを用意しておくで、自動でツイートしてくれるようになっています。

## まとめ

Github Actions で Twitter の Bot を稼働させる例を紹介しました。

Github Actions の yml ファイルとスクリプトファイルがさえあればすぐにでも作れるので、ぜひ参考にしてみてください！

また、Github Actions に関してはこちらの記事も書いたのでぜひ読んでいただければ！

https://qiita.com/nuko-suke/items/f397334c30817b22948c

[Qiita エンジニアフェスタ 2022](https://qiita.com/official-campaigns/engineer-festa/2022) というのを今やっているそうなので、興味ある方は記事投稿して盛り上げて行きましょう〜。

https://qiita.com/official-campaigns/engineer-festa/2022