2017年7月4日 星期二

Line Bot 實戰教學

環境
Windows + python

說明

可透過Line 官方推出的API 可以自行開發Line Bot,可以主動進行推撥,或是根據訊息進行相對應的回應

實作

1.申請帳號

參考下列網址申請 & 設定

2.設定ngrok


  • ngrok會給一組隨機的httpxxxxx & https xxxxxx 對應到本機localhost:xxxx 啟的server 
讓外部的網站能夠直接連接到localhost,節省掉開發的時間
主要也是因為在line bot 的設定上,需要給一組webhook url 所以可以透過該方式拿到一組https
入(下圖勾選的地方)
  • 透過linux將下載下來的ngrok最新版本移到/usr/bin,之後在bash輸入ngrok就可使用
$ sudo mv <檔案目前的位置> /usr/bin/

  • 此時使用
$ ngrok
  • 成功進行運作
  • 可透過下列方式指定要運行的port
$ ngrok http 5000

  • 下圖為運行成功後,即可看到ngrok給予的http網址,將網址貼在webhook url即可

3.執行Line API

from flask import Flask, request, abort

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

app = Flask(__name__)

line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')


@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))


if __name__ == "__main__":
    app.run()

4.使用Flake 作為Line bot 的server

  • 該範例會使用flask啟用一個server,當作line bot 的後端server 預設開啟為127.0.0.1:5000
可透過下方設定調整
if __name__ == "__main__":
    app.run(host='0.0.0.0',port=9000, debug=True)

5.碰到的問題,不斷的502 Bad Gateway

  • 當執行官方code後,出現systemExit:1
  • 而連結到網址,會發現ngrok出現該提示
  • 本以為是在jupyter開啟server會出問題,後來轉換成py,透過bash開啟,還是一樣,雖然似乎flask已與ngrok產生連結,但問題依舊存在,導致後面的line bot後續測試無法進行
  • 可能解決狀況
    • 把server架在vm中的docker上面,網路的設定可能有未知的問題
    • 或許可以嘗試在本機的jupyter上操作line bot 看看

6.自創的Line Bot帳號


7.嘗試在本機Jupyter使用falsk

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

結果成功了→斷定果然是因為跑在VM上面的關係

8.在本機操作Lint Bot

按照上方的步驟,結果在驗證時出現下面錯誤,至少錯誤跟之前不一樣QQ
[2017-07-04 14:48:33,233] ERROR in app: Exception on /callback [POST]
Traceback (most recent call last):
  File "C:\Anaconda2\lib\site-packages\flask\app.py", line 1988, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Anaconda2\lib\site-packages\flask\app.py", line 1641, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Anaconda2\lib\site-packages\flask\app.py", line 1544, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Anaconda2\lib\site-packages\flask\app.py", line 1639, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Anaconda2\lib\site-packages\flask\app.py", line 1625, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "<ipython-input-1-c3bc0381a4f5>", line 33, in callback
    handler.handle(body, signature)
  File "C:\Anaconda2\lib\site-packages\linebot\webhook.py", line 227, in handle
    func(event)
  File "<ipython-input-1-c3bc0381a4f5>", line 44, in handle_message
    TextSendMessage(text=event.message.text))
  File "C:\Anaconda2\lib\site-packages\linebot\api.py", line 94, in reply_message
    '/v2/bot/message/reply', data=json.dumps(data), timeout=timeout
  File "C:\Anaconda2\lib\site-packages\linebot\api.py", line 262, in _post
    self.__check_error(response)
  File "C:\Anaconda2\lib\site-packages\linebot\api.py", line 271, in __check_error
    raise LineBotApiError(response.status_code, error)
LineBotApiError: <LineBotApiError [Invalid reply token]>

9.成功運作(雖然出現上面那些錯誤)

但Line Bot卻可以正常運作了

10.設計回應的狀況

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    msg = event.message.text
    print(msg)
    msg = msg.encode('utf-8')
    if msg=="DOG":
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text="汪汪叫"))
    if msg=="ian":
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text="甚麼"))
    if msg=="lillian_hong":
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text="So cute"))
    else:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text=event.message.text))

小技巧

移除packeage

$ sudo apt-get --purge remove ngrok-client

利用docker 直接創建line bot


Python &  Line Bot 實作參考