contentGoogleAppsScriptでGoogleカレンダーの予定をチャットワークに通知するやつ作る【GAS初心者向け】GoogleAppsScriptChatworkはじめにこの記事は私が「GoogleカレンダーとGASとチャットワークを使って、予定を通知してくれるスクリプトを作る」という任をいただいた時に行ったことをまとめた記事になります。分かりやすくするために過程を多めに取っております。「コピペして動けばええんじゃ!急ぎなんじゃ!」という方にはまどろっこしいかもしれません。GAS初心者向けに書いた記事ですので、つたない部分もありますがご容赦ください。※コメントでのご指摘歓迎です。(下の三つが扱えて、かつ快適なネット環境に繋がっているPCであれば基本大丈夫です。(ChatWorkアカウントとGoogleアカウントが必要になります。)成果物Googleカレンダーからその日の予定を取得し当日の9:00に指定したルームへメッセージを送ってくれるBot前提条件GoogleアカウントがなければGoogleアカウントを取得する。ChatWorkのアカウントがなければChatWorkのアカウントを作成する。APIドキュメント何をするにしても、基本困ったらここを見れば大体なんとかなります。GASのScriptEditorオレオレチートシートショートカットの一覧が掲載されているので、凄く助かりました。(Mac)GASのスクリプトエディタについている入力保管機能こちらはWindowsの入力補完のショートカットです。補完使えるか使えないかでコーディングの快適さが大きく変わると思います。そもそもGASってなんだ?こちらにまとめてありました。簡単にまとめるとこのようになります。GASはGoogleが提供するサーバーサイド・スクリプト環境Google提供サービスを統合的に処理できるベースはJSで、Googleのサービスを利用するためのさまざまなオブジェクトがされているベースがJSなので、何かしらプログラミング言語に触れている方であれば、難なくコーディング出来るのではないかと思います。方でもとっつきやすい言語だと思うのでおすすめですGASを書くための準備をするGoogleにログインした状態でGoogleドライブにアクセスします。Scriptが「その他」に追加されるのでクリックこれでスクリプトを書く準備ができました。プロジェクト名は適当に付けてあげてください。それではここからガシガシコードを書いていきましょう。チャットワークに何かメッセージを送ってみる。GASやばいということを実感していただきたいのでとりあえず何かメッセージを送ってみましょう。Script」の追加が必要です。ルームIDのチェック個人的に一番簡単だったのはブラウザ版チャットワークで確認する方法でした。ブラウザ版でルームを開くと、URLの末尾に「/#!ridXXXXXXXXXXX」と記載されていると思います。このrid以降の数字の羅列がルームIDになります。トークントークンを取得するには、以下の手順を実行します。右上に表示されている「ユーザ名」をクリック→ドロップダウン内の「API設定」をクリッククリックするとブラウザが立ち上がって下のような画面が表示されると思います。「パスワードを入力」欄にChatWorkのパスワードを入力「表示」ボタンをクリックトークンが表示される→「コピー」を押してコピーを取る。Script」の追加GASには便利なライブラリがいくつかあるようです。今回は上記のライブラリを導入します。導入方法はこちらにとても分かりやすくまとめてありました。GASのライブラリはプロジェクトキーを使って追加します。必要なライブラリがあれば、その都度プロジェクトキーをコピペして追加していくことになります。上記の記事を参考にコードを書けばメッセージは送れてしまうのですが、今後のことを考えた上で書いていきたいと思います。sendChat関数を作るようやくプロトタイプのsendChat関数の作成に入ります。GASは最初にも挙げたようにベースがJSなので、関数の宣言はfunction、変数の宣言の際はvarを付けます。});}ChatWorkClient.factoryってなに?さて、突如として現れましたがこれはなんだ?と思われた方もいるのではないでしょうか。Script」によって使えるようになったオブジェクトとメソッドです。GASだけを使って外部サービスを操作するのは割と面倒です。(面倒さについてはこちらに分かりやすくまとめてありました)しかしながら私のようなGAS初心者であっても、簡単にそれを操作するための実装が出来るような仕組みが詰め込まれているのがライブラリです。})ChatWorkClient.factory()のひとまとまりでChatWorkオブジェクトを生成しています。オブジェクトといわれてピンとこない方は「チャットワークを操作してくれるモノ」だと思っていただければ十分です。factoryメソッドの引数は連想配列で、上でコピーしてきたトークンを張り付けています。※ここで「連想配列?」となる方はこちらを読むといいかもしれません。それを変数clientに代入します。それによって、clientに対してメソッド呼び出しを用いることでチャットワークの操作が出来るようになります。それでは、実際にメッセージを飛ばす部分を書いてみます。メッセージを飛ばすには、先ほど取得したclientからsendMessageメソッドを呼ぶだけです。これも引数が連想配列になります。});}これだけです!!!!!すごいかんたん!room_idには送りたいルームのIDを指定しているだけなので、もし他のルームに送りたいならIDを変えるだけでただこれだけでは味気ないので、送るメッセージをどんどんカッコよくするためにも次はGoogleカレンダーからデータを取得しましょう!GoogleカレンダーのIDを取得するGoogleカレンダー関連の操作はCalendarAppクラスを使います。IDを用いてカレンダーを探し、そのデータを取得するにはgetCalendarByIdメソッド」を使います。ここでいうIDとは「Gmailのアドレス」、あるいは「カレンダーID」のことを指します。Gmailのアドレスを指定すると、そのアドレスのデフォルトカレンダーを取得します。今回はgetCalendar関数を定義します。CalendarApp.getCalendarById('12345600@gmail.com')}引数には具体的なメールアドレス、カレンダーIDを記載してください。CalendarAppは自分が参照権限を持っているカレンダー(自分が作ったカレンダー、あるいは自分が所属しているカレンダー)しか取得できないため、注意が必要です。カレンダーのイベントを取得するタイトルを取得するそれでは、getCalendar関数を使って、カレンダーのイベントを取得する関数を作成します。名前はgetEventsとします。今日の日付の取得}まずカレンダーと今日の日付を取得します。これがベースになります。これらを使ってまずはGoogleカレンダーに登録されている、今日のイベントのタイトルを全件取得してみます。今日のイベント自体のデータを全件取得するには、取得したカレンダー情報に対して、getEventsForDayメソッドを使います。cal.getEventsForDay(date)このメソッドは引数に日付を取り、取得したカレンダーの中からその日付に紐づくイベントを取得してきます。取得したデータは配列として返ってきます。配列はそのままでは操作できないので、一件ずつ出力しなければなりません。そのためfor文を用いて展開していきます。}配列の要素の数だけfor文を回し、各要素のイベントタイトルを取得するように実装してみました。本当にタイトルが取れているのか確認するために、「Logger.log()」を使い、カレンダーの名前をログに出力してみます。()の中には出力したいものを入れます(今回は変数title)。クリックし「ログ」の項目を選択します。するとログが参照できます。Logger.log()1つにつき1つのログが出力されるので、for文で繰り返した回数、すなわち登録されているイベントの個数分ログが出力されていれば大丈夫です。私は今日(11/6)のカレンダーに「テスト」と「テスト2」というスケジュールを登録しました。ログは以下のようになります。イベントの開始時刻と終了時刻を取得するこれだけでも割といい感じなのですが、せっかくなので時間も取得してみます。「終日:テスト2」のように表示することが出来るようになります。カレンダーのイベント情報自体は変数「events」の中に全て格納してあるので、その中から1イベントにつき開始時刻と終了時刻を引っ張ってくるだけです。}}titleの下に二行追加しました。開始時刻はgetStartTime、終了時刻はgetEndTimeで取得できます。はちゃめちゃに簡単です。」と感じたかもしれません。次は時刻だけをいい感じに出力してくれる関数を作りたいと思います。「時:分」に変換してくれる関数を作ります。今回はUtilitiesオブジェクトからformatDateメソッドを呼びます。これを使うと日付フォーマットの変更ができるという優れものです。フォーマット)formatDateの引数は三つあります。日付の部分には先ほど取得した開始・終了日時がそれぞれ入ります。タイムゾーンは基本日本のもので大丈夫だと思うので'JST'を入れておきましょう。フォーマットについては書き方があるのですが、ここでは割愛しておきます。'HH:mm'と記載することで「時:分」に変換してくれます。実際の関数は以下のようになります。Utilities.formatDate(date,'JST','HH:mm');}今回はtimeFormatterという名前の関数を作ってみました。引数で受け取った値を変換し、変換した値を返してくれます。それでは、これをgetEventsの中に適用させていきます。}}getStartTimeメソッドとgetEndTimeメソッドの返り値を引数に、timeFormatter関数で変換していきます。それぞれの変数の中身を出力すると、ログへの出力がいい感じになっていると思います。材料が揃ったので、これを理想形に組み立てていきます。開始・終了時刻によって表示を変えるGoogleカレンダーは、isAllDayEventメソッドを使うことで、その予定が終日かどうかを確認することが出来ます。}}今回は材料を使ってデータを成型した上でそれを一つの配列に格納していこうと思います。if文の外で配列を定義して、その配列に文字列を入れ込んでいきます。arrEvents;}配列に対してはpushメソッドを使えば要素を追加していくことが出来ます。引数には配列に追加する要素(今回は文字列)を記載します。することで、「終日:休み」や「14:00~15:00:会議」のように加工された本日のスケジュールが配列の中に入っていくわけです。これをチャットワークでお知らせらしく表示できるように加工していきます。メッセージを成型するご存知の方もいらっしゃるかもしれませんが、チャットワークにはタグのようなものがあって、それを使うことによってカッコよくメッセージを表示することが出来ます。今回はそれを用いて「なんかいい感じにお知らせしてくれてる感」を醸し出してみましょう。今回作る関数はgetTodayScheduleです。getTodaySchedule関数では、内部でgetEvents関数を呼びます。date);}あれ?なんかちがうぞとなった方もいらっしゃるかと思います。今まではgetEvents関数内で取得していたカレンダー情報と日付をgetTodaySchedule内で取得しています。その上、getEvents関数の引数にそれらを渡しています。そんなことできるのか?といった感じですが、このままでは勿論できません。getEvents関数に修正を加えていきます。}引数にカレンダー情報と日付情報を受け取り、それを加工していくような形に変えました。これで少しだけgetEvents関数がすっきりします。それでは引き続き、getTodayScheduleを作っていきます。"おはようございます。今日も一日頑張りましょう。[/info]";}まずベースとなる部分のメッセージを作りました。直書きで不格好なのですが、今回はこれでよしとします。あとはheaderとintroductionとarrEventsとconclutionの四つを組み合わせていい感じの文字列にするだけです。arrEventsについては配列なので、それらを分解して文字列にしたいです。そのためにjoinメソッドを使います。joinメソッドは引数に取った文字列を要素と要素の間に挟んで配列を結合し、文字列にしてくれるメソッドです。今回は改行してほしいので"\n"でjoinしたいと思います。arrEvents.join("\n")これだけです!あとはこれも含めた上で一つの文字列にまとめます。"おはようございます。今日も一日頑張りましょう。conclution;}できた~~~!!気になる方はreturnしている返り値をLogger.logで見てみてください。最初に作ったsendChat関数もいよいよ進化の時がやってきました。私たちはもうメッセージを作れるようになったからです。「テスト」とだけ送っていたあの頃とは格が違います。そのメッセージを送るだけ!......なのですが、少しだけ修正を加えたいと思います。});}これで良くない!?という感じがしますよね、私はそう思ってました。実際全然よくなかったです......何故なら>>>スケジュールが登録されてないときもメッセージが来てしまう<<<今のままだとそうなってしまいます。スケジュールがあるかないかを判定するための関数が定義されていないからです。それらしいメッセージを送ることが出来た嬉しさですっかり失念していました。それでは、スケジュールの有無を判定するためのメソッドを作っていきましょう。スケジュールの有無が分かるようにgetTodayScheduleを修正していきます。getTodayScheduleの中で、getEventsを呼び出しています。この時返ってくるのは配列です。これを判断基準にしたいと思います。配列が空であれば空文字列を返す、そうでなければ成型した文字列を返すという風に修正していきます。"おはようございます。今日も一日頑張りましょう。"";}こんな感じです。これでgetTodayScheduleは「空文字列」あるいは「文字列」をかえしてくれるようになりました。sendChatも修正を加えて、「getTodayScheduleで取得した文字列が、空文字列でなければメッセージを送る」ようにします。}}これだけです!もしメッセージを送らないのではなく、「本日の予定はありません」のようなメッセージを通知したい!というのであれば、この二つの関数をいい感じに修正すればいい感じに出来ると思います。トリガーをセットするこれで大方完成なのですが、成果物のところに書いたこれGoogleカレンダーからその日の予定を取得し、当日の9:00に指定したルームへメッセージを送ってくれるBotの当日の9:00にの部分をまだ実装していませんでした。伸びしろが残っていました。GASには元々「トリガー」というものがあり、指定した関数を指定した時間に自動的に実行してくれます。残念なことに、GASの既存のトリガーにおいて、「日付ベースのタイマー」を選択すると「午前9時~午前10時」のように、一時間ごとのふわっとした時間指定しかできません。(実際その時間台の20分ごろに実行されていました。)「いいじゃんそのふわっとした感じで」と思われる方もいらっしゃるかもしれません。妥協はカッコよさを半減させます。ここまできたらぴたっと9時ジャストに通知させましょう。午前9時にトリガーが実行されるメッセージが届く?少し複雑です。トリガーを作るためのトリガーを実行しているので、わけがわからないことになってます。これを実際に実行すると、トリガーの一覧がこんな感じになります。下がトリガーを生成してくれる関数を実行したトリガー、上が生成されたトリガーです。このように二段階トリガーを扱うことで午前9時ジャストにメッセージを送るようにします。今回はsetTrigger関数を作ります。ScriptApp.newTrigger('sendChat').timeBased().at(setTime).create();}こんな感じです!「こんな感じです!」と言われても......って感じですよね。一つずつ見ていきましょう。これは今までも何度かやっていた現在の日時の取得を行っています。次に出てくるのがsetHours。'ミリ秒')まで設定できます!つまり、本当の本当に午前9時ジャストにセットしてくれるんですね!最後に出てきた魔法の呪文みたいな1行。これを解読していきたいと思います。ScriptAppまず出だし、ScriptAppクラスです。このクラスはスクリプトを公開したり、トリガーにアクセスして操作することが出来るクラスです。newTrigger('関数名')関数名を引数に渡します。これからこの関数を実行するトリガーつくるよ!と宣言するためのメソッドです。戻り値はTriggerBuilderオブジェクトになるので、以降はTriggerBuilderクラスのメソッドが呼び出せるようになります。timeBased()そしてこのメソッドは、そのTriggerBuilderクラスのメソッドの一つです。そもそもTriggerBuilderクラスは何をしてくれるのかというとトリガーのイベント指定をしてくれます。GASのトリガーには「時間ベース」などイベントが数種類あり、「これベースのトリガーだよ」というのを指定してあげる必要があります。今回は時間ベースなので、その名の通りtimeBasedメソッドを使いました。返り値はClockTriggerBuilderクラスです。at('時刻')つまり、このメソッドはClockTriggerBuilderクラスのメソッドというわけです。今回は特定の日時(9時ちょうど)を設定したいのでatメソッドで時刻を指定してあげます。create()今までの流れで作りたいトリガーの情報を蓄積してきました。このメソッドで、その蓄積してきたデータを用いて実際にトリガーを生成、保存します。紐解いていくと大したことはありませんよね。これだけで9時ちょうどにメッセージを送ってくれるトリガーを設定出来てしまうんです!すごい!もう完成!今度こそ完成!!既存の日時指定トリガーを削除する......終わらなかったです。特定日時で指定したトリガーって消えずにずっと蓄積されていくことに気付いてしまいました。数回だけならいいけど、これって年単位で使っていったら無効になったトリガーが何百件と存在してしまうことになるわけです。したものかと頭を抱えていたら、「トリガー作る前に古いトリガー消したらいいんじゃない」と鶴の一声。それだ!と思い、既存のトリガーを削除する関数を作成しました。}}今回もトリガーの操作を行うので、主に用いるのはScriptAppクラスです。何をしているのかこれも順番に見ていきましょう。ScriptApp.getProjectTriggers();getProjectTriggersメソッドは、プロジェクトに関連付けられている全てのトリガーを取得することが出来ます。返り値はTriggerオブジェクトの配列です。この中から、該当するトリガーを探して消す、という処理を行えばミッションコンプリートです。}これはfor文の中身です。if文の条件の部分に出てくるgetHandlerFunctionですが、これはトリガーが呼び出している関数の名前を取得できるメソッドです。今回削除対象になるのはsendChatを呼び出しているメソッドなので、取得した関数名が'sendChat'であれば削除の処理を行うようにします。deleteTriggerメソッドは、引数に渡したトリガーを削除するメソッドです。引数にはtriggers[i]を渡してやります。これで過去に生成したsendChatを実行するトリガーが削除されます。この関数を実際にsetTrigger関数の中に追加しましょう。ScriptApp.newTrigger('sendChat').TimeBaced().at(setTime).create();}これで不要なトリガーを残すことなく、毎日トリガーを新規生成出来るようになりました。大事なことを忘れていました!大元となるトリガーの設定です。今のままでは手動で関数を実行しないと何も起こらない状況です。新しいタブが開くので、右下の「トリガーを追加」を選択こんな感じの小窓が開きます。印をつけている個所を画像の通り編集します。時刻は正直日付が変わってから8:59くらいまでならどこでもいいのですが、最速の午前0時~1時にしておきます。これであとは寝て待つだけ!午前9時にはメッセージが届いているって寸法です。これを実装したら毎日チャットワークを開くのがきっと楽しくなるはずです。届いていることを確認することで、「自分がこれ作ったんです凄くない~!?」という気持ちがきっと湧き上がってくるはずです。最後にこんな感じで生まれて初めてのGASでチャットワークにGoogleカレンダー内のその日のイベントを送信してくれるbotのようなものを作ってみました。最初は「GAS?トリガー?」という感じだったのですが、実装し更にこうして纏めることによって少しはGASと仲良くなれたように思います。この記事が、私のようにGAS初めましての方にとって「GASやばい」と思える足掛かりになれば幸いです。requestStockLike19Mi@mi0プログラミング歴1年+αの2年目PG。あらゆるものを破壊する天才。日本を代表する企業様のIT化を推進・支援しています。upLoginユーザーは見つかりませんでした。