http.HandleFunc("/gamerBotReceiveMsg", receiveMsg)
接著來寫 receiveMsg 函式的內容吧:
sign := r.Header.Get("X-Baha-Data-Signature")
body, _ := ioutil.ReadAll(r.Body)
if sign == hmacSign(body, appSecret) {
fmt.Println("Message received: ", string(body))
} else {
fmt.Println("Fake request.")
}
為了方便看 code,我把計算 HMAC-SHA1 的過程獨立寫成一個函式 hmacSign 了:
func hmacSign(str []byte, key string) string {
h := sha1.New()
io.WriteString(h, string(str))
mac := hmac.New(sha1.New, []byte(key))
mac.Write([]byte(str))
return fmt.Sprintf("sha1=%x", mac.Sum(nil))
}
因為巴哈傳來的 X-Baha-Data-Signature 開頭還會有一個「sha1=」,所以計算出校驗值以後要再補上。
ListenAndServe 的步驟我就不贅述,做到這步的話 code 會長這樣:範例程式碼。
千萬別單純複製貼上就想拿去跑啊,範例程式碼裡面的 appSecret 是我隨便亂打的,這要改成你機器人的 App Secret 內容。
儲存好 code 以後,再回剛剛的 command 畫面執行指令:
heroku create upktest --buildpack heroku/go
upktest 這個位置填的是 App 名字,可以自己取,把它改成你想取的名字吧,這會影響到之後你 app 的網域名稱。
像我執行完以後,我的 App 位置就會在 https://upktest.herokuapp.com/,你也可以直接開 Heroku 網站的控制台查看 App 的相關資訊,但如果你想要把 code 上傳到 Heroku 的主機,就一定要用 command 執行 git 來把程式碼推上去。
如何把程式碼推上去呢?依序執行下列三條指令:
git add .
git commit -m "ver01"
git push heroku master
ver01 這個地方可以隨便填。等它跑完,至少出現 https://upktest.herokuapp.com/ deployed to Heroku 之類的內容,你的程式就差不多生效了。這時候你可以另外開一個 command 視窗,一樣在專案資料夾裡執行指令:
heroku logs --tail
就可以從遠端即時看到你 App 的 console 內容。
請注意,之後如果你要修改程式的話,每次修改完、存檔以後都要再執行一次上面三條 git 的指令。
https://upktest.herokuapp.com/gamerBotReceiveMsg
名字一樣只是舉例,請把 upktest 改為你的 App 名字。這裡的 gamerBotReceiveMsg 就是剛剛在 code 裡面談到可以自己任意取名的 route 位置了。
接著開啟哈哈姆特,對你的機器人隨便傳個訊息:
再來看看遠端的 console,成功了!不用幾行程式碼就可以接收到機器人的訊息,有沒有很簡單?你已經串接好一半了。再來想如何把 JSON 解碼、處理、判斷,做出你理想中的機器人,那就是你的事。
接下來談談傳送訊息吧。回去看看我剛才貼的架構圖就會知道,如果要傳送訊息的話就要傳給哈哈姆特指定好的 API,這個 API 的位置是:
https://us-central1-hahamut-8888.cloudfunctions.net/messagePush?access_token=5f566f5a14a3de1b6608
當然這裡的 access_token 要改成自己機器人的 Access Token,這樣哈哈姆特傳送訊息的 API 才能知道是你的機器人想傳訊息(而不是其他人的機器人)。
由機器人傳出去的訊息也要用 JSON 的格式,如下:
{
"recipient": {
"id": "<sender_id>"
},
"message": {
"type": "text",
"text": "你好我是機器人"
}
}
傳送貼圖也是傳到這個 API,但格式是像這樣:
{
"recipient": {
"id": "<sender_id>"
},
"message": {
"type": "sticker",
"sticker_group": "13",
"sticker_id": "06"
}
}
以上格式表示了「向 <sender_id> 這個巴哈帳號傳送第 13 組的第 6 張貼圖」,貼圖的編號資訊可以在哈哈姆特不 EY 的機器人開發者後台看到,不在列表上的貼圖就不能傳了。
要解析從哈哈姆特傳來的 JSON 原始訊息會麻煩一些,因為以 Golang 來說,還需要另外寫 struct 定義出這個 JSON 的結構,然後再把整段原始訊息 unmarshal,所以佛心的豬腳就乾脆幫你寫完整個 struct,連同傳送訊息、傳送貼圖的函式也都寫好了:範例在這裡。
傳送訊息:sendMessage(0, "傳送對象", "訊息內容")
傳送貼圖:sendMessage(1, "傳送對象", "貼圖組編號,貼圖編號")
至少上面這個範例已經具有了「如果傳『你好』給機器人,機器人就會回應『你好我是機器人』;如果傳其他訊息給機器人,機器人就會回應問號貼圖」的功能。
根於這樣的基礎,你就可以輕易地設定一些指令來讓使用者控制機器人了。
想讓機器人傳送圖片就比較麻煩。你需要讓程式去開啟圖片檔案,然後再把圖片的二進位資料連同其他資訊,用 multipart 的方式傳到站方設的傳送圖片專用 API:
https://us-central1-hahamut-8888.cloudfunctions.net/ImgmessagePush?access_token=5f566f5a14a3de1b6608
我也初步簡化了,只要 sendImg("傳送對象", "檔案路徑") 就可以傳圖片:
寫好的範例程式碼:這裡。
其中讀取圖片檔案跟上傳的步驟,來源是在這裡。
若想進階一點的話,可以再把機器人往外嵌更多東西,例如我目前寫的機器人就往外連了一個 MySQL 伺服器來存資料,又嵌了 Dialogflow 用語意分析來處理使用者傳的文字意思,還做了個功能是可以提供使用者目前水桶狀態資訊的服務,架構就變成這樣:
(註:本人實際並未受到水桶處分,僅為隨意挑選一巴友帳號作為查詢測試樣本)
所以,只要你的想像力豐富的話,機器人不只可以依照你設定的規則來應答,還可以叫他幫你查股票,甚至幫你推薦股票呢。有了這種 Webhook 的架構,能做的事情就很多。
以上就是豬腳最近寫哈哈姆特不 EY 機器人的心得分享,希望這篇文章可以幫想要寫機器人的開發者們減輕一些負擔,至少不用一直碰壁。
感謝你的觀看,我是豬腳,我們下次見~
本文縮圖來源:哈哈姆特不 EY 官方機器人桃子 BOT 大圖