KEIS BLOGは株式会社ケイズ・ソフトウェアが運営しています。

KEIS BLOG

ChatGPTに聞きながらランダム指名Slack botを作った話(前編)


はじめに

こんにちは!サヤマです。
ケイズ・ソフトウェアでは飲み会番長を名乗っているサヤマです。(弊社は酒飲みが少なく飲み会には決まった人しかきてくれません。シクシク)

弊社では最近、毎朝ランダムにメンバーを指名して『最近のGoodnews、嬉しかったこと(なるべく仕事でのこと)』を発表してもらうようになりました。
最初はSlackbotのリマインダーにリマインドしてもらって、Cat-Selectという他社さんのツールを手動で実行するという運用をしていました。
👉 cat-select 手動でチャンネル内のメンバーからランダムに選出してくれる便利ショートカット

 

毎日手動!?めんどくせい!毎朝自動で指名までしてほしいな!!…と思うサヤマ。
まずは愚直にググります。「slack ランダム 指名」っと。。。
AWSのLambdaを使う方法やGAS(GoogleAppScript)を使う方法が多めにヒットします。
それから、弊社内ではPythonスクリプトをメンバーのPC上でcronで動かしているチームもありました。これもだいぶ手軽でいいけど、PC落としてると動かないですね。
今回は、わたしのPCを閉じていても(わたしがお休みの日でも)動かしたかったのと、簡単&無料が一番!ということでGASを採用することにしました。(弊社ではすでにGoogleWorkSpaceを使用しています。)

 

できあがったもの

\パンパカパーン/土日祝日を除いた毎朝9:30に、上記のように投稿されるようになりました! やったぜ。

 

つくりかた

似たようなことをやっている記事はたくさんあるのですが、個別の事象について調べたり実装したりするのがめんどくさかったので(とくに今回は社内用ということと、動けばそれでよかったので)、さっそくChatGPTに相談。(以後、弊社の亀井が親しみを込めてちゃっぴーと呼んでいるのにならい、ちゃっぴーと呼びます。)

1. スプレッドシートに従業員一覧を用意
2. 従業員一覧からランダムに1名 選ぶ
3. 選ばれた人を、Slackに通知
★土日祝日を除く毎朝9:30に通知されるようにしたい

GASで実現可能?
サンプルコードも作って。

ちゃっぴーが出してきたスクリプトがこちら(原文ママ)。

// スプレッドシートIDとシート名
const SPREADSHEET_ID = 'your-spreadsheet-id';
const SHEET_NAME = 'your-sheet-name';

// Slack Webhook URL
const SLACK_WEBHOOK_URL = 'your-slack-webhook-url';

// 土日祝日を除外して、毎朝9:30にランダムに従業員を選び、Slackに通知する
function notifyRandomEmployee() {
  const today = new Date();
  
  // 土日を除外
  if (today.getDay() === 0 || today.getDay() === 6) {
    return;
  }
  
  // 祝日リスト(例として日本の祝日を追加、必要に応じて更新)
  const holidays = ['2024-01-01', '2024-12-25'];  // 追加する祝日
  const formattedToday = today.toISOString().slice(0, 10);
  
  if (holidays.includes(formattedToday)) {
    return;
  }
  
  // スプレッドシートから従業員一覧を取得
  const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
  const data = sheet.getRange(2, 1, sheet.getLastRow() - 1).getValues(); // 2行目から取得
  
  // ランダムに従業員を選ぶ
  const randomIndex = Math.floor(Math.random() * data.length);
  const employee = data[randomIndex][0]; // 1列目に名前があると仮定
  
  // Slackに通知
  const payload = {
    text: `本日の担当は ${employee} さんです!`
  };
  
  const options = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(payload)
  };
  
  UrlFetchApp.fetch(SLACK_WEBHOOK_URL, options);
}

// トリガーのセットアップ(初回実行時に手動で設定する必要あり)
function createTrigger() {
  ScriptApp.newTrigger('notifyRandomEmployee')
    .timeBased()
    .atHour(9)
    .nearMinute(30)
    .everyDays(1)
    .create();
}

いいじゃ〜ん。
よくない? すごくいい。ちゃっぴーありがとう。
スプレッドシートIDとシート名、Slack Webhook URLだけ書き換えれば動きました。イケてるぅ。

かゆいところに手が届いていないので、要望を伝えていきます。

// 祝日リスト(例として日本の祝日を追加、必要に応じて更新)
このリストもスプレッドシートからとるようにしたいな。
同じスプレッドシートの、違うシートからとるようにしようよ

わたしはけっこうフランクに話しかけるタイプ。
上記のプロンプトにより、holidaysシートから祝日を取得する関数が実装されます。

// スプレッドシートIDとシート名
const SPREADSHEET_ID = 'your-spreadsheet-id';
const SHEET_NAME = 'your-sheet-name';          // 従業員一覧があるシート
const HOLIDAY_SHEET_NAME = 'holidays';         // 祝日リストがあるシート名

// 土日祝日を除外して、毎朝9:30にランダムに従業員を選び、Slackに通知する
function notifyRandomEmployee() {
  // ーー中略ーー
  
  // スプレッドシートから祝日リストを取得
  const holidays = getHolidays();
  const formattedToday = today.toISOString().slice(0, 10);

  // 今日が祝日であれば処理を中止
  if (holidays.includes(formattedToday)) {
    return;
  }
  
  // ーー中略ーー
 
}

// 祝日リストをスプレッドシートから取得
function getHolidays() {
  const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(HOLIDAY_SHEET_NAME);
  
  if (!sheet) {
    throw new Error('祝日リストのシートが見つかりません');
  }

  // 祝日リストを取得 (1列目に日付があると仮定)
  const holidayData = sheet.getRange(2, 1, sheet.getLastRow() - 1).getValues(); // 2行目から取得
  return holidayData.map(row => new Date(row[0]).toISOString().slice(0, 10)); // 日付をISO形式の文字列に変換してリストにする
}

ただ、このままだとholidaysシートは手動でメンテしないといけないんですよね。
従業員一覧のメンテはまだしも、祝日一覧のメンテは自動化できるダロ。たのむぜちゃっぴー。

スプレッドシートに日本の祝日をインポートする方法はある?

またフランクにたずねます。
いくつか方法はありますが…といろいろ言ってきます。今回は、「方法 1: Google Calendar APIを使用して祝日を取得し、スプレッドシートにインポート」を採用します。
以下もちゃっぴーが出してきたコード原文ママです。

// 日本の祝日をGoogle Calendar APIから取得し、スプレッドシートにインポート
function importJapaneseHolidays() {
  const calendarId = 'ja.japanese#holiday@group.v.calendar.google.com'; // 日本の祝日カレンダーID
  const today = new Date();
  const nextYear = new Date(today.getFullYear() + 1, 0, 1); // 次の年まで
  const events = CalendarApp.getCalendarById(calendarId).getEvents(today, nextYear);

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('holidays');
  if (!sheet) {
    throw new Error('祝日シートが見つかりません');
  }

  // シートをクリアして、新しいデータを追加
  sheet.clear();
  sheet.getRange(1, 1).setValue('祝日');

  // 祝日を1列目に書き込む
  events.forEach((event, index) => {
    sheet.getRange(index + 2, 1).setValue(event.getStartTime());
  });
}

ありがてぇありがてぇ。

大体大枠が見えてきたところで、後編へ続きます!