--- title: LineBot tags: Python, LineBot, Lesson description: --- # LineBot :::info 這邊是以 Django 為框架來做 LineBot,也可以用 flask 來寫,基本上寫法都是一樣,只是建置的方式不一樣 **本日目標:在當前專案底下建一個 ECHO BOT** ::: ## OUTLINE [TOC] ## 建立 LINE Developers 帳號、專案 * 點進 [網站](https://developers.line.biz/en/) 登入 Line 帳號 ![](https://i.imgur.com/sxeRpQ8.png) * 按 Providers 旁邊的 Create ![](https://i.imgur.com/vWNGT0g.png) * 選擇建立 Messaging API channel,然後開始把該填的填一填 ![](https://i.imgur.com/1kPyCTf.png) :::success 建立好了就可以暫時放置 ::: ## 建立環境 :::info 打開之前的專案,進入虛擬環境 ::: ### 套件安裝 ```bash= $ pip install line-bot-sdk ``` ### 新增 app * 第一行是自己的專案名稱(反正就是進到有 `manage.py` 的資料夾) * 第二行建立一個 linebot 的 app(要取什麼名稱看個人) ```bash= $ cd locallibrary $ manage.py startapp line_bot ``` ### 將 app 加入專案 * 打開 `settings.py` ```python= INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'catalog', # 新增 'line_bot', ] ``` ### 設定連接到 line bot 的 token :::info Channel secret 在 LINE Developers 的 Basic settings 內 Channel access token 在 LINE Developers 的 Messaging API 的最底下 ::: #### 1. 超不安全的方法 * `settings.py` 加入 ```python= # LINE BOT CHANNEL_SECRET = "你的 CHANNEL_SECRET" CHANNEL_ACCESS_TOKEN = "你的 CHANNEL_ACCESS_TOKEN" ``` #### 2. 安全一點的方法 * 建立一個 `.txt` 檔寫入以下內容後,將整個檔名(包含副檔名)改為 `.env` * 跟 `manage.py` 放同一層資料夾 ``` CHANNEL_SECRET=你的 CHANNEL_SECRET CHANNEL_ACCESS_TOKEN=你的 CHANNEL_ACCESS_TOKEN ``` * 安裝套件 ```bash= $ pip install python-dotenv ``` * `settings.py` 加入 ```python= # LINE BOT from dotenv import load_dotenv load_dotenv(encoding="utf-8") CHANNEL_SECRET = os.getenv('CHANNEL_SECRET') CHANNEL_ACCESS_TOKEN = os.getenv('CHANNEL_ACCESS_TOKEN') ``` :::info 安全一點在於到時候上傳伺服器(heroku)時可以忽略 `.env` 檔 ::: ### 網址設定 * 在 line_bot 底下建立 `urls.py`,寫入內容 ```python= from django.urls import path from . import views urlpatterns = [ path('callback', views.callback) ] ``` * 在 locallibrary 底下的 `urls.py`,寫入內容 ```python= from django.urls import path, re_path, include urlpatterns = [ ... # 新增 line bot path('linebot/', include('line_bot.urls')), ] ``` :::info 網址結構: https://<domain name>/linebot/callback * 專案主程式網址 linebot/ * 加上 app 的 urls.py 檔案中所定義的網址「callback」 ::: #### 測試網址有無問題 * 打開 line_bot 中的 `views.py` ```python= from django.http import HttpResponse def callback(request): return HttpResponse("test!!") ``` * runserver,有字就是有連上 ## 功能開發 * 打開 line_bot 中的 `views.py` ```python= import logging from django.conf import settings from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse, HttpResponseBadRequest from linebot import LineBotApi, WebhookHandler from linebot.exceptions import InvalidSignatureError from linebot.models import * line_bot_api = LineBotApi(settings.CHANNEL_ACCESS_TOKEN) handler = WebhookHandler(settings.CHANNEL_SECRET) logger = logging.getLogger("django") ``` ```python= @csrf_exempt def callback(request): if request.method == "POST": # get X-Line-Signature header value signature = request.headers["X-Line-Signature"] # get request body as text body = request.body.decode() # logger.info("Request body: " + body) # handle webhook body try: handler.handle(body, signature) except InvalidSignatureError: print("Invalid signature. Please check your channel access token/channel secret.") return HttpResponseBadRequest() return HttpResponse("OK") else: return HttpResponseBadRequest() @handler.add(event=MessageEvent, message=TextMessage) def handl_message(event): line_bot_api.reply_message( reply_token=event.reply_token, messages=TextSendMessage(text=event.message.text), ) ``` * runserver ## 本機部屬 ### ngrok * 下載 [ngrok](https://ngrok.com/download) * 專案目錄下解壓縮(`manage.py` 那層),並執行 exe 檔 * 註冊帳號取得 [token](https://dashboard.ngrok.com/get-started/your-authtoken) * 終端機執行 ```bash= $ ngrok authtoken <YOUR_AUTH_TOKEN> ``` * 取得臨時網址(port 要跟 runserver 的一樣) ```bash= $ ngrok http <port> ``` * 複製 https 那行 ![](https://i.imgur.com/sZu0FkF.png) * `settings.py`修改 ```python= ALLOWED_HOSTS = ['你的網址'] ``` ### LINE developer 設定 * Messaging API 中的 Webhook 處貼上網址,並開啟 Webhook ![](https://i.imgur.com/6hmkm23.png) * LINE Official Account features 點進 Auto-reply messages 右邊的 Edit,關閉自動回應訊息 ![](https://i.imgur.com/cxTgaK5.png) * 測試 LINE BOT 能不能用 * 如果 ngrok 執行出現問題,把整個 ngrok 關閉 ```bash= $ taskkill /f /im ngrok.exe ``` :::warning ngrok 網址每次產生的都不一樣,因此如果把 ngrok 關掉重開的話所以有要改網址的地方都要記得改掉 ::: ## LAB > 能回應特定訊息的 BOT,範例如下: > * 傳:今天吃什麼 回:隨便 > * 傳:今天天氣真好 回:好個頭 > * 要搞成接歌或是誇誇 BOT 也是可以啦 ## 參考資料 * https://github.com/jhanjhenyi/django-line-echobot