どういう記事?
Discord鯖内で、ワンドロ(1時間とか時間制限ありで、決められたお題で絵を描くやつ)がしたいという要望があり、良い感じに自動化出来ないかなぁという所で、Google Form → Spreadsheet → Apps Script → Webhook(Discord)という構成でbot(厳密にはbotではない)を作ったという記事。
この記事ではwebhookの設定やapps script自体の設定は書きませんので、その辺は各自調べて下さい。
この構成の利点は?
- サーバーが要らないし、運用費もかからない
- Apps scriptのトリガーを使えば定期的な投稿もできる
- お題はコミュニティメンバーに投稿してもらう事で、お題を用意するタスクが分担できる
実際の処理の流れ
- ユーザーがGoogle Formに回答
- 回答がSpreadsheetに書き込まれる
- その回答を上から順に、Spreadsheetに紐づいたApps scriptがHTTPでDiscordのwebhookに投げる
- 一度送信したお題には、送信済みフラグを立てる
実装
コードはLLMが生成したのに必要に応じて手を加えたものです。
columnなどは各自のspreadsheetに合わせれば動くと思います。
コードとしては汚いですが、一応参考程度に置いておきます。
ここで想定しているspreadsheetのcolumnは以下です。
function sendToDiscordWebhook() {
const WEBHOOK_URL = '{your discord webhook url}';
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const lastRow = sheet.getLastRow();
if (lastRow < 2) {
console.log('データがありません。');
return;
}
const range = sheet.getRange(2, 1, lastRow - 1, 3);
const values = range.getValues();
let targetRow = null;
let targetValue = null;
// 残数を数える(ブールtrue もしくは文字列"TRUE"を完了扱い)
const isDone = v => v === true || (typeof v === 'string' && v.toUpperCase() === 'TRUE');
const remainingCount = values.reduce((acc, row) => acc + (isDone(row[2]) ? 0 : 1), 0);
for (let i = 0; i < values.length; i++) {
const bVal = values[i][1];
const cVal = values[i][2];
if (!isDone(cVal)) {
targetValue = bVal;
targetRow = i + 2;
break;
}
}
if (targetValue === null) {
console.log('条件に一致する行が見つかりませんでした。');
return;
}
const embed = {
title: "ワンドロ今回のお題",
description: "10秒/1分/10分/1時間/100分の中で時間制限を選び、絵をかいてみましょう!",
color: 0x3498db,
fields: [
{
name: "📝 お題",
value: `** 『${targetValue}』 **` || "(空)",
inline: true
},
],
footer: {
text: `お題残り:${remainingCount-1}`
},
timestamp: new Date().toISOString()
};
const payload = {
username: "ワンドロお題Bot",
embeds: [embed]
};
const options = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
payload: JSON.stringify(payload)
};
try {
const response = UrlFetchApp.fetch(WEBHOOK_URL, options);
if (response.getResponseCode() === 204) {
sheet.getRange(targetRow, 3).setValue(true);
} else {
console.error('送信に失敗しました:', response.getResponseCode());
}
} catch (error) {
console.error('エラーが発生しました:', error);
}
}
その他
Discordのwebhookで、forum内のチャンネルに投稿したい場合は、webhook URLの発行時にそのフォーラムを指定し、URLにthread_idをパラメーターとして付けてやる必要があるようです(これで無事いけてます)。
参考:
あとがき
我ながら丁度いい解法じゃないかと思います。