はじめに 実装に使った物 実装する機能 リマインダーを実装してみる 動作確認! おわりに 参考にした記事 はじめに こんにちは。新卒2年目のrs_chankoです。 まだまだ慣れない社会人。そんな中で思ったことがあります。 物忘れが酷すぎる。 これは元々分かっていたんですが、最近特に思います。 会社では朝にスケジュールを確認しますが、 プライベートではスケジュールを見る習慣がなく、忘れてしまいがち…。 「そうだ、LINEなら毎日見るし、自分で作っちゃうか。」 そう思い立ち、GASとLINE Messaging API を使ってリマインダーを作ることになりました。 実装に使った物 GAS( Google Apps Script) LINE Messaging API Google スプレッドシート 実装する機能 日付と予定を スプレッドシート に登録すると、登録されたデータを参照してメッセージとして送ってくれる (忘れがちなので)7時、12時、19時に今日と明日の予定を教えてくれる リマインダーを実装してみる LINE Messaging API とGASの接続方法は先輩がすでに書いていたのでそのまま参考にしました。 tech-blog.rakus.co.jp しかしそもそも JavaScript もあまりちゃんと書いたことがなく、GASやMessaging API も使ったことがない。 ひとまず練習するか、ということでお試しにオウム返し bot を作ってみました。 note.com これは簡単にできました。 さて、本題です。 ひとまずオウム返しで使った API 周りのコードを元に実装していきます。 //LINEのアクセストークン var channel_access_token = "アクセストークン" ; var headers = { "Content-Type" : "application/json; charset=UTF-8" , "Authorization" : "Bearer " + channel_access_token } ; //返信する function sendLineMessageFromReplyToken(token, replyText) { var url = "https://api.line.me/v2/bot/message/reply" ; var headers = { "Content-Type" : "application/json; charset=UTF-8" , "Authorization" : "Bearer " + channel_access_token } ; var postData = { "replyToken" : token, "messages" : [{ "type" : "text" , "text" : replyText }] } ; var options = { "method" : "POST" , "headers" : headers, "payload" : JSON.stringify(postData) } ; return UrlFetchApp.fetch(url, options); } //指定のuserIdにメッセージを送る function sendLineMessageFromUserId(userId, text) { var url = "https://api.line.me/v2/bot/message/push" ; var postData = { "to" : userId, "messages" : [{ "type" : "text" , "text" : text }] } ; var options = { "method" : "POST" , "headers" : headers, "payload" : JSON.stringify(postData) } ; return UrlFetchApp.fetch(url, options); } 準備が整いました。 それではまず Bot にやってほしいことをまとめます。 予定の登録 予定の削除 登録・削除時の返事 指定時刻の通知 登録されている予定の確認 上記ができるよう実装します。 //8桁日付のフォーマット function formatDateForDisplay (date) { var year = date.substr(0,4); var month = date.substr(4,2); var day = date.substr(6,2); var result = year + "/" + month + "/" + day; return result; } //Date型日付のフォーマット function formatDate (date, format) { format = format.replace( /yyyy/g , date.getFullYear()); format = format.replace( /MM/g , ( '0' + (date.getMonth() + 1)).slice(-2)); format = format.replace( /dd/g , ( '0' + date.getDate()).slice(-2)); return format; } ; //日付をシートに記載する function setDate(date, plan, row) { if (isNaN(date) || String (date).length != 8) { return '日付が正しくありません' ; } setFromRowAndLine(date, row, 0); return setPlan(plan, row); } //予定をシートに記載する function setPlan(plan, row) { setFromRowAndLine(plan, row, 1); return '予定を登録しました。' ; } //トリガー起動で当日と翌日の予定を返す function getTodayAndNextDayMessage() { var date = new Date (); var userId = ’LINEのユーザーID’; //今日の予定を取得 var remindText = getDatePlan(date); //明日の予定を取得 date.setDate(date.getDate() + 1); remindText += " \n " + getDatePlan(date); return sendLineMessageFromUserId(userId, remindText); } //指定日の予定を返す function getDatePlan(date) { if (date instanceof Date ) { date = formatDate(date, 'yyyyMMdd' ); } var day = formatDateForDisplay(date); var remindText = day + " \n " ; var plans = searchPlans(date); for ( var i = 0; i < plans.length; i++) { remindText += getFromRowAndLine( 'webhook' , plans [ i ] ); remindText += " \n " ; } remindText = remindText.slice(0,-1); if (remindText.length === 10) { remindText += " \n 明日は予定がありません。" ; } return remindText; } //受け取ったメッセージに対して返信する function doPost(e) { var webhookData = JSON.parse(e.postData.contents).events [ 0 ] ; var message, replyToken, replyText, userId; message = webhookData.message.text.split( " \n " ); replyToken = webhookData.replyToken; userId = webhookData.source.userId; var processing = message [ 0 ] ; var planDate = message [ 1 ] ; var plan = message [ 2 ] ; var row = getLastRow(); switch (processing) { case '登録' : replyText = setDate(planDate, plan, row); break ; case 'キャンセル' : replyText = cancel(planDate, plan); break ; case '確認' : replyText = planDate === undefined ? getDatePlan( new Date ()) : getDatePlan(planDate); break ; case 'test' : replyText = testSheet(); break ; default : replyText = "予定の登録・キャンセルができます。 \n\n 登録 \n 20200101 \n 予定 \n\n の形式で入力してください。" ; break ; } return sendLineMessageFromReplyToken(replyToken, replyText); } //予定を削除する function cancel(date,plan) { deleteRowOfDateAndPlan(date, plan); return '予定の登録をキャンセルしました。' } //トリガーをセットする function setTrigger() { const time = new Date (); time.setHours(7); time.setMinutes(00); ScriptApp.newTrigger( 'getTodayAndNextDayMessage' ).timeBased().at(time).create(); time.setHours(12); ScriptApp.newTrigger( 'getTodayAndNextDayMessage' ).timeBased().at(time).create(); time.setHours(19); ScriptApp.newTrigger( 'getTodayAndNextDayMessage' ).timeBased().at(time).create(); time.setDate(time.getDate() - 1); //前日の予定を削除する deleteRowOfDate(formatDate(time, 'yyyyMMdd' )); } //トリガーを削除する function delTrigger() { const triggers = ScriptApp.getProjectTriggers(); for ( const trigger of triggers) { if (trigger.getHandlerFunction() == "getTodayAndNextDayMessage" ) { ScriptApp.deleteTrigger(trigger); } } } このコードではLINEで実際に送るメッセージの生成・トリガーのセット・削除をしています。 GASのトリガーって定期実行をすると1時間の範囲内で実行されるらしいんですよね。 ちゃんと同じ時間に送ってほしいので、今回は指定の時間に通知用のメソッドをトリガーとしてセットするメソッドを定期実行にしました。 スプレッドシート とのテキストのやりとりは下記の実装をします。 //スプレッドシート var spreadsheet = SpreadsheetApp.openById( "スプレッドシートのID" ); var sheet = spreadsheet.getSheetByName( 'スプレッドシートのシート名' ); //受け取った日付の予定が記載されている行を返す function searchPlans(date) { var data = sheet.getDataRange().getValues(); var plans = [] ; for ( var i = 0; i < data.length; i++) { if (data [ i ][ 0 ] == date) { plans.push(i + 1); } } return plans; } //列を指定してデータを取得する function getFromRowAndLine(sheetName, row) { var data = sheet.getDataRange().getValues(); return data [ row - 1 ][ 1 ] ; } //列を指定してデータを書き込む function setFromRowAndLine(val, row, line) { sheet.getRange(row + 1, line + 1).setValue(val); } function getLastRow() { return sheet.getLastRow(); } //日付と予定から行を削除する function deleteRowOfDateAndPlan(date, plan) { var lastRow = getLastRow(); for ( var i = 1; i <= lastRow; i++) { if (sheet.getRange(i, 1).getValue() == date && sheet.getRange(i, 2).getValue() == plan) { sheet.deleteRows(i); } } } //指定の日付の行を削除する function deleteRowOfDate(date) { var lastRow = sheet.getDataRange().getLastRow(); for ( var i = 1; i <= lastRow; i++) { if (sheet.getRange(i, 1).getValue() == date) { sheet.deleteRows(i); } } } これで実際に スプレッドシート に日付と予定を書き込んだり、参照することができるようになりました。 こんな感じでLINEから送られてきた予定が書き込まれます。 動作確認! それでは実際にメッセージを見てみましょう。 おおおお! 予定の登録や確認ができ、19時に予定の通知がきました! そんなこんなで完成です。 おわりに 「リマインダー」について何も調べていなかったんですが、 作り終わってから調べたところ、すでにリマインド Bot が存在していました。。。 remine.akira108.com しかし作ってしまったものは作ってしまったので、今後はカスタマイズをして自分の好みのリマインダーを作っていこうと思います。 あとはLINEに予定を登録することを忘れないように…。 参考にした記事 qiita.com tonari-it.com エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com