Telegram Python Bot 内联菜单和词典

Telegram Python Bot Inline Menu and Dictionary

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", "compliant": "null"},
        "Shop C": {"crowd_level": "null", "compliant": "null"},
        "Shop D": {"crowd_level": "null", "compliant": "null"},
        "Shop E": {"crowd_level": "null", "compliant": "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()