diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index abfe64af..99f63d0f 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -357,6 +357,7 @@ def pyrogram_api(): set_chat_menu_button get_chat_menu_button answer_web_app_query + answer_pre_checkout_query get_bot_info set_bot_info """, @@ -504,6 +505,7 @@ def pyrogram_api(): ReactionType MessageReactionUpdated MessageReactionCountUpdated + SuccessfulPayment """, stories=""" Stories @@ -546,6 +548,9 @@ def pyrogram_api(): MenuButtonWebApp MenuButtonDefault SentWebAppMessage + PaymentInfo + PreCheckoutQuery + ShippingAddress """, bot_commands=""" Bot commands @@ -592,6 +597,10 @@ def pyrogram_api(): InlineQueryResultVoice ChosenInlineResult """, + pre_checkout_query=""" + PreCheckoutQuery + PreCheckoutQuery.answer + """, input_message_content=""" InputMessageContent InputMessageContent @@ -742,6 +751,10 @@ def pyrogram_api(): InlineQuery InlineQuery.answer """, + pre_checkout_query=""" + PreCheckoutQuery + PreCheckoutQuery.answer + """, chat_join_request=""" ChatJoinRequest ChatJoinRequest.approve diff --git a/compiler/docs/template/bound-methods.rst b/compiler/docs/template/bound-methods.rst index ff712cdf..61efa7db 100644 --- a/compiler/docs/template/bound-methods.rst +++ b/compiler/docs/template/bound-methods.rst @@ -101,6 +101,19 @@ InlineQuery {inline_query_toctree} +PreCheckoutQuery +----------- + +.. hlist:: + :columns: 2 + + {pre_checkout_query_hlist} + +.. toctree:: + :hidden: + + {pre_checkout_query_toctree} + ChatJoinRequest --------------- diff --git a/pyrogram/dispatcher.py b/pyrogram/dispatcher.py index 4931e34e..b97bdb6f 100644 --- a/pyrogram/dispatcher.py +++ b/pyrogram/dispatcher.py @@ -39,6 +39,7 @@ from pyrogram.handlers import ( RawUpdateHandler, InlineQueryHandler, PollHandler, + PreCheckoutQueryHandler, ConversationHandler, ChosenInlineResultHandler, ChatMemberUpdatedHandler, @@ -51,7 +52,7 @@ from pyrogram.raw.types import ( UpdateBotNewBusinessMessage, UpdateBotDeleteBusinessMessage, UpdateBotEditBusinessMessage, UpdateEditMessage, UpdateEditChannelMessage, UpdateDeleteMessages, UpdateDeleteChannelMessages, - UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, + UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, UpdateBotPrecheckoutQuery, UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll, UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant, UpdateBotStopped, UpdateBotChatInviteRequester, UpdateStory, @@ -80,6 +81,7 @@ class Dispatcher: MESSAGE_BOT_NA_REACTION_UPDATES = (UpdateBotMessageReaction,) MESSAGE_BOT_A_REACTION_UPDATES = (UpdateBotMessageReactions,) BOT_BUSSINESS_CONNECT_UPDATES = (UpdateBotBusinessConnect,) + PRE_CHECKOUT_QUERY_UPDATES = (UpdateBotPrecheckoutQuery,) def __init__(self, client: "pyrogram.Client"): self.client = client @@ -191,6 +193,12 @@ class Dispatcher: StoryHandler ) + async def pre_checkout_query_parser(update, users, chats): + return ( + await pyrogram.types.PreCheckoutQuery._parse(self.client, update, users), + PreCheckoutQueryHandler + ) + async def message_bot_na_reaction_parser(update, users, chats): return ( pyrogram.types.MessageReactionUpdated._parse(self.client, update, users, chats), @@ -224,6 +232,7 @@ class Dispatcher: Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser, Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser, Dispatcher.NEW_STORY_UPDATES: story_parser, + Dispatcher.PRE_CHECKOUT_QUERY_UPDATES: pre_checkout_query_parser, Dispatcher.MESSAGE_BOT_NA_REACTION_UPDATES: message_bot_na_reaction_parser, Dispatcher.MESSAGE_BOT_A_REACTION_UPDATES: message_bot_a_reaction_parser, Dispatcher.BOT_BUSSINESS_CONNECT_UPDATES: bot_business_connect_parser diff --git a/pyrogram/enums/message_service_type.py b/pyrogram/enums/message_service_type.py index bffa77fe..b53b7f50 100644 --- a/pyrogram/enums/message_service_type.py +++ b/pyrogram/enums/message_service_type.py @@ -111,3 +111,6 @@ class MessageServiceType(AutoName): BOOST_APPLY = auto() "Boost apply" + + SUCCESSFUL_PAYMENT = auto() + "Successful payment" diff --git a/pyrogram/filters.py b/pyrogram/filters.py index 8fbfb1ad..410f1aef 100644 --- a/pyrogram/filters.py +++ b/pyrogram/filters.py @@ -28,6 +28,7 @@ from pyrogram.types import ( InlineKeyboardMarkup, InlineQuery, Message, + PreCheckoutQuery, ReplyKeyboardMarkup, Story, Update, @@ -697,6 +698,17 @@ video_chat_members_invited = create(video_chat_members_invited_filter) """Filter messages for voice chat invited members""" +# endregion + +# region successful_payment_filter +async def successful_payment_filter(_, __, m: Message): + return bool(m.successful_payment) + + +successful_payment = create(successful_payment_filter) +"""Filter messages for successful payments""" + + # endregion # region service_filter @@ -710,7 +722,7 @@ service = create(service_filter) A service message contains any of the following fields set: *left_chat_member*, *new_chat_title*, *new_chat_photo*, *delete_chat_photo*, *group_chat_created*, *supergroup_chat_created*, *channel_chat_created*, *migrate_to_chat_id*, *migrate_from_chat_id*, *pinned_message*, *game_score*, -*video_chat_started*, *video_chat_ended*, *video_chat_members_invited*. +*video_chat_started*, *video_chat_ended*, *video_chat_members_invited*, *successful_payment*, *successful_payment*. """ @@ -909,6 +921,7 @@ def regex(pattern: Union[str, Pattern], flags: int = 0): - :obj:`~pyrogram.types.Message`: The filter will match ``text`` or ``caption``. - :obj:`~pyrogram.types.CallbackQuery`: The filter will match ``data``. - :obj:`~pyrogram.types.InlineQuery`: The filter will match ``query``. + - :obj:`~pyrogram.types.PreCheckoutQuery`: The filter will match ``payload``. When a pattern matches, all the `Match Objects `_ are stored in the ``matches`` field of the update object itself. @@ -928,6 +941,8 @@ def regex(pattern: Union[str, Pattern], flags: int = 0): value = update.data elif isinstance(update, InlineQuery): value = update.query + elif isinstance(update, PreCheckoutQuery): + value = update.payload else: raise ValueError(f"Regex filter doesn't work with {type(update)}") diff --git a/pyrogram/handlers/__init__.py b/pyrogram/handlers/__init__.py index e55ae028..90890994 100644 --- a/pyrogram/handlers/__init__.py +++ b/pyrogram/handlers/__init__.py @@ -32,6 +32,7 @@ from .edited_bot_business_message_handler import EditedBotBusinessMessageHandler from .inline_query_handler import InlineQueryHandler from .message_handler import MessageHandler from .poll_handler import PollHandler +from .pre_checkout_query_handler import PreCheckoutQueryHandler from .raw_update_handler import RawUpdateHandler from .user_status_handler import UserStatusHandler from .story_handler import StoryHandler diff --git a/pyrogram/handlers/pre_checkout_query_handler.py b/pyrogram/handlers/pre_checkout_query_handler.py new file mode 100644 index 00000000..7d2fc5a1 --- /dev/null +++ b/pyrogram/handlers/pre_checkout_query_handler.py @@ -0,0 +1,50 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# 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 . + +from typing import Callable + +from .handler import Handler + + +class PreCheckoutQueryHandler(Handler): + """The PreCheckoutQueryHandler handler class. Used to handle pre-checkout queries coming from buy buttons. + It is intended to be used with :meth:`~pyrogram.Client.add_handler` + + For a nicer way to register this handler, have a look at the + :meth:`~pyrogram.Client.on_pre_checkout_query` decorator. + + Parameters: + callback (``Callable``): + Pass a function that will be called when a new PreCheckoutQuery arrives. It takes *(client, pre_checkout_query)* + as positional arguments (look at the section below for a detailed description). + + filters (:obj:`Filters`): + Pass one or more filters to allow only a subset of callback queries to be passed + in your callback function. + + Other parameters: + client (:obj:`~pyrogram.Client`): + The Client itself, useful when you want to call other API methods inside the message handler. + + pre_checkout_query (:obj:`~pyrogram.types.PreCheckoutQuery`): + The received callback query. + """ + + def __init__(self, callback: Callable, filters=None): + super().__init__(callback, filters) diff --git a/pyrogram/methods/bots/__init__.py b/pyrogram/methods/bots/__init__.py index 717d1d1e..c2af56d5 100644 --- a/pyrogram/methods/bots/__init__.py +++ b/pyrogram/methods/bots/__init__.py @@ -19,6 +19,7 @@ from .answer_callback_query import AnswerCallbackQuery from .answer_inline_query import AnswerInlineQuery +from .answer_pre_checkout_query import AnswerPreCheckoutQuery from .answer_web_app_query import AnswerWebAppQuery from .delete_bot_commands import DeleteBotCommands from .get_bot_commands import GetBotCommands @@ -55,6 +56,7 @@ class Bots( GetBotInfo, SetChatMenuButton, GetChatMenuButton, - AnswerWebAppQuery + AnswerWebAppQuery, + AnswerPreCheckoutQuery ): pass diff --git a/pyrogram/methods/bots/answer_pre_checkout_query.py b/pyrogram/methods/bots/answer_pre_checkout_query.py new file mode 100644 index 00000000..adcd512f --- /dev/null +++ b/pyrogram/methods/bots/answer_pre_checkout_query.py @@ -0,0 +1,65 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# 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 . + +import pyrogram +from pyrogram import raw + + +class AnswerPreCheckoutQuery: + async def answer_pre_checkout_query( + self: "pyrogram.Client", + pre_checkout_query_id: str, + success: bool = None, + error: str = None + ): + """Send answers to pre-checkout queries. + + .. include:: /_includes/usable-by/bots.rst + + Parameters: + pre_checkout_query_id (``str``): + Unique identifier for the query to be answered. + + success (``bool``, *optional*): + Set this flag if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order. + Otherwise do not set it, and set the error field, instead. + + error (``str``, *optional*): + Error message in human readable form that explains the reason for failure to proceed with the checkout. + Required if ``success`` isn't set. + + Returns: + ``bool``: True, on success. + + Example: + .. code-block:: python + + # Proceed with the order + await app.answer_pre_checkout_query(query_id, success=True) + + # Answer with error message + await app.answer_pre_checkout_query(query_id, error=error) + """ + return await self.invoke( + raw.functions.messages.SetBotPrecheckoutResults( + query_id=int(pre_checkout_query_id), + success=success or None, + error=error or None + ) + ) diff --git a/pyrogram/methods/chats/get_chat_member.py b/pyrogram/methods/chats/get_chat_member.py index 75d276d4..7b86bf51 100644 --- a/pyrogram/methods/chats/get_chat_member.py +++ b/pyrogram/methods/chats/get_chat_member.py @@ -40,7 +40,7 @@ class GetChatMember: Unique identifier (int) or username (str) of the target chat. You can also use chat public link in form of *t.me/* (str). - user_id (``int`` | ``str``):: + user_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target user. For you yourself you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). diff --git a/pyrogram/methods/decorators/__init__.py b/pyrogram/methods/decorators/__init__.py index 8b978eea..cf2000a9 100644 --- a/pyrogram/methods/decorators/__init__.py +++ b/pyrogram/methods/decorators/__init__.py @@ -31,6 +31,7 @@ from .on_edited_bot_business_message import OnEditedBotBusinessMessage from .on_inline_query import OnInlineQuery from .on_message import OnMessage from .on_poll import OnPoll +from .on_pre_checkout_query import OnPreCheckoutQuery from .on_raw_update import OnRawUpdate from .on_user_status import OnUserStatus from .on_story import OnStory @@ -57,6 +58,7 @@ class Decorators( OnChatJoinRequest, OnStory, OnMessageReactionUpdated, - OnMessageReactionCountUpdated + OnMessageReactionCountUpdated, + OnPreCheckoutQuery ): pass diff --git a/pyrogram/methods/decorators/on_pre_checkout_query.py b/pyrogram/methods/decorators/on_pre_checkout_query.py new file mode 100644 index 00000000..922b213a --- /dev/null +++ b/pyrogram/methods/decorators/on_pre_checkout_query.py @@ -0,0 +1,62 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# 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 . + +from typing import Callable, Optional, Union + +import pyrogram +from pyrogram.filters import Filter + + +class OnPreCheckoutQuery: + def on_pre_checkout_query( + self: Union["OnPreCheckoutQuery", Filter, None] = None, + filters: Optional[Filter] = None, + group: int = 0, + ) -> Callable: + """Decorator for handling pre-checkout queries. + + This does the same thing as :meth:`~pyrogram.Client.add_handler` using the + :obj:`~pyrogram.handlers.PreCheckoutQueryHandler`. + + Parameters: + filters (:obj:`~pyrogram.filters`, *optional*): + Pass one or more filters to allow only a subset of callback queries to be passed + in your function. + + group (``int``, *optional*): + The group identifier, defaults to 0. + """ + + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.handlers.PreCheckoutQueryHandler(func, filters), group) + elif isinstance(self, Filter) or self is None: + if not hasattr(func, "handlers"): + func.handlers = [] + + func.handlers.append( + ( + pyrogram.handlers.PreCheckoutQueryHandler(func, self), + group if filters is None else filters + ) + ) + + return func + + return decorator diff --git a/pyrogram/methods/users/unblock_user.py b/pyrogram/methods/users/unblock_user.py index a97355d8..bfaf2bde 100644 --- a/pyrogram/methods/users/unblock_user.py +++ b/pyrogram/methods/users/unblock_user.py @@ -33,7 +33,7 @@ class UnblockUser: .. include:: /_includes/usable-by/users.rst Parameters: - user_id (``int`` | ``str``):: + user_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target user. For you yourself you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). diff --git a/pyrogram/types/bots_and_keyboards/__init__.py b/pyrogram/types/bots_and_keyboards/__init__.py index 78132892..228389b2 100644 --- a/pyrogram/types/bots_and_keyboards/__init__.py +++ b/pyrogram/types/bots_and_keyboards/__init__.py @@ -40,12 +40,16 @@ from .menu_button import MenuButton from .menu_button_commands import MenuButtonCommands from .menu_button_default import MenuButtonDefault from .menu_button_web_app import MenuButtonWebApp +from .payment_info import PaymentInfo +from .pre_checkout_query import PreCheckoutQuery from .reply_keyboard_markup import ReplyKeyboardMarkup from .reply_keyboard_remove import ReplyKeyboardRemove from .request_peer_type_channel import RequestPeerTypeChannel from .request_peer_type_chat import RequestPeerTypeChat from .request_peer_type_user import RequestPeerTypeUser from .sent_web_app_message import SentWebAppMessage +from .shipping_address import ShippingAddress +from .successful_payment import SuccessfulPayment from .web_app_info import WebAppInfo __all__ = [ @@ -78,5 +82,9 @@ __all__ = [ "MenuButtonCommands", "MenuButtonWebApp", "MenuButtonDefault", - "SentWebAppMessage" + "SentWebAppMessage", + "ShippingAddress", + "PaymentInfo", + "PreCheckoutQuery", + "SuccessfulPayment" ] diff --git a/pyrogram/types/bots_and_keyboards/payment_info.py b/pyrogram/types/bots_and_keyboards/payment_info.py new file mode 100644 index 00000000..a51b6ff0 --- /dev/null +++ b/pyrogram/types/bots_and_keyboards/payment_info.py @@ -0,0 +1,52 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# 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 . + +from ..object import Object + + +class PaymentInfo(Object): + """Contains information about a payment. + + Parameters: + name (``str``, *optional*): + User's name. + + phone_number (``str``, *optional*): + User's phone number. + + email (``str``, *optional*): + User's email. + + shipping_address (:obj:`~pyrogram.types.ShippingAddress`, *optional*): + User's shipping address. + """ + + def __init__( + self, *, + name: str = None, + phone_number: str = None, + email: str = None, + shipping_address: "types.ShippingAddress" = None + ): + super().__init__() + + self.name = name + self.phone_number = phone_number + self.email = email + self.shipping_address = shipping_address diff --git a/pyrogram/types/bots_and_keyboards/pre_checkout_query.py b/pyrogram/types/bots_and_keyboards/pre_checkout_query.py new file mode 100644 index 00000000..71c7bb44 --- /dev/null +++ b/pyrogram/types/bots_and_keyboards/pre_checkout_query.py @@ -0,0 +1,140 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# 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 . + +from typing import Union, List, Match, Optional + +import pyrogram +from pyrogram import raw, enums +from pyrogram import types +from ..object import Object +from ..update import Update +from ... import utils + + +class PreCheckoutQuery(Object, Update): + """An incoming pre-checkout query from a buy button in an inline keyboard. + + Parameters: + id (``str``): + Unique identifier for this query. + + from_user (:obj:`~pyrogram.types.User`): + User who sent the query. + + currency (``str``): + Three-letter ISO 4217 currency code. + + total_amount (``int``): + Total price in the smallest units of the currency. + + payload (``str``): + Bot specified invoice payload. + + shipping_option_id (``str``, *optional*): + Identifier of the shipping option chosen by the user. + + payment_info (:obj:`~pyrogram.types.PaymentInfo`, *optional*): + Payment information provided by the user. + """ + + def __init__( + self, + *, + client: "pyrogram.Client" = None, + id: str, + from_user: "types.User", + currency: str, + total_amount: int, + payload: str, + shipping_option_id: str = None, + payment_info: "types.PaymentInfo" = None + ): + super().__init__(client) + + self.id = id + self.from_user = from_user + self.currency = currency + self.total_amount = total_amount + self.payload = payload + self.shipping_option_id = shipping_option_id + self.payment_info = payment_info + + @staticmethod + async def _parse(client: "pyrogram.Client", pre_checkout_query, users) -> "PreCheckoutQuery": + # Try to decode pre-checkout query payload into string. If that fails, fallback to bytes instead of decoding by + # ignoring/replacing errors, this way, button clicks will still work. + try: + payload = pre_checkout_query.payload.decode() + except (UnicodeDecodeError, AttributeError): + payload = pre_checkout_query.payload + + return PreCheckoutQuery( + id=str(pre_checkout_query.query_id), + from_user=types.User._parse(client, users[pre_checkout_query.user_id]), + currency=pre_checkout_query.currency, + total_amount=pre_checkout_query.total_amount, + payload=payload, + shipping_option_id=pre_checkout_query.shipping_option_id, + payment_info=types.PaymentInfo( + name=pre_checkout_query.info.name, + phone_number=pre_checkout_query.info.phone, + email=pre_checkout_query.info.email, + shipping_address=types.ShippingAddress( + street_line1=pre_checkout_query.info.shipping_address.street_line1, + street_line2=pre_checkout_query.info.shipping_address.street_line2, + city=pre_checkout_query.info.shipping_address.city, + state=pre_checkout_query.info.shipping_address.state, + post_code=pre_checkout_query.info.shipping_address.post_code, + country_code=pre_checkout_query.info.shipping_address.country_iso2 + ) + ) if pre_checkout_query.info else None, + client=client + ) + + async def answer(self, success: bool = None, error: str = None): + """Bound method *answer* of :obj:`~pyrogram.types.PreCheckoutQuery`. + + Use this method as a shortcut for: + + .. code-block:: python + + await client.answer_pre_checkout_query( + pre_checkout_query.id, + success=True + ) + + Example: + .. code-block:: python + + await pre_checkout_query.answer(success=True) + + Parameters: + success (``bool`` *optional*): + If true, an alert will be shown by the client instead of a notification at the top of the chat screen. + Defaults to False. + + error (``bool`` *optional*): + If true, an alert will be shown by the client instead of a notification at the top of the chat screen. + Defaults to False. + """ + return await self._client.answer_pre_checkout_query( + pre_checkout_query_id=self.id, + success=success, + error=error + ) diff --git a/pyrogram/types/bots_and_keyboards/shipping_address.py b/pyrogram/types/bots_and_keyboards/shipping_address.py new file mode 100644 index 00000000..14508f4e --- /dev/null +++ b/pyrogram/types/bots_and_keyboards/shipping_address.py @@ -0,0 +1,62 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# 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 . + +from ..object import Object + + +class ShippingAddress(Object): + """Contains information about a shipping address. + + Parameters: + street_line1 (``str``): + First line for the address. + + street_line1 (``str``): + Second line for the address. + + city (``str``): + City for the address. + + state (``str``): + State for the address, if applicable. + + post_code (``str``): + Post code for the address. + + country_code (``str``): + Two-letter ISO 3166-1 alpha-2 country code. + """ + + def __init__( + self, *, + street_line1: str, + street_line2: str, + city: str, + state: str, + post_code: str, + country_code: str + ): + super().__init__() + + self.street_line1 = street_line1 + self.street_line2 = street_line2 + self.city = city + self.state = state + self.post_code = post_code + self.country_code = country_code diff --git a/pyrogram/types/bots_and_keyboards/successful_payment.py b/pyrogram/types/bots_and_keyboards/successful_payment.py new file mode 100644 index 00000000..f6b7ef01 --- /dev/null +++ b/pyrogram/types/bots_and_keyboards/successful_payment.py @@ -0,0 +1,112 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# 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 . + +from pyrogram import raw +from pyrogram import types +from ..object import Object + + +class SuccessfulPayment(Object): + """Contains information about a successful payment. + + Parameters: + currency (``str``): + Three-letter ISO 4217 currency code. + + total_amount (``int``): + Total price in the smallest units of the currency. + + payload (``str``, *optional*): + Bot specified invoice payload. Only available to the bot that received the payment. + + telegram_payment_charge_id (``str``, *optional*): + Telegram payment identifier. Only available to the bot that received the payment. + + provider_payment_charge_id (``str``, *optional*): + Provider payment identifier. Only available to the bot that received the payment. + + shipping_option_id (``str``, *optional*): + Identifier of the shipping option chosen by the user. Only available to the bot that received the payment. + + payment_info (:obj:`~pyrogram.types.PaymentInfo`, *optional*): + Payment information provided by the user. Only available to the bot that received the payment. + """ + + def __init__( + self, *, + currency: str, + total_amount: str, + payload: str, + telegram_payment_charge_id: str, + provider_payment_charge_id: str, + shipping_option_id: str = None, + payment_info: "types.PaymentInfo" = None + ): + super().__init__() + + self.currency = currency + self.total_amount = total_amount + self.payload = payload + self.telegram_payment_charge_id = telegram_payment_charge_id + self.provider_payment_charge_id = provider_payment_charge_id + self.shipping_option_id = shipping_option_id + self.payment_info = payment_info + + @staticmethod + def _parse(client: "pyrogram.Client", successful_payment) -> "SuccessfulPayment": + payload = None + telegram_payment_charge_id = None + provider_payment_charge_id = None + shipping_option_id = None + payment_info = None + + if isinstance(successful_payment, raw.types.MessageActionPaymentSentMe): + # Try to decode invoice payload into string. If that fails, fallback to bytes instead of decoding by + # ignoring/replacing errors, this way, button clicks will still work. + try: + payload = successful_payment.payload.decode() + except (UnicodeDecodeError, AttributeError): + payload = successful_payment.payload + + telegram_payment_charge_id = successful_payment.charge.id + provider_payment_charge_id = successful_payment.charge.provider_charge_id + shipping_option_id = successful_payment.shipping_option_id + payment_info = types.PaymentInfo( + name=successful_payment.info.name, + phone_number=successful_payment.info.phone, + email=successful_payment.info.email, + shipping_address=types.ShippingAddress( + street_line1=successful_payment.info.shipping_address.street_line1, + street_line2=successful_payment.info.shipping_address.street_line2, + city=successful_payment.info.shipping_address.city, + state=successful_payment.info.shipping_address.state, + post_code=successful_payment.info.shipping_address.post_code, + country_code=successful_payment.info.shipping_address.country_iso2 + ) + ) if successful_payment.info else None + + return SuccessfulPayment( + currency=successful_payment.currency, + total_amount=successful_payment.total_amount, + payload=payload, + telegram_payment_charge_id=telegram_payment_charge_id, + provider_payment_charge_id=shipping_option_id, + shipping_option_id=shipping_option_id, + payment_info=payment_info + ) diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index b5a100fb..5bc0d0f8 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -379,6 +379,9 @@ class Message(Object, Update): web_app_data (:obj:`~pyrogram.types.WebAppData`, *optional*): Service message: web app data sent to the bot. + successful_payment (:obj:`~pyrogram.types.SuccessfulPayment`, *optional*): + Service message: successful payment. + boosts_applied (``int``, *optional*): Service message: how many boosts were applied. @@ -509,6 +512,7 @@ class Message(Object, Update): video_chat_ended: "types.VideoChatEnded" = None, video_chat_members_invited: "types.VideoChatMembersInvited" = None, web_app_data: "types.WebAppData" = None, + successful_payment: "types.SuccessfulPayment" = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -616,6 +620,7 @@ class Message(Object, Update): self.video_chat_ended = video_chat_ended self.video_chat_members_invited = video_chat_members_invited self.web_app_data = web_app_data + self.successful_payment = successful_payment self.reactions = reactions self.raw = raw @@ -721,6 +726,7 @@ class Message(Object, Update): gifted_premium = None giveaway_launched = None giveaway_result = None + successful_payment = None boosts_applied = None service_type = None @@ -819,6 +825,9 @@ class Message(Object, Update): elif isinstance(action, raw.types.MessageActionBoostApply): boosts_applied = action.boosts service_type = enums.MessageServiceType.BOOST_APPLY + elif isinstance(action, (raw.types.MessageActionPaymentSent, raw.types.MessageActionPaymentSentMe)): + successful_payment = types.SuccessfulPayment._parse(client, action) + service_type = enums.MessageServiceType.SUCCESSFUL_PAYMENT from_user = types.User._parse(client, users.get(user_id, None)) sender_chat = types.Chat._parse(client, message, users, chats, is_chat=False) if not from_user else None @@ -858,6 +867,7 @@ class Message(Object, Update): gifted_premium=gifted_premium, giveaway_launched=giveaway_launched, giveaway_result=giveaway_result, + successful_payment=successful_payment, boosts_applied=boosts_applied, raw=message, client=client