mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-07-27 08:19:47 +03:00
Adding ReplyKeyboardMarkup and ReplyInlineMarkup custom types
This commit is contained in:
parent
ee3248c3a4
commit
21d2ded546
|
@ -45,7 +45,7 @@ from ..types import (
|
||||||
RecentAction,
|
RecentAction,
|
||||||
User,
|
User,
|
||||||
)
|
)
|
||||||
from ..types import buttons as btns
|
from ..types.buttons.reply_markup import ReplyMarkupType
|
||||||
from .auth import (
|
from .auth import (
|
||||||
bot_sign_in,
|
bot_sign_in,
|
||||||
check_password,
|
check_password,
|
||||||
|
@ -216,6 +216,7 @@ class Client:
|
||||||
datacenter: Optional[DataCenter] = None,
|
datacenter: Optional[DataCenter] = None,
|
||||||
connector: Optional[Connector] = None,
|
connector: Optional[Connector] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
assert isinstance(__package__, str)
|
||||||
base_logger = logger or logging.getLogger(__package__[: __package__.index(".")])
|
base_logger = logger or logging.getLogger(__package__[: __package__.index(".")])
|
||||||
|
|
||||||
self._sender: Optional[Sender] = None
|
self._sender: Optional[Sender] = None
|
||||||
|
@ -571,7 +572,7 @@ class Client:
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
buttons: Optional[ReplyMarkupType] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Edit a message.
|
Edit a message.
|
||||||
|
@ -1393,7 +1394,7 @@ class Client:
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
buttons: Optional[ReplyMarkupType] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send an audio file.
|
Send an audio file.
|
||||||
|
@ -1466,7 +1467,7 @@ class Client:
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]],
|
buttons: Optional[ReplyMarkupType],
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send any type of file with any amount of attributes.
|
Send any type of file with any amount of attributes.
|
||||||
|
@ -1633,7 +1634,7 @@ class Client:
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
buttons: Optional[ReplyMarkupType] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send a message.
|
Send a message.
|
||||||
|
@ -1687,7 +1688,7 @@ class Client:
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
buttons: Optional[ReplyMarkupType] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send a photo file.
|
Send a photo file.
|
||||||
|
@ -1755,7 +1756,7 @@ class Client:
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]],
|
buttons: Optional[ReplyMarkupType],
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send a video file.
|
Send a video file.
|
||||||
|
|
|
@ -17,14 +17,12 @@ from ..types import (
|
||||||
OutFileLike,
|
OutFileLike,
|
||||||
OutWrapper,
|
OutWrapper,
|
||||||
Peer,
|
Peer,
|
||||||
)
|
|
||||||
from ..types import buttons as btns
|
|
||||||
from ..types import (
|
|
||||||
expand_stripped_size,
|
expand_stripped_size,
|
||||||
generate_random_id,
|
generate_random_id,
|
||||||
parse_message,
|
parse_message,
|
||||||
try_get_url_path,
|
try_get_url_path,
|
||||||
)
|
)
|
||||||
|
from ..types.buttons.reply_markup import ReplyMarkupType
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .client import Client
|
from .client import Client
|
||||||
|
@ -59,7 +57,7 @@ async def send_photo(
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
buttons: Optional[ReplyMarkupType] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
return await send_file(
|
return await send_file(
|
||||||
self,
|
self,
|
||||||
|
@ -100,7 +98,7 @@ async def send_audio(
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
buttons: Optional[ReplyMarkupType] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
return await send_file(
|
return await send_file(
|
||||||
self,
|
self,
|
||||||
|
@ -140,7 +138,7 @@ async def send_video(
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]],
|
buttons: Optional[ReplyMarkupType],
|
||||||
) -> Message:
|
) -> Message:
|
||||||
return await send_file(
|
return await send_file(
|
||||||
self,
|
self,
|
||||||
|
@ -189,7 +187,7 @@ async def send_file(
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]],
|
buttons: Optional[ReplyMarkupType],
|
||||||
) -> Message:
|
) -> Message:
|
||||||
message, entities = parse_message(
|
message, entities = parse_message(
|
||||||
text=caption, markdown=caption_markdown, html=caption_html, allow_empty=True
|
text=caption, markdown=caption_markdown, html=caption_html, allow_empty=True
|
||||||
|
@ -299,7 +297,7 @@ async def do_send_file(
|
||||||
message: str,
|
message: str,
|
||||||
entities: Optional[list[abcs.MessageEntity]],
|
entities: Optional[list[abcs.MessageEntity]],
|
||||||
reply_to: Optional[int],
|
reply_to: Optional[int],
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]],
|
buttons: Optional[ReplyMarkupType],
|
||||||
) -> Message:
|
) -> Message:
|
||||||
random_id = generate_random_id()
|
random_id = generate_random_id()
|
||||||
return client._build_message_map(
|
return client._build_message_map(
|
||||||
|
@ -319,7 +317,7 @@ async def do_send_file(
|
||||||
media=input_media,
|
media=input_media,
|
||||||
message=message,
|
message=message,
|
||||||
random_id=random_id,
|
random_id=random_id,
|
||||||
reply_markup=btns.build_keyboard(buttons),
|
reply_markup=buttons.build() if buttons is not None else None,
|
||||||
entities=entities,
|
entities=entities,
|
||||||
schedule_date=None,
|
schedule_date=None,
|
||||||
send_as=None,
|
send_as=None,
|
||||||
|
|
|
@ -6,9 +6,16 @@ from typing import TYPE_CHECKING, Literal, Optional, Self
|
||||||
|
|
||||||
from ...session import ChannelRef, PeerRef
|
from ...session import ChannelRef, PeerRef
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
from ..types import AsyncList, Message, Peer, build_chat_map
|
from ..types import (
|
||||||
from ..types import buttons as btns
|
AsyncList,
|
||||||
from ..types import generate_random_id, parse_message, peer_id
|
Message,
|
||||||
|
Peer,
|
||||||
|
build_chat_map,
|
||||||
|
generate_random_id,
|
||||||
|
parse_message,
|
||||||
|
peer_id,
|
||||||
|
)
|
||||||
|
from ..types.buttons.reply_markup import ReplyMarkupType
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .client import Client
|
from .client import Client
|
||||||
|
@ -24,7 +31,7 @@ async def send_message(
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
buttons: Optional[ReplyMarkupType] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
random_id = generate_random_id()
|
random_id = generate_random_id()
|
||||||
|
|
||||||
|
@ -71,7 +78,7 @@ async def send_message(
|
||||||
),
|
),
|
||||||
message=message,
|
message=message,
|
||||||
random_id=random_id,
|
random_id=random_id,
|
||||||
reply_markup=btns.build_keyboard(buttons),
|
reply_markup=buttons.build() if buttons is not None else None,
|
||||||
entities=entities,
|
entities=entities,
|
||||||
schedule_date=None,
|
schedule_date=None,
|
||||||
send_as=None,
|
send_as=None,
|
||||||
|
@ -121,7 +128,7 @@ async def edit_message(
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
buttons: Optional[ReplyMarkupType] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
message, entities = parse_message(
|
message, entities = parse_message(
|
||||||
text=text, markdown=markdown, html=html, allow_empty=False
|
text=text, markdown=markdown, html=html, allow_empty=False
|
||||||
|
@ -134,7 +141,7 @@ async def edit_message(
|
||||||
id=message_id,
|
id=message_id,
|
||||||
message=message,
|
message=message,
|
||||||
media=None,
|
media=None,
|
||||||
reply_markup=btns.build_keyboard(buttons),
|
reply_markup=buttons.build() if buttons is not None else None,
|
||||||
entities=entities,
|
entities=entities,
|
||||||
schedule_date=None,
|
schedule_date=None,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import weakref
|
import weakref
|
||||||
from typing import TYPE_CHECKING, Optional
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from ....tl import abcs, types
|
from ....tl import abcs, types
|
||||||
from .button import Button
|
from .button import Button
|
||||||
from .callback import Callback
|
from .callback import Callback
|
||||||
from .inline_button import InlineButton
|
from .inline_button import InlineButton
|
||||||
|
from .reply_markup import ReplyInlineMarkup, ReplyKeyboardMarkup
|
||||||
from .request_geo_location import RequestGeoLocation
|
from .request_geo_location import RequestGeoLocation
|
||||||
from .request_phone import RequestPhone
|
from .request_phone import RequestPhone
|
||||||
from .request_poll import RequestPoll
|
from .request_poll import RequestPoll
|
||||||
|
@ -23,40 +24,6 @@ def as_concrete_row(row: abcs.KeyboardButtonRow) -> types.KeyboardButtonRow:
|
||||||
return row
|
return row
|
||||||
|
|
||||||
|
|
||||||
def build_keyboard(
|
|
||||||
btns: Optional[list[Button] | list[list[Button]]],
|
|
||||||
) -> Optional[abcs.ReplyMarkup]:
|
|
||||||
# list[button] -> list[list[button]]
|
|
||||||
# This does allow for "invalid" inputs (mixing lists and non-lists), but that's acceptable.
|
|
||||||
buttons_lists_iter = (
|
|
||||||
button if isinstance(button, list) else [button] for button in (btns or [])
|
|
||||||
)
|
|
||||||
# Remove empty rows (also making it easy to check if all-empty).
|
|
||||||
buttons_lists = [bs for bs in buttons_lists_iter if bs]
|
|
||||||
|
|
||||||
if not buttons_lists:
|
|
||||||
return None
|
|
||||||
|
|
||||||
rows: list[abcs.KeyboardButtonRow] = [
|
|
||||||
types.KeyboardButtonRow(buttons=[btn._raw for btn in btns])
|
|
||||||
for btns in buttons_lists
|
|
||||||
]
|
|
||||||
|
|
||||||
# Guaranteed to have at least one, first one used to check if it's inline.
|
|
||||||
# If the user mixed inline with non-inline, Telegram will complain.
|
|
||||||
if isinstance(buttons_lists[0][0], InlineButton):
|
|
||||||
return types.ReplyInlineMarkup(rows=rows)
|
|
||||||
else:
|
|
||||||
return types.ReplyKeyboardMarkup(
|
|
||||||
resize=False,
|
|
||||||
single_use=False,
|
|
||||||
selective=False,
|
|
||||||
persistent=False,
|
|
||||||
rows=rows,
|
|
||||||
placeholder=None,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def create_button(message: Message, raw: abcs.KeyboardButton) -> Button:
|
def create_button(message: Message, raw: abcs.KeyboardButton) -> Button:
|
||||||
"""
|
"""
|
||||||
Create a custom button from a Telegram button.
|
Create a custom button from a Telegram button.
|
||||||
|
@ -113,6 +80,8 @@ __all__ = [
|
||||||
"Button",
|
"Button",
|
||||||
"Callback",
|
"Callback",
|
||||||
"InlineButton",
|
"InlineButton",
|
||||||
|
"ReplyInlineMarkup",
|
||||||
|
"ReplyKeyboardMarkup",
|
||||||
"RequestGeoLocation",
|
"RequestGeoLocation",
|
||||||
"RequestPhone",
|
"RequestPhone",
|
||||||
"RequestPoll",
|
"RequestPoll",
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
from typing import Optional, TypeAlias
|
||||||
|
|
||||||
|
from ....tl import abcs, types
|
||||||
|
from .button import Button
|
||||||
|
|
||||||
|
|
||||||
|
def build_keyboard_rows(
|
||||||
|
btns: list[Button] | list[list[Button]],
|
||||||
|
) -> list[abcs.KeyboardButtonRow]:
|
||||||
|
# list[button] -> list[list[button]]
|
||||||
|
# This does allow for "invalid" inputs (mixing lists and non-lists), but that's acceptable.
|
||||||
|
buttons_lists_iter = [
|
||||||
|
button if isinstance(button, list) else [button] for button in (btns or [])
|
||||||
|
]
|
||||||
|
# Remove empty rows (also making it easy to check if all-empty).
|
||||||
|
buttons_lists = [bs for bs in buttons_lists_iter if bs]
|
||||||
|
|
||||||
|
return [
|
||||||
|
types.KeyboardButtonRow(buttons=[btn._raw for btn in btns])
|
||||||
|
for btns in buttons_lists
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ReplyKeyboardMarkup:
|
||||||
|
__slots__ = (
|
||||||
|
"_btns",
|
||||||
|
"resize",
|
||||||
|
"single_use",
|
||||||
|
"selective",
|
||||||
|
"persistent",
|
||||||
|
"placeholder",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
btns: list[Button] | list[list[Button]],
|
||||||
|
resize: bool,
|
||||||
|
single_use: bool,
|
||||||
|
selective: bool,
|
||||||
|
persistent: bool,
|
||||||
|
placeholder: Optional[str],
|
||||||
|
) -> None:
|
||||||
|
self._btns = build_keyboard_rows(btns)
|
||||||
|
self.resize = resize
|
||||||
|
self.single_use = single_use
|
||||||
|
self.selective = selective
|
||||||
|
self.persistent = persistent
|
||||||
|
self.placeholder = placeholder
|
||||||
|
|
||||||
|
def build(self) -> abcs.ReplyMarkup:
|
||||||
|
return types.ReplyKeyboardMarkup(
|
||||||
|
resize=self.resize,
|
||||||
|
single_use=self.single_use,
|
||||||
|
selective=self.selective,
|
||||||
|
persistent=self.persistent,
|
||||||
|
rows=self._btns,
|
||||||
|
placeholder=self.placeholder,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ReplyInlineMarkup:
|
||||||
|
__slots__ = ("_btns",)
|
||||||
|
|
||||||
|
def __init__(self, btns: list[Button] | list[list[Button]]) -> None:
|
||||||
|
self._btns = build_keyboard_rows(btns)
|
||||||
|
|
||||||
|
def build(self) -> abcs.ReplyMarkup:
|
||||||
|
return types.ReplyInlineMarkup(rows=self._btns)
|
||||||
|
|
||||||
|
|
||||||
|
ReplyMarkupType: TypeAlias = ReplyKeyboardMarkup | ReplyInlineMarkup
|
|
@ -22,7 +22,12 @@ from .._impl.client.types import (
|
||||||
RecentAction,
|
RecentAction,
|
||||||
User,
|
User,
|
||||||
)
|
)
|
||||||
from .._impl.client.types.buttons import Button, InlineButton
|
from .._impl.client.types.buttons import (
|
||||||
|
Button,
|
||||||
|
InlineButton,
|
||||||
|
ReplyInlineMarkup,
|
||||||
|
ReplyKeyboardMarkup,
|
||||||
|
)
|
||||||
from .._impl.session import ChannelRef, GroupRef, PeerRef, UserRef
|
from .._impl.session import ChannelRef, GroupRef, PeerRef, UserRef
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -42,6 +47,8 @@ __all__ = [
|
||||||
"Message",
|
"Message",
|
||||||
"Participant",
|
"Participant",
|
||||||
"PasswordToken",
|
"PasswordToken",
|
||||||
|
"ReplyInlineMarkup",
|
||||||
|
"ReplyKeyboardMarkup",
|
||||||
"RecentAction",
|
"RecentAction",
|
||||||
"User",
|
"User",
|
||||||
"Button",
|
"Button",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user