Telegram Python Bot 内联菜单和字典

问题描述

Click Here to see the flowchart 我的 Telegram 机器人需要一些帮助。我正在尝试创建一个机器人,它允许我修改一组选定的字典值并在其末尾以某种方式显示字典键和值。如代码所示,现在我无法弄清楚如何找出用户单击了哪个按钮并将其反映在该键的相应值中。 (例如,(KEY)Shop A - (VALUE)Low Crowd,Compliant...等对于此选定区域中的其他商店)。请注意,我目前仅编写了区域 1 的代码作为示例 -> 它还必须能够为其他选定区域使用它们自己的一组带有空值的预定义字典键。请参阅图片以更好地理解

#!/usr/bin/env python
# pylint: disable=C0116
    
    import logging
    
    from telegram import Update,ForceReply,InlineKeyboardButton,InlineKeyboardMarkup
    from telegram.ext import Updater,CommandHandler,MessageHandler,Filters,CallbackContext,CallbackQueryHandler
    
    # Enable logging
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',level=logging.INFO
    )
    
    logger = logging.getLogger(__name__)
    
    
    ############################ Keyboards #########################################
    def main_area_selection_kb():
        keyboard = [
            [
                InlineKeyboardButton("Area 1",callback_data='main_1'),],[
                InlineKeyboardButton("Area 2",callback_data='main_2'),[
                InlineKeyboardButton("Area 3",callback_data='main_3'),[
                InlineKeyboardButton("Area 4",callback_data='main_4'),[
                InlineKeyboardButton("Area 5",callback_data='main_5'),[
                InlineKeyboardButton("Area 6",callback_data='main_6'),]
        return InlineKeyboardMarkup(keyboard)
    
    def crowd_level_selection_kb():
        keyboard = [
            [
                InlineKeyboardButton("Low",callback_data='clvl_1'),InlineKeyboardButton("Moderate",callback_data='clvl_2'),InlineKeyboardButton("High",callback_data='clvl_3'),InlineKeyboardButton("Closed",callback_data='clvl_4'),]
        ]
    
        return InlineKeyboardMarkup(keyboard)
    
    def compliance_kb():
        keyboard = [
            [
                InlineKeyboardButton("Compliant",callback_data='com_1'),InlineKeyboardButton("Not Compliant",callback_data='com_2'),]
        ]
        return InlineKeyboardMarkup(keyboard)
    
    ############################ Selection #########################################
    def compliance_selection(update,_: CallbackContext) -> None:
        query = update.callback_query
        query.answer()
        if query.data == 'com_1':
            query.message.reply_text('Compliant')
        elif query.data == 'com_2':
            query.message.reply_text('Not Compliant')
    
    def crowd_level_selection(update,_: CallbackContext) -> None:
        query = update.callback_query
        query.answer() # How do I "pass" the dictionary in/return the value of the user selection back into the respective dictionary's key value?)
        if query.data == 'clvl_1':
            query.message.reply_text('You choose Low Crowd') 
        elif query.data == 'clvl_2':
            query.message.reply_text('You choose Moderate Crowd')
        elif query.data == 'clvl_3':
            query.message.reply_text('You choose High Crowd')
        elif query.data == 'clvl_4':
            query.message.reply_text('You choose Closed')
    
    def main_area_selection(update,_: CallbackContext) -> None:
        query = update.callback_query
    
        query.answer()
        # query.edit_message_text(text=f"Selected option: {query.data}")
        if query.data == 'main_1':
            query.message.reply_text('You choose Area 1')
            areamain(query)
        elif query.data == 'main_2':
            query.message.reply_text('You choose Area 2')
        elif query.data == 'main_3':
            query.message.reply_text('You choose Area 3')
        elif query.data == 'main_4':
            query.message.reply_text('You choose Area 4')
        elif query.data == 'main_5':
            query.message.reply_text('You choose Area 5')
        elif query.data == 'main_6':
            query.message.reply_text('You choose Area 6')
        else:
            query.message.reply_text('Error')
    
    ############################ Functions #########################################
    
    def start(update,context):
        """Send a message when the command /start is issued."""
        update.message.reply_text('Please Choose an Area',reply_markup=main_area_selection_kb())
    
    
    def areamain(update):
        areamaindict = {'Shop A': '','Shop B': '','Shop C': '','Shop D': '','Shop E': ''}
    
        for i in areamaindict:
            update.message.reply_text(f"{i} Crowd Level:",reply_markup=crowd_level_selection_kb())
            

            #Next step: Add in menu for compliance
            #Following that,Set this i value to <High/Medium/Low> Crowd and <Compliant/Not Compliant> once user selected both respective buttons
    
    ############################ Main #########################################
    def main():
        
        # Create the Updater and pass it your bot's token.
        updater = Updater("TOKEN")
    
        # Get the dispatcher to register handlers
        dispatcher = updater.dispatcher
    
        # on different commands - answer in Telegram
        dispatcher.add_handler(CommandHandler("start",start))
    
        ############################# Handlers #########################################
        updater.dispatcher.add_handler(CallbackQueryHandler(main_area_selection,pattern='main'))
        updater.dispatcher.add_handler(CallbackQueryHandler(crowd_level_selection,pattern='clvl'))
        updater.dispatcher.add_handler(CallbackQueryHandler(compliance_selection,pattern='com'))
    
    
        # Start the Bot/Listen for user input/messages
        updater.start_polling()
    
        # Run the bot until you press Ctrl-C or the process receives SIGINT,# SIGTERM or SIGABRT. This should be used most of the time,since
        # start_polling() is non-blocking and will stop the bot gracefully.
        updater.idle()
    
    
    if __name__ == '__main__':
        main()

解决方法

注意投诉没有实现,希望你能用同样的设计思路来实现。

#!/usr/bin/env python
# pylint: disable=C0116

import logging
from typing import Dict

from telegram import InlineKeyboardButton,InlineKeyboardMarkup
from telegram.ext import (
    Updater,CommandHandler,CallbackContext,CallbackQueryHandler,)

# Enable logging
logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",level=logging.INFO
)

logger = logging.getLogger(__name__)

temporary_data: Dict[int,dict] = {}


def compliance_kb():
    return InlineKeyboardMarkup(
        [
            [
                InlineKeyboardButton("Compliant",callback_data="com_1"),InlineKeyboardButton("Not Compliant",callback_data="com_2"),]
        ]
    )


# ########################### Selection #########################################
def compliance_selection(update,_: CallbackContext) -> None:
    query = update.callback_query
    query.answer()
    if query.data == "com_1":
        query.message.reply_text("Compliant")
    elif query.data == "com_2":
        query.message.reply_text("Not Compliant")


def crowd_level_selection(update,_: CallbackContext) -> None:
    global temporary_data
    query = update.callback_query
    query.answer()
    main_area_number = query.data.split("_")[-1]

    # we need to identify the shop right? for that we can take the message for example Shop C Crowd Level:
    # so taking the first 6 charachter from the message we got the key

    shop_level = update.effective_message.text[:6]
    update.effective_message.delete()
    if "clvl_1" in query.data:
        query.message.reply_text(
            f"You choose Low Crowd of main area {main_area_number}"
        )
        temporary_data[query.from_user.id]["shop_data"][shop_level][
            "crowd_level"
        ] = "Low"
    elif "clvl_2" in query.data:
        query.message.reply_text(
            f"You choose Moderate Crowd of main area {main_area_number}"
        )
        temporary_data[query.from_user.id]["shop_data"][shop_level][
            "crowd_level"
        ] = "Moderate"
    elif "clvl_3" in query.data:
        query.message.reply_text(
            f"You choose High Crowd of main area {main_area_number}"
        )
        temporary_data[query.from_user.id]["shop_data"][shop_level][
            "crowd_level"
        ] = "High"
    elif "clvl_4" in query.data:
        query.message.reply_text(f"You choose Closed of main area {main_area_number}")
        temporary_data[query.from_user.id]["shop_data"][shop_level][
            "crowd_level"
        ] = "Closed"

    from pprint import pprint

    print(shop_level)
    pprint(temporary_data)


def main_area_selection(update,_: CallbackContext) -> None:
    global temporary_data
    temporary_data[update.effective_chat.id] = {}

    query = update.callback_query
    query.answer()
    each_shop_dict = {
        "Shop A": {"crowd_level": "null","compliant": "null"},"Shop B": {"crowd_level": "null","Shop C": {"crowd_level": "null","Shop D": {"crowd_level": "null","Shop E": {"crowd_level": "null",}  # or {f"Shop {k}":{"crowd_level": "null","compliant": "null"} for k in ["A","B","C","D","E"]} but this makes confusion.

    update.effective_message.delete()
    if "main" in query.data:
        number = query.data.split("_")[-1]
        query.message.reply_text(f"You choose Area {number}")
        temporary_data[query.from_user.id].update(
            dict(main_area_number=int(number),shop_data=each_shop_dict)
        )
    for i in each_shop_dict:
        main_area_number = query.data.split("_")[-1]
        markup = InlineKeyboardMarkup(
            [
                [
                    InlineKeyboardButton(
                        "Low",callback_data=f"clvl_1_{main_area_number}"
                    ),InlineKeyboardButton(
                        "Moderate",callback_data=f"clvl_2_{main_area_number}"
                    ),InlineKeyboardButton(
                        "High",callback_data=f"clvl_3_{main_area_number}"
                    ),InlineKeyboardButton(
                        "Closed",callback_data=f"clvl_4_{main_area_number}"
                    ),]
            ]
        )
        query.message.reply_text(f"{i} Crowd Level:",reply_markup=markup)


# ########################### Functions #########################################


def start(update,context):
    """Send a message when the command /start is issued."""
    print(temporary_data.get(update.effective_chat.id,None))
    update.message.reply_text(
        "Please Choose an Area",reply_markup=InlineKeyboardMarkup(
            [
                [
                    InlineKeyboardButton("Area 1",callback_data="main_1"),],[
                    InlineKeyboardButton("Area 2",callback_data="main_2"),[
                    InlineKeyboardButton("Area 3",callback_data="main_3"),[
                    InlineKeyboardButton("Area 4",callback_data="main_4"),[
                    InlineKeyboardButton("Area 5",callback_data="main_5"),[
                    InlineKeyboardButton("Area 6",callback_data="main_6"),]
        ),)


# ########################### Main #########################################
def main():

    # Create the Updater and pass it your bot's token.
    updater = Updater("TOKEN")

    # Get the dispatcher to register handlers
    dispatcher = updater.dispatcher

    # on different commands - answer in Telegram
    dispatcher.add_handler(CommandHandler("start",start))

    # ############################ Handlers #########################################
    updater.dispatcher.add_handler(
        CallbackQueryHandler(main_area_selection,pattern="main")
    )
    updater.dispatcher.add_handler(
        CallbackQueryHandler(crowd_level_selection,pattern="clvl")
    )
    updater.dispatcher.add_handler(
        CallbackQueryHandler(compliance_selection,pattern="com")
    )

    # Start the Bot/Listen for user input/messages
    updater.start_polling()

    # Run the bot until you press Ctrl-C or the process receives SIGINT,# SIGTERM or SIGABRT. This should be used most of the time,since
    # start_polling() is non-blocking and will stop the bot gracefully.
    updater.idle()


if __name__ == "__main__":
    main()

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...