自动回复消息
顺利将 LINE BOT 串接 Webhook 后,就能透过 LINE Message API 开发聊天机器人,这篇教学会介绍回复消息的方法,并使用 Colab + bgrok 实做一个会自动回复客制化消息、表情贴图、图片、影片以及地址的 LINE BOT 聊天机器人,最后再将机器人部署到 Google Cloud Functions。
建议先阅读:
快速导览:
什么是 reply token?
不论 LINE BOT 接收那种类型的消息,回复消息都是使用 reply_message 方法进行回复,reply_message 方法包含一个 reply token 的参数,表示消息要回复到哪里,一个 reply token 只会在接收到消息时产生一次,如果回复过的消息需要再次回复,则需要再度接收消息才能回复,如果要多次主动推播消息,则需使用 push message 的方式处理。
回复文字消息
使用 reply_message 的“TextSendMessage”方法 ( 需要 import ),能够回复文字消息,相关参数如下:
| 参数 | 说明 |
|---|---|
| text | 要回复的文字 ( 不论放入什么内容都会被转换成文字 )。 |
使用下方的程序码执行后,用户输入了什么消息,LINE BOT 就会回复一模一样的文字消息。
注意,如果是 ngrok 产生的网址,每次重新执行就要再进入 LINE Developer 更新 Webhook。
from flask import Flask, request
from pyngrok import ngrok # Colab 使用,本機環境不需要
# 載入 LINE Message API 相關函式庫
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage
import json
app = Flask(__name__)
# Colab 使用,本機環境不需要下面三行
port = "5000"
public_url = ngrok.connect(port).public_url
print(f" * ngrok tunnel \"{public_url}\" -> \"http://127.0.0.1:{port}\" ")
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True) # 取得收到的訊息內容
try:
json_data = json.loads(body) # json 格式化訊息內容
access_token = '你的 access token'
secret = '你的 Channel secret'
line_bot_api = LineBotApi(access_token) # 確認 token 是否正確
handler = WebhookHandler(secret) # 確認 secret 是否正確
signature = request.headers['X-Line-Signature'] # 加入回傳的 headers
handler.handle(body, signature) # 綁定訊息回傳的相關資訊
msg = json_data['events'][0]['message']['text'] # 取得 LINE 收到的文字訊息
tk = json_data['events'][0]['replyToken'] # 取得回傳訊息的 Token
line_bot_api.reply_message(tk,TextSendMessage(msg)) # 回傳訊息
print(msg, tk) # 印出內容
except:
print(body) # 如果發生錯誤,印出收到的內容
return 'OK' # 驗證 Webhook 使用,不能省略
if __name__ == "__main__":
app.run()
回复表情贴图
使用 reply_message 的“StickerSendMessage”方法 ( 需要 import ),能够回复表情贴图,相关参数如下:
| 参数 | 说明 |
|---|---|
| package_id | 表情贴图所在群组 ID。 |
| sticker_id | 表情贴图 ID。 |
LINE BOT 默认的表情贴图只有 LINE 官方所提供的贴图,支援的表情贴图参考:List of available stickers。
下方的程序码执行后,当用户传送了表情贴图,LINE BOT 就会回复一模一样的表情贴图 ( 限制为官方默认的表情贴图 )。
注意,如果是 ngrok 产生的网址,每次重新执行就要再进入 LINE Developer 更新 Webhook。
from flask import Flask, request
from pyngrok import ngrok # Colab 使用,本機環境不需要
# 載入 LINE Message API 相關函式庫
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage, StickerSendMessage
# 注意,有載入 StickerSendMessage 模組
import json
app = Flask(__name__)
# Colab 使用,本機環境不需要下面三行
port = "5000"
public_url = ngrok.connect(port).public_url
print(f" * ngrok tunnel \"{public_url}\" -> \"http://127.0.0.1:{port}\" ")
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True) # 取得收到的訊息內容
try:
json_data = json.loads(body) # json 格式化訊息內容
access_token = '你的 access token'
secret = '你的 channel secret'
line_bot_api = LineBotApi(access_token) # 確認 token 是否正確
handler = WebhookHandler(secret) # 確認 secret 是否正確
signature = request.headers['X-Line-Signature'] # 加入回傳的 headers
handler.handle(body, signature) # 綁定訊息回傳的相關資訊
tk = json_data['events'][0]['replyToken'] # 取得回傳訊息的 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(body) # 如果發生錯誤,印出收到的內容
return 'OK' # 驗證 Webhook 使用,不能省略
if __name__ == "__main__":
app.run()
回复图片或影片消息
使用 reply_message 的“ImageSendMessage”或“VideoSendMessage”方法 ( 需要 import ),能够回复图片或影片,相关参数如下:
| 参数 | 说明 |
|---|---|
| original_content_url | 原始图片或影片网址。 |
| preview_image_url | 缩图网址。 |
下方的程序码执行后,当用户传送了某个文字,LINE BOT 就会回复跟这个文字有关的图片 ( 先建立好图片网址和文字对照的字典,图片来源是维基百科 ),如果找不到文字对应的图片,就会回传“找不到相关图片”。
注意,如果是 ngrok + Colab 产生的网址,每次重新执行就要再进入 LINE Developer 更新 Webhook。
from flask import Flask, request
from pyngrok import ngrok # Colab 環境需要,本機環境不需要
# 載入 LINE Message API 相關函式庫
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage, StickerSendMessage, ImageSendMessage
# 注意,有載入 ImageSendMessage 模組
import json
app = Flask(__name__)
# Colab 環境需要下面這三行,本機環境不需要
port = "5000"
public_url = ngrok.connect(port).public_url
print(f" * ngrok tunnel \"{public_url}\" -> \"http://127.0.0.1:{port}\" ")
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True) # 取得收到的訊息內容
try:
json_data = json.loads(body) # json 格式化訊息內容
access_token = '你的 access token'
secret = '你的 channel secret'
line_bot_api = LineBotApi(access_token) # 確認 token 是否正確
handler = WebhookHandler(secret) # 確認 secret 是否正確
signature = request.headers['X-Line-Signature'] # 加入回傳的 headers
handler.handle(body, signature) # 綁定訊息回傳的相關資訊
tk = json_data['events'][0]['replyToken'] # 取得回傳訊息的 Token
msg = json_data['events'][0]['message']['text']
if msg == '皮卡丘':
# 如果有圖片網址,回傳圖片
img_url = 'https://upload.wikimedia.org/wikipedia/en/a/a6/Pok%C3%A9mon_Pikachu_art.png'
img_message = ImageSendMessage(original_content_url=img_url, preview_image_url=img_url)
line_bot_api.reply_message(tk,img_message)
else:
# 如果沒有 msg,回傳文字
text_message = TextSendMessage(text='找不到相關圖片')
line_bot_api.reply_message(tk,text_message)
except:
print(body) # 如果發生錯誤,印出收到的內容
return 'OK' # 驗證 Webhook 使用,不能省略
if __name__ == "__main__":
app.run()
回复地址消息
使用 reply_message 的“LocationSendMessage”方法 ( 需要 import ),能够回复地址消息,相关参数如下:
| 参数 | 说明 |
|---|---|
| title | 地图标题。 |
| address | 地址标示。 |
| latitude | 纬度。 |
| longitude | 经度。 |
下方的程序码执行后,当用户传送了某个地点的文字,LINE BOT 就会回复跟这个地点的地图 ( 先建立文字和地址、经纬度的对照字典 ),如果找不到文字对应的地址,就会回传“找不到相关地点”。
注意,如果是 ngrok 产生的网址,每次重新执行就要再进入 LINE Developer 更新 Webhook。
from flask import Flask, request
from pyngrok import ngrok # Colab 環境需要,本機環境不需要
# 載入 LINE Message API 相關函式庫
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage, StickerSendMessage, ImageSendMessage, LocationSendMessage
# 注意,有載入 LocationSendMessage 模組
import json
app = Flask(__name__)
# Colab 環境需要下面這三行,本機環境不需要
port = "5000"
public_url = ngrok.connect(port).public_url
print(f" * ngrok tunnel \"{public_url}\" -> \"http://127.0.0.1:{port}\" ")
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True) # 取得收到的訊息內容
try:
json_data = json.loads(body) # json 格式化訊息內容
access_token = '你的 access token'
secret = '你的 channel secret'
line_bot_api = LineBotApi(access_token) # 確認 token 是否正確
handler = WebhookHandler(secret) # 確認 secret 是否正確
signature = request.headers['X-Line-Signature'] # 加入回傳的 headers
handler.handle(body, signature) # 綁定訊息回傳的相關資訊
tk = json_data['events'][0]['replyToken'] # 取得回傳訊息的 Token
msg = json_data['events'][0]['message']['text']
if msg == '101':
# 如果有地點資訊,回傳地點
location_message = LocationSendMessage(title='台北 101',
address='110台北市信義區信義路五段7號',
latitude='25.034095712145003',
longitude='121.56489941996108')
line_bot_api.reply_message(tk,location_message)
else:
# 如果是 False,回傳文字
text_message = TextSendMessage(text='找不到相關地點')
line_bot_api.reply_message(tk,text_message)
except:
print(body) # 如果發生錯誤,印出收到的內容
return 'OK' # 驗證 Webhook 使用,不能省略
if __name__ == "__main__":
app.run()
部署程序到 Google Cloud Functions
因为使用 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 的方式才能实现。
延伸阅读
微信扫码关注
抖音扫码关注