程式開發

把 LINE Notify 變成匿名提問箱!(下)

上一篇把後端寫到一半,是因為我覺得切前後端兩部分寫會太不平衡,加上我想睡覺了(主因)。現在,就來把這項功能正式完工吧!在這一篇文章我打算扯去 Ajax,所以說不定還會有第三部分,但目前我是寫上和下篇啦~
在完成後端部分,我們只需要將兩個串起來就可以了。doGet 函數會接收 GET 請求,並將參數放到 parameter 中。我們依序處理驗證與轉送後可以得出這樣的 Code:


function doGet(e) {
  var result;
  var isHuman = verify(e.parameter['token']);
 
  if (isHuman[0]) {
    var sendToLine = forward(e.parameter['message']);
 
    if (sendToLine[0]) {
      result = {
        success: true
      };
    } else {
      result = {
        success: false,
        error: 'LINE-Notify Failed: ' + sendToLine[1]
      }
    }
   
  } else {
    result = {
      success: false,
      error: 'reCaptcha Failed: ' + isHuman[1]
    };
  }
  return ContentService.createTextOutput(JSON.stringify(result));
}

然後就可以發布為服務了,我們會獲得一個網址。(我很懶得重拍,所以直接抓別文章的 XD)

而在前端部分,我們需要做到的事有:

  1. 載入 reCaptcha 
  2. 透過 Ajax傳送到後端
  3. 處理返回結果

載入 reCaptcha 的部分,我們需要把 token 存起來,用於後續發送時使用。


<script src="https://www.google.com/recaptcha/api.js?render={你的 reCaptcha 認證金鑰}"></script>
<script>
let token

grecaptcha.ready(function() {
grecaptcha.execute('<你的 reCaptcha 認證金鑰>', {action: 'LIME'}).then(function(t) {
token = t
})
})
</script>

(action 部分是我後來才發現的東西,但因為感覺沒差,就不回頭修改了)
Ajax 的部分,我們將運用 mini-xhr。網址是方才取得的,而欄位則是上篇所規畫好的,這邊接受 message 和一個 callback,便於後來使用。


<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/miniXhr.js"></script>;
<script>
    function sendToServer (message, token, callback) {
        miniXhr('https://........../exec?token=' / 你的 Apps Script 網址 / + token + '&message' + message, {}
        ).then(callback)
    }
</script>

完成後,我們開始處理能看見的部分(?),最基本就是一個輸入框(Input Text 或 Textarea)和一個按鈕,而我還會另外做一個顯示狀態的窗格。


<input type="text" id="message">
<button type="button" onclick="submit()">送出</button>
<div id="result"></div>

在上面我們對按鈕加入一個 Click 事件,指向 submit 函數。接下來就開始撰寫 submit 函數,message 就是單純讀取欄位,callback 則是將回傳狀態寫回狀態資訊窗格中。

<script>
  function submit () {
    let message = document.getElementById('message').value
    sendToServer(message, token, data => {
      data = JSON.parse(data)
      if (data.success) {
        document.getElementById('result').innerHTML = '成功'
      } else {
        document.getElementById('result').innerHTML = '失敗:' + data.error
      }
    })
  }
</script>

這樣就大功告成了,其餘美化的部分就交給各位了。(#)

這篇文章有許多處還滿隨便的,因為就是在一個很隨便的心情下寫的,如果想認真學習 JavaScript 的請…別模仿過度。
另外如果想可以一次多發,可以執行 grecaptcha.execute 處來重新獲得 token(token 只能用一次)。

閱讀全文
程式開發

把 LINE Notify 變成匿名提問箱!(上)

到底為什麼這個網站會充斥著 LINE Notify 嗎?我還真希望是業配,但可惜不是。在滿久以前我做了一個 LINE 我自己的小接口,最近莫名其妙被挖出來了,發現好像有人會感興趣。那位挖出來的捧油把它變成一個匿名提問箱,好像是不錯的主題?

這個小專案其實滿簡單,就是轉發請求到 LINE Notify 的 API 上,基於安全理由,不太可能讓使用者直接騷擾(?)LINE Notify,畢竟應該沒人想看到滿滿的垃圾訊息吧。

那麼要做的事情就很明顯了:

  • 前端接受訊息,傳遞至後端
  • 後端進行驗證,轉發到 LINE Notify

這邊驗證將使用 reCaptcha,首先先新增一個網站,進入 reCaptcha 首頁後右上方會有 Admin Console,如果沒有建立過就會自動跳轉,但已有建立過則需要按下新增。

在網域中填入靜態網頁存放的地方,如果是使用 GitHub Pages 可填入 github.io 或 <你的帳號>.github.io 等等。

完成後就會得到兩組鑰匙,先存放到其他地方。

接著到 Google Drive,新增一個 Google Apps Script。(如果不知道該怎麼新增請參考這篇文章)我們將會有兩個主要邏輯:驗證與轉送。

驗證部分,參考 reCaptcha Reference,我們可以知道要呼叫 siteverify,傳遞 Secret 和 Response 兩個參數,其中 Secret 是上一步的密鑰,Response 是使用者傳送的驗證代碼。
接著他會回傳一份 JSON,其中我們只需要 success 就夠了,但如果出問題,提供錯誤訊息或許也不錯。
製作 HTTP 請求的部分,我們可以應用 Google Apps Script 的 UrlFetchApp 服務。
綜合上述,參考 UrlFetchApp 後可以寫出這樣的 Code:


function verify(response) {
var secret = '' / 請放入你的 reCaptcha 認證金鑰 /;

var recaptcha = UrlFetchApp.fetch('https://www.google.com/recaptcha/api/siteverify', {
method: 'POST',
payload: 'secret=' + secret + '&response=' + response
}).getContentText();

var digested = JSON.parse(recaptcha);
if (digested['success']) {
return [true];
} else {
return [false, digested['error-codes']];
}
}

這樣只要傳入使用者的 Response,就可以獲得包含結果與錯誤的陣列。接著進行轉送,參考 LINE Notify 文件可以知道會需要 Token,進入個人頁面並發行個人權杖,並將權杖紀錄。

接著按照文件,我們需要的是傳送 Message(如果有想增加其他功能可自行類推),需要的是組成一個請求,Header 包含權杖,並傳遞 message 參數。而伺服器會透過 HTTP 狀態表明結果。結合以上,可以寫出這樣的 Code:


function forward(message) {
var token = '' / 放入你的 LINE Notify 權杖 /;

var notify = UrlFetchApp.fetch('https://notify-api.line.me/api/notify', {
'method': 'post',
'headers': {
'Authorization': 'Bearer '+ token
},
'payload': 'message=' + message
});

switch(notify.getResponseCode()) {
case 200:
return [true];
case 400:
return [false, 'Unauthorized'];
case 401:
return [false, 'Invalid Accesstoken'];
case 500:
return [false, 'Server Side Error'];
default:
return [false, 'Unexcepted Failed'];
}
}

如此一來,後端兩個主要邏輯就完成了,下一篇我們將把兩個邏輯組合,並製作前端。
下篇:https://limaois.me/archives/51

閱讀全文
程式開發

用 Google App Script 和 LINE Notify 製作一個每日通知的機器人‧外傳

前幾天就有考慮把它拓展成訂閱式的,今天目標告一段落,就回來動工。 很快地建立另一個 App,包含 storeToken、getTokens、send 以及處理請求的 doGet。

本記在這:https://limaois.me/archives/55
 研究了一下 LINE-Notify,首先會要求提供 Callback URL,接著將使用者導引到

https://notify-bot.line.me/oauth/authorize
?response_type=code
&client_id=your_client_id
&redirecturi=yourcallback_url
&scope=notify
&state=a_hash

其中 your_redirect_url 要與 Callback URL 一致,your_client_id 則登錄後會取得,state 用於防止 CSRF(跨站偽造請求),不過想不太到要怎麼驗證,所以姑且略過之。
當使用者進到這個網址會出現選擇聊天室的介面,選擇後會再把使用者導引到

http(s)://your_redirect_url
?code=user’s_code
?state=a_hash

得到 user’s_code 後,再發送 POST 請求到

https://notify-bot.line.me/oauth/token

並附帶

grant_type=authorization_code
redirect_uri=your_callback_url
client_id=your_client_id
client_secret=your_client_secret
code=user’s_code 

便會回傳 access_token,然後依照上篇處理即可。

閱讀全文
程式開發

用 Google App Script 和 LINE Notify 製作一個每日通知的機器人

  最近 Packt 的每日免費書回來了,便想用 LINE Notify 做一個自動通知當日免費書的工具,而為了一個小工具去 Heroku 之類的開專案又似乎有點小題大作,另外是我的額度也不夠讓我這樣隨便花了,所以就把目標轉移到功能較為簡單的 Google App Script。

  首先分析這個機器人的預期行為:

  1. 每日上午八點的時候到 Packt Free Learning – Free Programming eBook 取得新書的名稱和消息。
  2. 將取得的資料透過 LINE Notify 傳送到手機。

由於規模不大,將在這篇文一次講完(可能會有點長)。Google App Script 的這部分,參考文件是這份。首先開啟 Google Drive,新增一個 Google Apps Script,如果你沒用過需要到商店連結應用程式。

(對我是複製貼上別篇文章的。)
因為這次只有一個 Function,就用他預設的名稱,接著取得網頁資料,並且取出書本標題和介紹。

第二行讀取網頁,第三行將 HTML 中 > 後、 < 前的空白移除以方便操作,然後第四行透過切離 title"><h2> 後到 </h2> 的文字取得標題,再取得標題後的第一個 <div> 內容作為介紹。如果想看看取的甚麼內容,可以加入 Logger.log(title) 和 Logger.log(info),就可以在檢視中的紀錄看到了。
取得完畢後,必須發送到 LINE Notify,參考的文件是這份。進入個人頁面並發行個人權杖,並將權杖紀錄。

接著回到 Google App Script,對 LINE Notify 的 API 發送請求,注意必須使用 POST,並加入名為 Authorization 的 Header,內容是 Bearer <Token>。

這樣就完成啦!你可以執行看看,應該會在 LINE 收到今日的書。接著設定每日上午八點發作,進入編輯中的現有專案的啟動程序。

如此一來他便應該要在早上八點到九點這個時間通知新的書,本篇到此結束。
外傳:https://limaois.me/archives/54

閱讀全文