こんにちは。技術本部Digitization部データ化グループに所属している池田 力と申します。 普段はBill Oneで受領した、紙の請求書をスキャンするシステムの開発に携わっています。
今回の記事ではチームの朝会で使っている朝会担当お知らせbotを開発した話、そしてその後発展した結果21チーム、127人に使われるようになった経緯について紹介いたします。
朝会担当お知らせbotとは
私が所属しているデータ化グループではグループ全体で毎朝10:00から朝会(あさかいと発音します)を約10名程度で行っています。日替わりで司会が入れ替わり、司会になった人は「今日の小話」と「共有事項の確認」を行うというルールです。 この朝会の司会者を決め、トークテーマや全社告知の情報を共有してくれるのが、「朝会担当お知らせbot」です。朝会では、有給休暇などの理由で欠席者もいるので、単純にローテーションで回すだけでなく、その日の参加者の中から公平に割り振られるように司会をアサインする必要があります。さまざまな要件を考えた結果、Google スプレッドシート(以下、スプシ)とGASを使ってSlack botを開発することにしました。ちなみに記事執筆のために過去の投稿を見返したところ、初の実行はこの記事の公開のちょうど1年前の2022年6月28日でした。
スプシ上には、担当者と参加者の情報を日付ごとに保存しておき、過去1週間アサインされた人は除外できるようにしています。カレンダーへ「参加」と回答している人の中からランダムに司会が選ばれます。
絵文字は投稿をにぎやかにするためにつけた遊びの機能で、11個の朝に関連する絵文字の中からランダムに選択されるという実装にしました。
const emojis = [ "🌞", "🌤", "🔥", "☀️", "🔆", "🌻", "🐔", "🍦", "🌅", "🌄", "🍚", ];
これだけでも十分要件を満たしたbotだったのですが、1年をかけて以下のような機能を追加しました。
- Slack上のリアクションから不参加を押せるようにした
- トークテーマ機能を実装した (個人的推し機能)
- 参加者をメンションするようにした
- 汎用化し、他部署でも使えるようにした
- 全社告知の内容を自動でクロールするようにした
- 告知以外にもチームが関連するSlackチャンネルの投稿をクロールできるようにした
順を追って説明と機能の紹介を行います。
自チームでの課題から実装した機能
最初に追加した機能はSlack上のリアクションから不参加を表明できるようにするものです。この機能は 勉強会の出欠確認 Bot を参考に作りました。ロジックは単純で、9:30に通知されるリマインドの投稿に「不参加」のリアクションを押すと参加者から除外されるというものです。 当日有休を申請して休んだり、突発で対応すべきことが入って欠席する際にわざわざGoogle カレンダーを開いて「いいえ」を押す手間がありました。忙しい時の手間を省くことができる地味に便利な機能となっています。
次に実装したのがトークテーマ機能です。「今日の小話」を行うのに10日に1回の頻度でアサインされると、ときには話すことがなくなってしまうこともあります。また、ものすごく盛り上がる日もあれば、「小話は特に思いつかないのでないです。」→「共有事項ありますか?」→「ないみたいなので朝会は以上です。」だけで朝会が終わってしまう日があることも個人的に課題と思っていました。せっかくのチームメンバーが集まる時間を楽しい時間にするため、botによるトークテーマの共有機能を作ることにしました。
スプシにトークテーマを登録しておき、その中からランダムに選ばれるようにしています。朝会のマンネリ化を防ぐためにはたくさんのテーマが必要でした。開発する上でたくさん用意するということが一番のネックだったのですが、ちょうど チーム作りに効果的なアイスブレイクネタ 110 選 - asana という記事を見つけ、機能の実現に至ることができました。「お役立ちリソース」というカテゴリの記事となっていますが、本当にお役立ちすぎました。この場を借りて感謝申し上げます。ありがとうございます。
なお、その後トークテーマを追加し続け、現在では300件ほど登録されています。その中で自分で考えたものを GitHub に載せたので良かったら使ってください。個人的に気に入っているトークテーマは以下の3つです。
- 好きな色教えてください!できればカラーコードで!
- 山手線30駅の中で一番好きな駅を教えて下さい!
- 何もしていないのにパソコンが壊れた経験はありますか?
ユーザーグループのメンションから参加者の個人メンションへの切り替えも行いました。 10人ほどの人数で朝会を行っていると、誰が出席するのか把握することが難しくなります。参加する人をメンションすることで誰が参加するのか分かりやすいようにしました。
転機
上記の機能を実装し、エラーが発生することも減ってある程度満足していました。しかし、2023年になってから他部署の方からうちのチームでも使いたいとお声がけいただいたことがきっかけで汎用化することになりました。
その上で問題になったのはどのように共有するかです。チーム内で使うことを前提に、マルチテナンシーを考慮して実装をしていませんでした。コードを変更せずスプシ自体を複製し、自前で運用することも可能です。しかし、複製した場合新機能を追加するたびに再設定が必要になりますし、ある程度GASの知識がないと動かせないものになってしまいます。せっかく他部署に展開するのであればみんなが使えるものにしたいです。
また、先例として 勉強会の出欠確認 Bot が社内でいろんな人に活用されているのを見て、朝会担当お知らせbotもこうあるべきという思いもありました。
マルチテナンシーを実装することを決意し、最終的に +322 lines, -231 lines
の変更を1日で実装しきって対応することができました。
動作検証して動くことは分かっていたものの、細かいエッジケースの単体テストがないので、ひやひやしながら1週間ほど様子を見ていたのですが、大きなトラブルは発生せずとても安心したことを覚えています。
その後、他のチームでも導入いただき1ヶ月ほど安定して稼働することが確認でき、全社員が参加しているチャンネルで告知を行って現在の21チーム、127人での利用に至ります。
スプシ上では「カレンダーイベントのタイトル」「イベントが登録されているカレンダーのメールアドレス」「通知を送る時間」「通知内容のフラグ」のおおまかに4種類の項目を設定できるようにしました。
また、多くの方に使っていただくことを前提に作っていますので、SlackのチャンネルIDを意識せずとも投稿先を選べるように、設定変更用のフォームでプルダウンでチャンネルを選択できるようにしました。
クロール機能の実装
他部署への展開で嬉しいことがありました。一番はもちろん活用いただいていることですが、フィードバックをいただいて新機能の追加に結び付けられたことです。
全社告知を行うチャンネルがあり、勤怠入力のリマインドや対応必須事項の共有が行われます。一人ひとりが気をつけて見るということも大切ですが、朝会で共有するとより効果的な告知にできそうです。そこで、前日分の投稿内容をまとめて共有する機能を作成しました。
この機能は好評で対応必須事項を見逃しにくくなったという効果や流し読みで勘違いしていたことに気づくという効果もあったのですが、欠点として「全社告知を行うチャンネル」に投稿されなければ共有できないというものがありました。 全社ではなく部署限定で行われるようなものもありますし、全社でメンションするまでもないけど広く告知したい内容もあります。どのように解決できるか検討している中、フィードバックで具体的に3つのチャンネルを集約して朝会で共有したいという要望をいただき、実装することにしました。
チームごとに注視しているチャンネルが異なるため、チームとチャンネルを多対多で紐付けるようなデータ構造にする必要があります。設定を複数シート用意するなど色々考えた結果、スプシ上で完結させ、かつ実装工数も小さくできる方法として、最終的にJSONで購読内容を管理することにしました。
{ "購読したいチャンネル1": 1680000000000, "購読したいチャンネル2": 1680000000000 }
キーにチャンネルを、値に最後に共有した投稿のタイムスタンプを持つ構造になっています。毎朝共有するごとにタイムスタンプを更新することで差分を検知できるようになっています。
課題と今後の展望
良いところもあればイケていない部分もあります。
現状、一番大きな課題として、スプシ + GASの仕組みでは運用が難しい規模になってきています。チーム内のスクリプトという前提で開発を進めたため単体テストがなく、ポチポチ動作確認して挙動を確かめるしかないこと。導入チームが20チームを超えたことで定時実行するために設定しているトリガーの数が制限にひっかかってしまっていること。そして、自チームだけで運用していたときには見たこともなかったエラーが月に2,3回は発生してしまうことがあります。
例えば、スクリプトのステータスには「成功」と「失敗」以外に「不明」というものがあるのですが、説明を見ると以下のように記述されていました。
実行のステータスが不明というのは、Apps Script が実行結果を特定できなかったことを意味します。実行は、成功した可能性も失敗した可能性もあります。
これではどのように対処すればよいのかわかりません。
その他にも ストレージからの読み取り中にサーバーエラーが発生しました。エラーコード: INTERNAL。
というエラーが発生したり、スプシの編集権限を付与しているはずのアカウントで権限が不足しているという内容のエラーが発生することもありました。同じ設定で動くときと動かないときがあり、不安定なため対処は難しそうです。
暫定的な対応として次のような工夫をしています。 20チームを超えてしまった問題についてはシートを2つ作成するシャーディングのような手法で対処しました。不安定なエラーは失敗したときに1分後にリトライできるような機構を作っています。 いずれも本質的な解決に至っていないため、今後はCloud Functionsなど、GASよりも信頼性が高いシステムへ移行するのが良さそうです。
最後に
この1年で実装した内容を振り返ると改めて色んな機能を実装したなと自分でも驚きました。 ただ、まだまだ全社員の10%にしか満たない人にしか活用されていないため、より多くの人により安定的に使っていただけるように今後も開発を進めます。
この記事が読んでくださった方の参考になったり、社内ツールを開発する方の応援になれば幸いです。ぜひシェアやコメントをお願い致します。