繁体   English   中英

Python Telegram Bot:InlineKeyboardButton 并等待用户输入

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM