はじめに
でびるです。
今日は Slack bot を作成して、指定した時刻に任意のテキストを投稿する方法を紹介します。
この方法のポイント
- あらかじめ用意した好きなテキストを、ランダム or 順番に投稿できる
- 今回は順番に投稿してみます
- 1週目は「今週はAさん」、2週目は「今週はBさん」、3週目は「今週はCさん」、4周目は「今週はAさん」、のように順繰りに指定したテキストを投稿できます
- 「毎週金曜日の 10:00」に投稿できる
- GAS はデフォルトだと「10時〜11時の間に投稿する」のように1時間単位でしか時刻指定できず、分指定ができません
- これをハックして分指定までできるようにします(秒指定はできません。指定した時刻より20〜30秒ほど実行時刻は遅れるようです)
第1ステップ:Slack bot を Webhook で作成する
テキストを投稿するという単純な機能であっても Slack だけでは完結しません。Slack 側で Webhook を公開して、外部からその API を呼び出すという構成で bot を作成します。
- サイドバー「その他」から「自動化」を選びます
- そして「ワークフロー」画面から「ワークフローを作成する」ボタンを押します
- 右側サイドバーの「Webhook から」を選びます
- 「変数を設定する」ボタンを押します
- キーに「text」と入力して「終了」ボタンを押します
- 「続行する」ボタンを押します
- サイドバーから「メッセージ」を選んで「チャンネルへメッセージを送信する」を選びます
- 「変数を挿入する」から「text」を選びます。そして投稿したいチャンネルを選びます。また必要があればメッセージ欄を編集します。「text」の部分に外部から入力した任意のテキストが挿入されます
- ワークフロー名とアイコンを設定します。画面左上の「無題のワークフロー」の部分をクリックすると編集できます
- 「Webhook を使って開始する」を押して「ウェブリクエストの URL」の「リンクをコピーする」ボタンを押します
この「ウェブリクエストの URL」を控えておきます。
https://hooks.slack.com/triggers/ABCDEFGHI/1234567890123/1234567890abcdef1234567890abcdef
のような形式の URL なはずです。
第2ステップ:スプレッドシートを用意する
Google アカウントにログインした状態で、https://drive.google.com/drive/my-drive にアクセスします。
好きな場所にスプレッドシートファイルを作成します。
スプレッドシートのタイトルを入力して、画面下部のシートを2つ用意しておきます。シート1
をリネームして content
に、新たなシートを作成して log
という名前にしておきます。
content
シートには A 列に、順に表示したいテキストを入力しておきます。log
シートは空のままで大丈夫です。
メニューバーの「拡張機能」から「Apps Script」を選びます。
プロジェクト名(上部ヘッダ)と「コード.gs」の部分を変更しておきます。
そして、コード本文に以下のソースコードの内容を貼り付けます。
-
webhookUrl
は、先程控えた「ウェブリクエストの URL」に書き換えてください -
enablePost
の値をtrue
に変更すると、実際に Slack bot への投稿処理を実施するようになります - あとは、初回のトリガーをセットするだけです。Apps Script の画面から、
setNextTrigger
関数を一度実行してください - 投稿処理を試したければ、Apps Script の画面から
doSlackBot
関数を実行してください- 投稿が順繰りに行われるはずです。投稿のローテーションをリセットしたければ
log
シートの A1 セルの値を削除してください
- 投稿が順繰りに行われるはずです。投稿のローテーションをリセットしたければ
const Util = {
Weekdays: Object.freeze({ SUNDAY: 0, MONDAY: 1, TUESDAY: 2, WEDNESDAY: 3, THURSDAY: 4, FRIDAY: 5, SATURDAY: 6, length: 7 }),
getDefault(arg, def) { return arg == null || arg === '' ? def : arg; },
modInt(baseValue, modValue) { return ((baseValue % modValue) + modValue) % modValue; },
getDateStr(date) { if (date == null) date = new Date(); return Utilities.formatDate(date, 'JST', 'yyyy-MM-dd HH:mm:ss') },
output(range, value) { return range.setNumberFormat('@').setValue(value); },
};
function doSlackBot() {
setNextTrigger();
const webhookUrl = 'https://hooks.slack.com/triggers/***';
const enablePost = false;
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const contentSheet = spreadsheet.getSheetByName('content');
const contentLength = Math.max(contentSheet.getLastRow(), 1);
const logSheet = spreadsheet.getSheetByName('log');
const lastIndex = Util.getDefault(logSheet.getRange('A1').getValue() | 0, 0) - 1;
const nextIndex = Util.modInt(lastIndex + 1, contentLength);
const nextRow = nextIndex + 1;
Util.output(logSheet.getRange('A1'), nextRow);
const text = contentSheet.getRange(`A${nextRow}`).getValue();
const dateStr = Util.getDateStr();
const logNewRow = logSheet.getLastRow() + 1;
const getLogCell = (col) => logSheet.getRange(`${col}${logNewRow}`);
Util.output(getLogCell('A'), dateStr);
Util.output(getLogCell('B'), text);
const options = {
method : 'post',
contentType : 'application/json',
payload : JSON.stringify({ text }),
};
if (enablePost) UrlFetchApp.fetch(webhookUrl, options);
}
function setNextTrigger() {
const weekday = Util.Weekdays.FRIDAY;
const hour = 10;
const minute = 0;
const today = new Date();
const nextDay = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1, 0, 0, 0);
const weekdayDiff = (weekday + Util.Weekdays.length - nextDay.getDay()) % Util.Weekdays.length;
const nextTheWeekday = new Date(nextDay.getFullYear(), nextDay.getMonth(), nextDay.getDate() + weekdayDiff, hour, minute, 0);
removePrevTrigger();
const trigger = ScriptApp.newTrigger('doSlackBot').timeBased().at(nextTheWeekday).create();
}
function removePrevTrigger() {
const allTriggers = ScriptApp.getProjectTriggers();
allTriggers.forEach(trigger => {
if (trigger.getHandlerFunction() === 'doSlackBot') ScriptApp.deleteTrigger(trigger);
});
}
おわりに
GAS が指定した曜日の指定した時刻にトリガーが実行できれば setNextTrigger
や removePrevTrigger
のような実装は不要になるのですが、なぜか現状では分指定ができず1時間単位でしか時刻を指定できないのですよね。
この実装では、繰り返し予定によるトリガーではなく、次の一回の実行を日時指定するトリガーを、トリガー実行の度に付けたり外したりしています。
上記のコードは、毎週金曜日の10:00に投稿するサンプルですが、これを変更したければ setNextTrigger
の冒頭の部分を書き換えてください。
もし毎週1回ではなく毎日1回にしたい場合や、テキストを順繰りでなくランダム投稿にしたいような場合は、それぞれの関数を中身をそれなりに修正する必要があります。
修正方法が分からなければコメントしてください。
以上です。Slack bot で投稿を自動化する方法でした。