1

I need help creating those two menu

1 - menu that update itself when a button is clicked and remove that button. firstmenu

2 - menu that have next previous button. second menu

I try to check the update callback query data and check if the button is their so I deleted the problem is it delete all button it show that I clicked all the button in the same time. For the second menu I have no idea how. I need like a clarification or a logic how it work so I can start from their.

Minimal example with code can help Thanks

1 Answer 1

1

I tried to create a simple but functioning example with your specifications as i understood them. There are a bunch of comments, but let me know if something is still not clear.

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

REMOVE_BUTTONS_COUNT = 5
PAGES_COUNT = 10


def get_text_and_keyboard(page: int, removed_buttons: list):
    """Generates both the text and the inline keyboard to show to the user,
    based on the current page and on the buttons that have been removed
    """
    # Makes sure removed_buttons is a list
    text = f"You are on page {page + 1}" if page is not None else "You are on page 1"
    keyboard = InlineKeyboardMarkup(
        [
            [InlineKeyboardButton(text=f"RESET", callback_data="reset")],
            *[  # Each element generated is a row, notice the * before the [
                # and the [] wrapping the InlineKeyboardButton
                [InlineKeyboardButton(text=f"🗑 button {i}", callback_data=f"rm_{i}")]
                for i in range(REMOVE_BUTTONS_COUNT)
                if i not in removed_buttons
            ],
            [  # All the pages are on the same row
                InlineKeyboardButton(text=f"{i + 1}", callback_data=f"go_{i}")
                for i in range(PAGES_COUNT)
                if i != page
            ],
        ]
    )
    return text, keyboard


def remove_query(update: Update, context: CallbackContext):
    """Removes a button"""
    # The data is in the form "rm_<number>"
    button_idx = int(update.callback_query.data.replace("rm_", ""))
    rm_buttons = context.user_data.get("removed_buttons", [])
    rm_buttons.append(button_idx)
    context.user_data["removed_buttons"] = rm_buttons

    # I'm only interested in the keyboard, for the text message doesn't change
    _, keyboard = get_text_and_keyboard(None, rm_buttons)
    context.bot.edit_message_reply_markup(
        chat_id=update.callback_query.message.chat_id,
        message_id=update.callback_query.message.message_id,
        reply_markup=keyboard,
    )


def reset_query(update: Update, context: CallbackContext):
    """Resets both buttons and pages"""
    context.user_data["removed_buttons"] = []
    context.user_data["page"] = 0

    text, keyboard = get_text_and_keyboard(None, [])

    try:
        context.bot.edit_message_text(
            chat_id=update.callback_query.message.chat_id,
            message_id=update.callback_query.message.message_id,
            text=text,
            reply_markup=keyboard,
        )
    except BadRequest:  # The message was already in the default state
        pass


def go_to_page_query(update: Update, context: CallbackContext):
    """Goes to the provided page"""
    # The data is in the form "go_<number>"
    new_page = int(update.callback_query.data.replace("go_", ""))
    context.user_data["page"] = new_page
    removed_buttons = context.user_data.get("removed_buttons", [])

    text, keyboard = get_text_and_keyboard(new_page, removed_buttons)

    context.bot.edit_message_text(
        chat_id=update.callback_query.message.chat_id,
        message_id=update.callback_query.message.message_id,
        text=text,
        reply_markup=keyboard,
    )


def menu_cmd(update: Update, context: CallbackContext):
    """Handles the /menu  command.
    Shows the inline keyboard

    Args:
        update: update event
        context: context passed by the handler
    """
    # Both could be put on context.bot_data, context.chat_data, in a file or a database
    # depending on your requirements.
    # You may also want to reset them here
    page = context.user_data.get("page", 0)
    removed_buttons = context.user_data.get("removed_buttons", [])

    text, keyboard = get_text_and_keyboard(page, removed_buttons)

    context.bot.send_message(
        chat_id=update.message.chat_id,
        text=text,
        reply_markup=keyboard,
    )


def main():
    """Main function"""
    updater = Updater("TOKEN")
    updater.dispatcher.add_handler(CommandHandler("start", menu_cmd))
    # Regex is used in the pattern to match the callback_data coming from the buttons
    updater.dispatcher.add_handler(CallbackQueryHandler(remove_query, pattern=r"^rm_*"))
    updater.dispatcher.add_handler(CallbackQueryHandler(reset_query, pattern=r"^reset$"))
    updater.dispatcher.add_handler(CallbackQueryHandler(go_to_page_query, pattern=r"^go_*"))

    updater.start_polling()
    updater.idle()


if __name__ == "__main__":
    main()
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you @tend for the good clarification, that was what i'm locking for.I was able to create the first menu like you mention after reading many docs, but the second part (*[]) i understand it now thanks again ;).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.