LoginSignup
3
3

More than 1 year has passed since last update.

Google Calendar for Team Eventsを"使わずに"GoogleカレンダーとSlackを連携する

Last updated at Posted at 2020-11-23

はじめに

  • Google Calendar for Team EventsとSlackの連携アプリがチーム内の事情で使えないので、SlackのWebhookを利用してSlackの公式連携アプリ+αの機能をGoogleスプレッドシートとGASの連携で実現しました。

  • 完全に公式アプリのコピーだとなんだか寂しいので、備考欄も出力できるようにしました。

  • 正直、GoogleカレンダーとSlackの公式連携が使えるのであればそっちを使ったほうがはるかにラクです。(2022/12/24追記)なんとGoogle Calendar for Team Eventsが停止になるとのこと・・・。
    image.png
    image.png

  • 過去の記事ですが今なら需要がある気がするので、2年前の記事ですが、Google Apps Script Advent Calendar 2022 17日目の投稿として再掲します。

コード

Githubを参照してください。
https://github.com/iamakawa/GCal-GAS-Slack

実現した機能

予定追加、予定変更/削除、まもなく開始(10分前)に、

  • タイトル
  • 場所
  • 備考
    を通知します。

実現できていない機能

  • 繰り返し予定(events IDの発行ルールが複雑でエラーになりやすいです)
  • 毎週/毎日の予定通知(コードをいじればなんとでもなりますが)

Googleスプレッドシート

image.png

予定追加

image.png

予定変更

image.png

まもなく開始

image.png

コードについての解説

初期設定(Slack、Googleカレンダー)

GoogleCalendarIDを取得

連携したいGoogleカレンダーを選択→「設定と共有」から「カレンダーID」を取得してください。
image.png

Slack Webhookを取得

詳細な設定方法については割愛。

コード

取得したコードは下記のように設定します。


var properties = PropertiesService.getScriptProperties();
var calendarId = properties.getProperty("calendarID");
var url = properties.getProperty("slackWebhook");

Googleカレンダーの差分情報取得・カレンダー変更通知

  • Googleカレンダーの現在の全カレンダー情報をpropertiesに保存
  • onCalendarEditをGoogleカレンダーの編集をhookに起動
  • 同じように全カレンダー情報を取得し、その差分→つまり、今回編集分のカレンダー情報 を取得

コード(抜粋)

//カレンダー初期起動用(差分取得用)
function initialSync() {
  var events = Calendar.Events.list(calendarId,
   {
     timeMin: Moment.moment().toISOString(),
     timeMax: Moment.moment().add(3, 'months').local().toISOString(),
   });
  var nextSyncToken = events.nextSyncToken;
  Logger.log("Sync:"+ nextSyncToken);
  properties.setProperty("nextSyncToken", nextSyncToken);
}

//カレンダー更新時に、前回差分から取得できるように
function onCalendarEdit(e) {  
  var nextSyncToken = properties.getProperty("nextSyncToken");
  Logger.log("pre_Sync:"+nextSyncToken);
  var events = Calendar.Events.list(calendarId, {
    syncToken: nextSyncToken,
  });

//以下割愛

GASのトリガー設定

カレンダーのオーナーのメールアドレスには、「カレンダーID」を入力する。
image.png

「まもなく開始」機能の実装

  • 取得したスプレッドシートから、15分以内に開始する予定をSlackに投稿する
  • 投稿されたあとはリストから削除し、通知しない

コード

function noticeCalendarWillStart() {
  var dat = sheet.getDataRange().getValues();
  for(var i=1;i<dat.length;i++){
    var starttime = dat[i][3];
    var diff = Moment.moment(starttime).diff(Moment.moment(), "minutes")
    
    if(diff < 15) {
      var des_row = findRow(dat[i][0], CALENDAR_ID);
      if(des_row != 0){
        sendToSlack("まもなく開始する予定があります", getCalendarInfo(des_row),"#e8bccc");
        deleteCalendarInfo(des_row)
      }
      else {
        sendToSlack("予定通知でエラー発生", dat[i],"#e80055");
      }   
    }
  }
}

GASのトリガー設定

image.png

毎日のリスト更新

  • Googleスプレッドシートの定期的な更新を行う。(定期な予定を取得するため)

コード


function setCalendarList() {
  /* 時刻情報取得 */
  var date_0 = Moment.moment().local().startOf('day');
  var getRangeDate_0 = Moment.moment().add(3, 'months').local().startOf('day');
  var myCal =CalendarApp.getCalendarById(calendarId);
  var myEvents = myCal.getEvents(date_0.toDate(),getRangeDate_0.toDate());
  var to_row = 2;
  
  sheet.getRange(2,1,100).clear();
  myEvents.forEach(function(evt){
     sheet.getRange(to_row, 1).setValue(evt.getId());  
     sheet.getRange(to_row, 2).setValue(evt.getTitle());  
     sheet.getRange(to_row, 3).setValue(evt.getLocation());  
     sheet.getRange(to_row, 4).setValue(evt.getStartTime());  
     sheet.getRange(to_row, 5).setValue(evt.getEndTime());
     sheet.getRange(to_row, 6).setValue(evt.getDescription().replace("<br>","\n").replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'').replace(/&nbsp;/g,''));
     to_row++;    
  });
}

GASのトリガー設定

image.png

実行

GoogleCalendarAPIの設定

image.png

Momentライブラリの追加

Googleスプレッドシートでの時間計算には、Momentライブラリを使用しています。
詳細はhttps://tonari-it.com/gas-moment-js-moment/ を参照してください。
image.png

実行時に、GASからGoogleカレンダーが編集できるように設定

image.png
image.png
image.png

実行時、詳細を表示→安全ではないページに移動
image.png

おわりに

感想

  • Googleカレンダーの変更差分取得は非常にミニマムな設計がされており、半日くらいうまく設定ができず苦戦した。

残課題

  • CalendarApp.getCalendarByIdとCalendarを併用しており、同じ機能を呼び出しているのに別のAPIを使用しており、可読性に欠ける。

参考リンク

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3