简体   繁体   中英

Python Telegram Bot InlineKeyboard : ask for user confirmation

The user interacts with my Telegram bot using an Inline Keyboard. Some buttons execute functions that are sensitive and I would like to ask the user's confirmation before proceeding.

For example: in the main menu, the user chooses between two buttons Option 1 and Option 2 . If clicked, the sensitive functions do_action_1 and do_action_2 are executed respectively.

A minimal working example is below:

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


def start(update: Update, context: CallbackContext) -> None:
     update.message.reply_text('Please choose:',
                              reply_markup = keyboard_main_menu())


def main_menu(update: Update, context: CallbackContext) -> None:
    """ Displays the main menu keyboard when called. """

    query = update.callback_query
    query.answer()
    query.edit_message_text(text         = 'Please choose an option:',
                            reply_markup = keyboard_main_menu())


def keyboard_main_menu():
    """ Creates the main menu keyboard """

    keyboard = [
        [InlineKeyboardButton("Option 1", callback_data='1'),
         InlineKeyboardButton("Option 2", callback_data='2'),],
    ]

    return InlineKeyboardMarkup(keyboard)


def do_action_1(update: Update, context: CallbackContext) -> None:

    keyboard = [[InlineKeyboardButton("Main menu", callback_data='main')]]
    reply_markup = InlineKeyboardMarkup(keyboard)

    query = update.callback_query
    query.answer()
    query.edit_message_text(text=f"Selected option {query.data}\n"
                                 f"Executed action 1.",
                            reply_markup=reply_markup)


def do_action_2(update: Update, context: CallbackContext) -> None:

    keyboard = [[InlineKeyboardButton("Main menu", callback_data='main')]]
    reply_markup = InlineKeyboardMarkup(keyboard)

    query = update.callback_query
    query.answer()
    query.edit_message_text(text=f"Selected option {query.data}\n"
                                 f"Executed action 2.",
                            reply_markup=reply_markup)


def main() -> None:
    """Run the bot."""

    updater = Updater("TOKEN")

    updater.dispatcher.add_handler(CommandHandler('start', start))
    updater.dispatcher.add_handler(CallbackQueryHandler(main_menu, pattern='main'))
    updater.dispatcher.add_handler(CallbackQueryHandler(do_action_1, pattern='1'))
    updater.dispatcher.add_handler(CallbackQueryHandler(do_action_2, pattern='2'))

    # Start the Bot
    updater.start_polling()
    print('started')


if __name__ == '__main__':
    main()

Now, I would like to insert an intermediate step after clicking Option 1 or Option 2 , displaying a keyboard "Are you sure?" with two buttons Yes and No . Clicking Yes executes do_action_1 or do_action_2 based on the user's choice at the previous keyboard. Clicking No would bring the user back to the main menu.

How can I do that?

You can display a keyboard with the options YES and NO and handle the input like you handled the input for the other buttons. To keep track of which action to take when the user presses YES, you can either encode that action in the callback_data or store it temporarily. See also this wiki page an Storing Data .


Disclaimer: I'm currently the maintainer of python-telegram-bot

Thanks to @CallMeStag's answer, I managed to get a mwe:

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


def start(update: Update, context: CallbackContext) -> None:
    """Sends a message with three inline buttons attached."""

    update.message.reply_text('Please choose:',
                              reply_markup = keyboard_main_menu())


def main_menu(update: Update, context: CallbackContext) -> None:
    """ Displays the main menu keyboard when called. """

    query = update.callback_query
    query.answer()
    query.edit_message_text(text         = 'Please choose:',
                            reply_markup = keyboard_main_menu())


def keyboard_main_menu():
    """ Creates the main menu keyboard """

    keyboard = [
        [InlineKeyboardButton("Option 1", callback_data='1'),
         InlineKeyboardButton("Option 2", callback_data='2'),],
    ]

    return InlineKeyboardMarkup(keyboard)


def confirm(update: Update, context: CallbackContext) -> None:
    """Parses the CallbackQuery and updates the message text."""

    query = update.callback_query
    query.answer()

    keyboard = [
        [InlineKeyboardButton("Yes", callback_data=f'YES{query.data}'),
         InlineKeyboardButton("No",  callback_data='main'),],
    ]

    reply_markup = InlineKeyboardMarkup(keyboard)

    query.edit_message_text(text=f"Selected option {query.data}."
                                 f"Are you sure ? ",
                            reply_markup=reply_markup)


def do_action_1(update: Update, context: CallbackContext) -> None:

    keyboard = [[InlineKeyboardButton("Main menu", callback_data='main')]]
    reply_markup = InlineKeyboardMarkup(keyboard)

    query = update.callback_query
    query.answer()
    query.edit_message_text(text=f"Selected option {query.data}\n"
                                 f"Executed action 1.",
                            reply_markup=reply_markup)


def do_action_2(update: Update, context: CallbackContext) -> None:

    keyboard = [[InlineKeyboardButton("Main menu", callback_data='main')]]
    reply_markup = InlineKeyboardMarkup(keyboard)

    query = update.callback_query
    query.answer()
    query.edit_message_text(text=f"Selected option {query.data}\n"
                                 f"Executed action 2.",
                            reply_markup=reply_markup)


def main() -> None:
    """Run the bot."""
    # Create the Updater and pass it your bot's token.
    updater = Updater("TOKEN")

    updater.dispatcher.add_handler(CommandHandler('start', start))
    updater.dispatcher.add_handler(CallbackQueryHandler(main_menu, pattern='main'))
    updater.dispatcher.add_handler(CallbackQueryHandler(confirm, pattern='^(|1|2)$'))
    updater.dispatcher.add_handler(CallbackQueryHandler(do_action_1, pattern='YES1'))
    updater.dispatcher.add_handler(CallbackQueryHandler(do_action_2, pattern='YES2'))


    # Start the Bot
    updater.start_polling()
    print('started')

if __name__ == '__main__':
    main()

The bot now correctly asks for the user's confirmation before executing do_action_1 and do_action_2 . Thanks a lot !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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