系統特色
- 自動化提醒:定時檢查行程,智能發送通知
- 進度追蹤:即時計算當日行程完成百分比
- 整合地圖:一鍵查看景點位置和交通路線
- 多元查詢:支援今日行程、指定日期、景點詳情
- Flex Message:美觀的 LINE 訊息設計
系統架構
Google Apps Script
↓
┌─────────────────┐
│ 定時執行器 │ → 檢查行程時間 → 發送通知
└─────────────────┘
↓
┌─────────────────┐
│ Google Sheets │ ← 行程資料管理
└─────────────────┘
↓
┌─────────────────┐
│ LINE Bot API │ ← 即時通知發送
└─────────────────┘
專案結構
travel-bot/
├── Code.gs # 主要 Bot 邏輯
├── push.gs # 定時推送功能
└── 行程表.xlsx # Google Sheets 資料
核心技術實作
1. 定時檢查與通知系統
function trigger(){
var now = new Date();
var nowHours = now.getHours();
var nowMinutes = now.getMinutes();
var nowTotalMinutes = nowHours * 60 + nowMinutes;
// 取得今天的日期並格式化
var today = new Date();
var formattedToday = Utilities.formatDate(today, "GMT+08:00", "yyyy/MM/dd");
for(var i = 1; i <= LastRow - 1; i++){
// 解析日期字符串
var date = new Date(sheet.getRange(i+1,1).getValue());
// 轉換日期格式
var formattedDate = Utilities.formatDate(date, "GMT+08:00", "yyyy/MM/dd");
// 比較兩個日期是否相同
var isSameDate = (formattedDate === formattedToday);
if(isSameDate){
var cellValue = sheet.getRange(i+1,2).getValue();
var formattedTime = Utilities.formatDate(cellValue, "GMT+08:00", "HH:mm");
var timeParts = formattedTime.split(':');
var cellHours = parseInt(timeParts[0]);
var cellMinutes = parseInt(timeParts[1]);
var cellTotalMinutes = cellHours * 60 + cellMinutes;
// 計算時間差
var timeDiff = cellTotalMinutes - nowTotalMinutes;
if(timeDiff <= 60 && sheet.getRange(i+1,5).getValue() == "未傳送"){
sheet.getRange(i+1,5).setValue("已傳送");
var no = sheet.getRange(i+1,4).getValue();
if(no.includes("A")){
attractions(no);
}
else if(no.includes("T")){
transportation(no);
}
else if(no.includes("S")){
stay(no);
}
}
}
}
}
2. 行程進度計算
// 計算今日行程進度
var now = new Date();
var startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate());
var endOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
// 計算從今天開始到現在的毫秒數
var elapsed = now - startOfDay;
// 計算一天的總毫秒數
var total = endOfDay - startOfDay;
// 計算百分比
var percentage = (elapsed / total) * 100;
3. LINE Bot 訊息處理
function doPost(e) {
var event = JSON.parse(e.postData.contents).events[0];
var userid = event.source.userId;
var profile = client.getProfile(userid);
var name = profile.displayName;
var message = event.message.text;
var timestamp = new Date(event.timestamp);
//log
sheet2.getRange(LastRow2+1,1).setValue(name);
sheet2.getRange(LastRow2+1,2).setValue(message);
sheet2.getRange(LastRow2+1,3).setValue(timestamp);
sheet2.getRange(LastRow2+1,4).setValue(event);
if(message.includes("今日行程")){
// 處理今日行程查詢
sendTodaySchedule(event.replyToken);
}
else if(message.includes("/")){
// 處理指定日期查詢
sendDateSchedule(event.replyToken, message);
}
else if(message.includes("A")){
// 處理景點查詢
sendAttractionInfo(event.replyToken, message);
}
}
4. Flex Message 景點卡片
function attractions(no){
let result_array = [];
var flex_bubble_tmp;
var place = "";
for(let i = 1; i <= LastRowA - 1; i++){
if(sheetA.getRange(i + 1,1).getValue() == no){
place = sheetA.getRange(i+1,2).getValue();
flex_bubble_tmp = {
"type": "bubble",
"direction": "ltr",
"hero": {
"type": "image",
"url": sheetA.getRange(i+1,4).getValue(),
"size": "full",
"aspectRatio": "20:13",
"aspectMode": "cover",
},
"body": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": place,
"weight": "bold",
"size": "xl",
"contents": []
},
{
"type": "box",
"layout": "vertical",
"spacing": "sm",
"margin": "lg",
"contents": [
{
"type": "box",
"layout": "baseline",
"spacing": "sm",
"contents": [
{
"type": "text",
"text": "地址",
"size": "sm",
"color": "#AAAAAA",
"flex": 1,
"contents": []
},
{
"type": "text",
"text": sheetA.getRange(i+1,3).getValue(),
"size": "sm",
"color": "#666666",
"flex": 5,
"wrap": true,
"contents": []
}
]
}
]
}
]
},
"footer": {
"type": "box",
"layout": "vertical",
"flex": 0,
"spacing": "sm",
"contents": [
{
"type": "button",
"action": {
"type": "uri",
"label": "地點介紹",
"uri": sheetA.getRange(i+1,8).getValue()
},
"height": "sm",
"style": "link"
},
{
"type": "button",
"action": {
"type": "uri",
"label": "Map",
"uri": sheetA.getRange(i+1,5).getValue()
},
"height": "sm",
"style": "link"
}
]
}
}
}
}
result_array.push(flex_bubble_tmp);
sendLine(flex_content);
}
系統展示
相關資料
🔗 Google App Script 建立 LINE Bot
📊 完整原始碼 (Google Sheet 建立副本於擴充功能查看 App Script)