0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Slack bot で指定した曜日・時刻に任意のテキストを投稿する方法

Posted at

はじめに

でびるです。

今日は 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 を作成します。

  1. サイドバー「その他」から「自動化」を選びます
  2. そして「ワークフロー」画面から「ワークフローを作成する」ボタンを押します
  3. 右側サイドバーの「Webhook から」を選びます
  4. 「変数を設定する」ボタンを押します
  5. キーに「text」と入力して「終了」ボタンを押します
  6. 「続行する」ボタンを押します
  7. サイドバーから「メッセージ」を選んで「チャンネルへメッセージを送信する」を選びます
  8. 「変数を挿入する」から「text」を選びます。そして投稿したいチャンネルを選びます。また必要があればメッセージ欄を編集します。「text」の部分に外部から入力した任意のテキストが挿入されます
  9. ワークフロー名とアイコンを設定します。画面左上の「無題のワークフロー」の部分をクリックすると編集できます
  10. 「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 が指定した曜日の指定した時刻にトリガーが実行できれば setNextTriggerremovePrevTrigger のような実装は不要になるのですが、なぜか現状では分指定ができず1時間単位でしか時刻を指定できないのですよね。

この実装では、繰り返し予定によるトリガーではなく、次の一回の実行を日時指定するトリガーを、トリガー実行の度に付けたり外したりしています。

上記のコードは、毎週金曜日の10:00に投稿するサンプルですが、これを変更したければ setNextTrigger の冒頭の部分を書き換えてください。

もし毎週1回ではなく毎日1回にしたい場合や、テキストを順繰りでなくランダム投稿にしたいような場合は、それぞれの関数を中身をそれなりに修正する必要があります。

修正方法が分からなければコメントしてください。

以上です。Slack bot で投稿を自動化する方法でした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?