Skip to content

Wrapper around the telegram.keyboard object (keyboard_markup, reply and inline)Β #4608

@david-shiko

Description

What kind of feature are you missing? Where do you notice a shortcoming of PTB?

I want to use the.keyboard as a set of buttons rather than a nested list of rows, which are hard to manage and modify.
Indeed, I don't care which row or column contains my button.
Rows and columns are the technically unique identifiers of the button, but for human readability, the button's actual text is better because there can't be two identical buttons in the same keyboard.
In my opinion, it would be a nice fit into the telegram.ext package as the next generation of the keyboard object that we already have.
Prerequisites:

Looking for a proper button object in a nested loop is always tedious and requires some concentration and time.
Most medium and large PTB bots require a custom Button class to respect the DRY principle and keep the code clean.
Let's do it out of the box!

Describe the solution you'd like

I think it would be nice if you would add this feature.
See the possible usage example:

Notice:
keyboard = update.message.keyboard # incoming keyboard
Return type depend on the PTB policy because PTB objects are immutable.

# Text and callback modification example
keyboard.buttons.order_the_pizza.edit_text(new_text='pizza succussfuly ordered')
# or
keyboard.buttons.order_the_pizza.text = 'pizza succussfuly ordered'

# Callback modification example:
keyboard.buttons.some_emoji.callback = 'foo'
# Another possible method names: change order | update_index | set_priority, etc.
# Pattern example:
# P.S. Read only access to the patterns
print(keyboard.pattern)
print(keyboard.buttons.coffee.pattern)
# Order modification example:
keyboard.buttons.breaking_news.change_position(new_row_index=-1, new_column_index=2)
# Another possible method names: change order | update_index, etc.

# Another sample:
last_button_text = keyboard.buttons[-1][-1].text  # index access are also possible.
# Order aliases:
# Even more progressive way: buttons.last means buttons[-1][-1]
# The "last" name reserved but does the "last" may mean something else except the "last" button itself?
last_button = keyboard.buttons.last

# The same with a row:
last_row = keyboard.rows.last
first_column = keyboard.columns.first
fifty_column = keyboard.columns.fifty
from dataclasses import dataclass
from telegram import InlineKeyboardButton


@dataclass  # The struct of the button
class ButtonWrapper(InlineKeyboardButton):
    row_index: int  # new
    column_index: int  # new
    text: int
    callback: int
    ...  # all other regular attrs of InlineKeyboardButton

# Many possible useful methods and shortcuts 


Internal implementation:

  1. The wrapper itself resembles the SimpleNamespace Python class or the Dataclass.
  2. Order aliases (first, second, fifth, etc.) resemble the Enum.
  3. Order aliases may accept an optional strict policy as a parameter.
    Soft - If the count of buttons is less than the order alias (only two buttons in a row, for example), return the second button.
    Mediate - returns None.
    Hard - raises IndexError.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions