Add callback query support
This commit is contained in:
parent
c1459aa22c
commit
9c7935702f
@ -500,7 +500,9 @@ def start():
|
|||||||
f.write("\n 0xb0700020: \"pyrogram.client.types.reply_markup.InlineKeyboardMarkup\",")
|
f.write("\n 0xb0700020: \"pyrogram.client.types.reply_markup.InlineKeyboardMarkup\",")
|
||||||
f.write("\n 0xb0700021: \"pyrogram.client.types.reply_markup.KeyboardButton\",")
|
f.write("\n 0xb0700021: \"pyrogram.client.types.reply_markup.KeyboardButton\",")
|
||||||
f.write("\n 0xb0700022: \"pyrogram.client.types.reply_markup.ReplyKeyboardMarkup\",")
|
f.write("\n 0xb0700022: \"pyrogram.client.types.reply_markup.ReplyKeyboardMarkup\",")
|
||||||
f.write("\n 0xb0700023: \"pyrogram.client.types.reply_markup.ReplyKeyboardRemove\"")
|
f.write("\n 0xb0700023: \"pyrogram.client.types.reply_markup.ReplyKeyboardRemove\",")
|
||||||
|
|
||||||
|
f.write("\n 0xb0700024: \"pyrogram.client.types.CallbackQuery\"")
|
||||||
|
|
||||||
f.write("\n}\n")
|
f.write("\n}\n")
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ from .client.types import (
|
|||||||
Audio, Chat, ChatMember, ChatPhoto, Contact, Document, InputMediaPhoto,
|
Audio, Chat, ChatMember, ChatPhoto, Contact, Document, InputMediaPhoto,
|
||||||
InputMediaVideo, InputPhoneContact, Location, Message, MessageEntity,
|
InputMediaVideo, InputPhoneContact, Location, Message, MessageEntity,
|
||||||
PhotoSize, Sticker, Update, User, UserProfilePhotos, Venue, Video,
|
PhotoSize, Sticker, Update, User, UserProfilePhotos, Venue, Video,
|
||||||
VideoNote, Voice
|
VideoNote, Voice, CallbackQuery
|
||||||
)
|
)
|
||||||
from .client.types.reply_markup import (
|
from .client.types.reply_markup import (
|
||||||
ForceReply, InlineKeyboardButton, InlineKeyboardMarkup,
|
ForceReply, InlineKeyboardButton, InlineKeyboardMarkup,
|
||||||
@ -38,5 +38,6 @@ from .client.types.reply_markup import (
|
|||||||
)
|
)
|
||||||
from .client import (
|
from .client import (
|
||||||
Client, ChatAction, ParseMode, Emoji,
|
Client, ChatAction, ParseMode, Emoji,
|
||||||
MessageHandler, RawUpdateHandler, Filters
|
MessageHandler, CallbackQueryHandler, RawUpdateHandler,
|
||||||
|
Filters
|
||||||
)
|
)
|
||||||
|
@ -20,5 +20,5 @@ from .chat_action import ChatAction
|
|||||||
from .client import Client
|
from .client import Client
|
||||||
from .emoji import Emoji
|
from .emoji import Emoji
|
||||||
from .filters import Filters
|
from .filters import Filters
|
||||||
from .handlers import MessageHandler, RawUpdateHandler
|
from .handlers import MessageHandler, CallbackQueryHandler, RawUpdateHandler
|
||||||
from .parse_mode import ParseMode
|
from .parse_mode import ParseMode
|
||||||
|
@ -227,6 +227,13 @@ class Client:
|
|||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
def on_callback_query(self, filters=None, group: int = 0):
|
||||||
|
def decorator(func):
|
||||||
|
self.add_handler(pyrogram.CallbackQueryHandler(func, filters), group)
|
||||||
|
return func
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
def on_raw_update(self, group: int = 0):
|
def on_raw_update(self, group: int = 0):
|
||||||
"""Use this decorator to automatically register a function for handling
|
"""Use this decorator to automatically register a function for handling
|
||||||
raw updates. This does the same thing as :meth:`add_handler` using the
|
raw updates. This does the same thing as :meth:`add_handler` using the
|
||||||
@ -3525,3 +3532,19 @@ class Client:
|
|||||||
)
|
)
|
||||||
|
|
||||||
return messages if is_list else messages[0]
|
return messages if is_list else messages[0]
|
||||||
|
|
||||||
|
def answer_callback_cuery(self,
|
||||||
|
callback_query_id: str,
|
||||||
|
text: str = None,
|
||||||
|
show_alert: bool = None,
|
||||||
|
url: str = None,
|
||||||
|
cache_time: int = 0):
|
||||||
|
return self.send(
|
||||||
|
functions.messages.SetBotCallbackAnswer(
|
||||||
|
query_id=int(callback_query_id),
|
||||||
|
cache_time=cache_time,
|
||||||
|
alert=show_alert,
|
||||||
|
message=text,
|
||||||
|
url=url
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ -25,23 +25,23 @@ from threading import Thread
|
|||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import types
|
from pyrogram.api import types
|
||||||
from .. import utils
|
from .. import utils
|
||||||
from ..handlers import RawUpdateHandler, MessageHandler
|
from ..handlers import RawUpdateHandler, CallbackQueryHandler, MessageHandler
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Dispatcher:
|
class Dispatcher:
|
||||||
MESSAGE_UPDATES = (
|
NEW_MESSAGE_UPDATES = (
|
||||||
types.UpdateNewMessage,
|
types.UpdateNewMessage,
|
||||||
types.UpdateNewChannelMessage
|
types.UpdateNewChannelMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
EDIT_UPDATES = (
|
EDIT_MESSAGE_UPDATES = (
|
||||||
types.UpdateEditMessage,
|
types.UpdateEditMessage,
|
||||||
types.UpdateEditChannelMessage
|
types.UpdateEditChannelMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
ALLOWED_UPDATES = MESSAGE_UPDATES + EDIT_UPDATES
|
MESSAGE_UPDATES = NEW_MESSAGE_UPDATES + EDIT_MESSAGE_UPDATES
|
||||||
|
|
||||||
def __init__(self, client, workers):
|
def __init__(self, client, workers):
|
||||||
self.client = client
|
self.client = client
|
||||||
@ -84,18 +84,25 @@ class Dispatcher:
|
|||||||
|
|
||||||
args = (self.client, update, users, chats)
|
args = (self.client, update, users, chats)
|
||||||
else:
|
else:
|
||||||
if not isinstance(handler, MessageHandler):
|
|
||||||
continue
|
|
||||||
|
|
||||||
message = (update.message
|
message = (update.message
|
||||||
or update.channel_post
|
or update.channel_post
|
||||||
or update.edited_message
|
or update.edited_message
|
||||||
or update.edited_channel_post)
|
or update.edited_channel_post)
|
||||||
|
|
||||||
if not handler.check(message):
|
callback_query = update.callback_query
|
||||||
continue
|
|
||||||
|
|
||||||
args = (self.client, message)
|
if message and isinstance(handler, MessageHandler):
|
||||||
|
if not handler.check(message):
|
||||||
|
continue
|
||||||
|
|
||||||
|
args = (self.client, message)
|
||||||
|
elif callback_query and isinstance(handler, CallbackQueryHandler):
|
||||||
|
if not handler.check(callback_query):
|
||||||
|
continue
|
||||||
|
|
||||||
|
args = (self.client, callback_query)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
handler.callback(*args)
|
handler.callback(*args)
|
||||||
break
|
break
|
||||||
@ -117,7 +124,7 @@ class Dispatcher:
|
|||||||
|
|
||||||
self.dispatch(update, users=users, chats=chats, is_raw=True)
|
self.dispatch(update, users=users, chats=chats, is_raw=True)
|
||||||
|
|
||||||
if isinstance(update, Dispatcher.ALLOWED_UPDATES):
|
if isinstance(update, Dispatcher.MESSAGE_UPDATES):
|
||||||
if isinstance(update.message, types.Message):
|
if isinstance(update.message, types.Message):
|
||||||
parser = utils.parse_message
|
parser = utils.parse_message
|
||||||
elif isinstance(update.message, types.MessageService):
|
elif isinstance(update.message, types.MessageService):
|
||||||
@ -131,27 +138,35 @@ class Dispatcher:
|
|||||||
users,
|
users,
|
||||||
chats
|
chats
|
||||||
)
|
)
|
||||||
|
|
||||||
|
is_edited_message = isinstance(update, Dispatcher.EDIT_MESSAGE_UPDATES)
|
||||||
|
|
||||||
|
self.dispatch(
|
||||||
|
pyrogram.Update(
|
||||||
|
message=((message if message.chat.type != "channel"
|
||||||
|
else None) if not is_edited_message
|
||||||
|
else None),
|
||||||
|
edited_message=((message if message.chat.type != "channel"
|
||||||
|
else None) if is_edited_message
|
||||||
|
else None),
|
||||||
|
channel_post=((message if message.chat.type == "channel"
|
||||||
|
else None) if not is_edited_message
|
||||||
|
else None),
|
||||||
|
edited_channel_post=((message if message.chat.type == "channel"
|
||||||
|
else None) if is_edited_message
|
||||||
|
else None)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(update, types.UpdateBotCallbackQuery):
|
||||||
|
self.dispatch(
|
||||||
|
pyrogram.Update(
|
||||||
|
callback_query=utils.parse_callback_query(
|
||||||
|
self.client, update, users, chats
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
is_edited_message = isinstance(update, Dispatcher.EDIT_UPDATES)
|
|
||||||
|
|
||||||
self.dispatch(
|
|
||||||
pyrogram.Update(
|
|
||||||
message=((message if message.chat.type != "channel"
|
|
||||||
else None) if not is_edited_message
|
|
||||||
else None),
|
|
||||||
edited_message=((message if message.chat.type != "channel"
|
|
||||||
else None) if is_edited_message
|
|
||||||
else None),
|
|
||||||
channel_post=((message if message.chat.type == "channel"
|
|
||||||
else None) if not is_edited_message
|
|
||||||
else None),
|
|
||||||
edited_channel_post=((message if message.chat.type == "channel"
|
|
||||||
else None) if is_edited_message
|
|
||||||
else None)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(e, exc_info=True)
|
log.error(e, exc_info=True)
|
||||||
|
|
||||||
|
@ -16,4 +16,4 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .handlers import MessageHandler, RawUpdateHandler
|
from .handlers import MessageHandler, CallbackQueryHandler, RawUpdateHandler
|
||||||
|
@ -52,6 +52,18 @@ class MessageHandler(Handler):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CallbackQueryHandler(Handler):
|
||||||
|
def __init__(self, callback: callable, filters=None):
|
||||||
|
super().__init__(callback, filters)
|
||||||
|
|
||||||
|
def check(self, callback_query):
|
||||||
|
return (
|
||||||
|
self.filters(callback_query)
|
||||||
|
if self.filters
|
||||||
|
else True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class RawUpdateHandler(Handler):
|
class RawUpdateHandler(Handler):
|
||||||
"""The Raw Update handler class. Used to handle raw updates. It is intended to be used with
|
"""The Raw Update handler class. Used to handle raw updates. It is intended to be used with
|
||||||
:meth:`add_handler() <pyrogram.Client.add_handler>`
|
:meth:`add_handler() <pyrogram.Client.add_handler>`
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .audio import Audio
|
from .audio import Audio
|
||||||
|
from .callback_query import CallbackQuery
|
||||||
from .chat import Chat
|
from .chat import Chat
|
||||||
from .chat_member import ChatMember
|
from .chat_member import ChatMember
|
||||||
from .chat_photo import ChatPhoto
|
from .chat_photo import ChatPhoto
|
||||||
|
76
pyrogram/client/types/callback_query.py
Normal file
76
pyrogram/client/types/callback_query.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from pyrogram.api.core import Object
|
||||||
|
|
||||||
|
|
||||||
|
class CallbackQuery(Object):
|
||||||
|
"""This object represents an incoming callback query from a callback button in an inline keyboard.
|
||||||
|
If the button that originated the query was attached to a message sent by the bot, the field message
|
||||||
|
will be present. If the button was attached to a message sent via the bot (in inline mode),
|
||||||
|
the field inline_message_id will be present. Exactly one of the fields data or game_short_name will be present.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
ID: ``0xb0700024``
|
||||||
|
|
||||||
|
Args:
|
||||||
|
id (``str``):
|
||||||
|
Unique identifier for this query.
|
||||||
|
|
||||||
|
from_user (:obj:`User <pyrogram.types.User>`):
|
||||||
|
Sender.
|
||||||
|
|
||||||
|
chat_instance (``str``, optional):
|
||||||
|
Message with the callback button that originated the query. Note that message content and message date will
|
||||||
|
not be available if the message is too old.
|
||||||
|
|
||||||
|
message (:obj:`Message <pyrogram.types.Message>`, optional):
|
||||||
|
Identifier of the message sent via the bot in inline mode, that originated the query.
|
||||||
|
|
||||||
|
inline_message_id (``str``):
|
||||||
|
Global identifier, uniquely corresponding to the chat to which the message with the callback button was
|
||||||
|
sent. Useful for high scores in games.
|
||||||
|
|
||||||
|
data (``str``, optional):
|
||||||
|
Data associated with the callback button. Be aware that a bad client can send arbitrary data in this field.
|
||||||
|
|
||||||
|
game_short_name (``str``, optional):
|
||||||
|
Short name of a Game to be returned, serves as the unique identifier for the game.
|
||||||
|
|
||||||
|
"""
|
||||||
|
ID = 0xb0700024
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: str,
|
||||||
|
from_user,
|
||||||
|
chat,
|
||||||
|
chat_instance: str,
|
||||||
|
message=None,
|
||||||
|
inline_message_id: str = None,
|
||||||
|
data: str = None,
|
||||||
|
game_short_name: str = None
|
||||||
|
):
|
||||||
|
self.id = id # string
|
||||||
|
self.from_user = from_user # User
|
||||||
|
self.chat = chat
|
||||||
|
self.message = message # flags.0?Message
|
||||||
|
self.inline_message_id = inline_message_id # flags.1?string
|
||||||
|
self.chat_instance = chat_instance # string
|
||||||
|
self.data = data # flags.2?string
|
||||||
|
self.game_short_name = game_short_name # flags.3?string
|
@ -34,12 +34,12 @@ class InlineKeyboardButton(Object):
|
|||||||
text (``str``):
|
text (``str``):
|
||||||
Label text on the button.
|
Label text on the button.
|
||||||
|
|
||||||
url (``str``, optional):
|
|
||||||
HTTP url to be opened when button is pressed.
|
|
||||||
|
|
||||||
callback_data (``str``, optional):
|
callback_data (``str``, optional):
|
||||||
Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes.
|
Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes.
|
||||||
|
|
||||||
|
url (``str``, optional):
|
||||||
|
HTTP url to be opened when button is pressed.
|
||||||
|
|
||||||
switch_inline_query (``str``, optional):
|
switch_inline_query (``str``, optional):
|
||||||
If set, pressing the button will prompt the user to select one of their chats, open that chat and insert
|
If set, pressing the button will prompt the user to select one of their chats, open that chat and insert
|
||||||
the bot's username and the specified inline query in the input field. Can be empty, in which case just
|
the bot's username and the specified inline query in the input field. Can be empty, in which case just
|
||||||
@ -68,8 +68,8 @@ class InlineKeyboardButton(Object):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
text: str,
|
text: str,
|
||||||
url: str = None,
|
|
||||||
callback_data: str = None,
|
callback_data: str = None,
|
||||||
|
url: str = None,
|
||||||
switch_inline_query: str = None,
|
switch_inline_query: str = None,
|
||||||
switch_inline_query_current_chat: str = None,
|
switch_inline_query_current_chat: str = None,
|
||||||
callback_game=None,
|
callback_game=None,
|
||||||
@ -90,13 +90,13 @@ class InlineKeyboardButton(Object):
|
|||||||
text=b.text,
|
text=b.text,
|
||||||
url=b.url
|
url=b.url
|
||||||
)
|
)
|
||||||
|
|
||||||
if isinstance(b, KeyboardButtonCallback):
|
if isinstance(b, KeyboardButtonCallback):
|
||||||
return InlineKeyboardButton(
|
return InlineKeyboardButton(
|
||||||
text=b.text,
|
text=b.text,
|
||||||
callback_data=b.data.decode()
|
callback_data=b.data.decode()
|
||||||
)
|
)
|
||||||
|
|
||||||
if isinstance(b, KeyboardButtonSwitchInline):
|
if isinstance(b, KeyboardButtonSwitchInline):
|
||||||
if b.same_peer:
|
if b.same_peer:
|
||||||
return InlineKeyboardButton(
|
return InlineKeyboardButton(
|
||||||
@ -110,12 +110,12 @@ class InlineKeyboardButton(Object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def write(self):
|
def write(self):
|
||||||
if self.url:
|
|
||||||
return KeyboardButtonUrl(self.text, self.url)
|
|
||||||
|
|
||||||
if self.callback_data:
|
if self.callback_data:
|
||||||
return KeyboardButtonCallback(self.text, self.callback_data.encode())
|
return KeyboardButtonCallback(self.text, self.callback_data.encode())
|
||||||
|
|
||||||
|
if self.url:
|
||||||
|
return KeyboardButtonUrl(self.text, self.url)
|
||||||
|
|
||||||
if self.switch_inline_query:
|
if self.switch_inline_query:
|
||||||
return KeyboardButtonSwitchInline(self.text, self.switch_inline_query)
|
return KeyboardButtonSwitchInline(self.text, self.switch_inline_query)
|
||||||
|
|
||||||
|
@ -721,3 +721,23 @@ def parse_photos(photos):
|
|||||||
total_count=total_count,
|
total_count=total_count,
|
||||||
photos=user_profile_photos
|
photos=user_profile_photos
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_callback_query(client, callback_query, users, chats):
|
||||||
|
if isinstance(callback_query.peer, types.PeerUser):
|
||||||
|
chat = parse_user_chat(users[callback_query.peer.user_id])
|
||||||
|
elif isinstance(callback_query.peer, types.PeerChat):
|
||||||
|
chat = parse_chat_chat(chats[callback_query.peer.chat_id])
|
||||||
|
else:
|
||||||
|
chat = parse_channel_chat(chats[callback_query.peer.channel_id])
|
||||||
|
|
||||||
|
return pyrogram_types.CallbackQuery(
|
||||||
|
id=callback_query.query_id,
|
||||||
|
from_user=parse_user(users[callback_query.user_id]),
|
||||||
|
chat=chat,
|
||||||
|
message=client.get_messages(chat.id, callback_query.msg_id),
|
||||||
|
chat_instance=str(callback_query.chat_instance),
|
||||||
|
data=callback_query.data.decode(),
|
||||||
|
game_short_name=callback_query.game_short_name
|
||||||
|
# TODO: add inline_message_id
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user