diff --git a/telethon/client/buttons.py b/telethon/client/buttons.py index 7e848ab1..bc464e0a 100644 --- a/telethon/client/buttons.py +++ b/telethon/client/buttons.py @@ -7,8 +7,8 @@ from ..tl import types, custom class ButtonMethods: @staticmethod def build_reply_markup( - buttons: 'typing.Optional[hints.MarkupLike]', - inline_only: bool = False) -> 'typing.Optional[types.TypeReplyMarkup]': + buttons: 'typing.Optional[hints.MarkupLike]' + ) -> 'typing.Optional[types.TypeReplyMarkup]': """ Builds a :tl:`ReplyInlineMarkup` or :tl:`ReplyKeyboardMarkup` for the given buttons. @@ -26,9 +26,6 @@ class ButtonMethods: The button, list of buttons, array of buttons or markup to convert into a markup. - inline_only (`bool`, optional): - Whether the buttons **must** be inline buttons only or not. - Example .. code-block:: python @@ -42,8 +39,8 @@ class ButtonMethods: return None try: - if buttons.SUBCLASS_OF_ID == 0xe2e10ef2: - return buttons # crc32(b'ReplyMarkup'): + if buttons.SUBCLASS_OF_ID == 0xe2e10ef2: # crc32(b'ReplyMarkup'): + return buttons except AttributeError: pass @@ -57,6 +54,8 @@ class ButtonMethods: resize = None single_use = None selective = None + persistent = None + placeholder = None rows = [] for row in buttons: @@ -69,6 +68,10 @@ class ButtonMethods: single_use = button.single_use if button.selective is not None: selective = button.selective + if button.persistent is not None: + persistent = button.persistent + if button.placeholder is not None: + placeholder = button.placeholder button = button.button elif isinstance(button, custom.MessageButton): @@ -78,19 +81,21 @@ class ButtonMethods: is_inline |= inline is_normal |= not inline - if button.SUBCLASS_OF_ID == 0xbad74a3: - # 0xbad74a3 == crc32(b'KeyboardButton') + if button.SUBCLASS_OF_ID == 0xbad74a3: # crc32(b'KeyboardButton') current.append(button) if current: rows.append(types.KeyboardButtonRow(current)) - if inline_only and is_normal: - raise ValueError('You cannot use non-inline buttons here') - elif is_inline == is_normal and is_normal: + if is_inline and is_normal: raise ValueError('You cannot mix inline with normal buttons') elif is_inline: return types.ReplyInlineMarkup(rows) - # elif is_normal: return types.ReplyKeyboardMarkup( - rows, resize=resize, single_use=single_use, selective=selective) + rows=rows, + resize=resize, + single_use=single_use, + selective=selective, + persistent=persistent, + placeholder=placeholder + ) diff --git a/telethon/tl/custom/button.py b/telethon/tl/custom/button.py index 6ec09b54..ca9098fd 100644 --- a/telethon/tl/custom/button.py +++ b/telethon/tl/custom/button.py @@ -37,11 +37,14 @@ class Button: to 128 characters and add the ellipsis (…) character as the 129. """ - def __init__(self, button, *, resize, single_use, selective): + def __init__(self, button, *, resize, single_use, selective, + persistent, placeholder): self.button = button self.resize = resize self.single_use = single_use self.selective = selective + self.persistent = persistent + self.placeholder = placeholder @staticmethod def _is_inline(button): @@ -168,11 +171,15 @@ class Button: ) @classmethod - def text(cls, text, *, resize=None, single_use=None, selective=None): + def text(cls, text, *, resize=None, single_use=None, selective=None, + persistent=None, placeholder=None): """ Creates a new keyboard button with the given text. Args: + text (`str`): + The title of the button. + resize (`bool`): If present, the entire keyboard will be reconfigured to be resized and be smaller if there are not many buttons. @@ -187,48 +194,77 @@ class Button: users. It will target users that are @mentioned in the text of the message or to the sender of the message you reply to. + persistent (`bool`): + If present, always show the keyboard when the regular keyboard + is hidden. Defaults to false, in which case the custom keyboard + can be hidden and revealed via the keyboard icon. + + placeholder (`str`): + The placeholder to be shown in the input field when the keyboard is active; + 1-64 characters + When the user clicks this button, a text message with the same text as the button will be sent, and can be handled with `events.NewMessage `. You cannot distinguish between a button press and the user typing and sending exactly the same text on their own. """ - return cls(types.KeyboardButton(text), - resize=resize, single_use=single_use, selective=selective) + return cls( + types.KeyboardButton(text), + resize=resize, + single_use=single_use, + selective=selective, + persistent=persistent, + placeholder=placeholder + ) @classmethod - def request_location(cls, text, *, - resize=None, single_use=None, selective=None): + def request_location(cls, text, *, resize=None, single_use=None, selective=None, + persistent=None, placeholder=None): """ Creates a new keyboard button to request the user's location on click. - ``resize``, ``single_use`` and ``selective`` are documented in `text`. + ``resize``, ``single_use``, ``selective``, ``persistent`` and ``placeholder`` + are documented in `text`. When the user clicks this button, a confirmation box will be shown to the user asking whether they want to share their location with the bot, and if confirmed a message with geo media will be sent. """ - return cls(types.KeyboardButtonRequestGeoLocation(text), - resize=resize, single_use=single_use, selective=selective) + return cls( + types.KeyboardButtonRequestGeoLocation(text), + resize=resize, + single_use=single_use, + selective=selective, + persistent=persistent, + placeholder=placeholder + ) @classmethod - def request_phone(cls, text, *, - resize=None, single_use=None, selective=None): + def request_phone(cls, text, *, resize=None, single_use=None, + selective=None, persistent=None, placeholder=None): """ Creates a new keyboard button to request the user's phone on click. - ``resize``, ``single_use`` and ``selective`` are documented in `text`. + ``resize``, ``single_use``, ``selective``, ``persistent`` and ``placeholder`` + are documented in `text`. When the user clicks this button, a confirmation box will be shown to the user asking whether they want to share their phone with the bot, and if confirmed a message with contact media will be sent. """ - return cls(types.KeyboardButtonRequestPhone(text), - resize=resize, single_use=single_use, selective=selective) + return cls( + types.KeyboardButtonRequestPhone(text), + resize=resize, + single_use=single_use, + selective=selective, + placeholder=placeholder, + persistent=persistent + ) @classmethod - def request_poll(cls, text, *, force_quiz=False, - resize=None, single_use=None, selective=None): + def request_poll(cls, text, *, force_quiz=False, resize=None, single_use=None, + selective=None, persistent=None, placeholder=None): """ Creates a new keyboard button to request the user to create a poll. @@ -240,13 +276,20 @@ class Button: the votes cannot be retracted. Otherwise, users can vote and retract the vote, and the pol might be multiple choice. - ``resize``, ``single_use`` and ``selective`` are documented in `text`. + ``resize``, ``single_use``, ``selective``, ``persistent`` and ``placeholder`` + are documented in `text`. When the user clicks this button, a screen letting the user create a poll will be shown, and if they do create one, the poll will be sent. """ - return cls(types.KeyboardButtonRequestPoll(text, quiz=force_quiz), - resize=resize, single_use=single_use, selective=selective) + return cls( + types.KeyboardButtonRequestPoll(text, quiz=force_quiz), + resize=resize, + single_use=single_use, + selective=selective, + persistent=persistent, + placeholder=placeholder + ) @staticmethod def clear(selective=None): @@ -265,15 +308,8 @@ class Button: Forces a reply to the message with this markup. If used, no other button should be present or it will be ignored. - ``single_use`` and ``selective`` are as documented in `text`. + ``single_use``, ``selective`` and ``placeholder`` are as documented in `text`. - Args: - placeholder (str): - text to show the user at typing place of message. - - If the placeholder is too long, Telegram applications will - crop the text (for example, to 64 characters and adding an - ellipsis (…) character as the 65th). """ return types.ReplyKeyboardForceReply( single_use=single_use,