🤖

定例MTGの司会議事録を自動で決めてslack通知する仕組み

2024/08/13に公開

こんにちは!ゲンシュンです。

今まで様々なチームで、司会や議事録担当をbotに決めてもらってslack通知したい〜リマインドとかしてくれ〜などの要望からいろんなbot作ってきたので、今回は以下2つのbotを紹介します。

  • ランダムに司会と議事録を指名してslackに通知するbot
  • 一人ずつ順番に指名してslackに通知するbot

実装する上で大事な考え

実装内容よりも大事なことなので最初に書きますが、何でもかんでも要件を実現する必要はないと思います。「まだ指名されていない人を優先して選出させたい」「2連続同じ人が当たらないようにしたい」などの要望って結構寄せられますし、実現しようと思えば選出済みメンバーをスプシ等に書き出せたりすれば出来ると思うんですよね。

ただこの手の自前実装する通知って、ちょっと楽したい、リマインダー的に使いたいみたいな立ち位置なので、一回通知の仕組みを作った後はメンバー変更対応ぐらいだけの超最低限のメンテだけに留めるでいいと思ってます。アドバンスドな要求を対応していくとリターンに対するコストが上回っちゃって、皆が楽するために誰かが苦労するのは、本末転倒になるイメージです。

今回紹介する「1人ずつ順番指名する通知」も本来は別に要らないと思っているんですが、役員部長レイヤー等忙しい方への担当リマインダーな側面も含まれているので、「毎週順番に通知する」という最低限の要件だけを満たすもの作ってます。

仕組み

GASで実装 → SlackAppに連携 → slackチャンネルに投下です。

Slackの事前設定

Appを作成し、Permissionの設定、Tokenの取得、Appのインストールなどをやります。SlackApp作成に関しては世の中にたくさん記事あるのでここでは割愛!

GASの事前設定

Slack連携周りいい感じにやってくれるライブラリがあります。スクリプトID( 1on93YOYfSmV92R5q59NpKmsyWIQD8qnoLYk-gkQBI92C58SPyA2x1-bq )をコピってライブラリ追加するだけ。

通知タイミングはトリガーで設定します。今回は毎週月曜12時台に発射するような設定でいきます。

以後、GASで実装するコード紹介パートになります。

①ランダムに司会と議事録を指名する

社員メンバーの配列から2要素をランダムに取得してslack通知するだけです

//SlackAppで登録したBotUserOAuthTokenを定義
const SLACK_TOKEN = "xxxxxxxx";
//SlackBotがメッセージを投稿するチャンネルを定義
const SLACK_CHANNEL_NAME = "#yyyyyyy";
//社員の定義
const MEMBER_LIST = [
 {name: "A", userId: "AAAAAAA"},
 {name: "B", userId: "BBBBBBB"},
 {name: "C", userId: "CCCCCCC"},
 {name: "D", userId: "DDDDDDD"},
 {name: "E", userId: "EEEEEEE"},
 {name: "F", userId: "FFFFFFF"},
];

function postSlackMessage() {
 //ライブラリから導入したSlackAppを定義し、トークンを設定する
 const slackApp = SlackApp.create(SLACK_TOKEN);

 //配列からランダムに要素取得する関数
 const getRandomMember = (excludeIds = []) => {
   const filterMembers = MEMBER_LIST.filter(m => !excludeIds.includes(m.userId));
   const randomIndex = Math.floor(Math.random() * filterMembers.length);
   return filterMembers[randomIndex];
 }

 // 「司会」と「議事録」を担当するメンバーを選ぶ
 const shikai = getRandomMember();
 const gijiroku = getRandomMember([shikai.userId]);

 //投稿文
 const message = `今週の司会は <@${shikai.userId}> (${shikai.name}さん)
   議事録は <@${gijiroku.userId}> (${gijiroku.name}さん)です!
 ヨロシク〜!`;

 //SlackAppオブジェクトのpostMessageメソッドで投稿
 slackApp.postMessage(SLACK_CHANNEL_NAME, message);
}

こんな感じで投下してくれます。

②毎週一人ずつ順番に指名する

考え方としては週番号順に配列から要素を取り出しているだけです。◯◯から運用開始して一発目を△△さんを指名するようにしたい要望から ADJUSTMENT_INDEX という週番号に対する帳尻合わせみたいな変数用意してます。
この手の通知って年末年始は稼働止めてるので、年末にbot止めて年始1発目のbot稼働日に合わせて ADJUSTMENT_INDEX を変える年一回のメンテだけで済みます。

//SlackAppで登録したBotUserOAuthTokenを定義
const SLACK_TOKEN = "xxxxxxxx";
//SlackBotがメッセージを投稿するチャンネルを定義
const SLACK_CHANNEL_NAME = "#yyyyyyy";
//社員の定義
const MEMBER_LIST = [
  {name: "A", userId: "AAAAAAA"},
  {name: "B", userId: "BBBBBBB"},
  {name: "C", userId: "CCCCCCC"},
  {name: "D", userId: "DDDDDDD"},
  {name: "E", userId: "EEEEEEE"},
  {name: "F", userId: "FFFFFFF"},
];

// 2024-01-29が1発目の場合この日の週番号は5なので、TARGET_INDEXが0になるよう帳尻合わせ
// 普段は対応しないがどうしても一週間スキップする場合はこの数値を増やせばOK
const ADJUSTMENT_INDEX = 5;

function postSlackMessage() {
  const getTargetIndex = () => {
    // 週番号計算
    const currentdate = new Date();
    const oneJan = new Date(currentdate.getFullYear(), 0, 1);
    const numberOfDays = Math.floor((currentdate - oneJan) / (24 * 60 * 60 * 1000));
    const weekNumber = Math.ceil((currentdate.getDay() + 1 + numberOfDays) / 7);

    // 実行日の週番号から帳尻合わせ数値を引く
    return weekNumber - ADJUSTMENT_INDEX;
  };

  const TARGET_INDEX = getTargetIndex();

  // 担当者
  const presenter = MEMBER_LIST[TARGET_INDEX % MEMBER_LIST.length];
  // 次回担当者
  const nextPresenter = MEMBER_LIST[(TARGET_INDEX + 1) % MEMBER_LIST.length];
  // 次々回担当者
  const afterNextPresenter = MEMBER_LIST[(TARGET_INDEX + 2) % MEMBER_LIST.length];

  //ライブラリから導入したSlackAppを定義し、トークンを設定する
  const slackApp = SlackApp.create(SLACK_TOKEN);

  //投稿文
  const message = `今週の発表担当は <@${presenter.userId}> です!\n
  今週対応できない事情がある場合は、次の担当の方にご自身で直接ご依頼ください\n
  ※ 次回の発表担当は<@${nextPresenter.userId}> 次々回は<@${afterNextPresenter.userId}> です

  //SlackAppオブジェクトのpostMessageメソッドで投稿
  slackApp.postMessage(SLACK_CHANNEL_NAME, message);
}

いい感じにメンション飛ばしてくれます。今週出来ないから◯◯さんと交代したいは、ご本人に任せます。botはやらないという意思表明。

SlackApp×GAS便利

実際やりたいこと何でも実現できる故に、必要以上に要件を満たそうとしてしまうことだけ気をつけて、工数最小成果は最大な気持ちでやっていきましょ〜!

Discussion