Webサイト発注虎の巻ダウンロード
Webサイト発注虎の巻ダウンロード

GASを使ってGoogleカレンダーの内容をSlackステータスに反映する

Sarah

こんにちは。テクニカルディレクターのさらです。

LIGは社内のコミュニケーションツールにSlack、スケジュール管理にはGoogleカレンダーを使っている人が多いのですが、Slackのステータスをカレンダーと連動させることができたら便利ですよね。

Slack上で導入できるGoogleカレンダーのアプリには、予定が入っている時間に自動でステータスを変更してくれる機能がついています。が、カレンダー内容に関係なく全部カレンダーのマークのため、ステータスを見ただけだとミーティング中なのか、ただ作業をしているだけなのか判断できない…🗓

かわいくないし、せっかく色々な絵文字を設定できるのが活かせていなくて残念なので、GASを使って予定に応じた任意の絵文字とステータス文を設定できるようにPOSTを投げるスクリプトを実装してみました。

事前準備

ざっくり今回は、このような構成でいきます。
Googleカレンダー
↓ 内容読み込み
GAS
↓ Slack APIにPOST(ステータスを設定)
Slack
私は基本的に15分単位で予定を入れているので、GASのトリガーを15分周期で設定して自動実行することにします。

上記の構成で行うにあたり、まずSlack APIを作成して、下記2つの情報を取得する必要があります。

  • Google CalendarのcalendarID
  • Slack APIのアクセストークン

Google CalendarのcalendarIDを取得

Googleカレンダーで、予定を取得したいカレンダーの設定を開き、CalendarIDを取得します。

GASで呼び出す際に必要なので、控えておきましょう。

Slack APIを作成

Slack APIにてappを作成

Slack APIのページから「Create New App」をクリックし、appを作成します。

「Permission」からスコープを追加

users.profile:writeの権限を追加します。

アクセストークンを取得

対象のSlackワークスペースにappをインストールします。

appがインストールされるとトークンが生成されるので、「oAuth & Permissions」から取得します。

 

GASからSlack APIにアクセスする際に必要になるので、こちらも控えておきましょう。

ソースコード

function main() {
	const calendarID = "foo";
	var dateTime = new Date();
	var status;

	// 対象のカレンダーからその日の予定を取得
	var events = CalendarApp.getCalendarById(calendarID).getEventsForDay(dateTime);

	if (events.length == 0) {
		// イベントがなければ何も設定しない
		status = JSON.stringify({
			"profile": {
				"status_text": "",
				"status_emoji": ""
			}
		});
	} else {
		for (var i in events) {
			if (events[i].getStartTime() <= dateTime && events[i].getEndTime() >= dateTime) {
				status = identifyStatus(events[i]);
				break;
			} else {
				// その時間にイベントがなければステータスの内容をクリア
				status = JSON.stringify({
					"profile": {
						"status_text": "",
						"status_emoji": ""
					}
				});
			}
		}
	}

	postStatus(status);

}

function identifyStatus(event) {

	var event_title = event.getTitle();

	if (event_title.indexOf("ミーティング") > -1) {

		status = JSON.stringify({
			"profile": {
				"status_text": "ミーティング中",
				"status_emoji": ":calling:"
			}
		});

	} else if (event_title.indexOf("休憩") > -1) {

		status = JSON.stringify({
			"profile": {
				"status_text": "休憩中",
				"status_emoji": ":bubble_tea:"
			}
		});

	} else {

		status = JSON.stringify({
			"profile": {
				"status_text": "作業中",
				"status_emoji": ":computer:"
			}
		});
	}

	return status;

}

function postStatus(status) {
	// アクセス情報
	const URL = "https://slack.com/api/users.profile.set"; // Slack APIのusers.profile.setメソッド
	const TOKEN = "bar"; // アクセストークン

	// HTTPヘッダ設定
	const headers = {
		"Authorization" : "Bearer " + TOKEN,
		"Content-Type": "application/json; charset=utf-8"
	};

	// POSTデータを設定
	var post_data = {
		"headers": headers,
		"method": "POST",
		"payload": status
	};

	var fetch
	return fetch = UrlFetchApp.fetch(URL, post_data);

}

参考users.profile.setの公式ドキュメント

userの現在のステータスをアップロードするJSONには

  • ステータスの文言
  • ステータスの絵文字
  • 終了時間 (オプション)

の3つを設定することができます。

ただ、終了時間はUNIX時間で特定の時間を指定する(期間での設定ができない)形になるため、今回はトリガーを使って15分おきの自動実行で明示的にステータスをクリアする方法を取りました。

GASをデプロイし、Slack Appに連携

初回実行でGoogleカレンダーへのアクセス確認を求められるため、自動実行のトリガーを設定する前に、一度実行ボタンから実行しましょう。無事実行ができたら、早速デプロイします。

デプロイ

「デプロイ」→「新しいデプロイ」を選択します。「アクセスできるユーザー」に全員を選択し、デプロイします。

デプロイを実行するとURLが発行されるので、コピーします。

Slack Appへ連携

Slack Appに戻り、「Interactivity & Shortcuts」からInteractivityをOnにします。
Request URLに先ほどGASをデプロイした際に取得したURLを設定します。

完成🙌🏼

無事、ステータスが設定できました!

 

ミーティング中ということもわかる。

 


タピオカの絵文字かわいい。

トリガーの設定

GASエディタの左側の時計のアイコンから、自動実行のトリガーと実行頻度などを設定できます。今回は分間隔で15分おきの実行を設定しました。

おわりに

普段の業務では自分でコードを書くことがほとんどないので、久々に実装できて楽しかったです!

Slack APIの仕様がどんどんアップデートされているので参考にする記事とやり方が違ったりして疎通に少し苦戦しましたが、次はIncoming Webhookを使ってbot機能の実装などもしてみたいなと思いました。

この記事を書くにあたって、下記の記事を参考にさせていただきました(特にコードの処理フローはほとんどそのまま真似させていただきました)。ありがとうございました!
GoogleカレンダーとSlackステータスを連携する【GAS】
Slack botの作り方を、お節介なほど丁寧に説明