デザインワン・ジャパン Tech Blog

DesignOne Japan | Activate the World.

GAS で Slack 投稿してみたというお話

はじめに

こんにちは!株式会社デザインワン・ジャパンでエキテンの開発を担当しているサービス開発部の寺井です。

弊社ではスライド出社という制度があり、前日までに申請さえすれば、勤務開始時間を7時から11時の間で1時間単位でずらすことができます。 この制度は「前日夜遅いから翌日は11時出社にしよう」「退社後予定あるから7時出社にしよう」という感じで使える、プライベートの予定に強い制度です。

ただ、自由度が高い上に欠点がありました。それは、翌営業日のチームメンバーの出社時間がぱっとわからない、ということです。 各々の Google カレンダーには勤務時間がわかるように登録されているのですが、いちいち見に行かないと行けないし、勤務時間以外にも予定が入っていたりするので見にくいです。 それを解決するために、翌営業日のチームメンバーの勤怠情報を、 GAS (Google Apps Script) を使って、 Slack に流す Bot を作りました。

今回はそういうお話です。

Bot の設定

Slack の API 設定から、アプリを新しく作成し、投稿するための token を控えておきます(Bot User OAuth Token の方を使います)。

f:id:doj_rterai:20220228171809p:plain

GAS の方に SlackApp というライブラリをインストールします。これを使うことにより、簡単に Slack へメッセージを投げることができます(library を日本語で言うと図書館だけどさぁ...)。

f:id:doj_rterai:20220228172657p:plain

そして、先ほど控えた token をプロジェクトのプロパティに設定します。今回は TOKEN という値にセットします。

f:id:doj_rterai:20220228172444p:plain

以上で API の設定は完了です。実際にできるか試してみましょう。下記コードで Slack に投稿できるようになります。

function main() {
    bot("てーすーと", "#scpecial_hoge_hoge_value");
}

function bot(message, channelId) {
  // API用のトークン
  const slackApp = SlackApp.create(PropertiesService.getScriptProperties().getProperty('TOKEN'));

  const options = {
    username: "sliderman",
    icon_emoji: ":man-surfing:"
  }
  
  slackApp.postMessage(channelId, message, options);
}

実行したところ Slack に投稿されていました!ちなみに今回作る Bot の名前は sliderman です。スライド情報を伝える人ということから命名しました。どこかの蜘蛛男は関係ないです。

f:id:doj_rterai:20220228173216p:plain

Google カレンダーにフォーマット通り予定を入れてもらう

各自のカレンダーに、9時から18時の間でスライドによって不在になる時間帯に 【スライドのため不在】 という文言を含んだタイトルの予定を入れてもらいます(この人の場合、毎日10時出社にしているため、繰り返し設定で登録していますね)。

f:id:doj_rterai:20220228164622p:plain

GAS から Google カレンダーを呼び出す

メンバーの email と取得したい日付を渡して、その人のその日の予定を全て取得する関数を作ります。 getNextDay() は次の日を返す関数です。

function getEventFromGoogleCalendar(member, day) {
  const calendar = CalendarApp.getCalendarById(member.email);
  
  return calendar.getEvents(day, getNextDay(day));
}

カレンダー情報をメンバーオブジェクトに追加します。 events のところにカレンダーから取得してきたデータを入れます。 それによって後は menbersWithEvents という命名が微妙な変数で処理していけます。

const membersWithEvents = members.map(m => {m['events'] = getEventFromGoogleCalendar(m, getNextWeekday()); return m;});

ちなみに getNextWeekday() は翌営業日の日付を返してきます。営業日かどうかを判定する関数を作成し、明日の日付から一日ずつ判定していくという原始的な方法です(29日間連続で休みではないという前提。29日も連続で休みがある会社があったら入りたい)。

// 翌営業日の日付を取得する
function getNextWeekday() {
  var date = new Date();
  
  for (var tmp = 1; tmp < 30; tmp++) {
    date.setDate(date.getDate() + 1);
    if (isBusinessDay(date)) {
      break;
    }
  }
  
  return date;
}

// 与えられた日付が営業日かどうか判定する
function isBusinessDay(date){
  // 土日の場合
  if (date.getDay() == 0 || date.getDay() == 6) {
    return false;
  }

  // 祝日の場合(google の日本の祝日カレンダーを使って判定)
  const calJa = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
  if (calJa.getEventsForDay(date).length > 0) {
    return false;
  }

  // 適宜年末年始の場合を加える

  return true;
}

いい感じに整形する

あとはデータをいい感じに整形するだけです。この部分は解説しません(笑)。 というのもまだまだ長くなるというのと、整形部分は使う状況によって全然変わってくるので、そこは必要に応じて整形してもらえればと思います。

そして、いい感じに整形した結果...、で・き・た!

f:id:doj_rterai:20220228184213p:plain

(下の段は、スライドと同様に、在宅か出社かが分かるようにしたものである)

こうして、誰が何時に出勤か(そして、在宅か出社か)が簡単に分かるようになりました。 めでたしめでたし。

仲間を募集しております

募集中の職種については以下を御覧ください。

www.wantedly.com