3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GASでLINEリマインダーを作る。

Last updated at Posted at 2020-03-04

#GASでLINEリマインダーを作る
##動機
大学サークルの日程調整をよくLINEで行い、リマインドを毎回行うのが面倒で「自動化できたらな」と思っていたので作成に至った。

##目標
####学習の目標
GASの基本をマスター

  • Javascriptの書き方
  • Google Apps Scriptの書き方
  • 動的型付け言語の書き方

####プログラムの目標

  1. 予定の追加(Google Form)
  • 予定の記録(SpreadSheet)
  • 予定の確認(GAS)
  • 予定のリマインド(LINE)

以上を有するLINEBotを作る。

##筆者のスペック

  • 大学の情報系2回生
  • C,C++,Javaを講義で学んだ

記事は、ある程度プログラミングを学んだことのある人向けに。
自分の復習も兼ねて書きます。

#設計
####予定登録
#####トリガー
GASにはトリガー(引き金)と呼ばれる機能があります。
Googleフォームのスクリプトエディタで作成したスクリプトには、イベントのソースを選択に「時間主導型」の他にフォーム「フォームから」という選択肢がありこれを選択するとフォーム送信時にスクリプトを起動させる事ができます。

####1.フォーム作成
通常通り、Google Formを作成していきます。

  • 予定名
  • 場所
  • 予定の説明
  • 終日or時間指定(2つに対応させるためどちらか選択できるようにする)
  • 開始日と終了日(時間指定の分岐は時間も記述)
  • 登録者名(誰が作成したかわかるように)
    その他、念の為メールアドレスを収集しておきます。(事前に断っておきましょう.)

####2.SpreadSheet記録
Google Formを作成すると自動でSpreadSheetが作成されます。

図1.png
実際のスプレッドシートです。
MARK START END は現時点で気にしないでください。(上記のフォームを作成しただけだと作成されません。)

####3.いよいよScriptを書く

yotei_reg(1)
//1               2            3     4      5            6         7         8          9          10      11
//タイムスタンプ	メールアドレス	予定名	場所	予定の説明	イベントの長さ	開始日程	終了日程	開始日程	終了日程	登録者名
// 0              1             2    3     4             5         6         7          8           9       10

function submitForm(e) {
  
  var today=new Date();
  
  var spreadsheet = SpreadsheetApp.openById('/*-スプレッドシートのID-*/');
  var sheet = spreadsheet.getSheetByName('フォームの回答 1');
  var lastrow=sheet.getLastRow();
  
  var ans=[]
  ans=sheet.getRange(lastrow,1,1,11).getValues();
  //終日と指定日の振り分け
  //
  if(ans[0][6]===undefined || ans[0][6]==''){
    ans[0][6]=ans[0][8];
    ans[0][7]=ans[0][9];
  }
  
  
//
//カレンダー登録部
//
  var calendar = CalendarApp.getDefaultCalendar();
  var rtoday=Utilities.formatDate(today, "JST", "yyyy'年'MM'月'dd'日'")
  var option={
    description:ans[0][4]+'登録者:'+ans[0][10]+rtoday+'\n\nRegistered by Google Form',
    location:ans[0][3]
  }
  ans[0][6]=new Date(ans[0][6]);
  ans[0][7]=new Date(ans[0][7]);
  
//Formで登録した人のカレンダーに追加
  calendar.createEvent(ans[0][2],ans[0][6],ans[0][7], option);
  
//LINEメッセージ送信(別関数)
  pushMessage(ans);
}

フォーム起動時の動作は主に、フォームに入力した人自身のGoogleカレンダーに予定を追加することです。
試験的に(思いつき)で実装したものですが、GASでは結構簡単に実装できて驚きました。

pushMessage()は予定が登録された時にLINEに送信します。
pushMessage()関数以下のプログラムを以下に示します。

yotei_reg(2)

///////////////////////////////////////////////////////////////////////////////////////////////////
//LINE送信部////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////

//グローバル関数
var CHANNEL_ACCESS_TOKEN = '/*MessageAPIアクセストークン*/'; 
var USER_ID = '/*送信先UserID*/'; //*2

//タイムスタンプ	メールアドレス	予定名	場所	予定の説明	イベントの長さ	開始日程	終了日程	開始日程	終了日程	登録者名
// 0              1             2    3     4             5         6         7          8           9       10

function pushMessage(e) {
  var msg=''; //本文用変数(とりあえずStringで初期化)


  var date1=Utilities.formatDate(e[0][6] ,"JST", "yyyy'年'MM'月'dd'日'");
  var date2=Utilities.formatDate(e[0][7] ,"JST", "yyyy'年'MM'月'dd'日'");

//終日で1日だけの日程かどうかの判定
//日程の〇月〇日~〇月〇日とするか、◯月◯日のみの表示かを分岐する。
  if(date1!=date2){
    
    msg=''+e[0][2]+'\n'
          +'以下のイベントが登録されました。\n'
          +'【名前】'+e[0][2]+'\n'
          +'【場所】'+e[0][3]+'\n'
          +'【日程】'+ Utilities.formatDate(e[0][6] ,"JST", "MM'月'dd'日'")+'~'+Utilities.formatDate(e[0][7], "JST", "MM'月'dd'日'")+'\n'
          +'【詳細】'+e[0][4]+'\n\n\n'
          +'他の日程は以下から確認できます↓↓↓\n'
          +'/*予定を吐き出すサイトURL*/'
          +'\nGoogle カレンダー追加は以下から\n'
          +RegistURL(e);
    
    
  }else{
    msg=''+e[0][2]+'\n'
          +'以下のイベントが登録されました。\n'
          +'【名前】'+e[0][2]+'\n'
          +'【場所】'+e[0][3]+'\n'
          +'【日程】'+Utilities.formatDate(e[0][6], "JST", "MM'月'dd'日'")+'\n'
          +'【詳細】'+e[0][4]+'\n'
          +'他の日程は以下から確認できます↓↓↓\n'
          +'/*予定を吐き出すURL*/';
          +'\nGoogle カレンダー追加は以下から\n'
          +RegistURL(e);
    
  }
//*1
  var postData = {
    "to": USER_ID, 
    "messages": [{
      "type": "text",
      "text": msg,
    }]
  };

  //共通URL
  var url = "https://api.line.me/v2/bot/message/push";
  var headers = {
    "Content-Type": "application/json",
    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
  };

  var options = {
    "method": "post",
    "headers": headers,
    "payload": JSON.stringify(postData)
  };
  var response = UrlFetchApp.fetch(url, options);
}

*1
以下のサイトを参考にした。
https://qiita.com/ttexan/items/749bed9a60313e51b4c8

*2
UserIDはLINEIDではない。公式アカウントと個別ユーザに紐付いたIDである。
友達登録をしていないユーザには送信できない。

LINE messageAPI利用にはAPIキーの取得と、送信先のUSERIDを取得しておく必要があります。
ユーザを区別する必要が無い場合はSpreadSheetやプログラムに書く必要がなく
postリクエストで送られてきたIDでそのまま返信すれば良いのですが、
サークルの予定なので外部にホイホイ投げるわけにも行かないので、GROUPID(USERID)をPOSTリクエスト受信で予め取得しておき、そこだけに送信するようにしています。

*1のサイトのdoPost(e)を参考にUSERIDをSpreadSheetに記録するようにしました。

LINE MessageAPI側の操作は
https://note.com/data1/n/nc52a54e5a679
を参考に行った。
(ry

###おまけ
Googleカレンダーとせっかく連携できたので、Googleカレンダーにメンバにも予定を追加してほしいと思いながら、共有カレンダーだと自分の予定も見えてしまうので各自でURLで追加してもらうことにした。
googleカレンダーサイトのURLを自動生成できるらしいので、やってみた。

yoteireg(3)

///////////////////////////////////////////////////////////////////////////////////////////////////
//カレンダー作成////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////

//タイムスタンプ	メールアドレス	予定名	場所	予定の説明	イベントの長さ	開始日程	終了日程	開始日程(終日)	終了日程	登録者名
// 0              1             2    3     4             5         6         7          8                9       10
function RegistURL(ans){
  Logger.log(ans[0][6]);
  
  var DateS= new Date(ans[0][6]);
  var DateE= new Date(ans[0][7]);
  
  
  
    if(ans[0][5]=="終日"){
      
    DateE.setDate(DateE.getDate() + 1);  //bag対応(不具合あったら消す)
      
    DateS=Utilities.formatDate(DateS,"JST","yyyyMMdd");
    DateE=Utilities.formatDate(DateE,"JST","yyyyMMdd"); 
      
    }
  
  else{
    DateS=Utilities.formatDate(DateS,"JST","yyyyMMdd'T'HHmmss");
    DateE=Utilities.formatDate(DateE,"JST","yyyyMMdd'T'HHmmss"); 
  }
    
    var text=ans[0][2];
    var location=ans[0][3];
    var details=ans[0][4];
  
  if(location==""){
    location=" ";
  }
   if(details==""){
    details="詳細情報はありません";
  }
    
  return 'https://www.google.com/calendar/event?action=TEMPLATE'+
    '&text='    + encodeURIComponent(text) +
    '&dates='   + DateS + '/' + DateE+
    '&details=' + encodeURIComponent(details) +
    '&location='+ encodeURIComponent(location);
}

*3
以下のサイトを参考にした
https://qiita.com/s-mori/items/24c128e0b0d841036dd8

何故か、終了日程に-1日たされるというバグが有ったので1日加算することで対応しました。

以上で1~3までの機能が出来上がりました。これらをフォーム実行時にトリガーとして実行させます。

4番の解説は、
https://qiita.com/1_s_n/items/f6c02a80b4928bddcc8c
にて紹介しています!

3
4
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
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?