![](/img/trans.png)
[英]Send a command using InlineKeyboardButton python telegram bot
[英]Python Telegram Bot: InlineKeyboardButton and waiting for user input
我正在尝试制作一个与我正在开发的物联网系统交互的电报机器人。 实际上我一直在编程 python 电报机器人; 她是我的问题:在机器人的聊天中,用户可以调用 InlineKeyboardButtons 来打开/关闭灯或设置计时器。 当用户选择“计时器”按钮时,我想打开另一个 InlineKeyboardButtons 以使用户 select 其他参数,但使用我当前的代码我无法做到这一点,因为代码跳转到“回调处理程序”。 有什么建议吗? 我将发布整个代码:
from MyMQTT import *
import time
from datetime import datetime, timedelta
import json
import requests
import random
import telepot
from telepot.loop import MessageLoop
from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup
test=1
class tg_pub(object):
def __init__(self, clientID, broker, port, topic):
self.clientID = clientID
# self.topic = str(topic)
# self.topic = '/'.join([self.topic])
self.client = MyMQTT(clientID, broker, port, self)
self.__message = {
"bn": "TelegramBot",
"ip": "",
"e": [
{
"n": "lights_command",
"u": "boolean",
"t": "2021-04-15 16:59:12.586822",
"v": "ON"
},
{
"n": "conditioner_command",
"u": "boolean",
"t": "2021-04-15 16:59:12.586822",
"v": "OFF"
}
]
}
def sendData(self, topic, output):
message = self.__message
message['e'][0]['v'] = output
message['e'][0]['t'] = str(datetime.now())
self.client.myPublish(topic, message)
def start(self):
self.client.start()
def stop(self):
self.client.stop()
class Room_Bot:
def __init__(self, token, broker, port, topic):
# the bot token is to be saved in the Catalog !!!!
self.tokenBot = token # local token
# self.tokenBot = requests.get("http://catalogIP/telegram_token").json()["telegramToken"] # Catalog token
self.bot= telepot.Bot(self.tokenBot)
self.client = MyMQTT("telegramBot", broker, port, None) # to be a publisher
self.client.start()
self.topic = topic
self.__message={
"bn": "TelegramBot",
"ip": "",
"e": [
{
"n": "lights_command",
"u": "boolean",
"t": "2021-04-15 16:59:12.586822",
"v": "ON"
},
{
"n": "conditioner_command",
"u": "boolean",
"t": "2021-04-15 16:59:12.586822",
"v": "OFF"
}
]
}
### USING MESSAGES ###
# MessageLoop(self.bot,{'chat': self.on_chat_message}).run_as_thread()
### USING BUTTONS -> query callback ###
MessageLoop(self.bot, {'chat': self.on_chat_message, 'callback_query': self.on_callback_query}).run_as_thread()
def sendMessage(self, topic):
message=self.__message
message['e'][0]['v']=random.randint(0,1) # 0 = no movement detected
message['e'][0]['t']=str(datetime.now())
self.client.myPublish(topic, message)
def start (self):
self.client.start()
def stop (self):
self.client.stop()
#HANDLING THE MESSAGES
def on_chat_message(self, msg):
content_type, chat_type ,chat_ID = telepot.glance(msg)
message = msg['text'] #retrieve the message from the key 'text' in the json
### USING MESSAGES ###
# if message == "/switch_Lights_ON":
# payload = self.__message.copy()
# payload['e'][0]['v'] = "on"
# payload['e'][0]['t'] = str(datetime.now())
# self.client.myPublish(self.topic,payload)
# self.bot.sendMessage(chat_ID,text = "Lights switched on")
# else:
# self.bot.sendMessage(chat_ID, text="Command not supported")
## USING BUTTONS ###
if message == "/start":
#self.bot.sendMessage(chat_ID, text="Welcome, I am HioTel. Please press one of the available buttons to get started.")
keyboard = ReplyKeyboardMarkup(keyboard=[['Lights', 'Heater'], ['Status Info']])
self.bot.sendMessage(chat_ID, text='Welcome, I am HioTel. Please press one of the available buttons to get started.', reply_markup=keyboard)
elif message == "Lights":
#Matrix of buttons
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[
InlineKeyboardButton(text=f'Lights on 🟡', callback_data=f'direct ON '),
InlineKeyboardButton(text=f'Lights off ⚫', callback_data=f'direct OFF')
],
[
InlineKeyboardButton(text=f'Set timer ⏲️', callback_data=f'light_timer',test=0)
]
])
self.bot.sendMessage(chat_ID, text='Lights menu:', reply_markup=keyboard) #REPLY TO USER
elif message == "Heater":
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[
InlineKeyboardButton(text=f'Heat on 🟡', callback_data=f'heater_on'),
InlineKeyboardButton(text=f'Heat off ⚫', callback_data=f'heater_off')
],
[
InlineKeyboardButton(text=f'Heat up ☀️', callback_data=f'heat_up'),
InlineKeyboardButton(text=f'Heat down ❄️', callback_data=f'heat_down')
],
[
InlineKeyboardButton(text=f'Set timer ⏲️', callback_data=f'heater_timer')
]
])
self.bot.sendMessage(chat_ID, text='Heater menu:', reply_markup=keyboard)
elif message == "Status Info":
self.bot.sendMessage(chat_ID, text='💡 Lights: ON\n\n🌬 Air conditioner: ON, set on tot°\nCurrent room conditions:\n tot° - umidiccio')
else:
self.bot.sendMessage(chat_ID, text="Command not supported")
#HANDLING THE CALLBACKS
def on_callback_query(self, msg):
query_ID , chat_ID , query_data = telepot.glance(msg, flavor='callback_query')
payload = self.__message.copy()
#if query_data=="light_timer":
#keyboard = InlineKeyboardMarkup(inline_keyboard=[
#[
# InlineKeyboardButton(text=f'5 minutes', callback_data=f'durati ON 5'),
#InlineKeyboardButton(text=f'15 minutes', callback_data=f'durati ON 15')
#],
# [
# InlineKeyboardButton(text=f'30 minutes ', callback_data=f'durati ON 30')
#]
# ])
# self.bot.sendMessage(chat_ID, text='Set timer:', reply_markup=keyboard)
payload['e'][0]['v'] = query_data #SET AS MESSAGE WHAT USER SELECTED IN CHAT BUTTONS
payload['e'][0]['t'] = str(datetime.now())
self.client.myPublish(self.topic, payload) #PUBLISH MQTT MESSAGE
self.bot.sendMessage(chat_ID, text=f"{query_data}: done ✔") #FEEDBACK FOR THE USER
print(test)
if __name__ == '__main__':
url = "xxxxxx"
clientID = 'telegram'
settings = requests.post(url)
config = list(settings.json())
broker = config[0]["settings"][0]["broker"]
port = config[0]["settings"][0]["port"]
token = config[0]["settings"][0]["botToken"]
baseTopic = config[0]["settings"][0]["baseTopic"]
topic_pub_l = baseTopic + config[0]["settings"][0]["lightControlTopic"]
topic_pub_c = baseTopic + config[0]["settings"][0]["conditControlTopic"]
topic = baseTopic + topic_pub_l
pub_l = tg_pub(clientID, broker, port, topic_pub_l)
pub_l.start()
output = None
pub_l.sendData("hotel/catalog", output)
time.sleep(random.randint(1,10))
requests.post(url)
bot = Room_Bot(token,broker,port,topic)
while True:
time.sleep(2)
这是正确的,因为按下任何按钮 ( InlineKeyboardButtons
) 都会触发负责处理响应的CallbackHandler
。
一种选择是重构代码以创建发送给定响应的方法,例如
def send_lights(chat_ID) :
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[
InlineKeyboardButton(text=f'Heat on 🟡', callback_data=f'heater_on'),
InlineKeyboardButton(text=f'Heat off ⚫', callback_data=f'heater_off')
],
[
InlineKeyboardButton(text=f'Heat up ☀️', callback_data=f'heat_up'),
InlineKeyboardButton(text=f'Heat down ❄️', callback_data=f'heat_down')
],
[
InlineKeyboardButton(text=f'Set timer ⏲️', callback_data=f'heater_timer')
]
])
self.bot.sendMessage(chat_ID, text='Heater menu:', reply_markup=keyboard)
当用户按下给定按钮时,您可以从 CallbackHandler 调用新方法 ( send_lights
)。
第二种选择是使用一个同时处理消息和回调的方法:老实说,我不确定你如何使用telepot
来做到这一点,但使用 PythonTelegramBot 是可能的:在这种情况下,你可以在同一个地方处理所有响应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.