GAS × Slack App で当番をローテーションする通知botを作る
こんにちは。株式会社 Interfamilia の Waka です。
2025年初の記事投稿になります。
今回の記事では、弊社の業務効率化のために組んだSlack bot について紹介したいと思います!
目次
弊社では、毎週欠かさず社内の掃除を行っています🧹
オフィスを綺麗にすることで、気持ちよく仕事に臨めています✨
ですが、問題もありました。
掃除当番を毎週ローテーションで回しているのですが…
参加メンバーが増えるにつれ、今週の当番が誰なのか、パッと分からなくなってきたのです😭
毎週、Slackbotで↑のような通知を出していたのですが、これでは誰が当番なのか分かりません。
過去スレを辿り、先週は誰が当番だったか思い出し、ローテーションして今週の当番を記録。
翌週、翌々週も同じことの繰り返し…そんな運用を続けていました。
“自動でローテ回して「今週の掃除当番はこの人です!」とメンションしてくれる。
そんな便利なbotがあったらいいのになぁ…”
そんな風に考えてました。
調べてみたところ…理想的なSlackbot実装案が見えてきたので、作ってみました。
当番通知Slack botの実装手順は、以下の通りです
- Slack App作成 → GAS連携
- GASスクリプト実装
- GASを定期実行するトリガー追加
- 運用開始
bot用のSlack Appを作成。GAS (Google Apps Script) と連携させます。
この設定手順については既に多くの記事で紹介されていて、説明する事が無いので割愛します。
自分は以下の記事を参考にしました。
【参考リンク】
GASスクリプトコードを javascriptで記述していきます。
以下のようなコードを書きました。
// main
function myFunction() {
// PropertiesService
const scriptProperties = PropertiesService.getScriptProperties();
const token = scriptProperties.getProperty('SLACK_TOKEN');
const slackApp = SlackApp.create(token); // トークンを渡してSlack App作成
const channelId = '#channel';
// Slackメンション用メンバーリスト
const user1 = scriptProperties.getProperty('USER1');
const user2 = scriptProperties.getProperty('USER2');
const user3 = scriptProperties.getProperty('USER3');
const members = [user1, user2, user3];
// COUNT定数呼び出し
let count = parseInt(scriptProperties.getProperty('COUNT'));
// 担当ローテーション実行
const todaysMember = rotateArray(members, count % members.length)
// メッセージ組み立て
const message = [
'【タスク当番のお知らせ】',
'',
'今週の当番はこちらです:point_down:',
'',
'・タスク1: ' + todaysMember[0],
'・タスク2: ' + todaysMember[1],
'・タスク3: ' + todaysMember[2],
].join('\n');
// Slackメッセージ送信
slackApp.postMessage(channelId, message);
// COUNT定数のインクリメント・保存
count += 1;
if (count === 30) {
// 30くらいを目途に定数を初期化
count = 0;
}
scriptProperties.setProperty('COUNT', String(count));
}
// ローテーション関数
const rotateArray = function(collection, k) {
for (let i = 0; i < k; i++) {
collection.unshift(collection.pop());
}
return collection;
}
以下、コード実装にあたってのポイント紹介です。
GASでSlackメッセージを送信する時、以下の手順を踏みます。
const slackApp = SlackApp.create(token);
Slack Appを用意します。ここで予め用意したSlackトークンを使用します。xoxb-
から始まる「Bot User OAuth Token」です。
// メッセージ組み立て
const message = [
'【タスク当番のお知らせ】',
'',
'今週の当番はこちらです:point_down:',
'',
'・タスク1: ' + todaysMember[0],
'・タスク2: ' + todaysMember[1],
'・タスク3: ' + todaysMember[2],
].join('\n');
メッセージ本文。普通の文字列でOKです。
自分は可読性重視で、string配列 × join('\n')
で改行を挟むようにしてます。
⚠️ Slackユーザーにメンションを飛ばしたい場合は、注意が必要です。
ただ単に @ユーザー名
と書くだけでは、普通の文字列とみなされてしまいます。
ユーザーの「メンバーID」を取得して <@XXXXXXXXXXX>
という形式で指定しましょう。
以下の記事が詳しいです。
slackApp.postMessage(channelId, message);
最後に postMessage()
でメッセージ送信。
チャンネルID、メッセージ本文を引数で指定します。
// ローテーション関数
const rotateArray = function(collection, k) {
for (let i = 0; i < k; i++) {
collection.unshift(collection.pop());
}
return collection;
}
当番を毎週ローテーションする関数。
今回のbot実装で一番悩んだポイントです。
試行錯誤の結果、以下の Array関数の組み合わせで作りました。
- Array.prototype.unshift()
- 指定した要素を配列の先頭に置く
- Array.prototype.pop()
- 配列から一番最後の要素を取り出す
メンバー全員が入った配列を用意。[COUNT定数] % [メンバー人数]
の値分、pop() → unshift() を繰り返す。
処理完了後、COUNT定数
を+1 インクリメントして、次回に持ち越す。
これにより、最小限の労力でローテーションを回しています。
COUNT定数
は、放置すると無限に数値がインクリメントされてしまうので、
30くらいを目途に一旦0にリセットする実装も組んでます。
GASには「PropertiesService」という機能があります。
スクリプトの外部に、Key-Value形式で定数データを永続的に保存できます。
プロパティ サービスを使用すると、1 つのスクリプト、1 つのスクリプトのユーザー、またはアドオンが使用されている 1 つのドキュメントにスコープされた Key-Value ペア形式のシンプルなデータを保存できます。通常、デベロッパーの設定やユーザー設定を保存するために使用されます。プロパティはスクリプト間で共有されません。
今回、以下のようなデータ保存にPropertiesServiceを使っています。
- GASスクリプトに直接埋め込みたくない定数データ
- Slackトークン、ユーザー名 etc…
- 値を保存しておき、次の実行時に使い回したい定数データ
- ローテーション関数で使う
COUNT定数
をインクリメントした後、保存しています
- ローテーション関数で使う
Google Apps Scriptメインページ > プロジェクトの設定 > スクリプト プロパティ
に移動。
「スクリプト プロパティを追加」から、データ登録が可能です。
「プロパティ」がKey、「値」がValueです。いずれもstring型で保存されます。
※ 上記画像の COUNT: 16
も number型ではなく string型です。
// PropertiesServiceからデータ取得
const scriptProperties = PropertiesService.getScriptProperties();
const token = scriptProperties.getProperty('SLACK_TOKEN');
// PropertiesServiceのデータ更新
const number = 1;
scriptProperties.setProperty('COUNT', String(number)); // string変換して保存
保存したデータを操作する時は、↑のように Propertiesオブジェクトの各メソッドを使います。
以下の公式ドキュメントが詳しいです。
【参考リンク】 Class Properties | Apps Script | Google for Developers
GASスクリプトができたら、それを定期実行するためのトリガーを追加します。
Google Apps Scriptメインページ > トリガー
と移動。「トリガーを追加」で登録できます。
[例] 毎週木曜9:00-10:00頃に通知するbotを作りたい場合、以下のように設定します。
- 実行する関数:GASスクリプトのmain functionを指定
- イベントのソース:時間手動型
- 時間ベースのトリガーのタイプ:週ベースのタイマー
- 曜日:毎週木曜日
- 時刻:午前9時~10時
設定が終わったら運用開始です。
トリガーが上手く動けば、指定時間帯にSlackメッセージが送信されます💪
自分のSlack bot通知はうまく機能しました🎉
社内でも評判が良かったです(嬉しい)
今回実装したSlack botが抱える課題です。
以下のような例外的ケースには、現状非対応です😭
スクリプトを一部書き換えたり、定期実行を一旦停めるなど、手作業での変更が必須となっています。
- メンバー増減があった場合
- 長期休暇などで一定期間botを止めたい場合
これらの自動化も技術的には可能なハズ。必要性が増したら対応を検討したいです。
GAS標準の時間主導型トリガーは、スクリプトの実行時刻を正確に指定できません。
「毎週火曜日 12時~13時」といった具合に、かなりブレがあります。
自分が作ったbotは時刻「9時~10時」で設定しましたが、
9:40に動いてたり、9:50に動いたりと、非常に不安定です。
なお、正確な時間指定は、Googleカレンダー連携で実現できそうです。
(イベントの何分前に通知する、といった設定で可能)
現状あまり困ってないので優先度は低いですが、いずれ対応したいです。
以上、GAS × Slack API連携でタスク当番通知botを組んだ話でした。
「今週は誰が当番だったっけ…?」
「先週こうだったから、今週の当番は〇〇さんだ!あれ?違ったっけ?」
といった会話が不要になり、業務最適化が図れたのではないかと思います☺️
課題も見つかったので、それらを解消してより良いSlack botを組み、更なる効率化を目指したいですね。
それではまた次回!
- Google Apps Script 入門
- Slackに定期投稿してくれるBotをGASとSlack APIで作成してみた - Da Vinci Studio Blog
- 【Google App Script】GASを利用してslackに投稿するbotを作る | エクスチュア株式会社ブログ
- GASでトークン等を保存しておけるプロパティサービスについてまとめてみた #GoogleAppsScript - Qiita
- 【Google Apps Script】プロパティサービスを使ってGASで秘密情報を管理する|CREFIL
応募フォームには、外部サービスengageを利用しています。
ご応募に際して、何かわからないことなどございましたら こちら
からお気軽にお問い合わせください。