---
title: LineBot
tags: Python, LineBot, Lesson
description:
---
# LineBot
:::info
這邊是以 Django 為框架來做 LineBot,也可以用 flask 來寫,基本上寫法都是一樣,只是建置的方式不一樣
**本日目標:在當前專案底下建一個 ECHO BOT**
:::
## OUTLINE
[TOC]
## 建立 LINE Developers 帳號、專案
* 點進 [網站](https://developers.line.biz/en/) 登入 Line 帳號

* 按 Providers 旁邊的 Create

* 選擇建立 Messaging API channel,然後開始把該填的填一填

:::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 那行

* `settings.py`修改
```python=
ALLOWED_HOSTS = ['你的網址']
```
### LINE developer 設定
* Messaging API 中的 Webhook 處貼上網址,並開啟 Webhook

* LINE Official Account features 點進 Auto-reply messages 右邊的 Edit,關閉自動回應訊息

* 測試 LINE BOT 能不能用
* 如果 ngrok 執行出現問題,把整個 ngrok 關閉
```bash=
$ taskkill /f /im ngrok.exe
```
:::warning
ngrok 網址每次產生的都不一樣,因此如果把 ngrok 關掉重開的話所以有要改網址的地方都要記得改掉
:::
## LAB
> 能回應特定訊息的 BOT,範例如下:
> * 傳:今天吃什麼 回:隨便
> * 傳:今天天氣真好 回:好個頭
> * 要搞成接歌或是誇誇 BOT 也是可以啦
## 參考資料
* https://github.com/jhanjhenyi/django-line-echobot