RSSの新しい投稿をTwitterに投稿するGitHub Actionsを作りました。

IFTTTでRSSをTwitterに投稿していたのですが、2023年に無料プランが終了するので代替手段を探していました。 色々探したけど欲しいものがなかったので作りました。

RSSでTwitterに投稿してたのが、GitHub Pagesで管理してるブログだけだったのでGitHub ActionsでRSSをチェックしてTwitterに投稿するアクションを作りました。

準備

Twitter API Keyの取得

投稿するアカウントでTwitter Appsを作り、API KeyやAccess Tokenを取得する必要があります。

  1. 投稿したいアカウントでログインする
  2. Twitter Appをつくります - https://developer.twitter.com/en/portal/dashboard
  3. デフォルトのパーミッションがReadのみになってることがあるのでRead and Writeに変更します
  • User authentication settings という場所から設定できるので、パーミッションをRead and Writeに変更します
  • ss 1
  • ss 2
  1. API Key/API Key Secret と Access Token/Access Token Secretを取得します
  • それぞれAPI KeyといAccess Tokenをregenerateするなどでコピーしておきます
  • Twitter APIKEY
  • TWITTER_APIKEYTWITTER_APIKEY_SECRET
  • Twitter ACCESS TOKEN
  • TWITTER_ACCESS_TOKENTWITTER_ACCESS_TOKEN_SECRET
  • ⚠️ ちゃんと “Read and Write permissions” になってることを確認してからトークンを作ってください
  • Twitter v1 APIを作ってる場合はProjectがないこともあるので、そこからやってください
  • トークンがあってない時、V1のトークンの場合は403エラーになります

Twitter API KeyをGitHub Actionsに設定する

GitHub ActionsのSecretsにTwitter API Keyを設定します。

  • https://github.com/{owner}/{repo}/settings/secrets/actions から設定できます

次の4つのSecretsを設定します。

  • TWITTER_APIKEY: API KeyとAPI Key Secretの対
  • TWITTER_APIKEY_SECRET: API KeyとAPI Key Secretの対
  • TWITTER_ACCESS_TOKEN: Access TokenとAccess Token Secretの対
  • TWITTER_ACCESS_TOKEN_SECRET: Access TokenとAccess Token Secretの対

使い方

主に二つのユースケースを想定しています。

📝 RSS_URLでチェックするRSSのURLとTWEET_TEMPLATEの投稿内容は各自の環境に合わせて設定してくだあい。

スケジュール投稿

定期的にRSSをチェックして、新しい投稿があればTwitterに投稿します。

GitHub ActionsではCronが指定できるので、on.schedule.cronで定期的に実行するように設定します。

次のサンプルだと、15分ごとにRSSをチェックして、新しい投稿があればTwitterに投稿します。


name: rss-to-twitter
on:
  schedule:
    # every 15 minutes
    - cron: "*/15 * * * *"
  workflow_dispatch:
jobs:
  twitter:
    runs-on: ubuntu-latest
    steps:
      - uses: azu/rss-to-twitter@v1
        with:
          # RSS feed URL
          RSS_URL: "https://hnrss.org/newest"
          TWEET_TEMPLATE: 'New Post: "%title%" %url%'
          UPDATE_WITHIN_MINUTES: 15 # for workflow_dispatch
          TWITTER_APIKEY: ${{ secrets.TWITTER_APIKEY }}
          TWITTER_APIKEY_SECRET: ${{ secrets.TWITTER_APIKEY_SECRET }}
          TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
          TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}

仕組み的にはこのcron構文をパースしています。 Actionが起動した瞬間に、前回のJobの時間をCron構文から計算して、前回のJobの時間から現在の時間までの間にある投稿を取得してTwitterに投稿します。

起動時間は微妙にズレることはあるので、5分ぐらいのズレを許容しています。

GitHub Pagesの更新を検知して投稿

GitHub Pagesでブログなどを公開している場合は、ページのビルドが終わったタイミングで、RSSをチェックして投稿できます。

次のサンプルでは、ビルドが成功した付近の時間に公開された投稿をTwitterに投稿します。

  • page_build: 2023年 5月28日 日曜日 11時00分00秒 JST
  • 投稿される記事: 2023年 5月28日 日曜日 10時45分00秒 JST - 2023年 5月28日 日曜日 11時00分00秒 JST の記事

この投稿時間は、Jekyllだとdateで指定されているような公開時間になります。 更新時間にしてないのは、更新すると再度Twitterに投稿されても微妙なので、公開時間にしています。


name: rss-to-twitter
on:
  page_build
jobs:
  twitter:
    # if github.event.build.error.message is not null, it means that the build failed. Skip it
    if: ${{ github.event.build.error.message == null }}
    runs-on: ubuntu-latest
    steps:
      - uses: azu/rss-to-twitter@v1
        with:
          RSS_URL: "https://you.github.io/feed.xml"
          TWEET_TEMPLATE: 'New Post: "%title%" %url%'
          UPDATE_WITHIN_MINUTES: 15 # post items that are published within 15 minutes
          TWITTER_APIKEY: ${{ secrets.TWITTER_APIKEY }}
          TWITTER_APIKEY_SECRET: ${{ secrets.TWITTER_APIKEY_SECRET }}
          TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
          TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}

注意事項として、GitHub Actionsで ${{ secrets.GITHUB_TOKEN }} を使ってGitHub Pagesにデプロイしている場合 page_build イベントは発火しません。これは、GitHub Actionsで無限ループを防ぐための仕様になってます。

${{ secrets.GITHUB_TOKEN }}の代わりにPersonal Access Tokenを使うとpage_buildイベントが発火されるので、PATを使ってください。

PATの代わりにGitHub Appsからトークンを作成しても良いです。

TWEET_TEMPLATE

テンプレートとして使える構文です。

  • %title%: Item title
  • %url: Item URL
  • %desc%: Item content snip(max 280 characters)

一応勝手に280文字(140文字)に切り詰めています。 テンプレートは既存の処理を使い回していて、あんまり必要なものを考えて作ってないので、必要ならPRください。

おわりに

正直同じことをやってる人はいると思って、作るのは避けてたいました。 ただ、調べてみても見つからなかったので作りました。

  • テンプレートリポジトリ自体をCloneしてやるパターンは避けたかった → ブログのリポジトリに設定を紐付けたい
  • 欲しいのはGitHub Actionsでシンプルなものだった → CLIも探したけど、いまいち見つけられず
  • ページがビルドできたら、すぐに投稿したい

ということで、このような形になりました。

GitHub Actionsのリリースが面倒だったり、Node.jsだとbundleの問題があるので、DenoかBunを使いたかったけどテンプレートがなくて諦めました。