Implemented get_message, chat for types.UpdateInlineBotCallbackQuery for ButtonCallback event

This commit is contained in:
apepenkov 2023-12-17 22:35:48 +03:00
parent 69e741f2cf
commit 508a0ab59e

View File

@ -1,9 +1,10 @@
from __future__ import annotations from __future__ import annotations
import struct
from typing import TYPE_CHECKING, Dict, Optional, Self, Union from typing import TYPE_CHECKING, Dict, Optional, Self, Union
from ...tl import abcs, functions, types from ...tl import abcs, functions, types
from ..types import Chat, Message from ..types import Chat, Message, Channel
from .event import Event from .event import Event
from ..types.chat import peer_id from ..types.chat import peer_id
from ..client.messages import CherryPickedList from ..client.messages import CherryPickedList
@ -34,7 +35,10 @@ class ButtonCallback(Event):
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat] cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
) -> Optional[Self]: ) -> Optional[Self]:
if ( if (
isinstance(update, (types.UpdateBotCallbackQuery, types.UpdateInlineBotCallbackQuery)) isinstance(
update,
(types.UpdateBotCallbackQuery, types.UpdateInlineBotCallbackQuery),
)
and update.data is not None and update.data is not None
): ):
return cls._create(client, update, chat_map) return cls._create(client, update, chat_map)
@ -51,10 +55,41 @@ class ButtonCallback(Event):
""" """
The :term:`chat` where the button was clicked. The :term:`chat` where the button was clicked.
This will be :data:`None` if the message with the button was sent from a user's inline query. This will be :data:`None` if the message with the button was sent from a user's inline query, except in channel.
""" """
if isinstance(self._raw, types.UpdateInlineBotCallbackQuery): if isinstance(self._raw, types.UpdateInlineBotCallbackQuery):
return None owner_id = None
if isinstance(self._raw.msg_id, types.InputBotInlineMessageId):
_, 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
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.
return None
owner_id = -owner_id
access_hash = 0
packed = self.client._chat_hashes.get(owner_id)
if packed:
access_hash = packed.access_hash
return Channel._from_raw(
types.ChannelForbidden(
broadcast=True,
megagroup=False,
id=owner_id,
access_hash=access_hash,
title="",
until_date=None,
)
)
return self._chat_map.get(peer_id(self._raw.peer)) return self._chat_map.get(peer_id(self._raw.peer))
async def answer( async def answer(
@ -91,20 +126,57 @@ class ButtonCallback(Event):
If the message is inline, or too old and is no longer accessible, :data:`None` is returned instead. If the message is inline, or too old and is no longer accessible, :data:`None` is returned instead.
""" """
chat = None
if isinstance(self._raw, types.UpdateInlineBotCallbackQuery): if isinstance(self._raw, types.UpdateInlineBotCallbackQuery):
return None # 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)
)
elif isinstance(self._raw.msg_id, types.InputBotInlineMessageId64):
msg_id = self._raw.msg_id.id
owner_id = self._raw.msg_id.owner_id
else:
return None
pid = peer_id(self._raw.peer) msg = types.InputMessageCallbackQuery(
chat = self._chat_map.get(pid) id=msg_id, query_id=self._raw.query_id
if not chat: )
chat = await self._client._resolve_to_packed(pid) 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
else:
pid = peer_id(self._raw.peer)
msg = types.InputMessageCallbackQuery(
id=self._raw.msg_id, query_id=self._raw.query_id
)
lst = CherryPickedList(self._client, chat, []) chat = self._chat_map.get(pid)
lst._ids.append(types.InputMessageCallbackQuery(id=self._raw.msg_id, query_id=self._raw.query_id)) if not chat:
chat = await self._client._resolve_to_packed(pid)
message = (await lst)[0] if chat:
lst = CherryPickedList(self._client, chat, [])
lst._ids.append(msg)
return message or None res = await lst
if res:
return res[0] or None
res = await self._client(
functions.messages.get_messages(
id=[msg],
)
)
return res.messages[0] if res.messages else None
class InlineQuery(Event): class InlineQuery(Event):