diff --git a/client/src/telethon/_impl/client/events/queries.py b/client/src/telethon/_impl/client/events/queries.py index 340b1c1d..d0b2f318 100644 --- a/client/src/telethon/_impl/client/events/queries.py +++ b/client/src/telethon/_impl/client/events/queries.py @@ -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(" 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( - "