## 前言
由於Line Notify過期,突然想到用Line BOT本來就能達成相近的目的
因此嘗試實作,並搭配網路上的Google行事曆教學
# 前置作業
## Line Bot
[申請網站Line](https://account.line.biz/login?redirectUri=https%3A%2F%2Fdevelopers.line.biz%2Fconsole%2Fchannel%2F2007174340%2Fmessaging-api%3Fstatus%3Dsuccess) Line Developers
建立provider跟Messaging API(Line BOT)



帳號不用認證也沒關係
進入管理Line帳號頁面=>設定=>右側的Messaging API

啟用Messaging API =>選擇自己建立的provider=>同意=>確定=>確定
產生的<font color="#f00">**Channel secret**</font>會用到

回到Line Developers(非Line BOT管理頁面)
重新整理並從Channel找到自己的BOT

選擇後切到Messaging API

滑到最下方有個Channel access token=>按下Issue

產生新的<font color="#f00">**Channel access token**</font>會用到
## Google 行事曆
左側我的日曆
選擇自己想要通知的項目
設定和共用

整合日曆內可以看到自己的<font color="#f00">**日曆ID**</font>,也會用到

## Apps Script

從Google試算表中建立Apps Script=>建立新的試算表=>擴充功能=>Apps Script
試算表不能關掉(關掉後你的Apps Script也會關掉)

程式碼
```
/**
* 取得接下來一小時內的日曆事件
* @returns {GoogleAppsScript.Calendar.CalendarEvent[]} 接下來一小時的日曆事件列表
*/
function getCalendarEventsForNextHour() {
var now = new Date(); // 獲取現在的時間
var oneHourLater = new Date(now.getTime() + 60 * 60 * 1000); // 計算一小時後的時間(60分鐘 * 60秒 * 1000毫秒)
var events = calendar.getEvents(now, oneHourLater); // 獲取在此時間範圍內的所有事件
return events;
}
// LINE Bot 的認證資訊
var CHANNEL_ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('CHANNEL_ACCESS_TOKEN'); // 從腳本屬性中獲取 LINE Channel 訪問令牌
// Google Calendar API 設定
var calendar = CalendarApp.getCalendarById(PropertiesService.getScriptProperties().getProperty('CALENDAR_ID')); // 從腳本屬性中獲取要使用的日曆 ID
/**
* 獲取已發送提醒的記錄
* @returns {Array} 已發送提醒的記錄列表
*/
function getSentReminders() {
var sentRemindersData = PropertiesService.getScriptProperties().getProperty('sentRemindersData');
return sentRemindersData ? JSON.parse(sentRemindersData) : []; // 如果有資料則解析,否則返回空陣列
}
/**
* 保存已發送提醒的記錄
* @param {Array} reminders - 提醒記錄列表
*/
function saveSentReminders(reminders) {
PropertiesService.getScriptProperties().setProperty('sentRemindersData', JSON.stringify(reminders));
}
/**
* 檢查並發送日曆事件提醒
* 此函數應該被設置為定時觸發器來定期執行
*/
function sendCalendarReminders() {
var events = getCalendarEventsForNextHour(); // 獲取接下來一小時內的事件
var sentReminders = getSentReminders(); // 獲取已發送的提醒記錄
var now = new Date().getTime(); // 當前時間戳
var twoHoursAgo = now - 2 * 60 * 60 * 1000; // 兩小時前的時間戳
// 清理過期的提醒記錄(兩小時前發送的)
sentReminders = sentReminders.filter(function(reminder) {
return reminder.sentTime > twoHoursAgo;
});
var remindersToSend = []; // 待發送的提醒列表
events.forEach(function(event) {
var eventId = event.getId(); // 獲取事件 ID
var eventStartTime = event.getStartTime().getTime(); // 獲取事件開始時間的時間戳
var oneHourBefore = eventStartTime - 60 * 60 * 1000; // 計算事件開始前一小時的時間戳
// 檢查是否已發送過提醒
var alreadySent = sentReminders.some(function(reminder) {
return reminder.eventId === eventId;
});
// 檢查事件是否即將在一小時內開始,且尚未發送提醒
if (eventStartTime > now && !alreadySent) {
// 添加到待發送提醒列表
remindersToSend.push({
eventId: eventId,
title: event.getTitle(),
startTime: eventStartTime
});
// 記錄此提醒已發送
sentReminders.push({ eventId: eventId, sentTime: now });
}
});
// 如果有需要發送的提醒
if (remindersToSend.length > 0) {
// 格式化每個提醒訊息
var reminderMessages = remindersToSend.map(function(reminder) {
return '活動 "' + reminder.title + '" 將於 ' +
Utilities.formatDate(new Date(reminder.startTime), Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm") +
' 開始!';
});
// 組合完整的提醒訊息
var message = '行事曆提醒:\n\n' + reminderMessages.join('\n\n');
// 使用廣播功能發送提醒給所有用戶
var result = broadcastToRecentInteractions(message);
Logger.log('已發送行事曆提醒: ' + result); // 記錄到日誌
}
// 保存更新後的提醒記錄
saveSentReminders(sentReminders);
}
/**
* 向所有用戶廣播 LINE 訊息
* @param {string} message - 要廣播的訊息內容
* @returns {string} 廣播結果訊息
*/
function broadcastToRecentInteractions(message) {
var url = 'https://api.line.me/v2/bot/message/broadcast'; // LINE 廣播 API 端點
var headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN // 設置認證標頭
};
var payload = {
'messages': [{
'type': 'text',
'text': message || '這是一則廣播訊息!' // 如果未提供訊息內容,則使用預設訊息
}]
};
var options = {
'method': 'post',
'headers': headers,
'payload': JSON.stringify(payload) // 將負載轉換為 JSON 字串
};
var response = UrlFetchApp.fetch(url, options); // 發送 HTTP 請求到 LINE API
Logger.log('廣播訊息已成功發送!'); // 記錄訊息到日誌
return '廣播訊息已成功發送!';
}
/**
* 測試廣播功能
* @returns {string} 廣播結果訊息
*/
function testBroadcast() {
var message = "這是一則測試廣播訊息,發送時間: " + new Date().toLocaleString();
var result = broadcastToRecentInteractions(message);
Logger.log("廣播測試結果: " + result); // 記錄到日誌
return result;
}
```
專案設定=>指令碼屬性=>編輯指令碼屬性=>新增指令碼屬性

CALENDAR_ID(建議用自己的信箱,能不能用他人的信箱待驗證)
CHANNEL_ACCESS_TOKEN
CHANNEL_SECRET
觸發條件=>新增觸發條件

## Note!!
如果之後如下發現開不起來的話(Apps Script)得用無痕視窗,刪除cookie沒用

[參考教學](https://weijutu.github.io/2020/04/13/javascript/calendar-line-notify/)