運用コスト0円。社内コミュニケーションを活性化するSlackボットを作ってみた
なぜ作ったのか
リモートワークが当たり前になった今、メンバー同士の雑談が生まれにくくなったと感じています。
出社していた頃は、ランチや移動時間、ちょっとした立ち話の中で自然と相手の人柄を知ることができました。しかし、Slack中心のコミュニケーションになると、どうしても業務の会話が中心になります。
「この人って休日は何をしているんだろう?」
「どんなことに興味があるんだろう?」
そんなことを知る機会は、以前より少なくなりました。
そこで今回、社内向けのSlackボットを作りました。
世の中には「Colla」のようなサービスもありますが、「質問を送って回答を集めるだけなら自分たちでも作れるのでは?」と思い、一場が自作することにしました。
仕組みはシンプルです。
毎日ランダムに選ばれたメンバーへ質問をDMで送り、その回答をチャンネルへ投稿する。それだけです。
作ったもの
機能はかなりシンプルです。
① ランダムに質問を送る
毎日11:30に最大3名のメンバーへDMを送信します。
質問例
- 最近ハマっていることは?
- 子供の頃の夢は?
- 人生で一番緊張した瞬間は?
- 今行ってみたい場所は?
② DMの返信を取得する
ユーザーがDMへ返信すると、その内容をDBへ保存します。
③ 回答を社内へ共有する
13:00と15:30に回答をチャンネルへ投稿します。
たったこれだけです。
技術スタック
今回の構成はこちらです。
役割技術
Slack Bot
Slack Bolt (TypeScript)
Hosting
Vercel
Database
Supabase
Scheduler
cron-job.org
すべて無料枠で運用しています。
完全無料で動かす構成
最初はVercel Cronを使う予定でした。
ただしHobbyプランでは利用できる回数に制限があります。
今回のボットでは
- DM送信(11:00)
- 回答投稿(13:00)
- 回答投稿(15:30)
のように複数回実行したかったため別の方法を検討しました。
そこで採用したのが cron-job.org です。
cron-job.org
↓
Vercel Serverless Function
↓
Slack API
↓
Supabasecron-job.orgから指定時刻にHTTPリクエストを送るだけなので非常にシンプルです。
運用コストは現在0円です。
ハマったポイント①
Vercelのサーバーレス関数はレスポンス後に処理が継続するとは限らない
最初はレスポンスを先に返し、重い処理をバックグラウンドで実行する実装にしていました。
res.json({ ok: true });
sendDailyDMs();しかし、DMが送信されないことがありました。
ログを調べると、レスポンス返却後にサーバーレス関数自体が終了していました。
Node.jsの感覚だと「レスポンスを返した後も処理は続く」と考えがちですが、サーバーレス環境では必ずしもそうではありません。
最終的には処理完了を待ってからレスポンスを返す形に変更しました
await sendDailyDMs();
res.json({ ok: true });とすることで解決しました。
小さな修正ですが、実行環境の違いを理解する良い学びになりました。
ハマったポイント②
processBeforeResponseの落とし穴
Slack Boltには processBeforeResponse という設定があります。
サーバーレス環境では true が推奨されています。
ただしSlackは3秒以内の応答を求めます。
処理が重いと operation_timeout が発生します。
今回は
- DBアクセス回数削減
- Slack API呼び出し回数削減
- 一括取得
を行い、3秒以内に収まるよう改善しました。
実際に運用してみて
思った以上に反応がありました。
「元バンドマンでした」
「実はスカイダイビングが趣味です」
「休日は燻製ばかりしています」
など、業務では絶対に出てこない話題が自然と共有されます。
技術的には難しいことはしていません。
でも、
「雑談が減った」
という課題に対して、
「仕組みで解決できないか?」
と考え、実際に形にできたのは良い経験でした。