順利將 LINE BOT 串接 Webhook 後,就能透過 LINE Message API 開發聊天機器人,這篇教學會介紹回覆訊息的方法,並使用 Colab + bgrok 實做一個會自動回覆客製化訊息、表情貼圖、圖片、影片以及地址的 LINE BOT 聊天機器人,最後再將機器人部署到 Google Cloud Functions。
- 原文參考:自動回覆訊息
- 完整教學:LINE BOT 教學
不論 LINE BOT 接收那種類型的訊息,回覆訊息都是使用 reply_message 方法進行回覆,reply_message 方法包含一個 reply token 的參數,表示訊息要回覆到哪裡,一個 reply token 只會在接收到訊息時產生一次,如果回覆過的訊息需要再次回覆,則需要再度接收訊息才能回覆,如果要多次主動推播訊息,則需使用 push message 的方式處理。
使用 reply_message 的「TextSendMessage」方法 ( 需要 import ),能夠回覆文字訊息,相關參數如下:
參數 | 說明 |
---|---|
text | 要回覆的文字 ( 不論放入什麼內容都會被轉換成文字 )。 |
使用下方的程式碼執行後,使用者輸入了什麼訊息,LINE BOT 就會回覆一模一樣的文字訊息。
注意,如果是 ngrok + Colab 產生的網址,每次重新執行就要再進入 LINE Developer 更新 Webhook。
from flask_ngrok import run_with_ngrok # colab 使用,本機環境請刪除
from flask import Flask, request
from linebot import LineBotApi, WebhookHandler
from linebot.models import TextSendMessage # 載入 TextSendMessage 模組
import json
app = Flask(__name__)
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True)
json_data = json.loads(body)
print(json_data)
try:
line_bot_api = LineBotApi('你的 Channel access token')
handler = WebhookHandler('你的 LINE Channel secret')
signature = request.headers['X-Line-Signature']
handler.handle(body, signature)
tk = json_data['events'][0]['replyToken'] # 取得 reply token
msg = json_data['events'][0]['message']['text'] # 取得使用者發送的訊息
text_message = TextSendMessage(text=msg) # 設定回傳同樣的訊息
line_bot_api.reply_message(tk,text_message) # 回傳訊息
except:
print('error')
return 'OK'
if __name__ == "__main__":
run_with_ngrok(app)
app.run()
使用 reply_message 的「StickerSendMessage」方法 ( 需要 import ),能夠回覆表情貼圖,相關參數如下:
參數 | 說明 |
---|---|
package_id | 表情貼圖所在群組 ID。 |
sticker_id | 表情貼圖 ID。 |
LINE BOT 預設的表情貼圖只有 LINE 官方所提供的貼圖,支援的表情貼圖參考:List of available stickers。
下方的程式碼執行後,當使用者傳送了表情貼圖,LINE BOT 就會回覆一模一樣的表情貼圖 ( 限制為官方預設的表情貼圖 )。
注意,如果是 ngrok + Colab 產生的網址,每次重新執行就要再進入 LINE Developer 更新 Webhook。
from flask_ngrok import run_with_ngrok # colab 使用,本機環境請刪除
from flask import Flask, request
from linebot import LineBotApi, WebhookHandler
from linebot.models import StickerSendMessage # 載入 StickerSendMessage 模組
import json
app = Flask(__name__)
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True)
json_data = json.loads(body)
print(json_data)
try:
line_bot_api = LineBotApi('你的 Channel access token')
handler = WebhookHandler('你的 LINE Channel secret')
signature = request.headers['X-Line-Signature']
handler.handle(body, signature)
tk = json_data['events'][0]['replyToken'] # 取得 reply token
stickerId = json_data['events'][0]['message']['stickerId'] # 取得 stickerId
packageId = json_data['events'][0]['message']['packageId'] # 取得 packageId
sticker_message = StickerSendMessage(sticker_id=stickerId, package_id=packageId) # 設定要回傳的表情貼圖
line_bot_api.reply_message(tk,sticker_message) # 回傳訊息
except:
print('error')
return 'OK'
if __name__ == "__main__":
run_with_ngrok(app)
app.run()
使用 reply_message 的「ImageSendMessage」或「VideoSendMessage」方法 ( 需要 import ),能夠回覆圖片或影片,相關參數如下:
參數 | 說明 |
---|---|
original_content_url | 原始圖片或影片網址。 |
preview_image_url | 縮圖網址。 |
下方的程式碼執行後,當使用者傳送了某個文字,LINE BOT 就會回覆跟這個文字有關的圖片 ( 先建立好圖片網址和文字對照的字典,圖片來源是維基百科 ),如果找不到文字對應的圖片,就會回傳「找不到相關圖片」。
注意,如果是 ngrok + Colab 產生的網址,每次重新執行就要再進入 LINE Developer 更新 Webhook。
from flask_ngrok import run_with_ngrok # colab 使用,本機環境請刪除
from flask import Flask, request
from linebot import LineBotApi, WebhookHandler
from linebot.models import TextSendMessage, ImageSendMessage # 載入 TextSendMessage 和 ImageSendMessage 模組
import json
app = Flask(__name__)
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True)
json_data = json.loads(body)
print(json_data)
try:
line_bot_api = LineBotApi('你的 Channel access token')
handler = WebhookHandler('你的 LINE Channel secret')
signature = request.headers['X-Line-Signature']
handler.handle(body, signature)
tk = json_data['events'][0]['replyToken']
msg = json_data['events'][0]['message']['text']
img_url = reply_img(msg) # 取得對應的圖片,如果沒有取得,會是 False
if img_url:
# 如果有圖片網址,回傳圖片
img_message = ImageSendMessage(original_content_url=img_url, preview_image_url=img_url)
line_bot_api.reply_message(tk,img_message)
else:
# 如果是 False,回傳文字
text_message = TextSendMessage(text='找不到相關圖片')
line_bot_api.reply_message(tk,text_message)
except:
print('error')
return 'OK'
# 建立回覆圖片的函式
def reply_img(text):
# 文字對應圖片網址的字典
img = {
'皮卡丘':'https://upload.wikimedia.org/wikipedia/en/a/a6/Pok%C3%A9mon_Pikachu_art.png',
'傑尼龜':'https://upload.wikimedia.org/wikipedia/en/5/59/Pok%C3%A9mon_Squirtle_art.png'
}
if text in img:
return img[text]
else:
# 如果找不到對應的圖片,回傳 False
return False
if __name__ == "__main__":
run_with_ngrok(app)
app.run()
使用 reply_message 的「LocationSendMessage」方法 ( 需要 import ),能夠回覆地址訊息,相關參數如下:
參數 | 說明 |
---|---|
title | 地圖標題。 |
address | 地址標示。 |
latitude | 緯度。 |
longitude | 經度。 |
下方的程式碼執行後,當使用者傳送了某個地點的文字,LINE BOT 就會回覆跟這個地點的地圖 ( 先建立文字和地址、經緯度的對照字典 ),如果找不到文字對應的地址,就會回傳「找不到相關地點」。
注意,如果是 ngrok + Colab 產生的網址,每次重新執行就要再進入 LINE Developer 更新 Webhook。
from flask_ngrok import run_with_ngrok # colab 使用,本機環境請刪除
from flask import Flask, request
from linebot import LineBotApi, WebhookHandler
from linebot.models import TextSendMessage, LocationSendMessage # 載入 TextSendMessage 和 LocationSendMessage 模組
import json
app = Flask(__name__)
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True)
json_data = json.loads(body)
print(json_data)
try:
line_bot_api = LineBotApi('你的 Channel access token')
handler = WebhookHandler('你的 LINE Channel secret')
signature = request.headers['X-Line-Signature']
handler.handle(body, signature)
tk = json_data['events'][0]['replyToken']
msg = json_data['events'][0]['message']['text']
location_dect = reply_location(msg) # 取得對應的地址,如果沒有取得,會是 False
if location_dect:
# 如果有地點資訊,回傳地點
location_message = LocationSendMessage(title=location_dect['title'],
address=location_dect['address'],
latitude=location_dect['latitude'],
longitude=location_dect['longitude'])
line_bot_api.reply_message(tk,location_message)
else:
# 如果是 False,回傳文字
text_message = TextSendMessage(text='找不到相關地點')
line_bot_api.reply_message(tk,text_message)
except:
print('error')
return 'OK'
# 建立回覆地點的函式
def reply_location(text):
# 建立地點與文字對應的字典
location = {
'101':{
'title':'台北 101',
'address':'110台北市信義區信義路五段7號',
'latitude':'25.034095712145003',
'longitude':'121.56489941996108'
},
'總統府':{
'title':'總統府',
'address':'100台北市中正區重慶南路一段122號',
'latitude':'25.040319874750914',
'longitude':'121.51162883484746'
}
}
if text in location:
return location[text]
else:
# 如果找不到對應的地點,回傳 False
return False
if __name__ == "__main__":
run_with_ngrok(app) # colab 使用,本機環境請刪除
app.run()
因為使用 ngrok + Colab 的 Python 程式,只會運作幾個小時就停止,甚至再次執行時需要重新安裝相關函式庫,所以只能作為「開發中」使用,如果要真正建構 LINE BOT 的 Python 程式,除了可以使用類似 Heroku 之類的雲端伺服器,也可以直接使用 Google Cloud Functions 部署程式。
登入 Google 帳號,啟用 Google Cloud 和 Cloud Functions 後,建立一支 Cloud Functions 的程式,環境設定為 Python 3.7~3.9,進入點設定為 linebot。
編輯 requirements.txt,在 Cloud Functions 安裝 line-bot-sdk 函式庫。
編輯 main.py 主程式檔案,撰寫下方 Python 程式碼,綜合上方所有的範例,程式碼執行後會自動回覆使用者的訊息、表情貼圖、圖片與地點資訊。
import json
from linebot import LineBotApi, WebhookHandler
# 載入對應的函式庫
from linebot.models import TextSendMessage, StickerSendMessage, ImageSendMessage, LocationSendMessage
def linebot(request):
try:
body = request.get_data(as_text=True)
json_data = json.loads(body) # json 格式化收到的訊息
line_bot_api = LineBotApi('你的 Channel access token') # 輸入 你的 Channel access token
handler = WebhookHandler('你的 Channel secret') # 輸入 你的 Channel secret
signature = request.headers['X-Line-Signature']
handler.handle(body, signature)
tk = json_data['events'][0]['replyToken'] # 取得 reply token
tp = json_data['events'][0]['message']['type'] # 取得 message 的類型
if tp == 'text':
# 如果是文字類型的訊息
msg = reply_msg(json_data['events'][0]['message']['text']) # 取出文字並對應到 reply_msg 的函式
if msg[0] == 'text':
# 如果要回傳的訊息是 text,使用 TextSendMessage 方法
line_bot_api.reply_message(tk,TextSendMessage(text=msg[1]))
if msg[0] == 'location':
# 如果要回傳的訊息是 location,使用 LocationSendMessage 方法
line_bot_api.reply_message(tk,LocationSendMessage(title=msg[1]['title'],
address=msg[1]['address'],
latitude=msg[1]['latitude'],
longitude=msg[1]['longitude']))
if msg[0] == 'image':
# 如果要回傳的訊息是 image,使用 ImageSendMessage 方法
line_bot_api.reply_message(tk,ImageSendMessage(original_content_url=msg[1],
preview_image_url=msg[1]))
if tp == 'sticker':
# 如果收到的訊息是表情貼圖
stickerId = json_data['events'][0]['message']['stickerId'] # 取得 stickerId
packageId = json_data['events'][0]['message']['packageId'] # 取得 packageId
# 使用 StickerSendMessage 方法回傳同樣的表情貼圖
line_bot_api.reply_message(tk,StickerSendMessage(sticker_id=stickerId, package_id=packageId))
if tp == 'location':
# 如果是收到的訊息是地點資訊
line_bot_api.reply_message(tk,TextSendMessage(text='好地點!'))
if tp == 'image':
# 如果是收到的訊息是圖片
line_bot_api.reply_message(tk,TextSendMessage(text='好圖給讚!'))
if tp == 'audio':
# 如果是收到的訊息是聲音
line_bot_api.reply_message(tk,TextSendMessage(text='聲音讚喔~'))
if tp == 'video':
# 如果是收到的訊息是影片
line_bot_api.reply_message(tk,TextSendMessage(text='影片內容真是不錯!'))
except:
print('error', body)
return 'OK'
# 定義回覆訊息的函式
def reply_msg(text):
# 客製化回覆文字
msg_dict = {
'hi':'Hi! 你好呀~',
'hello':'Hello World!!!!',
'你好':'你好呦~',
'help':'有什麼要幫忙的嗎?'
}
# 如果出現特定地點,提供地點資訊
local_dict = {
'總統府':{
'title':'總統府',
'address':'100台北市中正區重慶南路一段122號',
'latitude':'25.040319874750914',
'longitude':'121.51162883484746'
}
}
# 如果出現特定圖片文字,提供圖片網址
img_dict = {
'皮卡丘':'https://upload.wikimedia.org/wikipedia/en/a/a6/Pok%C3%A9mon_Pikachu_art.png',
'傑尼龜':'https://upload.wikimedia.org/wikipedia/en/5/59/Pok%C3%A9mon_Squirtle_art.png'
}
# 預設回覆的文字就是收到的訊息
reply_msg_content = ['text',text]
if text in msg_dict:
reply_msg_content = ['text',msg_dict[text.lower()]]
if text in local_dict:
reply_msg_content = ['location',local_dict[text.lower()]]
if text in img_dict:
reply_msg_content = ['image',img_dict[text.lower()]]
return reply_msg_content
編輯完成後,部署程式,出現綠色打勾圖示表示部署完成。
程式部署後,選擇「觸發條件」頁籤,複製觸發的網址,更新 LINE Developer 的 Webhook。
驗證 Webhook 沒問題後,就可以在 LINE 與自己開發的 LINE BOT 聊天了。
了解 LINE Message API 回覆訊息的原理後,就能輕鬆做出一個會自動回覆訊息的 LINE BOT,不過回覆訊息的機制是「一來一往」,只有在發送訊息後取得 reply token 才能回覆訊息,如果要主動推播訊息,則需要使用 push messsage 的方式才能實現。
延伸閱讀
大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我有個超過一千篇教學的 STEAM 教育學習網,有興趣可以參考下方連結呦~ ^_^