using google Appscript to send messages through LINE NOTIFY

URL Link //n.sfs.tw/15222

2021-06-10 20:08:35 By jung

本來是想替縣市端IDP服務建一個檢測機制,不過團隊中有專業工程師已經建好並用telegram接收錯誤訊息了

所以我就想說試試看用LINE NOTIFY來做,在google app script當中,呼叫API來傳送訊息

因為我沒網域沒DNS,只能用curl定時檢測縣市端API服務,再把訊息寄到gmail,再想辦法處理

一開始的構想是,放到google spreadsheet,再做成web發布,

後來想到這樣會有一個問題,我要怎麼定時呈現最新的監測狀況呢?總不能一直生試算表吧

於是想到不如就直接傳給LINE API送到NOTIFY功能去傳訊息,先做到可以接收最新狀況就好

好吧,我這個外行紀錄一下心得==

1. 如何呼叫 LINE API 取得 token

這個網路上有很多教學了

例如:https://ithelp.ithome.com.tw/articles/10233841

這篇更厲害了,用試算表整理資料再傳給API:https://reurl.cc/7rDLo9

基本上就是走 OAuth2 流程

使用app script 操作LINE API 程式範例如下:

function doPost() {
UrlFetchApp.fetch('https://notify-api.line.me/api/notify',
{ 'headers': { 'Authorization': 'Bearer ' + '你的權杖', },
'method': 'post',
'payload': { 'message':message, 'stickerPackageId': '2', 'stickerId': '523' } 

//message可以從別的函式送過來,sticker欄位可傳LINE圖片

}); }

 

2. 處理gmail內容

這裡要用二個函式,一個是呼叫gmail,查詢並取得想要的信件內容,

另一個是用正則表達式處理信件裡的訊息內容

因為我用bash傳的東西會帶一堆\r\n之類的符號,要轉成字串又要合併成陣列

這裡我是參考這篇:

https://www.practicalecommerce.com/capture-gmail-messages-in-a-google-sheet

作者把gmail收到的信件內容整理後寫到試算表,這個以後也可以做別的用途

2-1: 取得目標信件程式範例

function getGmail() {
    const query = "from:roggio@yahoo.com AND subject:Charity Example NOT label:done";

    let threads = GmailApp.search(query);

    let label = GmailApp.getUserLabelByName("done");
    if (!label) {label = GmailApp.createLabel("done")}

    let messages = [];

    threads.forEach(thread => {
        messages.push(thread.getMessages()[0].getPlainBody());
        label.addToThread(thread);
    });

    return messages;
}

不過我發現作者用的查詢語法 AND , NOT 已經無法使用了

https://support.google.com/mail/answer/7190?hl=zh-Hant

試了半天,只能用正向查詢,反向的始終無法達成目標

可以把查詢語法貼到gmail的搜尋列去試試

不過作者的邏輯值得參考,他把信件撈出來,再加上處理過的標籤"done",可以避免重複取得相同的信件

但我怎麼做都沒辦法再加上NOT lable:done的反向查詢條件,只好之後再慢慢想辦法

2-2 處理文字內容

拿到訊息之後,要解析處理需要的文句後再傳送

正則表達式好難啊@@

function parseEmail(message){
    let parsed = message.replace(/,/g,'')
        .replace(/\n*.+:/g,',')
        .replace(/^,/,'')
        .replace(/\n/g,'')
        .split(',');

    let result = [0,1,2,3,4,6].map(index => parsed[index]);

    return result;
}

心得是,那個 /..../g 很重要,作者取的訊息還包括寄件人電郵地址等等欄位,所以他用map再處理索引,真厲害

我拿到的就一個陣列裡塞了好幾封信的訊息,所以就拆開解析而已比較簡單

2-3 傳送訊息

基本上完全我自己寫的大概就這段吧,所以我很弱

function sendMessage() {
let linetoken = "your_LINE_toke"; //放入自己申請得到的金鑰
var mailbody = parseEmail(getGmail());
var message= JSON.stringify(mailbody);//因為拿到陣列物件所以先轉成JSON字串
//mailbody.join(","); //結果字串的join不能用,我真是廢
//這邊卡到一關,如果拿到的是空物件,就不要處理,但是我不知道怎麼檢查空物件的語法
2021-06-30修正
經過團隊工程師提示,發現apps script轉過的message雖然是空的但是它把開頭和結尾的[]都當成字元,變成至少有2個字元@@
所以console.log很重要,用console.log(message.length)才發現的
if( Object.entries(message).length > 2) //改成大於2就成功了Orz
{LineNotify(message,linetoken);}
else {console.log(message);}}
 
大概4醬,做出很弱的成果,
最後用app script的定時執行功能跑而已~
繼續努力Orz