###### 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. 記住下面這個授權碼 ![](https://i.imgur.com/dr5XQXF.png) 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 ![](https://i.imgur.com/3qHDPu3.png) ![](https://i.imgur.com/Dr21kED.png) ### 改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 就不能動了