はじめに
この記事はプログラミングほぼ未経験だった僕が、プログラミングを学び、アウトプットとして作ったLINEBOTに関するものです。
初めての投稿なので、改善点やアドバイス、感想などあればコメントお願いします。
目次
1.作ろうと思った経緯
2.機能説明
3.予定追加・一週間の予定確認の実際のトーク画面
4.ソースコード
5.今後の改善点
6.参考にした記事
1.作ろうと思った経緯
就職活動がかなり忙しくなってきたときに、
使用頻度が高いLINEで予定追加と確認ができれば楽だな、と思ったからです。
また、inteeリアルカレッジのポートフォリオとして作成しました!
2.機能説明
リッチメニューの「予定追加」を押すと予定を追加。
「一週間の予定確認」を押すと、Googleカレンダーに記入されている一週間の予定を日付・時間帯・予定名でリスト化して返す。
「最初からやり直し」を押すと、予定追加を中断し、最初からやり直せる。
3.予定追加・一週間の予定確認の実際のトーク画面
##予定追加
###予定日→開始時刻→終了時刻→予定名→確認 の順に登録する。
一週間の予定確認
4.ソースコード
チャネルアクセストークン、スプレッドシートのID、Googleアカウントはご自身の物を使用されてください!
var CHANNEL_ACCESS_TOKEN = "チャネルアクセストークン";
var ERROR_SHEET_ID = "スプレッドシートのID";
//日付、時刻のフォーマット設定
var dateExp = /(\d{2})\/(\d{2})\s(\d{2}):(\d{2})/;
var dayExp = /(\d+)[\/月](\d+)/;
var hourMinExp = /(\d+)[:時](\d+)*/;
function doPost(e) {
try {
handleMessage(e);
} catch(error) {
logging("ToCalendarFromLineBot");
logging(JSON.stringify(e));
logging(JSON.stringify(error));
var replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
reply(replyToken, error.message);
}
}
function logging(str) {
var sheet = SpreadsheetApp.openById("スプレッドシートのID").getActiveSheet();
var ts = new Date().toLocaleString("japanese", {timeZone: "Asia/Osaka"});
sheet.appendRow([ts, str]);
}
function handleMessage(e) {
var replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
var lineType = JSON.parse(e.postData.contents).events[0].type
if (typeof replyToken === "undefined" || lineType === "follow") {
return;
}
var userMessage = JSON.parse(e.postData.contents).events[0].message.text;
var cache = CacheService.getScriptCache();
var type = cache.get("type");
if (type === null) {
if (userMessage === "予定追加") {
cache.put("type", 1);
reply(replyToken, "予定日を教えてください!\n「06/17, 6月17日」などの形式なら大丈夫です!");
} else if (userMessage === "一週間の予定確認") {
reply(replyToken, getEventss());
} else {
reply(replyToken, "リッチメニューの「予定追加」で予定追加を、「一週間の予定確認」で一週間の予定参照ができるので気軽に話しかけてくださいね!");
}
} else {
if (userMessage === "キャンセル") {
cache.remove("type");
reply(replyToken, "キャンセルしました!");
return;
}
switch(type) {
case "1":
// 予定日
var [matched, month, day] = userMessage.match(dayExp); //dayexpの型に合う文字列を取り出す。
cache.put("type", 2);
cache.put("month", month);
cache.put("day", day);
reply(replyToken, month + "/" + day + "ですね! 次に開始時刻を教えてください。「13:00, 13時, 13:20, 13時20分」などの形式なら大丈夫です!");
break;
case "2":
// 開始時刻
var [matched, startHour, startMin] = userMessage.match(hourMinExp);
cache.put("type", 3);
cache.put("start_hour", startHour);
if (startMin == null) startMin = "00";
cache.put("start_min", startMin);
reply(replyToken, startHour + ":" + startMin + "ですね! 次に終了時刻を教えてください。");
break;
case "3":
// 終了時刻
var [matched, endHour, endMin] = userMessage.match(hourMinExp);
cache.put("type", 4);
cache.put("end_hour", endHour);
if (endMin == null) endMin = "00";
cache.put("end_min", endMin);
reply(replyToken, endHour + ":" + endMin + "ですね! 最後に予定名を教えてください!");
break;
case "4":
// 予定名
cache.put("type", 5);
cache.put("title", userMessage);
var [title, startDate, endDate] = createEventData(cache);
reply(replyToken, toEventFormat(title, startDate, endDate) + "\nで間違いないでしょうか? よろしければ「はい」をやり直す場合は「いいえ」をお願いいたします!");
break;
case "5":
// 確認の回答がはい or いいえ
cache.remove("type");
if (userMessage === "はい") {
var [title, startDate, endDate] = createEventData(cache);
CalendarApp.getDefaultCalendar().createEvent(title, startDate, endDate);
reply(replyToken, "追加しました!\nお疲れ様でした!");
} else {
reply(replyToken, "お手数ですがもう一度お願いいたします!");
}
break;
default:
reply(replyToken, "申し訳ありません。\n形式に誤りがないか確認してみて、なければ「キャンセル」で予定入力をキャンセルすることができるので、そちらを試していただけますか?");
break;
}
}
}
function createEventData(cache) {
var year = new Date().getFullYear();
var title = cache.get("title");
var startDate = new Date(year, cache.get("month") - 1, cache.get("day"), cache.get("start_hour"), cache.get("start_min"));
var endDate = new Date(year, cache.get("month") - 1, cache.get("day"), cache.get("end_hour"), cache.get("end_min"));
return [title, startDate, endDate];
}
function toEventFormat(title, startDate, endDate) {
var start = Utilities.formatDate(startDate, "JST", "MM/dd HH:mm");
var end = Utilities.formatDate(endDate, "JST", "MM/dd HH:mm");
var str = title + ": " + start + " ~ " + end;
return str;
}
function reply(replyToken, message) {
var url = "https://api.line.me/v2/bot/message/reply";
UrlFetchApp.fetch(url, {
"headers": {
"Content-Type": "application/json; charset=UTF-8",
"Authorization": "Bearer " + CHANNEL_ACCESS_TOKEN,
},
"method": "post",
"payload": JSON.stringify({
"replyToken": replyToken,
"messages": [{
"type": "text",
"text": message,
}],
}),
});
return ContentService.createTextOutput(JSON.stringify({"content": "post ok"})).setMimeType(ContentService.MimeType.JSON);
}
function get_Calendar() {
var arrCals=[];
arrCals.push(CalendarApp.getCalendarById('使いたいGoogleカレンダーのアカウントのメールアドレス'));
return arrCals;
}
//1週間の予定を取得するメインの関数
function get_Week_Schedule(){
var arrCals = get_Calendar();
var dateNow = new Date();
var date = new Date();
var strBody ='';
var tmpBody ='';
var strIntro = "おつかれさまです。\n1週間の予定です。\n" ;
for (var j = 1; j < 7 ; j++ ){
date.setDate(dateNow.getDate()+j);
for (var i = 0 ; i < arrCals.length ; i++){
tmpBody = tmpBody + getEvents(arrCals[i],date);
}
if (tmpBody){
strBody = strBody + date.getDate() + '日\n' + tmpBody;
}
tmpBody = '';
}
return (strIntro + strBody);
}
//予定を取得する関数
function getEvents(Cals,getDate){
var arrEvents = Cals.getEventsForDay(getDate);//カレンダーの予定取得
var strEvents ='';
for (var i=0; i<arrEvents.length; i++){
var strTitle = arrEvents[i].getTitle();
var strStart = _HHmm(arrEvents[i].getStartTime());
var strEnd = _HHmm(arrEvents[i].getEndTime());
if (strStart == strEnd){
strEvents = strEvents + '終日イベント:' + strTitle + '\n';
}else{
strEvents = strEvents + strStart + '~' + strEnd+ ':' + strTitle + '\n';
}
}
return strEvents;
}
//予定確認時の関数
function getEventss() {
var events = CalendarApp.getDefaultCalendar().getEventsForDay(new Date());
var body;
if (events.length === 0) {
body = "今週の予定はありません!";
return body;
} else {
body = get_Week_Schedule();
return body;
}
}
function toHHmm(date){
return Utilities.formatDate(date, "JST", "HH:mm");
}
function _HHmm(str){
return Utilities.formatDate(str,'JST','HH:mm');
}
5.今後の改善点
-
ソースコードに書いたアカウントでしかGoogleカレンダーと連携できない。
→LINEトーク画面でアカウント切り替え・追加できるようにすればよいかも?
→また、個人で使うほかに、組織内共通のアカウントで使うとよいかもしれない。 -
一週間の予定確認をする際に、月を表示できるようにしたら見やすい。
-
予定追加の際、開始・終了時刻が24:00を超えた場合の処理
→入力し直せるようにする。 -
予定を削除する機能を付ける。
-
前日の夜や当日の朝に予定を連絡するリマインド機能を付ける。
-
今年の予定しか登録できない。
6.参考にした記事
①GAS上で一週間の予定確認する関数について書かれた記事
https://cyuraharuto.com/gas-googlecalender-week-get/
②Googleカレンダーと連携して予定追加・一日の予定確認をするLINEBOTの記事
https://qiita.com/gawawa124/items/384496ac31fac531f1f9
③リッチメニュー作成について書かれた記事
https://qiita.com/bow_arrow/items/32ac5d2b4c67bd0c1dc2
④タイムゾーン変更方法について
https://stabucky.com/wp/archives/13825
④については、自分が躓いたので、載せてます。