こんにちは。新卒2年目のrs_chankoです。 LINE Messaging APIとGASの接続方法は先輩がすでに書いていたのでそのまま参考にしました。
上記ができるよう実装します。
それでは実際にメッセージを見てみましょう。 「リマインダー」について何も調べていなかったんですが、 エンジニア中途採用サイト カジュアル面談お申込みフォーム ラクスDevelopers登録フォーム イベント情報 ◆TECH PLAY ◆connpassはじめに
まだまだ慣れない社会人。そんな中で思ったことがあります。
物忘れが酷すぎる。
これは元々分かっていたんですが、最近特に思います。
会社では朝にスケジュールを確認しますが、
プライベートではスケジュールを見る習慣がなく、忘れてしまいがち…。
「そうだ、LINEなら毎日見るし、自分で作っちゃうか。」
そう思い立ち、GASとLINE Messaging APIを使ってリマインダーを作ることになりました。
実装に使った物
実装する機能
リマインダーを実装してみる
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登録\n20200101\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に予定を登録することを忘れないように…。
参考にした記事
ラクスでは、エンジニア・デザイナーの中途採用を積極的に行っております!
ご興味ありましたら是非ご確認をお願いします。
https://career-recruit.rakus.co.jp/career_engineer/
どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。
以下フォームよりお申込みください。
rakus.hubspotpagebuilder.com
https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/
会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください!
techplay.jp
rakus.connpass.com