Keyboards¶
Buttons under a message. The guide is Commands and buttons.
Warning
Buttons are never encrypted, not even in encrypted chats: their text and their
callback_data travel in clear, because the server has to know which button was pressed.
- class Button(text, callback_data=None, url=None)¶
One button under a message: a callback button or a link button.
A callback button sends its
callback_databack to the bot when pressed, as aCallbackQuery. A link button offers to open itsurl, and the phone shows the address before opening it. Make one withcallbackorlink; the fields are also the constructor’s arguments, and exactly one ofcallback_dataandurlmust be set.Nothing is checked when a button is made. When its keyboard is sent, a broken rule raises
ValidationError(withfieldset to"markup"):textis not blank, has at most 64 characters (UTF-16 units) and no control characters. Spaces at both ends are trimmed when it is sent.callback_datahas 1 to 64 bytes in UTF-8 and no control characters, and no other button of the keyboard has the same.urlis an absolutehttporhttpsaddress with no user name or password, at most 1024 characters long.
Example
>>> from pgpcbot import Button >>> Button.callback("Yes", "vote:yes") Button(text='Yes', callback_data='vote:yes', url=None) >>> Button.link("Rules", "https://example.org/rules").to_json() {'text': 'Rules', 'url': 'https://example.org/rules'}
Warning
Buttons are never encrypted, not even in an encrypted chat: the server has to know which button was pressed. Keep personal data out of
textandcallback_data. Use an ID that means something only to your bot (order:8812), not the content (order:Anna Rossi, 3 pizzas).- classmethod callback(text, data)¶
Makes a callback button, which sends
databack to the bot when pressed.The press reaches the handlers of
Router.on_callback_queryas aCallbackQuerywhosedatais this string.
- classmethod link(text, url)¶
Makes a link button, which offers to open
url.The phone shows the address before opening it.
- to_json()¶
Converts the button to the API’s JSON form.
Nothing is checked or trimmed here.
- class InlineKeyboard(rows=<factory>)¶
The rows of buttons under a message.
Make one with
build, one argument per row, or with aKeyboardBuilder. The constructor takes the rows as a tuple of tuples. Pass the keyboard asmarkup=when sending or editing a message (Message.reply,Bot.send_message,CallbackQuery.edit_message…). Wherever a keyboard is accepted, the API’s JSON form works too, as adict.len(keyboard)is the number of rows.Nothing is checked while the keyboard is built. When it is sent, a broken rule raises
ValidationError(withfieldset to"markup") before anything leaves the process:up to 20 rows, 8 buttons in a row and 100 buttons in all;
each button follows the rules listed in
Button, and no two buttons have the samecallback_data;the whole keyboard is at most 8 KiB (8192 bytes) of JSON, measured the way the server measures it.
Empty rows are dropped, and a keyboard with no buttons is the same as no keyboard. Its buttons are never encrypted (see
Button).- rows¶
The rows, top to bottom, each a tuple of buttons from left to right.
Example
>>> from pgpcbot import Button, InlineKeyboard >>> keyboard = InlineKeyboard.build( ... [Button.callback("Yes", "vote:yes"), Button.callback("No", "vote:no")], ... [Button.link("Rules", "https://example.org/rules")], ... ) >>> len(keyboard) 2 >>> keyboard.find("vote:no").text 'No'
In a handler, the keyboard goes under the reply:
await message.reply("Do you agree?", markup=keyboard)
- classmethod build(*rows)¶
Makes a keyboard from rows of buttons, one argument per row.
InlineKeyboard.build([yes, no], [rules])putsyesandnoside by side, andrulesunder them.
- classmethod from_json(data)¶
Makes a keyboard from the API’s JSON form, the reverse of
to_json.Nothing is checked. Rows that are not lists and buttons that are not objects are skipped.
- Parameters:
data (Mapping[str, Any] | None) –
{"inlineKeyboard": [[...], ...]}, as the API writes it, orNone.- Returns:
The keyboard, or
Nonewhendatais not a mapping with aninlineKeyboardlist.- Return type:
InlineKeyboard | None
- to_json()¶
Converts the keyboard to the API’s JSON form.
Nothing is checked or dropped here: the rules apply when the keyboard is sent.
- Returns:
A dict,
{"inlineKeyboard": [[...], ...]}, with each button asButton.to_jsonwrites it.- Return type:
- buttons()¶
Lists every button of the keyboard.
- find(callback_data)¶
Finds the button that carries
callback_data.- Parameters:
callback_data (str) – The data to look for, such as the
dataof aCallbackQuery.- Returns:
The first button with that data, or
Nonewhen no button has it.- Return type:
Button | None
- class KeyboardBuilder(*, per_row=PER_ROW_MAX)¶
Builds a keyboard a row at a time, starting a new row when one is full.
addputs buttons in the current row and starts a new row afterper_rowbuttons;rowadds a row of its own. Both give the builder back, so calls can be chained, andbuildmakes theInlineKeyboard. Nothing is checked until the keyboard is sent.Example
>>> from pgpcbot import Button, KeyboardBuilder >>> towns = ["Rome", "Milan", "Turin", "Bari"] >>> keyboard = ( ... KeyboardBuilder(per_row=3) ... .add(*[Button.callback(town, f"town:{town.lower()}") for town in towns]) ... .row(Button.link("All towns", "https://example.org/towns")) ... .build() ... ) >>> [[button.text for button in row] for row in keyboard.rows] [['Rome', 'Milan', 'Turin'], ['Bari'], ['All towns']]
Starts an empty keyboard.
- Parameters:
per_row (int) – How many buttons
addputs in a row before it starts the next one, from 1 to 8 (the server’s limit). The default is 8.- Raises:
ValueError – When
per_rowis not between 1 and 8.
- add(*buttons)¶
Adds buttons to the current row, starting a new row when it is full.
A row is full when it has
per_rowbuttons. Afterrow, the next button starts a new row.- Parameters:
*buttons (Button) – The buttons, from left to right.
- Returns:
This builder, so calls can be chained.
- Return type:
- row(*buttons)¶
Adds a row of its own with these buttons; the next
addstarts a new row.per_rowdoes not apply to this row, but the server’s limit of 8 buttons a row does. With no buttons, it only ends the current row.- Parameters:
*buttons (Button) – The buttons of the row, from left to right.
- Returns:
This builder, so calls can be chained.
- Return type:
- build()¶
Makes the keyboard from the rows added so far. Empty rows are left out.
- Returns:
The
InlineKeyboard.- Return type: