mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-06-17 10:36:37 +00:00
feat(keyboard): Add persistent
and placeholder
options
Introduce `persistent` and `placeholder` parameters for `ReplyKeyboardMarkup`. These new options control keyboard visibility and input field text. Available for text, location, phone, and poll buttons. Remove vestigial `inline_only` from `build_reply_markup` as its functionality is implicitly covered by the general rule against mixing inline and normal buttons.
This commit is contained in:
parent
69e4493c04
commit
863365983d
@ -7,8 +7,8 @@ from ..tl import types, custom
|
|||||||
class ButtonMethods:
|
class ButtonMethods:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_reply_markup(
|
def build_reply_markup(
|
||||||
buttons: 'typing.Optional[hints.MarkupLike]',
|
buttons: 'typing.Optional[hints.MarkupLike]'
|
||||||
inline_only: bool = False) -> 'typing.Optional[types.TypeReplyMarkup]':
|
) -> 'typing.Optional[types.TypeReplyMarkup]':
|
||||||
"""
|
"""
|
||||||
Builds a :tl:`ReplyInlineMarkup` or :tl:`ReplyKeyboardMarkup` for
|
Builds a :tl:`ReplyInlineMarkup` or :tl:`ReplyKeyboardMarkup` for
|
||||||
the given buttons.
|
the given buttons.
|
||||||
@ -26,9 +26,6 @@ class ButtonMethods:
|
|||||||
The button, list of buttons, array of buttons or markup
|
The button, list of buttons, array of buttons or markup
|
||||||
to convert into a markup.
|
to convert into a markup.
|
||||||
|
|
||||||
inline_only (`bool`, optional):
|
|
||||||
Whether the buttons **must** be inline buttons only or not.
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -42,8 +39,8 @@ class ButtonMethods:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if buttons.SUBCLASS_OF_ID == 0xe2e10ef2:
|
if buttons.SUBCLASS_OF_ID == 0xe2e10ef2: # crc32(b'ReplyMarkup'):
|
||||||
return buttons # crc32(b'ReplyMarkup'):
|
return buttons
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -57,6 +54,8 @@ class ButtonMethods:
|
|||||||
resize = None
|
resize = None
|
||||||
single_use = None
|
single_use = None
|
||||||
selective = None
|
selective = None
|
||||||
|
persistent = None
|
||||||
|
placeholder = None
|
||||||
|
|
||||||
rows = []
|
rows = []
|
||||||
for row in buttons:
|
for row in buttons:
|
||||||
@ -69,6 +68,10 @@ class ButtonMethods:
|
|||||||
single_use = button.single_use
|
single_use = button.single_use
|
||||||
if button.selective is not None:
|
if button.selective is not None:
|
||||||
selective = button.selective
|
selective = button.selective
|
||||||
|
if button.persistent is not None:
|
||||||
|
persistent = button.persistent
|
||||||
|
if button.placeholder is not None:
|
||||||
|
placeholder = button.placeholder
|
||||||
|
|
||||||
button = button.button
|
button = button.button
|
||||||
elif isinstance(button, custom.MessageButton):
|
elif isinstance(button, custom.MessageButton):
|
||||||
@ -78,19 +81,21 @@ class ButtonMethods:
|
|||||||
is_inline |= inline
|
is_inline |= inline
|
||||||
is_normal |= not inline
|
is_normal |= not inline
|
||||||
|
|
||||||
if button.SUBCLASS_OF_ID == 0xbad74a3:
|
if button.SUBCLASS_OF_ID == 0xbad74a3: # crc32(b'KeyboardButton')
|
||||||
# 0xbad74a3 == crc32(b'KeyboardButton')
|
|
||||||
current.append(button)
|
current.append(button)
|
||||||
|
|
||||||
if current:
|
if current:
|
||||||
rows.append(types.KeyboardButtonRow(current))
|
rows.append(types.KeyboardButtonRow(current))
|
||||||
|
|
||||||
if inline_only and is_normal:
|
if is_inline and is_normal:
|
||||||
raise ValueError('You cannot use non-inline buttons here')
|
|
||||||
elif is_inline == is_normal and is_normal:
|
|
||||||
raise ValueError('You cannot mix inline with normal buttons')
|
raise ValueError('You cannot mix inline with normal buttons')
|
||||||
elif is_inline:
|
elif is_inline:
|
||||||
return types.ReplyInlineMarkup(rows)
|
return types.ReplyInlineMarkup(rows)
|
||||||
# elif is_normal:
|
|
||||||
return types.ReplyKeyboardMarkup(
|
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
|
||||||
|
)
|
||||||
|
@ -37,11 +37,14 @@ class Button:
|
|||||||
to 128 characters and add the ellipsis (…) character as
|
to 128 characters and add the ellipsis (…) character as
|
||||||
the 129.
|
the 129.
|
||||||
"""
|
"""
|
||||||
def __init__(self, button, *, resize, single_use, selective):
|
def __init__(self, button, *, resize, single_use, selective,
|
||||||
|
persistent, placeholder):
|
||||||
self.button = button
|
self.button = button
|
||||||
self.resize = resize
|
self.resize = resize
|
||||||
self.single_use = single_use
|
self.single_use = single_use
|
||||||
self.selective = selective
|
self.selective = selective
|
||||||
|
self.persistent = persistent
|
||||||
|
self.placeholder = placeholder
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_inline(button):
|
def _is_inline(button):
|
||||||
@ -168,11 +171,15 @@ class Button:
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@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.
|
Creates a new keyboard button with the given text.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
text (`str`):
|
||||||
|
The title of the button.
|
||||||
|
|
||||||
resize (`bool`):
|
resize (`bool`):
|
||||||
If present, the entire keyboard will be reconfigured to
|
If present, the entire keyboard will be reconfigured to
|
||||||
be resized and be smaller if there are not many buttons.
|
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
|
users. It will target users that are @mentioned in the text
|
||||||
of the message or to the sender of the message you reply to.
|
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
|
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
|
as the button will be sent, and can be handled with `events.NewMessage
|
||||||
<telethon.events.newmessage.NewMessage>`. You cannot distinguish
|
<telethon.events.newmessage.NewMessage>`. You cannot distinguish
|
||||||
between a button press and the user typing and sending exactly the
|
between a button press and the user typing and sending exactly the
|
||||||
same text on their own.
|
same text on their own.
|
||||||
"""
|
"""
|
||||||
return cls(types.KeyboardButton(text),
|
return cls(
|
||||||
resize=resize, single_use=single_use, selective=selective)
|
types.KeyboardButton(text),
|
||||||
|
resize=resize,
|
||||||
|
single_use=single_use,
|
||||||
|
selective=selective,
|
||||||
|
persistent=persistent,
|
||||||
|
placeholder=placeholder
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request_location(cls, text, *,
|
def request_location(cls, text, *, resize=None, single_use=None, selective=None,
|
||||||
resize=None, single_use=None, selective=None):
|
persistent=None, placeholder=None):
|
||||||
"""
|
"""
|
||||||
Creates a new keyboard button to request the user's location on click.
|
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
|
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
|
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.
|
bot, and if confirmed a message with geo media will be sent.
|
||||||
"""
|
"""
|
||||||
return cls(types.KeyboardButtonRequestGeoLocation(text),
|
return cls(
|
||||||
resize=resize, single_use=single_use, selective=selective)
|
types.KeyboardButtonRequestGeoLocation(text),
|
||||||
|
resize=resize,
|
||||||
|
single_use=single_use,
|
||||||
|
selective=selective,
|
||||||
|
persistent=persistent,
|
||||||
|
placeholder=placeholder
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request_phone(cls, text, *,
|
def request_phone(cls, text, *, resize=None, single_use=None,
|
||||||
resize=None, single_use=None, selective=None):
|
selective=None, persistent=None, placeholder=None):
|
||||||
"""
|
"""
|
||||||
Creates a new keyboard button to request the user's phone on click.
|
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
|
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
|
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.
|
bot, and if confirmed a message with contact media will be sent.
|
||||||
"""
|
"""
|
||||||
return cls(types.KeyboardButtonRequestPhone(text),
|
return cls(
|
||||||
resize=resize, single_use=single_use, selective=selective)
|
types.KeyboardButtonRequestPhone(text),
|
||||||
|
resize=resize,
|
||||||
|
single_use=single_use,
|
||||||
|
selective=selective,
|
||||||
|
placeholder=placeholder,
|
||||||
|
persistent=persistent
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request_poll(cls, text, *, force_quiz=False,
|
def request_poll(cls, text, *, force_quiz=False, resize=None, single_use=None,
|
||||||
resize=None, single_use=None, selective=None):
|
selective=None, persistent=None, placeholder=None):
|
||||||
"""
|
"""
|
||||||
Creates a new keyboard button to request the user to create a poll.
|
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 votes cannot be retracted. Otherwise, users can vote and retract
|
||||||
the vote, and the pol might be multiple choice.
|
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
|
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.
|
poll will be shown, and if they do create one, the poll will be sent.
|
||||||
"""
|
"""
|
||||||
return cls(types.KeyboardButtonRequestPoll(text, quiz=force_quiz),
|
return cls(
|
||||||
resize=resize, single_use=single_use, selective=selective)
|
types.KeyboardButtonRequestPoll(text, quiz=force_quiz),
|
||||||
|
resize=resize,
|
||||||
|
single_use=single_use,
|
||||||
|
selective=selective,
|
||||||
|
persistent=persistent,
|
||||||
|
placeholder=placeholder
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def clear(selective=None):
|
def clear(selective=None):
|
||||||
@ -265,15 +308,8 @@ class Button:
|
|||||||
Forces a reply to the message with this markup. If used,
|
Forces a reply to the message with this markup. If used,
|
||||||
no other button should be present or it will be ignored.
|
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(
|
return types.ReplyKeyboardForceReply(
|
||||||
single_use=single_use,
|
single_use=single_use,
|
||||||
|
Loading…
Reference in New Issue
Block a user