定例会議の予定をSlackでリマインドする当社の敏腕秘書"Dev夫人"

### 背景
-----------------------------------------
- オフィスのない当社はスケジュール調整をGoogleカレンダーで行っている
- 開発部門用のSlack Channelでやり取りしている
- 2週間に1回の定例会議を行っている
- 中にはGoogleカレンダーで管理していないメンバーもいるっぽい(定例会議を忘れてしまう)

### Dev夫人とは？
-----------------------------------------
![image](https://qiita-image-store.s3.amazonaws.com/0/38292/067d2403-1d89-4042-9acb-34dec9028380.png)


- 語尾に"ざます"とつくざます
- 定例会議のn日前にGoogleカレンダーのイベントを確認してリマインドするざます(スクリプトで調整可能)
- (当社はオフィスがないので)レンタル会議室の予約をリマインドするざます
    - レンタル会議室が決まっていれば、その場所をお知らせするざます
- 80歳くらいで多分独身でペットのワンちゃんたちと暮らしているざます
- ス〇ルノさんとは別人ざます
    - マ〇オンとか知らないざます

### 確認するGoogleカレンダーのイベント
-----------------------------------------
![image](https://qiita-image-store.s3.amazonaws.com/0/38292/838deb2d-1202-6954-99e7-6d27bc084b8b.png)

- タイトルが"Dev.MTG"としているもの(スクリプトで調整可能)

### Slack用のGoogle Apps Scriptライブラリを利用する
-----------------------------------------

[soundTricker/SlackApp](https://github.com/soundTricker/SlackApp)

GASエディタにライブラリを追加して使う。Google Apps Script Editorのリソース→ライブラリから```M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO```を検索して追加しておく。
![image](https://qiita-image-store.s3.amazonaws.com/0/38292/e72e4bed-a71f-760f-8b66-a65c7744efe6.png)

### SlackのIncoming Webhookを作っておく
-----------------------------------------

このあたりを読んでガンバレ！
[Slack APIを使ってプッシュ通知を受け取ろう | 株式会社バニーホップ](http://www.bunnyhop.jp/lab-20141020/)

### Google Apps Scriptな内容
-----------------------------------------

```gas:コード.gs
var postUrl = 'https://hooks.slack.com/services/********************';
var postChannel = '#{チャンネル名}';
var username = 'bot名';
var days = 3; // 何日前からリマインドするか？

function postToSlack() {
	var calendarId = '{参照先のカレンダーID}@group.calendar.google.com';
	var calendar = CalendarApp.getCalendarById(calendarId);
	var targetDate = new Date();
	targetDate.setDate(targetDate.getDate()+days);
	var searchStr = 'Dev.MTG'; // イベントタイトルに含めたい文字列
	var events = calendar.getEventsForDay(targetDate, {search: searchStr});
	var no_reservation_msg = '';

	if(events[0]){
		var title = events[0].getTitle();
		var start = events[0].getStartTime();
		var location = events[0].getLocation();
		var description = events[0].getDescription();
		var start_month = start.getMonth()+1;
		var WeekChars = [ "日", "月", "火", "水", "木", "金", "土" ];
		var start_day = WeekChars[start.getDay()]; // 曜日
		var start_time = start.getHours() + ':' + pad(start.getMinutes());
		var start_date = start.getDate(); //日
		
		var message = '【お知らせ】次回のDev.MTGは' + start_month.toString() + '月' + start_date.toString() + '日(' + start_day + ')の' + start_time + 'からとさせていただくざます。';

		if(location){
			message = message + '場所は' + location + 'ざます。';
		}else{
			no_reservation_msg = '皆様、会議室の予約（プロジェクター等）は必要ざますか？';
		}

		message = message + 'よろしくお願いしますざます。';

		if(description){
			message = message + '\n' + '[詳細情報]' + '\n' + description;
		}
		sendHttpPost(message, username);
	}
	// 会議室が予約されていない場合→通知
	if(no_reservation_msg){
		// Dev.MTG確認
		var confirm_agenda = '@tokifuji: Dev.MTGするざますか？ 課題とAgendaを確認して欲しいざます。';
		sendHttpPost(confirm_agenda, username);
		sendHttpPost(no_reservation_msg, username);
	}
}

function sendHttpPost(message, username)
{
	var jsonData =
	{
		 "channel" : postChannel,
		 "username" : username,
		 "text" : message,
		 "link_names": 1
	};
	var payload = JSON.stringify(jsonData);
	var options =
	{
		"method" : "post",
		"contentType" : "application/json",
		"payload" : payload
	};
 
	UrlFetchApp.fetch(postUrl, options);
}

function pad(n){return n<10 ? '0'+n : n}
```

#### 1度postToSlackを実行して認証しておこう
![image](https://qiita-image-store.s3.amazonaws.com/0/38292/936a92a5-c80f-669b-9efd-3b4191655c01.png)



### 毎日決まった時間に実行させる
-----------------------------------------

- GASエディタ→リソース→現在のプロジェクトのリソース、から毎日決まった時刻にpostToSlackを実行するトリガーを設定しておく
- 当社の場合、昼休み中(Slack見てくれそうな時間帯)としている

![image](https://qiita-image-store.s3.amazonaws.com/0/38292/d9ea909f-e7ff-480a-f0f6-5893b24f7da9.png)



### こんな怖いおばちゃんがリマインドしてくれるようになる
-----------------------------------------

![image](https://qiita-image-store.s3.amazonaws.com/0/38292/067d2403-1d89-4042-9acb-34dec9028380.png)

### Google Apps Scriptは便利だね
-----------------------------------------

でも、結構CRONジョブがなぁなぁだったり、長い処理時間に耐えられなかったり(Max6分間)とかいろいろと制限はあるけど、インフラを運用せずにこういった簡単なタスクを自動化できるのはありがたいですね。また、JavaScriptベースなので教育コストも低いです。是非、有効にご活用ください。