###### tags: `LineBot`
# LineBot基礎設定教學
### 下載 vs code 和 python
download [vs code](https://code.visualstudio.com/)
download [python3](https://www.python.org/downloads/)
### 打開 [line developer](https://developers.line.biz/en/)
1. 右上角 log in
2. click “create new provider”
3. 隨便輸入 provider name(這是在幫專案分類的感覺 如果有很多專案的話就可以建立在不同的provider下面) 然後按create
4. 點 message API create channel
5. 填資料:app name就是機器的名字(之後可以改名), 選developer trial
6. 該勾的勾一勾就可以create了
### 打開 vs code
:::success
- Ctrl+`(ESC下面那顆) 可以打開terminal
- Ctrl+C 可以終止terminal
- vs code 左上角點 file,把 auto save 打勾,不想要的話就是做完事一定要記得存檔
- $ 的後面就是要輸入terminal的指令,$本身不用輸進去
:::
### 使用terminal裝資料夾
```python=1
$ pip install Django
$ pip install line-bot-sdk
$ pip install virtualenv
$ cd C:/
$ django-admin startproject '專案名稱’
$ cd '專案名稱’
$ python manage.py startapp 'APP名稱'
$ md templates
$ md static
```
> '專案名稱'就是你的整個專案的這個資料夾要叫甚麼名字 不是指你的linebot的那個頻道的名字 像我的就是Mylinebot
> 'App名稱'是Django框架的code會放在這個資料夾裡 然後這個資料夾是存在剛剛那個專案(Mylinebot)裡面 我的的話是叫MylinebotApp
### 改 settings.py(找到相對應的地方進行修改,不是直接複製貼上)
```python
import os
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
LINE_CHANNEL_ACCESS_TOKEN = '你的LINE Channel Access Token' #在line developer的message api裡
LINE_CHANNEL_SECRET = '你的LINE Channel Secret' #在line developer的basic setting裡
SECRET_KEY = 'Django專案的Secret Key'#此處不需更改
ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'APP名稱'#新增自己的APP名稱
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')], #加這個
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
LANGUAGE_CODE = 'zh-hant'
TIME_ZONE = 'Asia/Taipei'
STATIC_URL = '/static/'
STATICILES_DIRS = [
os.path.join(BASE_DIR,'static')
]
```
:::success
- vscode 裡含有 settings.py, urls.py, wsgi.py 的資料夾叫作 <font color="#f00">Mylinebot</font> 之後用紅色標記
- vscode 裡含有 admin.py, apps.py, models.py, view.py 的資料夾叫 <font color="#00f">MylinebotApp</font> 之後用藍色標記
- 每個人的檔案名稱不一樣 遇到就要改成自己的
:::
### 改 urls.py
```python
from django.contrib import admin
from django.urls import path
from MylinebotApp import views #MylinebotApp改成自己藍色的資料夾
urlpatterns = [
path('admin/', admin.site.urls),
path('callback', views.callback),
]
```
### 資料庫遷移初始化
```python=1
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py createsuperuser(創完記住自己的帳號密碼)
$ python manage.py runserver
```
google 網址進入 127.0.0.1:8000/admin
### 使用 ngrok
1. 進入[ngrok官網](https://ngrok.com/) 按download 下載那個zip檔
2. 把ngrok.exe放在Mylinebot資料夾裡(跟manage.py同一層)
3. 在ngrok官網註冊帳號
4. 記住下面這個授權碼

6. 開第二個terminal 輸入以下指令
```python=1
$ ./ngrok authtoken 'ngrok授權碼’
$ ./ngrok http 8000
```
### 啟用 webhook url
1. 回到line developer 把 webhook url 啟用(在message api裡)
2. 把出現的url貼到webhook url(在message api裡) 記得加 /callback


### 改view.py→試試看回聲機器人有沒有成功
```python
from django.shortcuts import render
# Create your views here.
from django.conf import settings
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
from django.views.decorators.csrf import csrf_exempt
from linebot import LineBotApi, WebhookParser
from linebot.exceptions import InvalidSignatureError, LineBotApiError
from linebot.models import MessageEvent, TextSendMessage
line_bot_api = LineBotApi(settings.LINE_CHANNEL_ACCESS_TOKEN)
parser = WebhookParser(settings.LINE_CHANNEL_SECRET)
@csrf_exempt
def callback(request):
if request.method == 'POST':
signature = request.META['HTTP_X_LINE_SIGNATURE']
body = request.body.decode('utf-8')
try:
events = parser.parse(body, signature)
except InvalidSignatureError:
return HttpResponseForbidden()
except LineBotApiError:
return HttpResponseBadRequest()
for event in events:
if isinstance(event, MessageEvent):
mtext=event.message.text
message=[]
message.append(TextSendMessage(text=mtext))
line_bot_api.reply_message(event.reply_token,message)
return HttpResponse()
else:
return HttpResponseBadRequest()
```
若是打了甚麼機器人就會回復甚麼就表示成功了
---
## 連接資料庫
### 改 views.py
1. 最上面新增 from Mylinebot.models import *
2. 主程式整個callback函式改成這樣
```python
@csrf_exempt
def callback(request):
if request.method == 'POST':
signature = request.META['HTTP_X_LINE_SIGNATURE']
body = request.body.decode('utf-8')
try:
events = parser.parse(body, signature)
except InvalidSignatureError:
return HttpResponseForbidden()
except LineBotApiError:
return HttpResponseBadRequest()
for event in events:
if isinstance(event, MessageEvent):
mtext=event.message.text
uid=event.source.user_id
profile=line_bot_api.get_profile(uid)
name=profile.display_name
pic_url=profile.picture_url
points=0
message=[]
if event.message.text=='開始遊戲':
if User_Info.objects.filter(uid=uid).exists()==False:
User_Info.objects.create(uid=uid,name=name,pic_url=pic_url,mtext=mtext,points=points)
message.append(TextSendMessage(text='註冊成功'))
else:
message.append(TextSendMessage(text='已註冊'))
elif event.message.text=='輸出會員資料':
user_info = User_Info.objects.filter(uid=uid,name=name,pic_url=pic_url)
for user in user_info:
info = 'UID=%s\nNAME=%s\n大頭貼=%s\n'%(user.uid,user.name,user.pic_url)
message.append(TextSendMessage(text=info))
else:
message.append(TextSendMessage(text='再想想'))
line_bot_api.reply_message(event.reply_token,message)
return HttpResponse()
else:
return HttpResponseBadRequest()
```
### 改 models.py
```python
from django.db import models
# Create your models here.
class User_Info(models.Model):
uid = models.CharField(max_length=50,null=False,default='') #user_id
name = models.CharField(max_length=255,blank=True,null=False) #LINE名字
pic_url = models.CharField(max_length=255,null=False) #大頭貼網址
mtext = models.CharField(max_length=255,blank=True,null=False) #文字訊息紀錄
mdt = models.DateTimeField(auto_now=True) #物件儲存的日期時間
def __str__(self):
return self.uid
```
### 改 admin.py
```python
from django.contrib import admin
# Register your models here.
from MylinebotApp.models import * #MylinebotApp改成自己綠色的資料夾
class User_Info_Admin(admin.ModelAdmin):
list_display = ('uid','name','pic_url','mtext','mdt')
admin.site.register(User_Info,User_Info_Admin)
```
### 回到 terminal
```python=1
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
```
- 這兩行是拿來更新資料庫的 之後資料庫有變動都要寫這兩行
- 在 127.0.0.1:8000/admin 裡看資料庫
- LineBot輸入'開始遊戲'就會註冊並回復註冊成功,如果已經註冊就會回復'已註冊',輸入'輸出會員資料'就會輸出自己的資料
---
### 每一次重開專案
1. 打開 vs code → file → open folder → 打開Mylinebot
2. terminal1(注意要在Mylinebot這個資料夾底下才能跑這行)
```python=1
$ python manage.py runserver
```
3. terminal2
```python=1
$ ./ngrok config add-authtoken ‘ngrok授權碼’
$ ./ngrok http 8000
```
4. 打開 line developer,更改 webhook url(從 terminal2 那裡複製,在 message api 裡,按 edit)
5. google 網址進入 127.0.0.1:8000/admin
---
以上是基礎功能,用本機作為server連接資料庫,以下講解幾個比較進階的功能
### 資料庫使用方法
要加 column
1. admin.py 的 list_display 裡加需要的column的名字
2. models.py 加一行 '名字’ = models.______Field(default=0)
從資料庫裡拿到某某東西
```python
user_info = User_Info.objects.filter(uid=uid,name=name,pic_url=pic_url) #讀取到user_info
for user in user_info: #對於user_info裡每一個user來說
info = 'UID=%s\nNAME=%s\n大頭貼=%s\n'%(user.uid,user.name,user.pic_url) #這是一個字串 會動到的是這行 決定要輸出些甚麼東西
message.append(TextSendMessage(text=info))
```
修改資料
```python!
User_Info.objects.filter(data=data).update(data=new_data)
```
刪除資料
```python!
User_Info.objects.filter(uid=uid,name=name,pic_url=pic_url).delete()
```
新增資料
```python
User_Info.objects.create(uid=uid,name=name,pic_url=pic_url,mtext=mtext,points=points)
```
### 建立圖文選單(rich menu)
新增 menu.py(建哪都可以),貼上以下程式碼
```python=
import requests
import json
from linebot import (
LineBotApi, WebhookHandler
)
headers = {"Authorization":"Bearer 'Channel access token'"} #這裡要改
line_bot_api = LineBotApi('Channel access token') #這裡要改
body = {
"size": {"width": 1200, "height": 810},
"selected": "true",
"name": "Controller",
"chatBarText": "Controller",
"areas":[
{
"bounds": {"x": 0, "y": 0, "width": 400, "height": 405},
"action": {"type": "message", "text": "leftup"}
},
{
"bounds": {"x": 400, "y": 0, "width": 400, "height": 405},
"action": {"type": "message", "text": "up"}
},
{
"bounds": {"x": 800, "y": 0, "width": 400, "height": 405},
"action": {"type": "message", "text": "rightup"}
},
{
"bounds": {"x": 0, "y": 405, "width": 400, "height": 405},
"action": {"type": "message", "text": "leftdown"}
},
{
"bounds": {"x": 400, "y": 405, "width": 400, "height": 405},
"action": {"type": "message", "text": "down"}
},
{
"bounds": {"x": 800, "y": 405, "width": 400, "height": 405},
"action": {"type": "message", "text": "rightdown"}
}
]
}
req = requests.request('POST', 'https://api.line.me/v2/bot/richmenu',
headers=headers,data=json.dumps(body).encode('utf-8'))
print(req.text)
```
> - 'Channel access token' 改成自己的 LINE channel access token
> - bounds 表示按鈕的大小及位置
> - action 表示互動的形式
> - 執行 python menu.py 後,會上傳圖表並輸出這個 rich menu 的 id
建立 image.py
```python=
from linebot import (
LineBotApi, WebhookHandler
)
line_bot_api = LineBotApi('Channel access token')
with open("'image name'", 'rb') as f:
line_bot_api.set_rich_menu_image("'rich menu id'", "image/jpeg", f)
```
> - 將要用的照片放到同一層資料夾中,rich menu有固定規格,細節請參照[官網](https://developers.line.biz/en/reference/messaging-api/#uri-action),這邊使用的是1200*810
> - 'Channel access token' 改成自己的 LINE channel access token
> - 'image name' 改成照片名稱
> - 'rich menu id' 改成剛剛輸出的 rich menu 的 id
> - 執行 python image.py 後,這張照片就已經上傳上去了
建立 bot.py
```python=
import requests
headers = {"Authorization":"Bearer 'Channel access token'"}
req = requests.request('POST', 'https://api.line.me/v2/bot/user/all/richmenu/'rich menu id'', headers=headers)
print(req.text)
```
> - 'Channel access token' 改成自己的 LINE channel access token
> - 'rich menu id' 改成剛剛輸出的 rich menu 的 id
> - 執行 python bot.py 後,linebot就會吃到剛剛上傳上去的圖表了
> - rich menu可以做很多事情,可以根據不同 user id 製作不同的圖表,詳細內容請參照[官網](https://developers.line.biz/en/reference/messaging-api/#uri-action)
列出目前上傳的圖表(免費版最多上傳1000個)
```python=
from linebot import (
LineBotApi, WebhookHandler
)
line_bot_api = LineBotApi('Channel access token')
rich_menu_list = line_bot_api.get_rich_menu_list()
for rich_menu in rich_menu_list:
print(rich_menu.rich_menu_id)
```
刪除已上傳的圖表
```python=
from linebot import (
LineBotApi, WebhookHandler
)
line_bot_api = LineBotApi('Channel access token')
rich_menu_list = line_bot_api.get_rich_menu_list()
line_bot_api.delete_rich_menu('要刪除的rich menu id')
```
### 將資料庫改成 phpmyadmin
這只是自己的某個專案會用到,實際上可以接到任何想的到的資料庫
1. download xampp
2. start apache, start mySQL
3. 打開 mySQL,建立一個table(記住名字)
4. 更改 settings.py
```python=
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': '剛剛table名字',
'USER': 'root',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'init_command': "set sql_mode='STRICT_TRANS_TABLES'"
},
}
}
```
5. 最後記得資料庫遷移那三條要執行,然後記得要再createsuper一次,再來就可以到 127.0.0.1:8000/admin 裡看資料庫了
### 上傳至heroku
只用本機作為 server 的話,電腦關機 linebot 就不能動了