ryotatake blog

Webエンジニア

GASでTimeTreeの今日の予定をLINEに通知する

先日TimeTree(タイムツリー)でAPIを使って予定の取得ができるようになりました。

カレンダーシェアアプリ「TimeTree」の予定取得API公開、Alexaに対応:CodeZine(コードジン)

私は普段TimeTreeを使っているので、Google Apps Scriptを使ってTimeTreeの今日の予定をLINEに送るようにしてみました。

準備

TimeTreeとLINE Notifyのパーソナルアクセストークンを取得します。

TimeTree API ドキュメント - TimeTree Developer Platform

[超簡単]LINE notify を使ってみる - Qiita

Google Apps Scriptのプロジェクトを作成した後、これらのトークンをスクリプトプロパティに保存します。それぞれプロパティ名をtimetree_personal_access_tokenline_notify_access_tokenとします。

また、予定を取得したいTimeTreeのカレンダー名もプロパティ名をcalendar_nameとしてスクリプトプロパティに保存しておきます(今のところ一つのカレンダーの予定だけ取得できるようなコードになっています)。

GAS|プロジェクト(スクリプト)のプロパティに情報を保存する|非エンジニアのための「Google Apps Script」|カットボス|note

通知用スクリプト

以下のスクリプトをエディタに貼り付けます。

var calendar_name = PropertiesService.getScriptProperties().getProperty("calendar_name");
var weekday = ["日", "月", "火", "水", "木", "金", "土"];

// メインの処理
function notifyTodayEvents() {
  var todayEvents = JSON.parse(timetreeGetUpcomingEventsByName(calendar_name)).data;
  var message = "今日の予定だよ!\n\n" + createMessage(todayEvents);

  sendMessageToLine(message);
}

function createMessage(events) {
  var message = '';
  var eventsSize = events.length;

  if (eventsSize === 0) {
    return message += "予定はないよ"
  }

  events.forEach(function(event, index) {
    var allDay = event.attributes.all_day;
    var title = event.attributes.title;
    var startAt = formatDate(new Date(event.attributes.start_at), allDay);
    var endAt = formatDate(new Date(event.attributes.end_at), allDay);

    message += startAt + ' - ' + endAt + "\n" + title;

    if (index < eventsSize - 1) message += "\n\n";
  });

  return message;
}

function formatDate(date, allDay) {
  if (allDay) {
    return Utilities.formatDate(date, 'JST', 'MM/dd(' + weekday[date.getDay()] + ')');
  } else {
    return Utilities.formatDate(date, 'JST', 'MM/dd(' + weekday[date.getDay()] + ') HH:mm');
  }
}

// TimeTree用の処理
function timetreeGetUpcomingEventsByName(name) {
  var id = timetreeGetCalendarIdByName(name);
  return timetreeGetUpcomingEvents(id);
}

function timetreeGetUpcomingEvents(id) {
  var url = 'https://timetreeapis.com/calendars/' + id + '/upcoming_events?timezone=Asia/Tokyo';
  var method = 'GET'; 
  var payload = '';
  return timetreeAPI(url, method, payload);
}

function timetreeGetCalendars() {
  var url = 'https://timetreeapis.com/calendars';
  var method = 'GET';
  var payload = '';
  return timetreeAPI(url, method, payload);
}

function timetreeGetCalendarIdByName(name) {
  var response = timetreeGetCalendars();
  var calendars = JSON.parse(response).data;

  var calendar = calendars.filter(function(data){
    return data.attributes.name.toString() === name;
  });
  return calendar[0].id;
}

function timetreeAPI(url, method, payload) {
  var accessToken = PropertiesService.getScriptProperties().getProperty('timetree_personal_access_token');
  var headers = {
    'Authorization': 'Bearer '+ accessToken
  };
  var options = {
    'method': method,
    'headers': headers,
    'payload': payload
  };

  return UrlFetchApp.fetch(url, options);
}

// LINE Notify用の処理
function sendMessageToLine(message) {
  var url = 'https://notify-api.line.me/api/notify';
  var payload = "message=" + message;
  lineNotifyAPI(url, 'post', payload);
}

function lineNotifyAPI(url, method, payload){
  var accessToken = PropertiesService.getScriptProperties().getProperty('line_notify_access_token');
  var headers = {
   'Authorization': 'Bearer '+ accessToken
  };
  var options = {
     "method": method,
     "headers": headers,
     "payload": payload
  };

  return UrlFetchApp.fetch(url, options);
}

毎朝通知するように設定する

LINEグループに通知が送られる時間を設定します。

毎朝送られてほしいので、次のように設定しました。

f:id:ryotatake:20200126235918p:plain

LINEでの表示

毎朝以下のように通知されます。

f:id:ryotatake:20200127001428j:plain

まとめ

簡易的ですが、初めてでも3時間程度で作成できて、Google Apps Scriptすごいなと感じました。

コードはGithubでも管理しているので、随時更新していきます。

github.com

参考

家族のGoogleカレンダーの予定をLINEに通知する - Qiita

[WIP] GASでTimeTree APIを触るサンプル|TOKIMETSUの刃

TimeTree API ドキュメント - TimeTree Developer Platform

Reference overview  |  Apps Script  |  Google Developers