Pathee engineering blog

世界をしなやかに変えるエンジニアたちのブログ

Google Apps ScriptとGoogle カレンダーを使って会議室の予定終了5分前に音楽を再生する

Pathee Advent Calendar 2019 の12日目の記事です。

この度Patheeの会議文化をハックする部隊に任命してもらいまして、エンジニアリングで会議をよくできないか考え、実行しています。

現状、会議の終了時刻に話題の収束が間に合わず、次の予定との転換に時間がかかることがあり、終了前に通知して話題が時間内に収束するよう、Google Apps Scriptを用いてリマインドするアプリを作ってみました。

構成

追々誰でもメンテナンスできるように、Patheeのエンジニアが常々触っている言語を使いました。

クライアント

サーバ

サーバを作る

クライアントからのリクエストを受け取って、会議室の情報と、終了5分前かどうかをjson形式で返すサーバをGoogle Apps Scriptで作ります。

Google Apps Scriptには clasp というCLIがあり、それも最近TypeScriptで作れるようになっており、そちらを使って作ってみました。

TypeScriptとclaspでの開発に関しての記事は既に多くありますので、そちらに譲ります。

まず会議室の情報を用意しておきます。

type MeetingRoom = {
  id: string;
  room_id: number;
  name: string;
};

const MEETING_ROOMS: MeetingRoom[] = [
  {
    name: '会議室(大)',
    id: 'xxxxxxxx@resource.calendar.google.com',
    room_id: 0
  },
  {
    name: '会議室(中)',
    id: 'xxxxxxxx@resource.calendar.google.com',
    room_id: 1
  },
  {
    name: 'オープンカフェ',
    id: 'xxxxxxxx@resource.calendar.google.com',
    room_id: 2
  },
  {
    name: 'オープンステージ',
    id: 'xxxxxxxx@resource.calendar.google.com',
    room_id: 3
  }
];

カレンダーの現在行われているイベントが、終了5分前かどうかを取得します。

export class CalendarService {
  static isFiveMinutesBeforeEndTimeOfEvent(calendarId: string): string {
    const now = new Date();
  
    const calendar = CalendarApp.getCalendarById(MEETING_ROOMS[calendarId]);
    const events = calendar.getEventsForDay(now);
    const currentEvent = events.filter(
      event => now > event.getStartTime() && now < event.getEndTime()
    );
  
    if (currentEvent.length === 0) return '{"data": "予定なし"}';
  
    const isFiveMinutesBeforeEndTimeOfEvent =
      currentEvent[0].getEndTime().getMinutes() === addMinutes(now, 5).getMinutes(); // addMinutes() は自作のutilメソッド
  
    return isFiveMinutesBeforeEndTimeOfEvent ? '{"data": "会議終了5分前"}' : `{"data": "${currentEvent[0].getTitle()}"}`;
  }
}

index.tsdoGet 関数を記述することで、リクエストを受け取った際の挙動を定義できます。

import { CalendarService } from './calendar.service';

declare var global: any;

global.doGet = (e: any): any => {
  const {
    parameters: { room_id }
  } = e;

  const retVal = CalendarService.isFiveMinutesBeforeEndTimeOfEvent(room_id);

  return ContentService.createTextOutput(JSON.stringify(retVal));
};

出来たら clasp push し、Google Apps Scriptの画面を開き (clasp open) 、ウェブアプリケーションとして導入します。

クライアントを作る

クライアントは、 sched を使って1分ごとの定期実行をさせ、実行ごとにサーバにリクエストを投げ、5分前という文字列が返ってくると、 playsound を使って音楽を再生するものを作ってみました。

playsoundは外部モジュールなので準備が必要です。

pip install playsound

用意が出来たら、コードを書いていきます。

import requests
import playsound
import sched, time

ROOM_ID = 0
URL = 'https://script.google.com/macros/s/xxxxxxxx/exec?room_id={room_id}'.format(room_id=ROOM_ID)

s = sched.scheduler(time.time, time.sleep)

def run(sc):
  res = requests.get(URL)

  print(res.json())
  print(res.json().get("data"))

  if res.json().get("data") == "会議終了5分前":
    playsound.playsound('sound.mp3', True)

  s.enter(60, 1, run, (sc,))

s.enter(60, 1, run, (s,))
s.run()

実際に鳴らしてみた

時間を意識してよりよい会議になるといいですね!

明日は、週6でスイミングに通って無限にジムの元を取っているという驚異のヘルシーエンジニア irihit さんがstyled-componentとAtomic Designについて話してくれます!