はじめに
皆さま初めまして。
HapinessChainというオンラインスクールで奮闘中のKeiと申します。
ここでは学習した内容をメンターに日報として報告していますが、
成果をXにも投稿したく今まではGithub上にある日報を手動でコピーしてポストしていました。
大した労力ではないですが、毎日となると案外手間なので、
GitHubプッシュ時にコミットした内容を自動的にポストするようにしました。
実際にやってみるとそこまで難しくなく実装できたので、
今回はGitHub Actionsを利用してポストを自動投稿するやり方を紹介します。
環境構築と実装については以下の記事を参考にさせて頂いております。
X Developer Portalの登録
X Developer Portal
は、開発者がXのAPIを利用してアプリケーションを構築するためのプラットフォームになります。
まずはX Developer Portalにプロジェクトとアプリケーションを登録します。
- 右上の
開発者ポータル
を押下します - Xにログインしていない場合はログインしてください
- 画面下の
Sign up for Free Account
を選びます -
Describe all of your use cases of Twitter’s data and API
欄に使用用途を英語で記載し、Submit
を押下してください。内容で精査されることは基本的にありません
画面左側のProject & Apps
にプロジェクトとAPIが作成されていると思います。
認証設定
デフォルトではXへの書き込み権限がないためまずは認証設定を行います。
- 遷移していない場合は
開発者ポータル
画面に遷移します - 左側のメニューより
[Project & Apps] > [xxxxxxAccountName]
を選択し、APIの管理画面に遷移します - 画面中央の
User authentication settingsの[Set up]
を押下します -
App permissions
はRead and write
をまたはRead and write and Direct Message
を選択します。Read
だとXにポストできません -
Type of App
の欄ですが今回はWebアプリなのでWeb App Automated App or Bot
を選択します -
App info
のCallback URI
とWebsite URL
欄はOAuth認証が必要な場合において設定します。必須項目ではありますが、今回は特に使用しないので自分のXアカウントのURLを指定してください - 内容に問題なければ
Save
を押下してください
これでXへの書き込み権限が付与されます。
APIキーの取得
Xへの連携用のキーを取得します。
今回は以下の5つのAPIキーを使用します。
- Consumer API Key
- Consumer API Secret
- Bearer Token
- Access Token
- Access Token Secret
- 左側のメニューより
[Project & Apps] > [xxxxxxAccountName]
を選択し、APIの管理画面に遷移します - 画面上部のタブより
Keys and tokens
を選択します - 以下の項目において
generate
を押下し、APIキーを取得してください。紛失時は再度生成する必要があるため、しっかりとメモしておいてください- API Key and Secret
- Bearer Token
- Access Token and Secret
キー取得後の画面になります。初回実行時はgenerate
となっているので、押下して取得します。
注意点はAccess Token and Secret
の赤枠欄がRead Write
またはRead Write and Direct Message
となっている事を確認してください。
認証設定の節でも説明しましたが、Read
となっているとXにポストできません。
なっていない場合はもう一度認証設定の節を確認して設定してください。
なお、設定後はキーの再生成が必要になります。
Githubリポジトリの作成
作成していない場合はGitHubリポジトリを新規作成してローカル環境にクローンします。
なおリポジトリ作成後にPersonal Access Tokens
を設定してコミットできるようにしておきます。
権限内容についてですが、
Actions
、Workflows
はワークフローを作成するのでRead and write
としてください。
またSecretsから環境変数を読み込むのでSecrets
はRead
としてください。
GitHubに環境変数を設定
後述するGitHubActionsのスクリプトからAPIキーを読みませるために環境変数を設定します。
GitHubリポジトリの管理画面を表示し、以下の画像を参考に設定してください。
- TWITTER_ACCESS_TOKEN
- TWITTER_ACCESS_TOKEN_SECRET
- TWITTER_BEARER_TOKEN
- TWITTER_CONSUMER_KEY
- TWITTER_CONSUMER_SECRET
スクリプトファイルの作成
Github Acitonsで実行するスクリプトファイルを作成します。
今回はpythonで作成しtweetpy
というX APIを使用して連携します。
作成したスクリプトをローカルリポジトリの直下に配置してください。
今回の仕様として、リポジトリ内にYYYY/MM/DD.md
という日報が存在し、
Githubプッシュ時にファイル名の日付が最新の日報をXにポストします。
import tweepy
import os
import glob
from datetime import datetime
# Twitter APIのキーとトークンを環境変数から取得
ck = os.environ['TWITTER_CONSUMER_KEY']
cs = os.environ['TWITTER_CONSUMER_SECRET']
bt = os.environ['TWITTER_BEARER_TOKEN']
at = os.environ['TWITTER_ACCESS_TOKEN']
ats = os.environ['TWITTER_ACCESS_TOKEN_SECRET']
# Twitter APIのクライアントを初期化
client = tweepy.Client(
bearer_token=bt,
consumer_key=ck,
consumer_secret=cs,
access_token=at,
access_token_secret=ats
)
# 最新の.mdファイルを取得
def get_latest_markdown_file():
# サブフォルダ内のすべての.mdファイルを再帰的に取得
markdown_files = glob.glob('**/*.md', recursive=True)
if not markdown_files:
return None
latest_file = None
latest_date = None
for file in markdown_files:
# ディレクトリ名とファイル名から日付を取得
# 例: 2024/09/20.md から "2024-09-20" を抽出
path_parts = file.split('/')
if len(path_parts) >= 3:
date_str = f"{path_parts[-3]}-{path_parts[-2]}-{path_parts[-1][:-3]}" # YYYY-MM-DD
try:
date = datetime.strptime(date_str, "%Y-%m-%d")
except ValueError:
continue # 日付が無効な場合はスキップ
# 最新の日付を更新
if latest_date is None or date > latest_date:
latest_date = date
latest_file = file
return latest_file
# ツイート内容を取得
latest_md_file = get_latest_markdown_file()
if latest_md_file:
with open(latest_md_file, 'r', encoding='utf-8') as file:
content = file.read()
# ツイート内容をトリミング
if len(content) > 264:
content = content[:261] + '...' # トリミングして「...」を追加
# ハッシュタグを追加
hashtags = "#今日の積み上げ"
tweet_content = f"{content}\n\n{hashtags}"
# ツイートを投稿
try:
client.create_tweet(text=tweet_content)
print('Tweet sent successfully!')
except tweepy.errors.Forbidden as e:
print('Error posting tweet: Forbidden', e)
except Exception as e:
print('Error posting tweet:', e)
else:
print('No markdown files found.')
ワークフロー定義の作成
Github Actionsで実行するワークフローファイルを作成します。
クローンしたローカルリポジトリ内に.github/workflows
ディレクトリを作成して
.yml
ファイルを作成してください。
今回は便宜上tweet.yml
としておきます。
GitHubプッシュ時にGitHub Actionsのトリガーが起動するように設定しているので、
ワークフローファイルとスクリプトを配置するだけで実行されるようになります。
# ワークフローの名称。
name: Create X Post
# トリガーの指定。GitHubにプッシュされた時に実行する
on:
push:
branches:
- main
# ワークフローの作成。pythonのバージョンは実行環境に応じて変更してください。
jobs:
tweet:
runs-on: ubuntu-latest
environment: X_Automation
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
# X API(tweepy)を使用して連携を実施します
- name: Install dependencies
run: |
pip install tweepy
# 実行ファイルと環境変数の読み込み
- name: Post article
env:
TWITTER_CONSUMER_KEY: ${{ secrets.TWITTER_CONSUMER_KEY }}
TWITTER_CONSUMER_SECRET: ${{ secrets.TWITTER_CONSUMER_SECRET }}
TWITTER_BEARER_TOKEN: ${{ secrets.TWITTER_BEARER_TOKEN }}
TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
run: python tweet.py
Github Actionsのログを確認
問題無ければプッシュ時にポストされていると思います。
Xにポストされているか確認しましょう。
もしされていない場合はGitHubアクション内でエラーが発生していると思うので、
GitHubのリポジトリ管理画面よりActions
タブを押下してエラー内容を確認してください。
参考程度に筆者が沼ったのは以下でした。
- 環境変数のキーと値に誤りがある
- 認証設定で
read and write
になっていない - 認証設定変更語にトークンの再取得をしていない
上記が正しく設定できていないと、
X ポスト時に権限エラーで403 Forbidden
が表示されていると思います。
おわりに
GitHub Actionsを利用してコミット内容をXにポストする方法を紹介させて頂きました。
非常に簡単で色々応用ができそうですね。
定期的に学習して更に便利な使い方を模索していきたいと思います。