所以,為什麼要串這個?
嗯…就…方便吧。把 LINE 當成一個輸入介面,資料自動進 Google Sheet。省得手動複製貼上。很多小型應用,像點餐、報名,都這樣玩。 算是一個最基礎的自動化。省時,少出錯。
重點是…免費。用 Google Apps Script (GAS) 當中間的橋樑,幾乎不用錢就能搞定。 不用自己架伺服器。 這點對剛開始玩的人來說,很重要。
開始之前…要準備什麼?
嗯,大概就兩樣東西。一個是 LINE Developers 的帳號,用來生出你的 Bot。另一個當然是 Google 帳號,用來開試算表跟寫 GAS。 聽起來很基本,但少了哪個都不行。
在 LINE Developers Console 裡面,要创建一个 Provider,然後再建一個 Messaging API Channel。 這過程會拿到最重要的東西:Channel Access Token。這東西…就像密碼,要收好。 還有,要把 Webhook URL 的功能打開。 之後要填上我們 GAS 的網址。
中間的橋樑:Google Apps Script (GAS)
好了,重頭戲。打開 Google Drive,開一個新的試算表,然後從「擴充功能」進去,找到「Apps Script」。 這裡就是我們要寫程式的地方。
主要的 function 是 `doPost(e)`。 當 LINE 收到訊息,它會用 HTTP POST 的方式把資料丟到我們指定的 Webhook URL。 這個 `e` 參數,就包含了所有來的資料,是 JSON 格式。
所以第一步,就是解析它。
// 這邊的 Token 要換成你自己的
const CHANNEL_ACCESS_TOKEN = '你的Channel Access Token';
// 還有你的 Google Sheet ID
const SPREADSHEET_ID = '你的Google Sheet ID';
function doPost(e) {
// 解析 LINE 傳來的資料
const event = JSON.parse(e.postData.contents).events;
// 取得回覆用的 token 和使用者訊息
const replyToken = event.replyToken;
const userMessage = event.message.text;
const userId = event.source.userId;
// 寫入 Google Sheet
const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName('工作表1');
sheet.appendRow([new Date(), userId, userMessage]); // 把時間、使用者ID、訊息寫進去
// 準備回覆的訊息
const replyMessage = {
"type": "text",
"text": `收到:「${userMessage}」,已記錄。`
};
// 把訊息回傳給 LINE
replyToLine(replyToken, replyMessage);
}
function replyToLine(replyToken, message) {
const 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': [message]
}),
});
}
這段程式碼很基本。就是收到訊息、寫入試算表、然後回覆使用者說「收到了」。 iT 邦幫忙上有很多類似的基礎教學,大同小異。 早期很多人是這樣開始的。
讓它動起來:部署與串接
寫好程式碼之後,要「部署」。在 GAS 編輯器右上角,點「部署」->「新增部署作業」。類型選「網頁應用程式」,執行身分選「我」,誰可以存取要選「任何人」。
部署完,GAS 會給你一串網址。這就是 Webhook URL。把它複製起來,回到 LINE Developers Console,貼到你 Channel 的「Messaging API」設定裡的「Webhook URL」欄位。 然後按下「Verify」測試一下。
這樣,兩邊就接上了。試著在 LINE Bot 裡傳個訊息,去 Google Sheet 看看,資料應該就會跑出來了。
不只是寫入,還要查詢回覆
單純寫入很無聊。進階一點,是讓 Bot 能查詢試算表裡的資料。 比如說,我輸入一個關鍵字,Bot 就去試算表找對應的資料,然後回覆我。這在做一些簡單的庫存查詢、名單查詢時蠻好用的。
這就需要修改一下 `doPost` 的邏輯了。大概會像這樣:
function doPost(e) {
// ... (前面的解析部分一樣)
const userMessage = event.message.text;
if (userMessage.startsWith('查詢:')) {
// 如果訊息是 "查詢:xxx" 開頭
const keyword = userMessage.split(':');
const searchResult = searchSheet(keyword); // 去試算表查資料
let replyText = '找不到資料。';
if (searchResult) {
replyText = `找到了!資料是:${searchResult}`;
}
replyToLine(event.replyToken, { "type": "text", "text": replyText });
} else {
// 否則就一樣寫入資料
const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName('工作表1');
sheet.appendRow([new Date(), event.source.userId, userMessage]);
replyToLine(event.replyToken, { "type": "text", "text": `收到:「${userMessage}」,已記錄。` });
}
}
function searchSheet(keyword) {
const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName('查詢資料'); // 假設資料在另一個工作表
const data = sheet.getDataRange().getValues(); // 取得所有資料
for (let i = 1; i < data.length; i++) { // 從第二行開始找
if (data[i] == keyword) { // 假設關鍵字在第一欄
return data[i]; // 回傳第二欄的資料
}
}
return null; // 找不到就回傳 null
}
這個 `searchSheet` 函式很陽春,但邏輯就是這樣。讀取整個工作表的資料,然後一筆一筆去比對。資料量一大,效能會變差,但對小應用來說,夠了。 日本有些教學文章也會提到類似的作法,他們那邊也很常用 GAS。
兩種做法,有什麼差?
所以,單向寫入跟雙向查詢,到底差在哪?整理一下。
| 比較項目 | 單純寫入 (Write-Only) | 查詢與回覆 (Read-Write) |
|---|---|---|
| 用途 | 就像個記事本。訂單、回報、簽到…。 | 比較像個助理。查庫存、問進度、找資料。 |
| 程式複雜度 | 很低。一個 `appendRow` 就差不多了。 | 中等。要多寫一個讀取跟搜尋資料的邏輯。 |
| 使用者體驗 | 有點單向…就只是個紀錄工具。 | 互動性好很多,感覺比較「聰明」。 |
| 試算表規劃 | 通常一張表就夠了。 | 可能要分兩張表,一張寫入紀錄,一張當資料庫。 |
常見的坑…跟提醒
實際做的時候,還是會遇到一些鳥事。嗯…
第一個是權限。GAS 要存取 Google Sheet,第一次部署執行時會跳出授權請求,一定要同意。 還有,部署成網頁應用程式時,存取權限要設「任何人」,不然 LINE 的 Webhook 會進不來。
再來是 Token。Channel Access Token 貼錯一個字,或是前後多了空格,都不會動。 而且這東西像密碼,不要亂傳給別人。
還有,Google Sheet 裡的資料格式也要注意。有時候一個多餘的空格或錯誤的資料類型,會讓你的指令跑失敗,然後 Bot 就完全沒反應。 除錯起來有點煩,要有點耐心。
最後,如果你是用免費帳號,LINE Messaging API 和 GAS 都有一些用量限制。 一般小打小鬧是沒差,但如果要做的應用流量很大,就要去研究一下他們的收費方案了。 免得玩到一半被停掉。
差不多就是這樣。你都用 LINE Bot 來自動化什麼事?還是有遇過更麻煩的坑?留言聊聊吧。
