ひょんなことからあるコミュニティの業務自動化をお願いされたので、備忘録として記載します。
まずは自動通知機能を作りたい。…が、DiscordBotでのメンション機能をつけるにはDiscord上で一意となるユーザIDなるものが必要とな。
※人が手でメンションする分には「@+ニックネーム」でOKなんですが、Botで自動通知するには不正防止のためにユーザIDをメンションしないとメンションとして飛ばないそうです。
ということで開発手前段階のDiscordユーザIDを全取得する機能を作りました。
やることぜーんぶちゃっぴーに教えてもらったので、記事もほとんどチャッピーに書いてもらいました。ありがとうチャッピー。
やったこと
- Discord Bot 作成
- GCP側の準備
- ソース作成
- Cloud Run にデプロイ
最終的に、
👉 Cloud RunのURLにアクセスすると
👉 Discordメンバー一覧がスプレッドシートに自動反映
するところまで完成させます。
全体構成
Discord API
↑
Cloud Run (Node.js + discord.js)
↓
Google Sheets API
↓
Googleスプレッドシート
① Discord Botを作成
1. Developer Portalへアクセス
2. New Application
任意の名前を入力
3. Botを作成
- 左メニュー「Bot」
- 「Add Bot」
4. Members Intent をON
Bot設定画面で:
- ✅ Server Members Intent を有効化
これをONにしないとメンバー一覧は取得できません。
5. Botトークンを取得
「Reset Token」→ Copy
⚠ このトークンは後でCloud Runの環境変数に設定します。
6. Botをサーバーに招待
OAuth2 → URL Generator
7. サーバーIDを取得
② GCP側の準備
1. プロジェクト作成
Google Cloud Consoleで新規プロジェクト作成
2. Cloud Runを有効化
APIとサービス → ライブラリ → Cloud Run API 有効化
3. Google Sheets API有効化
APIとサービス → ライブラリ → Google Sheets API 有効化
③ スプレッドシート準備
新規スプレッドシートを作成
1行目にヘッダーを入れる:
| A列 | B列 |
|---|---|
| DiscordユーザID | ユーザ名 |
スプレッドシートURLの:
/d/【ここ】/edit
の部分が SPREADSHEET_ID になります。
⚠ このIDは後でCloud Runの環境変数に設定します。
④ Cloud Runのサービスアカウント設定
1. Cloud Runのサービスアカウント確認
Cloud Run → サービス → セキュリティタブ
例:
123456789-compute@developer.gserviceaccount.com
※セキュリティタブにいない場合はIAM → サービスアカウント で上のようなアカウントを見つけられたらOKです。
2. IAMで権限付与
IAM → 上記サービスアカウントに
編集者
ロールを付与
3. スプレッドシートに共有
スプレッドシート → 共有
サービスアカウントメールを追加
権限:編集者
⑤ ローカル環境準備(Node.js)
1. フォルダ作成
mkdir discord-member-export
cd discord-member-export
2. 初期化
npm init -y
3. 必要パッケージ
npm install express discord.js googleapis
⑥ ソースコード
index.js
// ===== 必要ライブラリ読み込み =====
const express = require('express');
const { Client, GatewayIntentBits } = require('discord.js');
const { google } = require('googleapis');
// ===== Expressサーバー設定(Cloud Run用)=====
const app = express();
const PORT = process.env.PORT || 8080;
// ===== HTTP GET "/" にアクセスされたときの処理 =====
app.get('/', async (req, res) => {
// ===== Discordクライアント生成(メンバー取得Intent必須)=====
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers
]
});
try {
// ===== Discord Botログイン =====
await client.login(process.env.BOT_TOKEN);
// ===== 指定サーバー取得 =====
const guild = await client.guilds.fetch(process.env.GUILD_ID);
// ===== サーバー内メンバー全件取得 =====
const members = await guild.members.fetch();
// ===== シートに書き込むデータ作成 =====
// A列:DiscordメンバーID
// B列:globalName(なければusername)
const values = members.map(member => ([
member.user.id,
member.user.globalName ?? member.user.username
]));
await client.destroy();
// ===== Google Sheets API 認証 =====
const auth = new google.auth.GoogleAuth({
scopes: ['https://www.googleapis.com/auth/spreadsheets']
});
const sheets = google.sheets({ version: 'v4', auth });
// ===== 既存データ削除(A2:B)=====
await sheets.spreadsheets.values.clear({
spreadsheetId: process.env.SPREADSHEET_ID,
range: 'Sheet1!A2:B'
});
// ===== データ書き込み(A2から)=====
await sheets.spreadsheets.values.update({
spreadsheetId: process.env.SPREADSHEET_ID,
range: 'Sheet1!A2',
valueInputOption: 'RAW',
requestBody: {
values: values
}
});
res.send("スプレッドシート更新完了");
} catch (error) {
console.error(error);
res.status(500).send("Error");
}
});
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});
package.json
{
"name": "discord-member-fetch",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"discord.js": "^14.0.0",
"express": "^4.18.2",
"googleapis": "^171.4.0"
}
}
⑦ Dockerfile
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
ENV PORT=8080
CMD ["node", "index.js"]
最終的に以下のフォルダ構成になっています。
discord-member-fetch/
│
├─ index.js
├─ package.json
├─ package-lock.json ※npm install時に勝手にできる
└─ Dockerfile
⑧ デプロイ
プロジェクトフォルダで:
gcloud run deploy discord-member-export \
--source . \
--region asia-northeast1 \
--allow-unauthenticated
⑨ 環境変数設定(Cloud Run)
Cloud Run → 新しいリビジョンの編集とデプロイ → 変数とシークレット
追加:
| 名前 | 値 |
|---|---|
| BOT_TOKEN | Discordトークン |
| GUILD_ID | サーバーID |
| SPREADSHEET_ID | シートID |
設定できたら「デプロイ」
⑩ 動作確認
Cloud RunのURLにアクセス
スプレッドシート更新完了
と表示され、
スプレッドシートに
- DiscordメンバーID
- ニックネーム
私が詰まったエラー
TokenInvalid
→ BOT_TOKEN未設定
Unable to parse range
→ シート名が一致していない(例:Sheet1とシート1)
JSON is undefined
→ 環境変数未設定
まとめ
情弱エンジニア1人でやったら何日もかかる機能が1日でできちゃうGCPとChatGPTすごい。






