🕑
【GAS】Discord Botをお手軽にスケジューリング
準備
Discordチャンネルのウェブフックを発行
Botのメッセージを飛ばしたいチャンネルに外部からアクセスためのウェブフックURLを発行する
- チャンネル設定
- ウェブフックの作成 (連携サービス)
- ウェブフックURLをコピー
画像での説明
チャンネル設定
ウェブフックの作成(連携サービス)
ウェブフックURLをコピー
GASの新規プロジェクトを作成
下記のリンクカードをクリックして、空のプロジェクトを作る
権限の承認
UrlFetchApp
とScriptApp
を使うために下記のコードをコピペしてmyFunction
を実行する
function myFunction() {
UrlFetchApp.fetch("https://example.com");
ScriptApp.getProjectTriggers();
}
右下の「許可」を押す
メッセージの送信
定型文を送る(Hello World)
WEBHOOK_URL
に発行されたウェブフックURLをコピペしてHelloWorld
を実行
function HelloWorld() {
const message = {
"username": "お手軽Bot",
"content": "Hello, World!",
"tts": false,
};
PostMessageToDiscord(message);
}
function PostMessageToDiscord(message) {
const WEBHOOK_URL = "<URL>"
const options =
{
"method": "POST",
"headers": { "Content-type": "application/json" },
"payload": JSON.stringify(message)
};
UrlFetchApp.fetch(WEBHOOK_URL, options);
}
ランダムなメッセージを送る
何度かRandomMessage
を実行してランダムなメッセージが送られていることを確認
function RandomMessage() {
const contents = ["Hello, World!", "はろーわーるど!", "ハローワールド!"];
const message = {
"username": "お手軽Bot",
"content": contents[GetRandomInt(0, contents.length)],
"tts": false,
};
PostMessageToDiscord(message);
}
function GetRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min) + min);
}
埋め込みコンテンツを送る
ドキュメントを参照しながら好きなように改造
function EmbedMessage() {
const message = {
"username": "お手軽Bot",
"content": "埋め込みもできるよ",
"tts": false,
"embeds": [
{
"title": "【GAS】Discord Botのお手軽な作り方【Zenn】",
"description": "#埋め込みコンテンツを送る",
"url": "https://zenn.dev/rrisland/articles/9d28cfddb1ffb7",
"color": 0x3ea8ff,
}
]
}
PostMessageToDiscord(message);
}
スケジューリング
1時間ごとに1回、n分に実行予約する
GASのトリガーを「1時間ごと」にすると1時間のうち00分~59分のランダムなタイミングで実行される
トリガーのたびに1時間後のn分を指定してNewTrigger
することで時間のブレが起こらなくなる
function Scheduler() {
const date = AddHours(new Date(), 1);
DeleteTrigger("RandomMessage");
date.setMinutes(0);
NewTrigger("RandomMessage", date);
// DeleteTriggerで他関数の実行予約を消さないようにSchedulerはトリガーの中で一番最後に実行する
DeleteTrigger("Scheduler");
date.setMinutes(55);
NewTrigger("Scheduler", date);
}
function AddHours(date, hours, minutes = 0) {
date.setTime(date.getTime() + (hours * 60 * 60 * 1000) + (minutes * 60 * 1000));
return date;
}
function DeleteTrigger(funcName) {
const triggers = ScriptApp.getProjectTriggers();
for (const trigger of triggers) {
if (trigger.getHandlerFunction() !== funcName) continue;
ScriptApp.deleteTrigger(trigger);
}
}
function NewTrigger(funcName, date) {
ScriptApp.newTrigger(funcName).timeBased().at(date).create();
}
トリガーが「無効」になる問題
V8ランタイムのバグでNewTrigger
しても正常に動作しないことがある
回避策は2つ
- デプロイしたバージョンの
Scheduler
をトリガーへ登録する - Headの
Scheduler
を手動実行せずにトリガーへ登録する
参考
Discussion