Discordの /addch name:<チャンネル名> コマンドでテキストチャンネルを作成する、Cloud Run向けのHTTP Interactionサーバーです。
- DiscordのEd25519署名とタイムスタンプを検証します。
MANAGE_CHANNELSまたはADMINISTRATOR権限を持つメンバーだけが実行できます。- Botトークンを使い、Discord API v10でテキストチャンネルを作成します。
DISCORD_CATEGORY_IDの設定時は、指定したカテゴリー配下にチャンネルを作成します。- 成功メッセージはチャンネルに公開し、エラーは実行者だけに表示します。
GET /healthをヘルスチェックとして提供します。
Discord Developer PortalでApplicationとBotを作成し、次の値を控えます。
- Application ID
- General InformationにあるPublic Key
- Bot Token
Botをサーバーへ追加するときは、次のscopeと権限を付けてください。
- scope:
bot,applications.commands - Bot permission:
MANAGE_CHANNELS(16)
Message Content IntentやGateway Intentは不要です。
Go 1.26以降を使用します。
go test ./...
go vet ./...ローカルサーバーを起動する場合は .env.sample を参考に環境変数を設定します。通常のブラウザーやcurlから送ったPOSTはDiscord署名がないため、401 Unauthorized になります。
export DISCORD_BOT_TOKEN='...'
export DISCORD_PUBLIC_KEY='...'
export DISCORD_CATEGORY_ID='作成先カテゴリーID'
go run .Docker Composeを使う場合:
cp .env.sample .env
# .envを編集
docker compose up --build最初はテスト用サーバーのGuild IDを指定すると、コマンドが即時反映されます。
export DISCORD_BOT_TOKEN='...'
export DISCORD_APPLICATION_ID='...'
export DISCORD_GUILD_ID='テスト用Guild ID'
go run ./cmd/register全サーバー向けのグローバルコマンドとして登録する場合は、DISCORD_GUILD_ID を設定せずに実行します。同名コマンドへのPOSTはDiscord側で更新として扱われます。
scripts/deploy.sh はCloud RunとArtifact Registryを東京リージョンに置いたまま、Cloud BuildのソースだけをCloud Storage無料枠対象のus-west1へ保存します。Cloud RunからDiscordの署名付きリクエストを受けるため、サービス自体は未認証アクセスを許可し、アプリケーション内で署名を検証します。
プロジェクトの初期設定後、.envを用意して次を実行します。
./scripts/deploy.shこのスクリプトは次を実施します。
us-west1のソースバケットを作成し、1日経過したビルドソースを削除する- ソースバケットのSoft Deleteを無効にする
- Cloud Buildでコンテナを作成し、既存の東京Artifact Registryへ保存する
- Secretを新バージョンとして追加し、その番号をCloud Runへ固定してデプロイする
- ヘルスチェック成功後に旧Secretバージョンを破棄する
- Artifact Registryで最新1イメージだけを保持するcleanup policyを有効にする
Secretの旧バージョン破棄は取り消せません。また、旧コンテナの削除後は過去のCloud Runリビジョンへロールバックできないため、必要な場合は先に別途バックアップしてください。
以下は初期構築を手動で行う場合の例です。
export PROJECT_ID='Google CloudプロジェクトID'
export REGION='asia-northeast1'
export SERVICE_NAME='addchan'
export RUNTIME_SERVICE_ACCOUNT="addchan-run@${PROJECT_ID}.iam.gserviceaccount.com"
gcloud config set project "$PROJECT_ID"
gcloud services enable \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
secretmanager.googleapis.com
gcloud iam service-accounts create addchan-run \
--display-name='addchan Cloud Run runtime'
gcloud secrets create addchan-discord-bot-token \
--replication-policy=automatic
printf '%s' "$DISCORD_BOT_TOKEN" | \
gcloud secrets versions add addchan-discord-bot-token --data-file=-
gcloud secrets add-iam-policy-binding addchan-discord-bot-token \
--member="serviceAccount:${RUNTIME_SERVICE_ACCOUNT}" \
--role='roles/secretmanager.secretAccessor'
gcloud builds submit . \
--region="$REGION" \
--gcs-source-staging-dir="gs://addchan-build-source-${PROJECT_ID}-us-west1/source" \
--tag="${REGION}-docker.pkg.dev/${PROJECT_ID}/cloud-run-source-deploy/${SERVICE_NAME}:manual"
gcloud run deploy "$SERVICE_NAME" \
--image="${REGION}-docker.pkg.dev/${PROJECT_ID}/cloud-run-source-deploy/${SERVICE_NAME}:manual" \
--region="$REGION" \
--allow-unauthenticated \
--service-account="$RUNTIME_SERVICE_ACCOUNT" \
--cpu=1 \
--memory=512Mi \
--concurrency=20 \
--min-instances=0 \
--max-instances=1 \
--timeout=5s \
--set-env-vars="DISCORD_PUBLIC_KEY=${DISCORD_PUBLIC_KEY},DISCORD_CATEGORY_ID=${DISCORD_CATEGORY_ID}" \
--set-secrets='DISCORD_BOT_TOKEN=addchan-discord-bot-token:latest'デプロイ後、URLを確認します。
SERVICE_URL="$(gcloud run services describe "$SERVICE_NAME" \
--region="$REGION" \
--format='value(status.url)')"
curl "${SERVICE_URL}/health"Discord Developer PortalのGeneral InformationにあるInteractions Endpoint URLへ、次を設定します。
https://Cloud-RunのURL/interactions
Discordが署名付きPINGを送り、サーバーがPONGを返すとURLが保存されます。その後、上記の登録ツールで /addch を登録してください。
| 名前 | 必須 | 説明 |
|---|---|---|
DISCORD_BOT_TOKEN |
はい | Discord Bot Token。Cloud RunではSecret Managerから注入します。 |
DISCORD_PUBLIC_KEY |
はい | Discord ApplicationのEd25519 Public Key(16進文字列)。 |
DISCORD_CATEGORY_ID |
いいえ | チャンネル作成先のDiscordカテゴリーID。未設定ならGuild直下に作成します。 |
PORT |
いいえ | HTTPポート。既定値は8080で、Cloud Runが自動設定します。 |
DISCORD_API_BASE_URL |
いいえ | テスト用Discord API URL。通常は設定しません。 |
登録ツールでは追加で DISCORD_APPLICATION_ID が必要です。DISCORD_GUILD_ID を指定するとGuild command、省略するとGlobal commandになります。
- DiscordはInteractionへの初回応答を3秒以内に要求します。Discord API呼び出しには2秒のタイムアウトを設定しています。
min-instances=0ではコールドスタートが発生します。通常は小さなGoバイナリで収まりますが、3秒以内の応答を保証したい場合はCloud Runの最小インスタンスを検討してください。- Cloud Runのサービスは公開URLになるため、Bot Tokenを通常の環境変数へ直接保存しないでください。
max-instances=1は小規模利用向けのコスト保護設定です。利用が増えた場合は引き上げてください。
MIT License