mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-22 09:26:37 +03:00
update get_message and @property chat for ButtonCallback
This commit is contained in:
parent
5b33b4b9c1
commit
fbf0adb87b
|
@ -4,8 +4,10 @@ import struct
|
|||
import typing
|
||||
from typing import TYPE_CHECKING, Dict, Optional, Self, Union
|
||||
|
||||
from .. import errors
|
||||
from ...session import PackedType
|
||||
from ...tl import abcs, functions, types
|
||||
from ..types import Chat, Message, Channel
|
||||
from ..types import Chat, Message, Channel, Group
|
||||
from .event import Event
|
||||
from ..types.chat import peer_id
|
||||
from ..client.messages import CherryPickedList
|
||||
|
@ -64,8 +66,8 @@ class ButtonCallback(Event):
|
|||
@property
|
||||
def message_id(self) -> typing.Union[int, abcs.InputBotInlineMessageId]:
|
||||
"""
|
||||
The ID of the message containing the button that was clicked.
|
||||
|
||||
The identifier of the message containing the button that was clicked.
|
||||
|
||||
If the message is inline, :class:`abcs.InputBotInlineMessageId` will be returned.
|
||||
You can use it in :meth:`~telethon._tl.functions.messages.edit_inline_bot_message` to edit the message.
|
||||
|
||||
|
@ -81,38 +83,56 @@ class ButtonCallback(Event):
|
|||
This may be :data:`None` if :data:`via_inline` is :data:`True`, as the bot might not be part of the chat.
|
||||
"""
|
||||
if isinstance(self._raw, types.UpdateInlineBotCallbackQuery):
|
||||
# for that type of update, the msg_id and owner_id are present, however bot is not guaranteed
|
||||
# to have "access" to the owner_id.
|
||||
owner_id = None
|
||||
if isinstance(self._raw.msg_id, types.InputBotInlineMessageId):
|
||||
_, owner_id = struct.unpack("<ii", struct.pack("<q", self._raw.msg_id.id))
|
||||
# telegram used to pack msg_id and peer_id into InputBotInlineMessageId.id
|
||||
# I assume this is for the chats with IDs, fitting into 32-bit integer.
|
||||
_, owner_id = struct.unpack(
|
||||
"<ii", struct.pack("<q", self._raw.msg_id.id)
|
||||
)
|
||||
elif isinstance(self._raw.msg_id, types.InputBotInlineMessageId64):
|
||||
_ = self._raw.msg_id.id
|
||||
owner_id = self._raw.msg_id.owner_id
|
||||
else:
|
||||
raise RuntimeError(f"unexpected type of msg_id: {type(self._raw.msg_id)}")
|
||||
|
||||
if owner_id is None:
|
||||
return None
|
||||
|
||||
if owner_id > 0:
|
||||
# We can't know if it's really a chat with user, or an ID of the user who issued the inline query.
|
||||
# So it's better to return None, then to return wrong chat.
|
||||
# So it's better to return None, than to return wrong chat.
|
||||
return None
|
||||
|
||||
owner_id = -owner_id
|
||||
|
||||
access_hash = 0
|
||||
packed = self.client._chat_hashes.get(owner_id)
|
||||
if packed:
|
||||
access_hash = packed.access_hash
|
||||
if owner := self._chat_map.get(owner_id):
|
||||
return owner
|
||||
|
||||
return Channel._from_raw(
|
||||
types.ChannelForbidden(
|
||||
broadcast=True,
|
||||
megagroup=False,
|
||||
id=owner_id,
|
||||
access_hash=access_hash,
|
||||
title="",
|
||||
until_date=None,
|
||||
)
|
||||
packed = self.client._chat_hashes.get(owner_id)
|
||||
|
||||
raw = types.ChannelForbidden(
|
||||
broadcast=False,
|
||||
megagroup=False,
|
||||
id=owner_id,
|
||||
access_hash=0,
|
||||
title="",
|
||||
until_date=None,
|
||||
)
|
||||
|
||||
if packed:
|
||||
raw.access_hash = packed.access_hash
|
||||
|
||||
if packed.ty == PackedType.MEGAGROUP or packed.ty == PackedType.GIGAGROUP:
|
||||
if packed.ty == PackedType.GIGAGROUP:
|
||||
raw.gigagroup = True
|
||||
else:
|
||||
raw.megagroup = True
|
||||
return Group._from_raw(self.client, raw)
|
||||
raw.broadcast = True
|
||||
return Channel._from_raw(raw)
|
||||
return self._chat_map.get(peer_id(self._raw.peer))
|
||||
|
||||
async def answer(
|
||||
|
@ -149,54 +169,37 @@ class ButtonCallback(Event):
|
|||
|
||||
If the message is inline, or too old and is no longer accessible, :data:`None` is returned instead.
|
||||
"""
|
||||
chat = None
|
||||
chat = self.chat
|
||||
|
||||
# numeric_id, received in this case, is:
|
||||
# - a correct message id, if it was sent in a channel (or megagroup, gigagroup)
|
||||
# - a sender's message id, if it was sent in a private chat. So it's not a correct ID from bot perspective,
|
||||
# as each account has its own message id counter for private chats (pm, small group chats).
|
||||
if isinstance(self._raw, types.UpdateInlineBotCallbackQuery):
|
||||
# for that type of update, the msg_id and owner_id are present, however bot is not guaranteed
|
||||
# to have "access" to the owner_id.
|
||||
if isinstance(self._raw.msg_id, types.InputBotInlineMessageId):
|
||||
# telegram used to pack msg_id and peer_id into InputBotInlineMessageId.id
|
||||
# I assume this is for the chats with IDs, fitting into 32-bit integer.
|
||||
msg_id, owner_id = struct.unpack(
|
||||
"<ii", struct.pack("<q", self._raw.msg_id.id)
|
||||
)
|
||||
numeric_id, _ = struct.unpack("<ii", struct.pack("<q", self._raw.msg_id.id))
|
||||
elif isinstance(self._raw.msg_id, types.InputBotInlineMessageId64):
|
||||
msg_id = self._raw.msg_id.id
|
||||
owner_id = self._raw.msg_id.owner_id
|
||||
numeric_id = self._raw.msg_id.id
|
||||
else:
|
||||
return None
|
||||
|
||||
msg = types.InputMessageCallbackQuery(
|
||||
id=msg_id, query_id=self._raw.query_id
|
||||
)
|
||||
if owner_id < 0:
|
||||
# that means update's owner_id actually is the peer (channel), where the button was clicked.
|
||||
# if it was positive, it'd be the user who issued the inline query.
|
||||
try:
|
||||
chat = await self._client._resolve_to_packed(-owner_id)
|
||||
except ValueError:
|
||||
pass
|
||||
raise RuntimeError(f"unexpected type of msg_id: {type(self._raw.msg_id)}")
|
||||
else:
|
||||
pid = peer_id(self._raw.peer)
|
||||
msg = types.InputMessageCallbackQuery(
|
||||
id=self._raw.msg_id, query_id=self._raw.query_id
|
||||
)
|
||||
|
||||
chat = self._chat_map.get(pid)
|
||||
if not chat:
|
||||
chat = await self._client._resolve_to_packed(pid)
|
||||
numeric_id = self._raw.msg_id
|
||||
|
||||
if chat:
|
||||
lst = CherryPickedList(self._client, chat, [])
|
||||
lst._ids.append(msg)
|
||||
|
||||
res = await lst
|
||||
if res:
|
||||
return res[0] or None
|
||||
lst = CherryPickedList(self._client, chat, [numeric_id])
|
||||
try:
|
||||
res = await lst
|
||||
if res:
|
||||
return res[0] or None
|
||||
except errors.RpcError as e:
|
||||
if e.name != "CHANNEL_INVALID" and e.name != "MESSAGE_IDS_EMPTY":
|
||||
raise
|
||||
|
||||
# I didn't notice a single case, when this request returns a message.
|
||||
# However, theoretically, self._raw.msg_id is a valid type of InputMessageID, so it may be possible.
|
||||
res = await self._client(
|
||||
functions.messages.get_messages(
|
||||
id=[msg],
|
||||
id=[self._raw.msg_id],
|
||||
)
|
||||
)
|
||||
return res.messages[0] if res.messages else None
|
||||
|
|
Loading…
Reference in New Issue
Block a user