Monday, May 15, 2017

Practice Line Bot

之前就看過Julian大大分享的 Line Bot 心得
所以大概知道Line Messaging API 運作的方式
不過一直都沒想到比較有意思的題目, 所以就沒寫來玩玩看

最近突然想起, 有時候忘了看女兒的聯絡簿時, 都不知道她們最近教了些什麼東西
於是就決定來寫個聯絡簿的通知小幫手

首先由於我比較熟悉的後端框架是node.js , 跟 J大用的 GO 不同
所以還是另外參考了node上的Line bot 教學文章

在 Line Business Center 申請好帳號之後
需要設定Webhook的網址
也就是 Line 會把一些 event 透過 http 發到該網址

首先npm install linebot --save 之後 ,就能安裝node下的linebot 套件
寫了最基本的程式碼後 , 就能監聽收到訊息時的event
(還得上傳上 Heroku 或類似的服務)

let app = express()
const server = require('http').Server(app)
let bot = LINEBot.create({
  channelID,
  channelSecret,
  channelToken
}, server)

bot.on('message', function(event) {
  console.log(event); //把收到訊息的 event 印出來看看
});

app.use(bot.webhook('/webhook'))

能夠知道使用者發了怎樣的訊息 , 就能利用字串比對的方法
來應答各種不同的回覆訊息

但是我準備嘗試的聯絡簿通知幫手 , 並不需要針對使用者的訊息做回應
而是定期的去爬學校的電子聯絡簿網頁 , 然後發現有新的內容時, 就發給所有使用者

所以在event的部分, 我關心的只有哪個 user 或哪個group 加了我的bot
或移除了bot , 我只要在DB維護這個 userId 跟 groupId的清單
每當有新的聯絡簿內容時 , 就發給他們即可

爬蟲的部分, 我就參考上面連結中使用的 js-crawler 跟 cheerio 兩個套件
去處理學校的聯絡簿網址 , 然後再分別拿到聯絡簿內容與當天的日期
如果發現當天沒有聯絡簿內容(可能老師還沒寫或當天是假日) ,就直接結束
如果有看到內容就將該日期與內容與 DB 內最新的內容做比對
如果日期不同, 就刷新 DB的內容, 並將內容發給所有訂閱的userId / groupId
如果日期相同, 就代表該內容已經發出去過了, 可以略過

雖然兩三年前就加減學過node.js , 但一直也沒有一個題目來認真寫
這次這個題目不僅嘗試了 Line的 Messaging API
另外也第一次在 node.js上使用 mongo db 跟爬蟲
而由於這一些非同步的指令在javascript 上都會使用callback來回傳結果
所以初版寫完之後, 馬上就遇上又臭又長的 callback hell

還好這半年有在Android 上使用 RxJava的經驗
在Javascript上學起 Promise 就較為容易上手
於就再花了些時間把code用Promise 重構 (聽說 Async / Await 更潮, 不過就下次吧)