質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.64%

【GAS】Googleカレンダーの予定をLINEに通知

受付中

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 425

ryu01212008

score 24

実現したいこと

①Googleカレンダーの予定をLINEに通知
②Google Todoのリストをカレンダーの通知と一緒にLINEに通知したい

①でうまくいっていないく、
別の方法で②も一緒に試しましたが、それぞれ壁にぶち当たりまして困っています。
皆様のお力を貸してください。
情報が不足していたら何なりと仰ってください。

何卒、宜しくお願い致します。

①の該当のソースコード

function sendTodaySchedule() {
  var accessToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
  // 引数により取得する日付を変えられるようにしたいので、
  // 今日から何日後かを渡すようにします。
  var message = getMessage(0);
  var options =
   {
     'method'  : 'post'
    ,'payload' : 'message=' + message
    ,'headers' : {'Authorization' : 'Bearer '+ accessToken}
    ,muteHttpExceptions:true
   };
  UrlFetchApp.fetch('https://notify-api.line.me/api/notify',options);
}

/**
* メッセージ内容取得
* @param {number} 今日起算の日数
* @return {string} メッセージ内容
*/
function getMessage(prm) {
  const week = ['日','月','火','水','木','金','土'];
  var cal = CalendarApp.getCalendarById('xxxxxxxxx@gmail.com');
  var date = new Date();
  var strBody = '';
  var strHeader = '';
  // タイトル
  if ( prm==0 ) {
    strHeader = '今日 ';
  } else if ( prm==1 ) {
    strHeader = '明日 ';
  } 
  date = new Date(date.getYear(),date.getMonth(),date.getDate() + prm);
  strHeader += Utilities.formatDate(date,'JST','yyyy/M/d')
                + '(' +week[date.getDay()] + ') の予定\n';
  // 内容
  strBody = getEvents(cal,date);
  if ( _isNull(strBody) ) strBody = '予定はありません。';
  return strHeader + strBody;
}

/**
* カレンダーイベント内容取得
* @param {object} カレンダー
* @param {date} 日付
* @return {string} イベント内容
*/
function getEvents(prmCal,prmDate) {
  var strEvents = '';
  var strStart = '';
  var strEnd = '';
  var strTime = '';
  var strLocation = '';
  var strDescription = '';
  if ( !_isNull(prmCal) ) {
     var arrEvents = prmCal.getEventsForDay(new Date(prmDate));
     for (var i=0; i<arrEvents.length; i++) {
       if ( !_isNull(strEvents) ) strEvents += '\n';
       strStart = _HHmm(arrEvents[i].getStartTime());
       strEnd = _HHmm(arrEvents[i].getEndTime());
       if ( strStart===strEnd ) {
         strTime = '終日';
       } else {
         strTime = strStart + '~' + strEnd;
       }
       strEvents += '・' + strTime + '【' + arrEvents[i].getTitle() + '】';
       strLocation = arrEvents[i].getLocation();
       strDescription = arrEvents[i].getDescription();
       if ( !_isNull(strLocation) ) strEvents += '\n 場所:' + strLocation;
       if ( !_isNull(strDescription) ) strEvents += '\n 説明:' + strDescription;
     }
  }
  return strEvents;
}
/**
* 時刻フォーマット
*/
function _HHmm(str){
  return Utilities.formatDate(str,'JST','HH:mm');
}
/**
* NULL判定
* @param {object} 判定対象
* @return {bool} NULLの場合TRUE
*/
function _isNull(prm) {
  if ( prm=='' || prm===null || prm===undefined ) {
    return true;
  } else {
    return false;
  }
}

function sendTomorrowSchedule() {
  var accessToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
  // getMessage()の引数を1にするだけです。
  // 明後日なら3、1週間後なら7にすれば該当するイベント情報を取得できます。
  var message = getMessage(1);
  var options =
   {
     'method'  : 'post'
    ,'payload' : 'message=' + message
    ,'headers' : {'Authorization' : 'Bearer '+ accessToken}
    ,muteHttpExceptions:true
   };
  UrlFetchApp.fetch('https://notify-api.line.me/api/notify',options);
}

①の設定項目

・ Gメールのアドレスの設置
・ LINEトークンを下記手順で設定
 ファイル > プロジェクトのプロパティ > スクリプトのプロパティ > 行を追加 > LINEトークンを入力 > 保存

①で発生している問題

下記のエラーのみが発生しているようです。
これを解決する方法を教えてください。

メソッド formatDate((class),string,string) が見つかりません。(行 79、ファイル「コード」)

別の方法で試したコード

下記のコードを利用して、①と②を一緒に実現しようと思って試しましたが、こちらもうまくいきませんでした。

var lineToken = " ライントークンID ";

function myFunction() {
  var calendars = CalendarApp.getAllCalendars();
  var text = Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + "\n";

 //Calender
  for(i in calendars) {
    var calendar = calendars[i];
    var events = calendar.getEventsForDay(new Date());

    for(j in events) {
      var event = events[j];
      var title = event.getTitle();
      var start = toTime(event.getStartTime());
      var end = toTime(event.getEndTime());
      text += start + ' - ' + end + " " + title + '\n';
    }

    if( events.length > 0 ) {
      text += "\n";
    }
  }
  //sendToLine(text);

  //Todo List
  var myTaskLists = getTaskLists();
  var myTasks       = getTasks( myTaskLists[0].id );
  var msg = "[Todo List]\n";

  Logger.log( myTasks );
  /*myTask[0].titleの配列を変更することで他のリストに変更することができる。*/
  Logger.log( myTasks[0].title ); // = "first todo"

  for(i in myTasks){
    msg += myTasks[i].title + "\n";
    }
  text +=msg;
  sendToLine(text);
}

function sendToLine(text){
  var token = lineToken;
  var options =
   {
     "method"  : "post",
     "payload" : "message=" + text,
     "headers" : {"Authorization" : "Bearer "+ token}

   };
   UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}

function toTime(str){
  return Utilities.formatDate(str, 'JST', 'HH:mm');
}

function getTaskLists() {
  var taskLists = Tasks.Tasklists.list().getItems();
  if (!taskLists) {
    return [];
  }
  return taskLists.map(function(taskList) {
    return {
      id: taskList.getId(),
      name: taskList.getTitle()
    };
  });
}

function getTasks(taskListId) {
  var tasks = Tasks.Tasks.list(taskListId).getItems();
  if (!tasks) {
    return [];
  }
  return tasks.map(function(task) {
    return {
      id: task.getId(),
      title: task.getTitle(),
      notes: task.getNotes(),
      completed: Boolean(task.getCompleted())
    };
  }).filter(function(task) {
    return task.title;
  });
}


こちらのエラーは下記のように出てしまいました。

https://notify-api.line.me のリクエストに失敗しました(エラー: 401)。サーバー応答の一部: {"status":401,"message":"Invalid access token"}(応答の全文を見るには muteHttpExceptions オプションを使用してください)(行 51、ファイル「コード」)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

①のエラー行数的に_HHmmですかね?
だとするとarrEvents[i].getStartTime()arrEvents[i].getEndTime()Date以外が返っているような感じですかね。

Logger.log(str);
return Utilities.formatDate(str, 'JST', 'HH:mm');


上記ログを追加して、エラーが出る直前のstrの内容を確認してみてください。


②は、トークンエラーなので、冒頭の

var lineToken = " ライントークンID ";


このライントークンIDが間違ってるのかなぁ。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/19 13:51

    ①のstrの内容はundefinedになっていました。

    キャンセル

  • 2019/09/19 16:31

    undefinedになることがあるのですね。
    私の方でも様々試してみましたが、undefinedになることが再現できませんでした。

    下記のあたりで原因になっているカレンダーのイベントを特定してみてください。

    Logger.log(arrEvents[i].getTitle());
    strStart = _HHmm(arrEvents[i].getStartTime());
    strEnd = _HHmm(arrEvents[i].getEndTime());

    キャンセル

0

①の該当のソースコード

-  var accessToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');

+  var properties = PropertiesService.getScriptProperties();
+  properties.setProperty("LINE_TOKEN", "xxxxxx");
+  var accessToken = properties.getProperty("LINE_TOKEN");

試してみたところ、上記の変更のみで実際に動作しました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/19 06:04

    すみません、回答が雑だったので補足します。
    > "message":"Invalid access token
    と表示されていたので、accessTokenに正常に値が入っていないことが推察されました。そのため、回答のコードにより値を定義し、動作を確認しました。

    なお、オブジェクトに値が入っているかは
    ```
    Logger.log(accessToken)
    ```
    にて確認が取れますのでご参考までに。

    キャンセル

  • 2019/09/19 06:18

    properties.setProperty("LINE_TOKEN", "xxxxxx");
    このxxxxxxはなにを入れれば良いのでしょうか?

    キャンセル

  • 2019/09/19 06:36

    https://notify-bot.line.me/my/ より取得した、40桁くらいのLINEトークン文字列です

    キャンセル

  • 2019/09/19 09:05

    この変更は全くの無意味です。
    実践しないでくださいね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる