はじめに
Discordサーバーで「もくもく読書会」なるゆるーい読書会を定期開催しており、その運営をサポートする 2種類の機能を持つBot を作成しました。
- 読書ログを自動でまとめて投稿するBot(週次)
- 読書会のリマインドや開始・終了をお知らせするBot(スケジュール実行)
最初はすべて GitHub Actions で実装していたのですが、 読書会の「開始・終了合図」には向いていない という気づきから、一部を AWS Lambda + EventBridge に切り替えました。
読書ログを自動でまとめて投稿するBotの内容は別の記事にメモしてます。本記事では、もう一つのリマインドする機能について記載します。
構成要素:読書会の合図投稿(開始前・開始時・終了5分前)
- 「明日の朝やります!」
- 「読書開始の合図です」
- 「終了5分前です〜感想を投稿してね」 などを自動投稿。
- イベントの直前通知なので、 正確な時刻での実行 が求められます。
イベントの直前通知が目的なので、正確なタイミングでの実行が重要です。これまでは手動で投稿していましたが、読書に集中するために、Botに任せることにしました。
GitHub Actions ではなく AWS Lambda を選んだ理由
GitHub Actions を試したときの課題
- スケジュール(cron)を設定しても、最大で1時間程度のラグが発生することがありました。
- 読書会の「開始1時間後に『始めます』が届く」といった事態も起こりえます。
これらの理由から、タイミングが重要な通知には不向きであると判断しました。
AWS Lambda + EventBridge にした理由
項目 | GitHub Actions | AWS Lambda + EventBridge | ローカルサーバー |
---|---|---|---|
実行の正確性 | △ 少しラグあり | ◎ 秒単位で正確 | ◎ 秒単位で制御可能 |
管理・保守 | ◎ GitHubに集約 | △ LambdaとGitHubで分散 | △ サーバー管理が必要 |
実行コスト | ◎ 無料プランあり | 〇 週1程度ならほぼ無料 | 〇 電気代程度 |
拡張性 | △ 限定的 | ◎ 他のAWSサービスと連携可 | ○ ローカルで自由に拡張可能 |
→ スケジュール通知BotはLambda or ローカルが相性良し。読書ログBotはGitHub Actionsで十分。
Raspberry Pi や常時稼働のLinuxマシンがあるなら、ローカルサーバーでの運用でもOKです。
AWS Lambda 側の構成
ファイル構成(一部抜粋)
.
├── greet_lambda.py # モード(day_before/start_notice/end_notice)で定型文送信
├── lambda_package/ # Lambda用のコード+依存ライブラリ(requestsなど)
├── lambda.zip # アップロード用zipファイル
└── .github/workflows/booklog.yml # GitHub Actionsのスケジュール設定
greet_lambda.py
は、例えば以下のような内容です。
引数で以下のモードを受け取り、メッセージを投稿します。
- day_before:「明日の朝やります!」
- start_notice:「読書開始の合図です」
- end_notice:「終了5分前です〜感想を投稿してね」
import os
import discord
import asyncio
DISCORD_TOKEN = os.environ["DISCORD_BOT_TOKEN"]
CHANNEL_ID = int(os.environ["DISCORD_CHANNEL_ID"])
MESSAGES = {
"day_before": "明日の朝も「もくもく読書会」やります!\nジャンル不問ですし、ほかの人の面白そうな本と出合えるかもしれません。気軽にご参加ください~!",
"start_notice": "おはようございます☀ 今日ももくもく読書していきましょう!\n\n「読む本のタイトル or 内容」を軽く投稿してください。\n例:「○○の設計思想(3章から)読みます」\n\n📖読書スタート📖",
"end_notice": "終了5分前~アウトプットタイムです\n読んだ内容や感想・学びを共有(短くてもOK!)"
}
async def send_message(mode):
intents = discord.Intents.default()
client = discord.Client(intents=intents)
@client.event
async def on_ready():
print(f"Discordに接続成功!モード: {mode}")
channel = await client.fetch_channel(CHANNEL_ID)
await channel.send(MESSAGES.get(mode, f"(未定義モード: {mode})"))
await client.close()
await client.start(DISCORD_TOKEN)
def lambda_handler(event, context):
print("Lambda 起動")
print(f"イベント受信: {event}")
# モード取得とバリデーション
mode = event.get("mode")
if not mode:
print("[Error] モードが指定されていません")
return {
"statusCode": 400,
"body": "Error: 'mode' must be specified in the event payload."
}
if mode not in MESSAGES:
print(f"[Error] 無効なモード: {mode}")
return {
"statusCode": 400,
"body": f"Error: Invalid mode '{mode}' specified."
}
print(f"使用モード: {mode}")
asyncio.run(send_message(mode))
return {
"statusCode": 200,
"body": f"Message sent in mode: {mode}"
}
Lambdaデプロイ手順
Lambda関数の作成
- AWSマネジメントコンソールにログイン
- 「Lambda」→「関数の作成」→「一から作成」
- 関数名、ランタイム(例:Python 3.10)を設定
- 適切なIAMロールを設定
※ Secrets Manager等へのアクセスを許可しておくと便利です
環境変数の設定(Lambda内)
環境変数キー | 内容 |
---|---|
DISCORD_BOT_TOKEN |
Discord Bot のトークン |
DISCORD_CHANNEL_ID |
投稿先チャンネルのID |
Lambda ZIPパッケージの作成とアップロード
ZIPパッケージの作成手順
mkdir lambda_package
# 必要なPythonスクリプトやライブラリを配置
pip install -r requirements.txt -t lambda_package
cp greet_lambda.py lambda_package/
cd lambda_package
zip -r ../lambda.zip .
ZIPのアップロード手順
- Lambda関数の「コード」タブを開く
- 「アップロード」→「.zipファイルをアップロード」を選択
- 作成した
lambda.zip
をアップロードし、保存
- Lambda のタイムアウト設定は 最低10秒以上 を推奨します。3秒だとタイムアウトになりました。
テスト実行
Lambda管理画面 → 「テスト」で以下のようなJSONを指定します。
{
"mode": "start_notice"
}
mode
には day_before
, start_notice
, end_notice
のいずれかを指定します。
※ CloudWatch Logs で実行ログも確認可能です。
EventBridgeによるスケジュール実行
EventBridge → 「ルールの作成」から、以下のスケジュールを設定します。
GitHub ActionsではUTC時刻での設定ですが、EventBridgeではJST時刻で時間指定することができます。日本人にとってはわかりやすいです。
例えば、毎週金曜の21:00にリマインドをする場合、cron式で00 12 ? * FRI *
と記述します。
ターゲットの選択オプションで、今回作成したDiscord bot用のLambda関数を指定し、ペイロードに JSON形式で引数を指定します。
今回は3つのリマインドを引数を変えて実行するので、以下の3つのスケジュールを作成します。
以下のように投稿してくれるようになります。
今後の展望
- 定型文ではなく、毎回異なるあいさつをするように対応
- Botからリアクションを返す機能
- リマインドBotもGitHubでバージョン管理しやすい構成へ改善
まとめ
Botの種類 | 実行基盤 | 実行頻度 | 備考 |
---|---|---|---|
読書ログまとめ | GitHub Actions | 週1 or 月1回 | まとめるだけなら十分 |
読書会リマインド | AWS Lambda | 毎週3回 | イベント直前通知に最適 |
シンプルなBotでも、自動化すると運営の負担がかなり軽くなりました。
個人の備忘録ですが、同じように読書会やイベントを運営している方や、自動化ツールの参考になれば幸いです。