rumors-line-bot 過去傳過訊息implementation - HackMD
文章推薦指數: 80 %
透過push API 或LINE Notify 告知Chatbot 使用者有新回應。
該notification 的call-to-action 就是請使用者打開「查詢過的訊息列表」介面。
更新相對應的新reply 標記( ...
Signin
---
tags:cofacts
---
#rumors-line-bot過去傳過訊息implementation
Pastdiscussion:https://github.com/cofacts/rumors-line-bot/issues/133
##Userstory
-作為**Chatbot使用者**,我希望chatbot可以列出我過去傳過的訊息以及回應的狀況,讓我能在有需要的時候快速翻找。
-作為**Chatbot使用者**,我希望chatbot在我傳過的訊息有新回應的時候可以通知我,讓我接收最新的不同意見。
##Taskbreakdown
1.Chatbotserver需連結至新的資料庫。
此資料庫:
-記錄每名chatbot使用者曾經查詢過哪些article、哪些有新reply
-記錄每名chatbot使用者是否點擊觀看新reply(列表標上「新reply標記」,在使用者點入連結前持續顯示)
-紀錄每名chatbot使用者曾經接收過哪些reply的推播(避免重複推播)
2.Chatbot提供一個「查詢過的訊息列表」
-應使用LIFF實作、透過richmenu觸發
-使用者透過訊息列表點入訊息,需要標記成已讀、消除新reply標記
>「點入訊息」應該無法直接顯示文章頁面,因為這樣無法送出「有用」或「沒用」。
>這可能要回到chatbot顯示或者直接在LIFF另外實作,才能正常讓使用者送出「有用」或者是「沒用」。
-應[重構現有LIFF實作](https://github.com/cofacts/rumors-line-bot/issues/144),套用server-render或clientUIlibrary以利開發
-應讓postbackbutton[往上捲回去的時候仍然可用](https://github.com/cofacts/rumors-line-bot/issues/49)
-~~需在chatbotserver上建立APIserver支援上述列表與操作~~~~server-siderrender,實作CSRFprotection~~不想proxyCofactsAPI也想降低serverload而不走server-siderender,最後作成GraphQLserver+token-basedauthentication
3.需實作一cronjob實作通知,包含:
-透過pushAPI或LINENotify告知Chatbot使用者有新回應。
該notification的call-to-action就是請使用者打開「查詢過的訊息列表」介面。
-更新相對應的新reply標記(標成未讀)
##資料庫:mongodbw/[mLab](https://elements.heroku.com/addons/mongolab)
496MBFree!
##資料表:`UserArticleLinks`
紀錄每個botuser與訊息的羈絆(?)
-`userId`:ID
-`articleId`:ID
-`createdAt`:timestamp使用者傳送此訊息、建立此link的時間
-`lastViewedAt`:timestamp使用者上次查看此訊息~~回應~~的時間。
-2020/7/4討論後追加:`UserArticleLink`create時必會寫入
-~~`lastRepliedAt`:timestampCofacts資料庫內最新回應的時間,cronjob或view時更新~~(不用惹)
-~~`lastPositiveFeedbackRepliedAt`:[timestamp資料庫內評價為正的最新回應時間](https://g0v-slack-archive.g0v.ronny.tw/index/channel/C2PPMRQGP#ts-1584172124.191900),cronjob或view時更新~~(不用惹)
###什麼時候會新增一筆`UserArticleLink`
-傳訊息、資料庫沒有、填寫理由送出後
-傳訊息、選擇一則資料庫訊息,但該訊息沒有回應。
(沒填理由也算)
-傳訊息、選擇一則資料庫訊息,有回應。
:::info
大小估算:
2017~2020年所有userselectsanarticle+confirmsubmitarticle=(270,018+18,369)~=300,000,每個都是一個user-articlelink
粗估每個document500byte
300,000*0.5KB=150MB
:::
##資料表:`UserSettings`
一個LINEbotuser僅會有一筆UserSetting。
-`userId`
-`allowNewReplyUpdate`:使用者是否允許我們推新回應。
預設true
-`newReplyNotifyToken`:若使用者有設定LINENotify,此欄位會存LINEnotify用的token。
預設為空。
:::info
大小估算:
200byte/record*200KLINEbotusers=40MB
:::
###什麼時候會新增一筆`UserSettings`
使用者加chatbot為好友時。
##LINEbotuserflow
1.User點擊richmenu選擇看過去訊息/收到notification並點按
2.LINEbot跳出全頁LIFF,展示文章列表:
-時間
-文章內文節錄(即時從CofactsAPI抓)
-未讀回應數(即時從CofactsAPI抓回應,然後挑出比`lastViewedAt`晚的)+未讀標記
3.點擊文章列表項目,會傳訊息進Cofactschatbot,chatbot列出未讀的回應列表,供使用者點按,進入`CHOOSING_REPLY`state。
若只有一則未讀回應,自動`skipUser`
-此時要更新corresponding`UserArticleLink`的`lastViewedAt`
-此設計讓使用者能下接「有用沒用」回應
-此設計亦方便使用者轉傳回應
###Implementationdetail(2020/5/10)
分成下面三個部分:
####1.LIFF<>chatbotGraphQLAPI的新認證方式
目前LIFF與chatbotGraphQL的authentication,仰賴chatbot在URL上帶有的自產JWT,讓chatbotGraphQL知道目前是哪個`userId`在使用LIFF,以及是哪個searchsession(by`sessionId`)的按鈕。
可是,新功能「過去傳過訊息」LIFF會放在richmenu,URL裡無法帶有會過期的JWT;直接不放exp或設定過久的exp也有些危險,畢竟JWT被chatbotgraphql視為等同密碼的存在,一但leak出去,只要exp沒到,攻擊者就可以一直用該JWT的身份存取API。
因此,我們會新增一種新的authentication:LINEIDtoken法。
1.LIFF透過[liff.getIDToken()](https://developers.line.biz/en/reference/liff/#get-id-token)拿到LINE發的OpenIDIDtoken
2.LIFF發request到chatbotGraphQL時帶有`Authorization:line${IDtoken}`(`line`是為了與JWT使用的`bearer`做出區隔的自訂authenticationtype)
3.chatbotGraphQL收到`line`開頭的authorizationheader之後,使用[verifyIDtoken](https://developers.line.biz/en/reference/social-api/#verify-id-token)API檢查是否正確,並且取用回傳的userID(`sub`)。
以上也是[LINE官方文件](https://developers.line.biz/en/docs/line-login/take-over-session/#transfer-login-session)中提到的作法。
由於LINEIDtoken必須呼叫LINEAPI才能取得,不會有洩漏的機會,所以比目前chatbot自發JWT的機制還更安全。
不過,目前有些功能仍然需要保留「從chatbot傳資料給LIFF回到GraphQL」的機制(如在按鈕上帶當時的`sessionId`,LIFF發request時也必須帶有該`sesionId`回到GraphQL,且此`sessionId`不該在LIFF端被竄改),chatbot自發JWT依然有不可取代的功能在,故會兩者並行。
不過,使用此種方式,會有下面的限制:
-LINEdeveloper的LIFFscope設定必須要勾選openid
![](https://s3-ap-northeast-1.amazonaws.com/g0v-hackmd-images/uploads/upload_25d6cd753775a7d5ea75931110150b7f.png)
-LIFFchannel的provider必須與chatbot(messagingAPI)provider一致,才能共用userid。
-ChatbotGraphQL會多一個與LINEserver發API確認token的工。
####2.LIFF顯示文章列表的機制
LIFF從chatbotGraphQL取回的資料將不會帶有訊息文字之類的訊息。
整個載入流程會是:
1.LIFF透過`myArticleLinks`API取得要顯示的articlelinks
2.LIFF顯示表格、可點選的超連結,文字部分則為loading樣態(類似https://github.com/zalog/placeholder-loading)
另外,顯示時發送GAvisitevent,`utm_source=myArticleLink`,`utm_medium`從URL拿,預設是`richmenu`。
####3.點擊項目時觸發的東西
點擊表內訊息後,送出「📃Seenewrepliesof`https://cofacts.g0v.tw/article/
如此方可將「自己從richmenu點開LIFF」的動作,與「看了pushmessage之後點進來LIFF」,跟其他一般查詢(完全不帶有utm_xxx)分開。
:::
####2020/7/10Update
根據GA文件[trafficsourcedimensions](https://support.google.com/analytics/answer/1033173)與[collectcampaigndata](https://support.google.com/analytics/answer/1033863),`utm_source`應是「導流量到這個網站的來源」、`utm_medium`則是媒介。
對於LIFF裡的網頁來說,source就是顯示URL/button讓使用者進來的流量來源,對這裡來說就是特定的LINEchannel;而媒介則可能是pushmessaage或是richmenu。
因此:
-若從rumors-line-bot的richmenu點按進LIFF:
-來源是Cofacts的bot、媒介是richmenu
-故為`utm_source=rumors-line-bot&utm_medium=richmenu`
-若是收到rumors-line-bot的pushnotification:
-來源是Cofacts的bot、媒介是pushmessage
-故為`utm_source=rumors-line-bot&utm_medium=push`。
`utm_source`
-若收到LINEnotify的更新:
-來源是叫做LINEnotify的channel(預設),媒介也是pushmessage
-故為`utm_source=line-notify&utm_medium=push`
-未來若有其他地方點了可以打開LIFF,那應該要使用新的`utm_source`,並且斟酌打開方式來設計`utm_medium`。
![](https://s3-ap-northeast-1.amazonaws.com/g0v-hackmd-images/uploads/upload_04aaea5b5442f0426b777244a59dd319.png)
##Cronjob邏輯
1.從所有`UserArticleLinks`找出最大的`lastRepliedAt`作為`lastScannedAt`
3.去`ListArticle`API(sortby`lastRepliedAt`)列出所有在`lastScannedAt`以後才新建立、且未刪除的`ArticleReply`
-刪除回應不會被偵測到
-編輯審閱時間:去掉最近12hr的articleReply
5.由2整理出listofunique,updatedarticleids
6.從user<>selectedarticle關聯表,找出要通知的對象(listofuniqueuserstoupdate)
7.比照這些使用者的`UserSettings`,使用multicastAPI&LINENotify告知使用者「之前的訊息有回應囉」導引使用者點開LIFF
8.redisorDB紀錄這次執行的timestamp
×
Signin
Email
Password
Forgotpassword
or
SigninviaFacebook
SigninviaGitHub
SigninviaGoogle
NewtoHackMD?Signup
延伸文章資訊
- 1rumors-line-bot 過去傳過訊息implementation - HackMD
透過push API 或LINE Notify 告知Chatbot 使用者有新回應。該notification 的call-to-action 就是請使用者打開「查詢過的訊息列表」介面。 更新相...
- 2焦糖幫你記ChatBot || Line Bot 實作 - Medium
很陽春的功能,但只要正在使用Line 聊天,隨手和**焦糖幫你記Bot**說句話, ... 想要將某件記事標記為完成-> 再說一遍;焦糖:[message] checked!
- 3請問line bot有辦法tag群組的某人嗎 - Facebook
請問line bot有辦法tag群組的某人嗎? 爬文大多是說明如何get user id,僅看到有人2017年回覆說不能tag人,請問現在有辦法了嗎~? 感謝.
- 4line機器人- 優惠推薦- 2022年10月| 蝦皮購物台灣
【呼in】防翻群機器人line群防翻/群組點名/全體標記/查已讀/抽獎/星座運勢/簽到買斷. $230 - $620 ... LINE社群標記機器人 ... python 與line bot機器...
- 5Lesson 1-LINE官方帳號-聊天機器人與一對一聊天介紹
3. 聊天狀態:可根據標記的狀態管理聊天視窗。 從聊天室可標記「處理完畢」、「待處理」。用戶檔案可將訊息「設定為垃圾訊息」。