Skip to content
12 changes: 12 additions & 0 deletions compiler/docs/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,11 @@ def get_title_list(s: str) -> list:
""",
business="""
Telegram Business & Fragment
answer_pre_checkout_query
get_business_connection
get_collectible_item_info
refund_star_payment
send_invoice
""",
)

Expand Down Expand Up @@ -564,6 +567,11 @@ def get_title_list(s: str) -> list:
BusinessOpeningHoursInterval
CollectibleItemInfo
Invoice
LabeledPrice
OrderInfo
PreCheckoutQuery
ShippingAddress
SuccessfulPayment
""",
users_chats="""
Users & Chats
Expand Down Expand Up @@ -705,6 +713,10 @@ def get_title_list(s: str) -> list:
InlineQuery
InlineQuery.answer
""",
pre_checkout_query="""
PreCheckoutQuery
PreCheckoutQuery.answer
""",
chat_join_request="""
ChatJoinRequest
ChatJoinRequest.approve
Expand Down
13 changes: 13 additions & 0 deletions compiler/docs/template/bound-methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ InlineQuery

{inline_query_toctree}

PreCheckoutQuery
-----------

.. hlist::
:columns: 2

{pre_checkout_query_hlist}

.. toctree::
:hidden:

{pre_checkout_query_toctree}

ChatJoinRequest
---------------

Expand Down
3 changes: 3 additions & 0 deletions docs/source/releases/changes-in-this-fork.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ If you found any issue or have any suggestions, feel free to make `an issue <htt
| Scheme layer used: 181 |
+------------------------+

- Added the types :obj:`~pyrogram.types.LabeledPrice`, :obj:`~pyrogram.types.OrderInfo`, :obj:`~pyrogram.types.PreCheckoutQuery`, :obj:`~pyrogram.types.ShippingAddress`, :obj:`~pyrogram.types.SuccessfulPayment`, :obj:`~pyrogram.types.`.
- Added the ``successful_payment`` parameter to the :obj:`~pyrogram.types.Message`. Added the filter :obj:`~pyrogram.filters.successful_payment` to detect service messages of Successful Payment type.
- Added the methods :meth:`~pyrogram.Client.send_invoice`, :meth:`~pyrogram.Client.answer_pre_checkout_query` (:meth:`~pyrogram.types.PreCheckoutQuery.answer`), :meth:`~pyrogram.Client.refund_star_payment`.
- Added the :meth:`~pyrogram.Client.send_web_app_custom_request`.
- Added the :meth:`~pyrogram.Client.search_public_hashtag_messages` and :meth:`~pyrogram.Client.search_public_hashtag_messages_count`.
- Added the ``fetch_replies`` parameter to :obj:`~pyrogram.Client`.
Expand Down
15 changes: 12 additions & 3 deletions pyrogram/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
ChosenInlineResultHandler,
CallbackQueryHandler,


PreCheckoutQueryHandler,
PollHandler,


Expand All @@ -57,7 +57,8 @@
UpdateBotMessageReactions,
UpdateBotNewBusinessMessage,
UpdateBotEditBusinessMessage,
UpdateBotDeleteBusinessMessage
UpdateBotDeleteBusinessMessage,
UpdateBotPrecheckoutQuery
)

log = logging.getLogger(__name__)
Expand All @@ -76,6 +77,7 @@ class Dispatcher:
CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,)
MESSAGE_BOT_NA_REACTION_UPDATES = (UpdateBotMessageReaction,)
MESSAGE_BOT_A_REACTION_UPDATES = (UpdateBotMessageReactions,)
PRE_CHECKOUT_QUERY_UPDATES = (UpdateBotPrecheckoutQuery,)

def __init__(self, client: "pyrogram.Client"):
self.client = client
Expand Down Expand Up @@ -173,6 +175,12 @@ async def message_bot_a_reaction_parser(update, users, chats):
MessageReactionCountUpdatedHandler
)

async def pre_checkout_query_parser(update, users, chats):
return (
await pyrogram.types.PreCheckoutQuery._parse(self.client, update, users),
PreCheckoutQueryHandler
)

self.update_parsers = {
Dispatcher.NEW_MESSAGE_UPDATES: message_parser,
Dispatcher.EDIT_MESSAGE_UPDATES: edited_message_parser,
Expand All @@ -185,7 +193,8 @@ async def message_bot_a_reaction_parser(update, users, chats):
Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser,
Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser,
Dispatcher.MESSAGE_BOT_NA_REACTION_UPDATES: message_bot_na_reaction_parser,
Dispatcher.MESSAGE_BOT_A_REACTION_UPDATES: message_bot_a_reaction_parser
Dispatcher.MESSAGE_BOT_A_REACTION_UPDATES: message_bot_a_reaction_parser,
Dispatcher.PRE_CHECKOUT_QUERY_UPDATES: pre_checkout_query_parser
}

self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}
Expand Down
3 changes: 3 additions & 0 deletions pyrogram/enums/message_service_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,6 @@ class MessageServiceType(AutoName):

GENERAL_FORUM_TOPIC_UNHIDDEN = auto()
"a forum general topic unhidden in the chat"

SUCCESSFUL_PAYMENT = auto()
"Successful payment"
16 changes: 15 additions & 1 deletion pyrogram/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
CallbackQuery,
InlineQuery,
InlineKeyboardMarkup,
PreCheckoutQuery,
ReplyKeyboardMarkup,
Update,
)
Expand Down Expand Up @@ -757,6 +758,16 @@ async def video_chat_participants_invited_filter(_, __, m: Message) -> bool:

# 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
async def service_filter(_, __, m: Message) -> bool:
Expand All @@ -769,7 +780,7 @@ async def service_filter(_, __, m: Message) -> bool:
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_participants_invited*.
*video_chat_started*, *video_chat_ended*, *video_chat_participants_invited*, *successful_payment*.
"""


Expand Down Expand Up @@ -958,6 +969,7 @@ def regex(pattern: Union[str, Pattern], flags: int = 0) -> Filter:
- :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 <https://docs.python.org/3/library/re.html#match-objects>`_ are
stored in the ``matches`` field of the update object itself.
Expand All @@ -977,6 +989,8 @@ async def func(flt, _, update: Update) -> bool:
value: str | bytes = update.data
elif isinstance(update, InlineQuery):
value: str = update.query
elif isinstance(update, PreCheckoutQuery):
value: str = update.payload
else:
raise ValueError(f"Regex filter doesn't work with {type(update)}")

Expand Down
1 change: 1 addition & 0 deletions pyrogram/handlers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@
from .user_status_handler import UserStatusHandler
from .message_reaction_updated_handler import MessageReactionUpdatedHandler
from .message_reaction_count_updated_handler import MessageReactionCountUpdatedHandler
from .pre_checkout_query_handler import PreCheckoutQueryHandler
51 changes: 51 additions & 0 deletions pyrogram/handlers/pre_checkout_query_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <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 typing import Callable

from .handler import Handler


class PreCheckoutQueryHandler(Handler):
"""The PreCheckoutQueryHandler handler class. Used to handle pre-checkout queries coming from invoice 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)
6 changes: 6 additions & 0 deletions pyrogram/methods/business/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@
# 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 .answer_pre_checkout_query import AnswerPreCheckoutQuery
from .get_business_connection import GetBusinessConnection
from .get_collectible_item_info import GetCollectibleItemInfo
from .refund_star_payment import RefundStarPayment
from .send_invoice import SendInvoice


class TelegramBusiness(
AnswerPreCheckoutQuery,
GetBusinessConnection,
GetCollectibleItemInfo,
RefundStarPayment,
SendInvoice,
):
pass
67 changes: 67 additions & 0 deletions pyrogram/methods/business/answer_pre_checkout_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <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/>.

import pyrogram
from pyrogram import raw


class AnswerPreCheckoutQuery:
async def answer_pre_checkout_query(
self: "pyrogram.Client",
pre_checkout_query_id: str,
ok: bool,
error_message: str = None
):
"""Once the user has confirmed their payment and shipping details, the API sends the final confirmation in the form of an :obj:`~pyrogram.handlers.PreCheckoutQueryHandler`.

Use this method to respond to such pre-checkout queries.

**Note**: The API must receive an answer within 10 seconds after the pre-checkout query was sent.

.. include:: /_includes/usable-by/bots.rst

Parameters:
pre_checkout_query_id (``str``):
Unique identifier for the query to be answered.

ok (``bool``):
Specify True if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order. Use False if there are any problems.

error_message (``str``, *optional*):
Required if ok is False. Error message in human readable form that explains the reason for failure to proceed with the checkout (e.g. "Sorry, somebody just bought the last of our amazing black T-shirts while you were busy filling out your payment details. Please choose a different color or garment!"). Telegram will display this message to the user.

Returns:
``bool``: True, on success.

Example:
.. code-block:: python

# Proceed with the order
await app.answer_pre_checkout_query(query_id, ok=True)

# Answer with error message
await app.answer_pre_checkout_query(query_id, ok=False, error_message="Error Message displayed to the user")

"""
return await self.invoke(
raw.functions.messages.SetBotPrecheckoutResults(
query_id=int(pre_checkout_query_id),
success=ok or None,
error=error_message or None
)
)
53 changes: 53 additions & 0 deletions pyrogram/methods/business/refund_star_payment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <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 typing import Union

import pyrogram
from pyrogram import raw


class RefundStarPayment:
async def refund_star_payment(
self: "pyrogram.Client",
user_id: Union[int, str],
telegram_payment_charge_id: str
) -> bool:
"""Refunds a successful payment in `Telegram Stars <https://t.me/BotNews/90>`_.

.. include:: /_includes/usable-by/bots.rst

Parameters:
user_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target user, whose payment will be refunded.

telegram_payment_charge_id (``str``):
Telegram payment identifier.

Returns:
``bool``: True on success

"""

r = await self.invoke(
raw.functions.payments.RefundStarsCharge(
user_id=await self.resolve_peer(user_id),
charge_id=telegram_payment_charge_id
)
)
return bool(r)
Loading