GoogleAppsScriptでGoogleカレンダーの予定をチャットワークに通知するやつ作る【GAS初心者向け】

## はじめに
この記事は私が

「GoogleカレンダーとGASとチャットワークを使って、予定を通知してくれるスクリプトを作る」

という任をいただいた時に行ったことをまとめた記事になります。
なお、分かりやすくするために過程を多めに取っております。「コピペして動けばええんじゃ！急ぎなんじゃ！」という方にはまどろっこしいかもしれません。

※GAS初心者かつプログラミング初心者:beginner:がGAS初心者向けに書いた記事ですので、つたない部分もありますがご容赦ください。
※コメントでのご指摘歓迎です。何卒よろしくお願いいたします。

## 環境
- Windows10 Pro
 （下の三つが扱えて、かつ快適なネット環境に繋がっているPCであれば基本大丈夫です。）
- Googleドライブ
- ChatWork v2
- Googleカレンダー
（ChatWorkアカウントとGoogleアカウントが必要になります。）

## 成果物
- Googleカレンダーからその日の予定を取得し当日の9:00に指定したルームへ  
メッセージを送ってくれるBot
![pic13.PNG](https://qiita-image-store.s3.amazonaws.com/0/273022/4fc14cf1-31fe-3a61-02f3-6bc4420e27e2.png)

## 前提条件
- GoogleアカウントがなければGoogleアカウントを取得する。
- ChatWorkのアカウントがなければChatWorkのアカウントを作成する。

## 困ったときはコレ
- [【保存版】Google Apps Scriptリファレンス～キーワード別インデックス](https://tonari-it.com/google-apps-script-reference/)
- [GAS公式リファレンス](https://developers.google.com/apps-script/reference/script/)
- [chatwork APIドキュメント](developer.chatwork.com/ja/)

何をするにしても、基本困ったらここを見れば大体なんとかなります。

- [GASのScriptEditorオレオレチートシート](https://qiita.com/soundTricker/items/c9091a63de5401f2d49e)
ショートカットの一覧が掲載されているので、凄く助かりました。(Mac)

- [GASのスクリプトエディタについている入力保管機能](https://www.xenos.jp/~zen/blog2/index.php/2018/05/03/post-744/)
こちらはWindowsの入力補完のショートカットです。補完使えるか使えないかでコーディングの快適さが大きく変わると思います。

## そもそもGASってなんだ？
[こちら](http://makimakimakino.hatenablog.com/entry/2017/03/16/010759)にまとめてありました。
簡単にまとめるとこのようになります。

- GASはGoogleが提供するサーバーサイド・スクリプト環境
- Google提供サービスを統合的に処理できる
- ベースはJSで、Googleのサービスを利用するためのさまざまなオブジェクトがされている

ベースがJSなので、何かしらプログラミング言語に触れている方であれば、難なくコーディング出来るのではないかと思います。
勿論初めての方でもとっつきやすい言語だと思うのでおすすめです:wink:

## GASを書くための準備をする
 Googleにログインした状態でGoogleドライブにアクセスします。

- 「新規」→「その他」→「アプリを追加」
![s_pic1.PNG](https://qiita-image-store.s3.amazonaws.com/0/273022/1d8b0cea-f640-0b3b-2d5c-e96a49795f73.png)

- 「Google Apps Script」で検索→「接続」
![s_pic2.PNG](https://qiita-image-store.s3.amazonaws.com/0/273022/51c3dae7-26b6-f88b-fbce-99aa456eddfb.png)

- Google Apps Scriptが「その他」に追加されるのでクリック
![pic3.png](https://qiita-image-store.s3.amazonaws.com/0/273022/0ef55fb4-3ebb-3025-3996-657fccf2fb15.png)

これでスクリプトを書く準備ができました。プロジェクト名は適当に付けてあげてください。
それではここからガシガシコードを書いていきましょう。

## とりあえずチャットワークに何かメッセージを送ってみる。
GASやばいということを実感していただきたいのでとりあえず何かメッセージを送ってみましょう。チャットワークのルームへメッセージを送信するには

- ルームID
- トークン
- ライブラリ「ChatWorkClient for Google Apps Script」の追加

が必要です。
### ルームIDのチェック
個人的に一番簡単だったのはブラウザ版チャットワークで確認する方法でした。
ブラウザ版でルームを開くと、URLの末尾に
「/#!ridXXXXXXXXXXX」
と記載されていると思います。
このrid以降の数字の羅列がルームIDになります。
### トークン
トークンを取得するには、以下の手順を実行します。

- 右上に表示されている「ユーザ名」をクリック→ドロップダウン内の「API設定」をクリック

![pic4.png](https://qiita-image-store.s3.amazonaws.com/0/273022/b6d249eb-3ceb-2768-041c-8118d8c2746d.png)

クリックするとブラウザが立ち上がって下のような画面が表示されると思います。

- 「パスワードを入力」欄にChatWorkのパスワードを入力「表示」ボタンをクリック
- トークンが表示される→「コピー」を押してコピーを取る。

### ライブラリ「ChatWorkClient for Google Apps Script」の追加
GASには便利なライブラリがいくつかあるようです。今回は上記のライブラリを導入します。
導入方法は[こちら](https://qiita.com/y_minowa/items/39db8ca5bffc9c440caf)にとても分かりやすくまとめてありました。
GASのライブラリはプロジェクトキーを使って追加します。
必要なライブラリがあれば、その都度プロジェクトキーをコピペして追加していくことになります。

正直上記の記事を参考にコードを書けばメッセージは送れてしまうのですが、今後のことを考えた上で書いていきたいと思います。

### sendChat関数を作る
ようやくプロトタイプのsendChat関数の作成に入ります。
GASは最初にも挙げたようにベースがJSなので、関数の宣言はfunction、変数の宣言の際はvarを付けます。

```js
function sendChat(){
  var roomId = 'rid以下の数字';
  var client = ChatWorkClient.factory({ token: "コピーしてきたトークン" });
}
```
### ChatWorkClient.factoryってなに？
さて、突如として現れましたがこれはなんだ？と思われた方もいるのではないでしょうか。
正体は、少し上の方で追加したライブラリ「ChatWorkClient for Google Apps Script」によって使えるようになったオブジェクトとメソッドです。
正直、GASだけを使って外部サービスを操作するのは割と面倒です。（面倒さについては[こちら](https://tonari-it.com/gas-web-api-http-urlfetch/#toc7)に分かりやすくまとめてありました）
しかしながら私のようなGAS初心者であっても、簡単にそれを操作するための実装が出来るような仕組みが詰め込まれているのがライブラリです。

```js
ChatWorkClient.factory({ token: "コピーしてきたトークン" })
```

ChatWorkClient.factory()のひとまとまりでChatWorkオブジェクトを生成しています。オブジェクトといわれてピンとこない方は「チャットワークを操作してくれるモノ」だと思っていただければ十分です。
factoryメソッドの引数は連想配列で、上でコピーしてきたトークンを張り付けています。

※ここで「連想配列？」となる方は[こちら](https://qiita.com/hakozaru/items/c00e472ab0f5e823098c)を読むといいかもしれません。

それを変数clientに代入します。それによって、clientに対してメソッド呼び出しを用いることでチャットワークの操作が出来るようになります。

それでは、実際にメッセージを飛ばす部分を書いてみます。
メッセージを飛ばすには、先ほど取得したclientから`sendMessage`メソッドを呼ぶだけです。これも引数が連想配列になります。

```js
function sendChat(){
  var roomId = 'rid以下の数字';
  var client = ChatWorkClient.factory({ token: "コピーしてきたトークン" });

  client.sendMessage({
    room_id: roomId,
    body: "テスト"
  });
}
```

これだけです！！！！！すごいかんたん！
room_idには送りたいルームのＩＤを指定しているだけなので、もし他のルームに送りたいならＩＤを変えるだけで:ok_hand:
ただこれだけでは味気ないので、送るメッセージをどんどんカッコよくするためにも次はGoogleカレンダーからデータを取得しましょう！

## GoogleカレンダーのIDを取得する
Googleカレンダー関連の操作は`CalendarApp`クラスを使います。そしてIDを用いてカレンダーを探し、そのデータを取得するには`getCalendarById`メソッド」を使います。
ここでいうIDとは「Gmailのアドレス」、あるいは「カレンダーID」のことを指します。Gmailのアドレスを指定すると、そのアドレスのデフォルトカレンダーを取得します。
今回は`getCalendar`関数を定義します。

```js
// カレンダーを取得する
function getCalendar(){
  return CalendarApp.getCalendarById('12345600@gmail.com')
}
```

引数には具体的なメールアドレス、カレンダーIDを記載してください。なお、`CalendarApp`は自分が参照権限を持っているカレンダー（自分が作ったカレンダー、あるいは自分が所属しているカレンダー）しか取得できないため、注意が必要です。

## カレンダーのイベントを取得する
### タイトルを取得する
それでは、`getCalendar`関数を使って、カレンダーのイベントを取得する関数を作成します。名前は`getEvents`とします。

```js
// イベントを取得する
function getEvents(){
  var cal = getCalendar(); // カレンダーの取得
  var date = new Date(); // 今日の日付の取得
}
```

まずカレンダーと今日の日付を取得します。これがベースになります。
これらを使ってまずはGoogleカレンダーに登録されている、今日のイベントのタイトルを全件取得してみます。
今日のイベント自体のデータを全件取得するには、取得したカレンダー情報に対して、`getEventsForDay`メソッドを使います。

```js
var events = cal.getEventsForDay(date)
```

このメソッドは引数に日付を取り、取得したカレンダーの中からその日付に紐づくイベントを取得してきます。
取得したデータは配列として返ってきます。
配列はそのままでは操作できないので、一件ずつ出力しなければなりません。そのためfor文を用いて展開していきます。

```diff
// イベントを取得する 
function getEvents(){
  var cal = getCalendar(); // カレンダーの取得
  var date = new Date(); // 今日の日付の取得
+ var events = cal.getEventsForDay(date);
+ for(var i = 0; i < events.length; i++){
+   var title = events[i].getTitle();
  }
```

配列の要素の数だけfor文を回し、各要素のイベントタイトルを取得するように実装してみました。
本当にタイトルが取れているのか確認するために、「Logger.log()」を使い、カレンダーの名前をログに出力してみます。()の中には出力したいものを入れます（今回は変数`title`）。

```diff
// イベントを取得する 
function getEvents(){
  var cal = getCalendar(); // カレンダーの取得
  var date = new Date(); // 今日の日付の取得
  var events = cal.getEventsForDay(date);
  for(var i = 0; i < events.length; i++){
    var title = events[i].getTitle();
+   Logger.log(title);
  }
}
```

ログに出力するには、関数名を選択した上で、その関数を実行します（今回は`getEvents`）。
実行後、「表示」をクリックし「ログ」の項目を選択します。するとログが参照できます。`Logger.log()`１つにつき１つのログが出力されるので、for文で繰り返した回数、すなわち登録されているイベントの個数分ログが出力されていれば大丈夫です。

私は今日（11/6）のカレンダーに「テスト」と「テスト２」というスケジュールを登録しました。ログは以下のようになります。
![pic7.PNG](https://qiita-image-store.s3.amazonaws.com/0/273022/df58b79d-990f-aa3e-96cc-2002a6750afe.png)
### イベントの開始時刻と終了時刻を取得する
これだけでも割といい感じなのですが、せっかくなので時間も取得してみます。これを取得することで

「10:00～12:00：テスト」
「終日：テスト２」

のように表示することが出来るようになります。カレンダーのイベント情報自体は変数「events」の中に全て格納してあるので、その中から1イベントにつき開始時刻と終了時刻を引っ張ってくるだけです。

```diff
// イベントを取得する 
function getEvents(){
  var cal = getCalendar();              // カレンダーの取得
  var date = new Date();                // 今日の日付の取得
  var events = cal.getEventsForDay(date);
  for(var i = 0; i < events.length; i++){
    var title = events[i].getTitle();
-   Logger.log(title);
+   var startTime = events[i].getStartTime(); // 開始時刻の取得
+   var endTime = events[i].getEndTime();     // 終了時刻の取得
  }
}
```

titleの下に二行追加しました。開始時刻は`getStartTime`、終了時刻は`getEndTime`で取得できます。はちゃめちゃに簡単です。
しかしこれもログで見よう！と思いログで出力してみた方は「思っていたのと出力結果が違う…:anguished:」と感じたかもしれません。

なので、次は時刻だけをいい感じに出力してくれる関数を作りたいと思います。

### 時間表示を変更する

開始時刻、終了時刻を表示するにあたって「何時何分か」という情報だけあれば事足りそうなので、先ほど取得した開始日時、終了日時を「時：分」に変換してくれる関数を作ります。

今回は`Utilities`オブジェクトから`formatDate`メソッドを呼びます。これを使うと日付フォーマットの変更ができるという優れものです。

```js

Utilities.formatDate(日付, タイムゾーン, フォーマット)
```

`formatDate`の引数は三つあります。
日付の部分には先ほど取得した開始・終了日時がそれぞれ入ります。
タイムゾーンは基本日本のもので大丈夫だと思うので'JST'を入れておきましょう。
フォーマットについては書き方があるのですが、ここでは割愛しておきます。'HH:mm'と記載することで「時：分」に変換してくれます。
実際の関数は以下のようになります。

```js
function timeFormatter(date){ 
  return Utilities.formatDate(date,'JST','HH:mm');
}
```
今回は`timeFormatter`という名前の関数を作ってみました。引数で受け取った値を変換し、変換した値を返してくれます。
それでは、これを`getEvents`の中に適用させていきます。

```diff
// イベントを取得する 
function getEvents(){
  var cal = getCalendar();              // カレンダーの取得
  var date = new Date();                // 今日の日付の取得
  var events = cal.getEventsForDay(date);
  for(var i = 0; i < events.length; i++){
    var title = events[i].getTitle();
-   var startTime = events[i].getStartTime(); // 開始時刻の取得
+   var startTime = timeFormatter(events[i].getStartTime()); // 開始時刻の取得
-   var endTime = events[i].getEndTime();     // 終了時刻の取得
+   var endTime = timeFormatter(events[i].getEndTime());     // 終了時刻の取得
  }
}
```

`getStartTime`メソッドと`getEndTime`メソッドの返り値を引数に、`timeFormatter`関数で変換していきます。改めてそれぞれの変数の中身を出力すると、ログへの出力がいい感じになっていると思います。
材料が揃ったので、これを理想形に組み立てていきます。

### 開始・終了時刻によって表示を変える
Googleカレンダーは、isAllDayEventメソッドを使うことで、その予定が終日かどうかを確認することが出来ます。

```diff
// イベントを取得する 
function getEvents(){
  var cal = getCalendar();              // カレンダーの取得
  var date = new Date();                // 今日の日付の取得
  var events = cal.getEventsForDay(date);
  for(var i = 0; i < events.length; i++){
    var title = events[i].getTitle();
    var startTime = timeFormatter(events[i].getStartTime()); // 開始時刻の取得
    var endTime = timeFormatter(events[i].getEndTime());     // 終了時刻の取得

+   if(events[i].isAllDayEvent()){
+     // 終日の時の処理
+   }else{
+     // 終日設定じゃないときの処理
+   }
  }
}
```
今回は材料を使ってデータを成型した上でそれを一つの配列に格納していこうと思います。
if文の外で配列を定義して、その配列に文字列を入れ込んでいきます。

```diff
function getEvents(){
// 中略
  var events = cal.getEventsForDay(date);
+ var arrEvents = []; 
  for(var i = 0; i < events.length; i++){
    var title = events[i].getTitle();
    var startTime = timeFormatter(events[i].getStartTime()); // 開始時刻の取得
    var endTime = timeFormatter(events[i].getEndTime());     // 終了時刻の取得
    if(events[i].isAllDayEvent){
+      arrEvents.push("　終日：" + title);
    }else{
+      arrEvents.push("　" + startTime + "～" + endTime + "："　+ title);
    }
  }
+ return arrEvents;
}
```
配列に対しては`push`メソッドを使えば要素を追加していくことが出来ます。引数には配列に追加する要素（今回は文字列）を記載します。
こうすることで、「終日：休み」や「14:00～15:00：会議」のように加工された本日のスケジュールが配列の中に入っていくわけです。これをチャットワークでお知らせらしく表示できるように加工していきます。

## メッセージを成型する
ご存知の方もいらっしゃるかもしれませんが、チャットワークにはタグのようなものがあって、それを使うことによってカッコよくメッセージを表示することが出来ます。
今回はそれを用いて「なんかいい感じにお知らせしてくれてる感」を醸し出してみましょう。
今回作る関数は`getTodaySchedule`です。`getTodaySchedule`関数では、内部で`getEvents`関数を呼びます。

```js
function getTodaySchedule(){
  var cal = getCalendar();
  var date = new Date;
  var arrEvents = getEvents(cal, date);
}
```
あれ？なんかちがうぞとなった方もいらっしゃるかと思います。今までは`getEvents`関数内で取得していたカレンダー情報と日付を`getTodaySchedule`内で取得しています。
その上、`getEvents`関数の引数にそれらを渡しています。
そんなことできるのか？といった感じですが、このままでは勿論できません。なので、`getEvents`関数に修正を加えていきます。

```diff
+ function getEvents(cal, date){
-  var cal = getCalendar();              // カレンダーの取得
-  var date = new Date();                // 今日の日付の取得
   var events = cal.getEventsForDay(date);
   for(var i = 0; i < events.length; i++){
     var title = events[i].getTitle();
// 中略
   }
 }
```
引数にカレンダー情報と日付情報を受け取り、それを加工していくような形に変えました。
これで少しだけ`getEvents`関数がすっきりします。
それでは引き続き、`getTodaySchedule`を作っていきます。

```diff
function getTodaySchedule(){
   var cal = getCalendar();
   var date = new Date();
   var arrEvents = getEvents(cal, date);

+  var header = "[info][title]お知らせ[/title]";
+  var introduction = "おはようございます。今日の予定は\n";
+  var conclution = "\nです。今日も一日頑張りましょう。[/info]";
}
```

まずベースとなる部分のメッセージを作りました。直書きで不格好なのですが、今回はこれでよしとします。
あとは`header`と`introduction`と`arrEvents`と`conclution`の四つを組み合わせていい感じの文字列にするだけです。ただし、`arrEvents`については配列なので、それらを分解して文字列にしたいです。
そのために`join`メソッドを使います。
`join`メソッドは引数に取った文字列を要素と要素の間に挟んで配列を結合し、文字列にしてくれるメソッドです。今回は改行してほしいので"\n"でjoinしたいと思います。

```js
arrEvents.join("\n")
```

これだけです！あとはこれも含めた上で一つの文字列にまとめます。

```diff
function getTodaySchedule(){
　　// 省略
   var header = "[info][title]お知らせ[/title]";
   var introduction = "おはようございます。今日の予定は\n";
   var conclution = "\nです。今日も一日頑張りましょう。[/info]";

+  return header + introduction + arrEvents.join("\n") + conclution;
}
```

できた～～～！！:blush:
気になる方はreturnしている返り値を`Logger.log`で見てみてください。いい感じに出力されているはずです！
ここまで来たらあと一息！頑張りましょう！

## sendChat関数の修正
一番最初に作った`sendChat`関数もいよいよ進化の時がやってきました。
何故なら私たちはもうメッセージを作れるようになったからです。「テスト」とだけ送っていたあの頃とは格が違います。
だからそのメッセージを送るだけ！……なのですが、少しだけ修正を加えたいと思います。

```diff
function sendChat(){
  // 省略
  client.sendMessage({
    room_id: roomId,
+   body: getTodaySchedule()
  });
}
```
これで良くない！？という感じがしますよね、私はそう思ってました。実際全然よくなかったです……何故なら

＞＞＞スケジュールが登録されてないときもメッセージが来てしまう＜＜＜

今のままだとそうなってしまいます。スケジュールがあるかないかを判定するための関数が定義されていないからです。
それらしいメッセージを送ることが出来た嬉しさですっかり失念していました。

それでは、スケジュールの有無を判定するためのメソッドを作っていきましょう。まず、スケジュールの有無が分かるように`getTodaySchedule`を修正していきます。
`getTodaySchedule`の中で、`getEvents`を呼び出しています。この時返ってくるのは配列です。
これを判断基準にしたいと思います。

`もし配列が空であれば空文字列を返す、そうでなければ成型した文字列を返す`

という風に修正していきます。

```diff
function getTodaySchedule(){
   var cal = getCalendar();
   var date = new Date();
   var arrEvents = getEvents(cal, date);

+  if(arrEvents != []){
     var header = "[info][title]お知らせ[/title]";
     var introduction = "おはようございます。今日の予定は\n";
     var conclution = "\nです。今日も一日頑張りましょう。[/info]";
     return header + introduction + arrEvents.join("\n") + conclution;
+  }
+  return "";
}
```
こんな感じです。たったこれだけです。
これで`getTodaySchedule`は「空文字列」あるいは「文字列」をかえしてくれるようになりました。
なので`sendChat`も修正を加えて、「`getTodaySchedule`で取得した文字列が、空文字列でなければメッセージを送る」ようにします。

```diff
function sendChat(){
  // 省略
  var client = ChatWorkClient.factory({ token: "コピーしてきたトークン" });
+ var message = getTodaySchedule();
+ if(message != ""){
    client.sendMessage({
      room_id: roomId,
-     body: getTodaySchedule()
+     body: message   
    });
+ }
}
```
これだけです！
もしメッセージを送らないのではなく、「本日の予定はありません」のようなメッセージを通知したい！というのであれば、この二つの関数をいい感じに修正すればいい感じに出来ると思います。

## トリガーをセットする
これで大方完成なのですが、成果物のところに書いたこれ

- Googleカレンダーからその日の予定を取得し、当日の9:00に指定したルームへメッセージを送ってくれるBot

の`当日の9:00に`の部分をまだ実装していませんでした。まだ伸びしろが残っていました。
GASには元々「トリガー」というものがあり、指定した関数を指定した時間に自動的に実行してくれます。
しかし残念なことに、GASの既存のトリガーにおいて、「日付ベースのタイマー」を選択すると「午前9時～午前10時」のように、一時間ごとのふわっとした時間指定しかできません。（実際その時間台の20分ごろに実行されていました。）

「いいじゃんそのふわっとした感じで」と思われる方もいらっしゃるかもしれません。しかし妥協はカッコよさを半減させます。ここまできたらぴたっと9時ジャストに通知させましょう。

### 考え方
- 「午前9時に関数を実行するトリガーを作る」ための関数を作る
- 日付が変わってからその関数を指定したトリガーを実行
- 午前9時にトリガーが実行される
- メッセージが届く

？:open_mouth:
少し複雑です。トリガーを作るためのトリガーを実行しているので、わけがわからないことになってます。これを実際に実行すると、トリガーの一覧がこんな感じになります。

![pic8.PNG](https://qiita-image-store.s3.amazonaws.com/0/273022/3252e919-7675-bba4-9a17-d97faf0e97b0.png)

下がトリガーを生成してくれる関数を実行したトリガー、上が生成されたトリガーです。
このように二段階トリガーを扱うことで午前9時ジャストにメッセージを送るようにします。
今回は`setTrigger`関数を作ります。

```js
function setTrigger(){
  var setTime = new Date;
  setTime.setHours(9, 0, 0, 0);
  ScriptApp.newTrigger('sendChat').timeBased().at(setTime).create();
}
```
こんな感じです！
「こんな感じです！」と言われても……って感じですよね。一つずつ見ていきましょう。
まず変数setTime。これは今までも何度かやっていた現在の日時の取得を行っています。

次に出てくるのが`setHours`。これは時刻をセットしてくれるメソッドなのですが、なんと引数を4つ渡せて('時', '分', '秒', 'ミリ秒')まで設定できます！つまり、本当の本当に午前9時ジャストにセットしてくれるんですね！

最後に出てきた魔法の呪文みたいな1行。これを解読していきたいと思います。

### ScriptApp
まず出だし、`ScriptApp`クラスです。このクラスはスクリプトを公開したり、トリガーにアクセスして操作することが出来るクラスです。

### newTrigger('関数名')
関数名を引数に渡します。これからこの関数を実行するトリガーつくるよ！と宣言するためのメソッドです。
なお、戻り値はTriggerBuilderオブジェクトになるので、以降はTriggerBuilderクラスのメソッドが呼び出せるようになります。

### timeBased()
そしてこのメソッドは、そのTriggerBuilderクラスのメソッドの一つです。
そもそもTriggerBuilderクラスは何をしてくれるのかというとトリガーのイベント指定をしてくれます。
GASのトリガーには「時間ベース」などイベントが数種類あり、「これベースのトリガーだよ」というのを指定してあげる必要があります。
今回は時間ベースなので、その名の通り`timeBased`メソッドを使いました。
返り値はClockTriggerBuilderクラスです。

### at('時刻')
つまり、このメソッドはClockTriggerBuilderクラスのメソッドというわけです。
今回は特定の日時（9時ちょうど）を設定したいので`at`メソッドで時刻を指定してあげます。

### create()
今までの流れで作りたいトリガーの情報を蓄積してきました。
このメソッドで、その蓄積してきたデータを用いて実際にトリガーを生成、保存します。

紐解いていくと大したことはありませんよね。これだけで9時ちょうどにメッセージを送ってくれるトリガーを設定出来てしまうんです！すごい！
もう完成！今度こそ完成！！

## 既存の日時指定トリガーを削除する
……終わらなかったです。特定日時で指定したトリガーって消えずにずっと蓄積されていくことに気付いてしまいました。
数回だけならいいけど、これって年単位で使っていったら無効になったトリガーが何百件と存在してしまうことになるわけです。
どうしたものかと頭を抱えていたら、「トリガー作る前に古いトリガー消したらいいんじゃない」と鶴の一声。それだ！と思い、既存のトリガーを削除する関数を作成しました。

```js
function deleteYesterdayTrigger(){
  var triggers = ScriptApp.getProjectTriggers();
  for(var i = 0; i < triggers.length; i++){
    if(triggers[i].getHandlerFunction() == 'sendChat'){
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}
```
今回もトリガーの操作を行うので、主に用いるのはScriptAppクラスです。何をしているのかこれも順番に見ていきましょう。

```js
var triggers = ScriptApp.getProjectTriggers();
```

`getProjectTriggers`メソッドは、プロジェクトに関連付けられている全てのトリガーを取得することが出来ます。返り値はTriggerオブジェクトの配列です。

この中から、該当するトリガーを探して消す、という処理を行えばミッションコンプリートです。

```js
    if(triggers[i].getHandlerFunction() == 'sendChat'){
      ScriptApp.deleteTrigger(triggers[i]);
    }
```
これはfor文の中身です。
if文の条件の部分に出てくる`getHandlerFunction`ですが、これはトリガーが呼び出している関数の名前を取得できるメソッドです。
今回削除対象になるのは`sendChat`を呼び出しているメソッドなので、取得した関数名が`'sendChat'`であれば削除の処理を行うようにします。

`deleteTrigger`メソッドは、引数に渡したトリガーを削除するメソッドです。引数にはtriggers[i]を渡してやります。これで過去に生成した`sendChat`を実行するトリガーが削除されます。

では、この関数を実際に`setTrigger`関数の中に追加しましょう。

```diff
function setTrigger(){
+ deleteYesterdayTrigger();
  var setTime = new Date;
  setTime.setHours(9, 0, 0, 0);
  ScriptApp.newTrigger('sendChat').TimeBaced().at(setTime).create();
}
```
これで不要なトリガーを残すことなく、毎日トリガーを新規生成出来るようになりました。
## トリガーの設定
一番大事なことを忘れていました！大元となるトリガーの設定です。
今のままでは手動で関数を実行しないと何も起こらない状況です。なので

「日付が変わってから`setTrigger`を実行するトリガー」

をセットします。
「編集」→「現在のプロジェクトのトリガー」を選択
![pic9_1.png](https://qiita-image-store.s3.amazonaws.com/0/273022/42592928-8ef4-8b0a-898a-9eda86e90489.png)

新しいタブが開くので、右下の「トリガーを追加」を選択
![pic10_1.png](https://qiita-image-store.s3.amazonaws.com/0/273022/cd582c05-0543-4883-02c2-147eb6ab97c9.png)

こんな感じの小窓が開きます。
![s_pic11.PNG](https://qiita-image-store.s3.amazonaws.com/0/273022/83182609-0c5c-9171-878c-9bcf3ef95914.png)


印をつけている個所を画像の通り編集します。時刻は正直日付が変わってから8:59くらいまでならどこでもいいのですが、最速の午前0時～1時にしておきます。
![s_pic12.png](https://qiita-image-store.s3.amazonaws.com/0/273022/7bb01c6c-295a-744c-18b4-b31a6c0d6cae.png)

これであとは寝て待つだけ！午前9時にはメッセージが届いているって寸法です。これを実装したら毎日チャットワークを開くのがきっと楽しくなるはずです。ちゃんと届いていることを確認することで、「自分がこれ作ったんです凄くない～！？」という気持ちがきっと湧き上がってくるはずです。

## 最後に
こんな感じで生まれて初めてのGASでチャットワークにGoogleカレンダー内のその日のイベントを送信してくれるbotのようなものを作ってみました。
最初は「GAS？トリガー？」という感じだったのですが、実装し更にこうして纏めることによって少しはGASと仲良くなれたように思います。
この記事が、私のようにGAS初めましての方にとって「GASやばい」と思える足掛かりになれば幸いです。

## おまけ「土日祝日は予定があってもメッセージを送らない」

※後日更新予定