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
import struct
from typing import TYPE_CHECKING, Dict, Optional, Self, Union
from ...tl import abcs, functions, types
from ..types import Chat, Message
from ..types import Chat, Message, Channel
from .event import Event
from ..types.chat import peer_id
from ..client.messages import CherryPickedList
@ -34,7 +35,10 @@ class ButtonCallback(Event):
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
) -> Optional[Self]:
if (
isinstance(update, (types.UpdateBotCallbackQuery, types.UpdateInlineBotCallbackQuery))
isinstance(
update,
(types.UpdateBotCallbackQuery, types.UpdateInlineBotCallbackQuery),
)
and update.data is not None
):
return cls._create(client, update, chat_map)
@ -51,10 +55,41 @@ class ButtonCallback(Event):
"""
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):
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))
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.
"""
chat = None
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)
chat = self._chat_map.get(pid)
if not chat:
chat = await self._client._resolve_to_packed(pid)
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
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, [])
lst._ids.append(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)
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):