DJANGO WEBHOOK

      在〈DJANGO WEBHOOK〉中尚無留言

閱讀本篇前,需要先架設 Nginx/Django 伺服器,並且要有自已的網域並使用 SSL 加密憑証。

上一篇的 Line BOT 簡介中,BOT 可以自動回覆訊息,但功能極為陽春。雖然也可以設定 AI 自動回覆訊息,但這功能將於 2024/05/15 停用。

所以我們必需架設一台伺服器,分析客戶端傳入的內容才決定要如何回應,最終將回應訊息透過 BOT 傳送給客戶端手機,示意圖如下。

Line Channel access token 

在底下的伺服器代碼中,有二個很重要的變數要設定,分別是 Line Channel acccess token 及 Line secret。因為 Line 網站上查詢這二個變數的位置有變,所以先說明一下取得的方式。

請先由 https://developers.line.biz/zh-hant/ 選擇 Console,再按下 Messaging API。

接下來再選擇 Messageing API 分頁

往下拉後,會看到 Channel access token,第一次需按下 issue 按鈕產生新的 access token,日後若要變更,可以按下 Reissue。請把 access token 複製記下,等會要填入 python 代碼中的 access_token 變數。

再切換到 Basic settings 分頁

往下拉即可看到 Channel secret,此數字也需記要,要填入後面 python 代碼的 secret 變數中。

Line BOT 設定

請進入 Line BOT 網站的設定/Messaging API,將聊天關掉,Webhook 打開。

Django 新增 app

在 Django 專案下,執行 python manage.py startapp line,新增一個 line app。urls.py 新增如下網址設設。

from line import views as line
urlpatterns = [
...................
path('line/', line.html, name="line_bot_webhook"),
]

view.py

在 line 目錄下的 views.py 修改如下

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
@csrf_exempt
def html(request):
    try:
        pass
    except:
        pass
    return HttpResponse("OK")#隨便回覆一個字串,但不可以是空字串

測試

請由 https://developers.line.biz/zh-hant/ 然後按 Console ,選 Messaging API/Messaging API,再編輯 Webhook URL 並輸入 https://xxx.ddns.net/line/。 請注意 Django 架設的網站,必需在  Webhook URL  網址最後面要加入 “/”。 若是由 flask 架設的網站,則不需輸入 “/”。

然後按下 Verify,即可看到連線成功

取得客戶端 Line 傳入的訊息

安裝 line bot 套件

pip install line-bot-sdk

在 line/views.py 更改如下

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
import json
from linebot.models import TextSendMessage
from linebot import LineBotApi
from G import G
line_bot_api = LineBotApi(G.line_access_token)
@csrf_exempt#取消 CSRF保護
def html(request):
    try:
        body=request.body.decode()
        data=json.loads(body)
        tk = data['events'][0]['replyToken']
        type = data['events'][0]['message']['type']     # 取得 LINe 收到的訊息類型
        if type=='text':
            msg = data['events'][0]['message']['text']  # 取得 LINE 收到的文字訊息
            reply = msg
        else:
            reply = '你傳的不是文字呦~'
        line_bot_api.reply_message(tk,TextSendMessage(reply))# 回傳訊息
    except:
        pass
    return HttpResponse("不可以是空字串")

然後使用客戶端的 Line 對 Line bot 輸入文字,Line Bot 即會以相同的訊息傳給客戶端。

天氣預報/地震速報

底下的代碼,可以預報天氣及查詢地震

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
import json
from linebot.models import TextSendMessage, ImageSendMessage
from linebot import LineBotApi
import requests
from G import G
import time
line_bot_api = LineBotApi(G.line_access_token)
answer_menu="""
本官網僅對上課內容發佈最新訊息

可供查詢的內容如下
天氣預報
地震速報
"""

@csrf_exempt#取消 CSRF保護
def html(request):
    try:
        body=request.body.decode()
        data=json.loads(body)
        tk = data['events'][0]['replyToken']
        type = data['events'][0]['message']['type']     # 取得 LINe 收到的訊息類型
        user_id = data['events'][0]['source']['userId']
        if type=='text':
            msg = data['events'][0]['message']['text']  # 取得 LINE 收到的文字訊息
            reply = msg
            if '天氣預報' in msg:
                line_bot_api.push_message(user_id, TextSendMessage(text='抓取資料中....'))   # 一開始先發送訊息
                img_url = f'https://cwaopendata.s3.ap-northeast-1.amazonaws.com/Observation/O-A0058-001.png?{time.time_ns()}'
                img_message = ImageSendMessage(original_content_url=img_url, preview_image_url=img_url)
                line_bot_api.reply_message(tk, img_message)
            elif '地震速報' in msg:
                line_bot_api.push_message(user_id, TextSendMessage(text='抓取資料中....'))
                reply = earth_quake()   # 執行函式,讀取數值
                text_message = TextSendMessage(text=reply[0])        # 取得文字內容
                line_bot_api.reply_message(tk,text_message) # 傳送文字
                line_bot_api.push_message(user_id, ImageSendMessage(original_content_url=reply[1], preview_image_url=reply[1])) # 傳送圖片
            else:
                line_bot_api.reply_message(tk, TextSendMessage(answer_menu))
        else:
            reply = '你傳的不是文字呦~'
        line_bot_api.reply_message(tk,TextSendMessage(reply))# 回傳訊息
    except:
        pass
    return HttpResponse("不可以是空字串")
def earth_quake():
    try:
        url = f'https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0016-001?Authorization={G.earth_quake_code}'
        data = requests.get(url)  # 爬取資料
        data_json = data.json()   # 轉換成 json
        eq = data_json['records']['Earthquake'][0]           # 取得第一筆地震資訊
        result = [eq['ReportContent'], eq['ReportImageURI']] # 回傳地震報告和地震圖
    except Exception as e:
        print(e)
        result = ['抓取失敗...','']
    return result

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *