mirror of
https://github.com/TeamPGM/pyrogram.git
synced 2024-11-28 00:56:19 +00:00
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 0xb0700021: \"pyrogram.client.types.reply_markup.KeyboardButton\",")
|
||||
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")
|
||||
|
||||
|
@ -30,7 +30,7 @@ from .client.types import (
|
||||
Audio, Chat, ChatMember, ChatPhoto, Contact, Document, InputMediaPhoto,
|
||||
InputMediaVideo, InputPhoneContact, Location, Message, MessageEntity,
|
||||
PhotoSize, Sticker, Update, User, UserProfilePhotos, Venue, Video,
|
||||
VideoNote, Voice
|
||||
VideoNote, Voice, CallbackQuery
|
||||
)
|
||||
from .client.types.reply_markup import (
|
||||
ForceReply, InlineKeyboardButton, InlineKeyboardMarkup,
|
||||
@ -38,5 +38,6 @@ from .client.types.reply_markup import (
|
||||
)
|
||||
from .client import (
|
||||
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 .emoji import Emoji
|
||||
from .filters import Filters
|
||||
from .handlers import MessageHandler, RawUpdateHandler
|
||||
from .handlers import MessageHandler, CallbackQueryHandler, RawUpdateHandler
|
||||
from .parse_mode import ParseMode
|
||||
|
@ -227,6 +227,13 @@ class Client:
|
||||
|
||||
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):
|
||||
"""Use this decorator to automatically register a function for handling
|
||||
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]
|
||||
|
||||
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
|
||||
from pyrogram.api import types
|
||||
from .. import utils
|
||||
from ..handlers import RawUpdateHandler, MessageHandler
|
||||
from ..handlers import RawUpdateHandler, CallbackQueryHandler, MessageHandler
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Dispatcher:
|
||||
MESSAGE_UPDATES = (
|
||||
NEW_MESSAGE_UPDATES = (
|
||||
types.UpdateNewMessage,
|
||||
types.UpdateNewChannelMessage
|
||||
)
|
||||
|
||||
EDIT_UPDATES = (
|
||||
EDIT_MESSAGE_UPDATES = (
|
||||
types.UpdateEditMessage,
|
||||
types.UpdateEditChannelMessage
|
||||
)
|
||||
|
||||
ALLOWED_UPDATES = MESSAGE_UPDATES + EDIT_UPDATES
|
||||
MESSAGE_UPDATES = NEW_MESSAGE_UPDATES + EDIT_MESSAGE_UPDATES
|
||||
|
||||
def __init__(self, client, workers):
|
||||
self.client = client
|
||||
@ -84,18 +84,25 @@ class Dispatcher:
|
||||
|
||||
args = (self.client, update, users, chats)
|
||||
else:
|
||||
if not isinstance(handler, MessageHandler):
|
||||
continue
|
||||
|
||||
message = (update.message
|
||||
or update.channel_post
|
||||
or update.edited_message
|
||||
or update.edited_channel_post)
|
||||
|
||||
if not handler.check(message):
|
||||
continue
|
||||
callback_query = update.callback_query
|
||||
|
||||
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)
|
||||
break
|
||||
@ -117,7 +124,7 @@ class Dispatcher:
|
||||
|
||||
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):
|
||||
parser = utils.parse_message
|
||||
elif isinstance(update.message, types.MessageService):
|
||||
@ -131,27 +138,35 @@ class Dispatcher:
|
||||
users,
|
||||
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:
|
||||
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:
|
||||
log.error(e, exc_info=True)
|
||||
|
||||
|
@ -16,4 +16,4 @@
|
||||
# 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 .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):
|
||||
"""The Raw Update handler class. Used to handle raw updates. It is intended to be used with
|
||||
:meth:`add_handler() <pyrogram.Client.add_handler>`
|
||||
|
@ -17,6 +17,7 @@
|
||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .audio import Audio
|
||||
from .callback_query import CallbackQuery
|
||||
from .chat import Chat
|
||||
from .chat_member import ChatMember
|
||||
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``):
|
||||
Label text on the button.
|
||||
|
||||
url (``str``, optional):
|
||||
HTTP url to be opened when button is pressed.
|
||||
|
||||
callback_data (``str``, optional):
|
||||
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):
|
||||
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
|
||||
@ -68,8 +68,8 @@ class InlineKeyboardButton(Object):
|
||||
def __init__(
|
||||
self,
|
||||
text: str,
|
||||
url: str = None,
|
||||
callback_data: str = None,
|
||||
url: str = None,
|
||||
switch_inline_query: str = None,
|
||||
switch_inline_query_current_chat: str = None,
|
||||
callback_game=None,
|
||||
@ -90,13 +90,13 @@ class InlineKeyboardButton(Object):
|
||||
text=b.text,
|
||||
url=b.url
|
||||
)
|
||||
|
||||
|
||||
if isinstance(b, KeyboardButtonCallback):
|
||||
return InlineKeyboardButton(
|
||||
text=b.text,
|
||||
callback_data=b.data.decode()
|
||||
)
|
||||
|
||||
|
||||
if isinstance(b, KeyboardButtonSwitchInline):
|
||||
if b.same_peer:
|
||||
return InlineKeyboardButton(
|
||||
@ -110,12 +110,12 @@ class InlineKeyboardButton(Object):
|
||||
)
|
||||
|
||||
def write(self):
|
||||
if self.url:
|
||||
return KeyboardButtonUrl(self.text, self.url)
|
||||
|
||||
if self.callback_data:
|
||||
return KeyboardButtonCallback(self.text, self.callback_data.encode())
|
||||
|
||||
if self.url:
|
||||
return KeyboardButtonUrl(self.text, self.url)
|
||||
|
||||
if self.switch_inline_query:
|
||||
return KeyboardButtonSwitchInline(self.text, self.switch_inline_query)
|
||||
|
||||
|
@ -721,3 +721,23 @@ def parse_photos(photos):
|
||||
total_count=total_count,
|
||||
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