diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index 2e8b0421..c5aaef30 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -369,6 +369,7 @@ def pyrogram_api(): answer_web_app_query answer_pre_checkout_query answer_shipping_query + refund_star_payment get_bot_info set_bot_info get_collectible_item_info diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index 1793472d..e1c1c869 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -18,7 +18,7 @@ # along with Pyrofork. If not, see . __fork_name__ = "PyroFork" -__version__ = "2.3.29" +__version__ = "2.3.31" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __copyright__ = "Copyright (C) 2022-present Mayuri-Chan " diff --git a/pyrogram/methods/bots/__init__.py b/pyrogram/methods/bots/__init__.py index f37303d1..69910a74 100644 --- a/pyrogram/methods/bots/__init__.py +++ b/pyrogram/methods/bots/__init__.py @@ -29,6 +29,7 @@ from .get_chat_menu_button import GetChatMenuButton from .get_collectible_item_info import GetCollectibleItemInfo from .get_game_high_scores import GetGameHighScores from .get_inline_bot_results import GetInlineBotResults +from .refund_stars_payment import RefundStarPayment from .request_callback_answer import RequestCallbackAnswer from .send_game import SendGame from .send_inline_bot_result import SendInlineBotResult @@ -59,6 +60,7 @@ class Bots( GetChatMenuButton, AnswerWebAppQuery, AnswerPreCheckoutQuery, + RefundStarPayment, GetCollectibleItemInfo ): pass diff --git a/pyrogram/methods/bots/refund_stars_payment.py b/pyrogram/methods/bots/refund_stars_payment.py new file mode 100644 index 00000000..efcfdd07 --- /dev/null +++ b/pyrogram/methods/bots/refund_stars_payment.py @@ -0,0 +1,54 @@ +# Pyrofork - Telegram MTProto API Client Library for Python +# Copyright (C) 2022-present Mayuri-Chan +# +# This file is part of Pyrofork. +# +# Pyrofork 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. +# +# Pyrofork 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 Pyrofork. If not, see . + +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: + """Refund the star to the user. + + Parameters: + user_id (``int`` | ``str``): + The user id to refund the stars. + + telegram_payment_charge_id (``str``): + The charge id to refund the stars. + + Returns: + `bool`: On success, a True is returned. + + Example: + .. code-block:: python + + await app.refund_star_payment(user_id, telegram_payment_charge_id) + """ + await self.invoke( + raw.functions.payments.RefundStarsCharge( + user_id=await self.resolve_peer(user_id), + charge_id=telegram_payment_charge_id + ) + ) + + return True diff --git a/pyrogram/methods/messages/send_invoice.py b/pyrogram/methods/messages/send_invoice.py index 0dde16d9..6fc090a6 100644 --- a/pyrogram/methods/messages/send_invoice.py +++ b/pyrogram/methods/messages/send_invoice.py @@ -39,6 +39,7 @@ class SendInvoice: message_thread_id: int = None, quote_text: str = None, quote_entities: List["types.MessageEntity"] = None, + reply_markup: "types.InlineKeyboardMarkup" = None ): """Use this method to send invoices. @@ -56,12 +57,14 @@ class SendInvoice: currency (``str``): Three-letter ISO 4217 currency code. + `XTR` for Telegram Stars. prices (List of :obj:`~pyrogram.types.LabeledPrice`): Price with label. provider (``str``, *optional*): Payment provider. + Get this from botfather. provider_data (``str``, *optional*): Provider data in json format. @@ -96,22 +99,49 @@ class SendInvoice: List of special entities that appear in quote_text, which can be specified instead of *parse_mode*. for reply_to_message only. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*): + An inline keyboard. If empty, one 'Buy' button will be shown. + Returns: :obj:`~pyrogram.types.Message`: On success, the sent message is returned. Example: .. code-block:: python + # USD app.send_invoice(chat_id, types.InputMediaInvoice( title="Product Name", description="Product Description", currency="USD", prices=[types.LabeledPrice("Product", 1000)], - provider="Stripe", + provider="Stripe_provider_codes", provider_data="{}" )) + + # Telegram Stars + app.send_invoice(chat_id, types.InputMediaInvoice( + title="Product Name", + description="Product Description", + currency="XTR", + prices=[types.LabeledPrice("Product", 1000)] + )) """ + if reply_markup is not None: + has_buy_button = False + for i in reply_markup.inline_keyboard: + for j in i: + if isinstance(j, types.InlineKeyboardButtonBuy): + has_buy_button = True + if not has_buy_button: + text = "Pay" + if currency == "XTR": + prices_total = 0 + for price in prices: + prices_total += price.amount + text = f"Pay ⭐️{prices_total}" + reply_markup.inline_keyboard.insert(0, [types.InlineKeyboardButtonBuy(text=text)]) + reply_to = await utils.get_reply_to( client=self, chat_id=chat_id, @@ -145,7 +175,8 @@ class SendInvoice: ), random_id=self.rnd_id(), reply_to=reply_to, - message="" + message="", + reply_markup=await reply_markup.write(self) if reply_markup is not None else None ) ) @@ -157,7 +188,7 @@ class SendInvoice: raw.types.UpdateNewChannelMessage ) ): - return types.Message._parse( + return await types.Message._parse( self, i.message, users={i.id: i for i in r.users}, diff --git a/pyrogram/types/bots_and_keyboards/inline_keyboard_button_buy.py b/pyrogram/types/bots_and_keyboards/inline_keyboard_button_buy.py index 3f74f2a1..1ac3effe 100644 --- a/pyrogram/types/bots_and_keyboards/inline_keyboard_button_buy.py +++ b/pyrogram/types/bots_and_keyboards/inline_keyboard_button_buy.py @@ -15,9 +15,12 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Pyrofork. If not, see . +import pyrogram from ..object import Object +from pyrogram import raw + class InlineKeyboardButtonBuy(Object): """One button of the inline keyboard. For simple invoice buttons. @@ -42,4 +45,7 @@ class InlineKeyboardButtonBuy(Object): text=b.text ) - # TODO: Implement write method + async def write(self, _: "pyrogram.Client"): + return raw.types.KeyboardButtonBuy( + text=self.text + ) diff --git a/pyrogram/types/bots_and_keyboards/inline_keyboard_markup.py b/pyrogram/types/bots_and_keyboards/inline_keyboard_markup.py index e91d1e0d..7ddcb69e 100644 --- a/pyrogram/types/bots_and_keyboards/inline_keyboard_markup.py +++ b/pyrogram/types/bots_and_keyboards/inline_keyboard_markup.py @@ -29,8 +29,10 @@ class InlineKeyboardMarkup(Object): """An inline keyboard that appears right next to the message it belongs to. Parameters: - inline_keyboard (List of List of :obj:`~pyrogram.types.InlineKeyboardButton`): + inline_keyboard (List of List of :obj:`~pyrogram.types.InlineKeyboardButton` | :obj:`~pyrogram.types.InlineKeyboardButtonBuy`): List of button rows, each represented by a List of InlineKeyboardButton objects. + :obj:`~pyrogram.types.InlineKeyboardButtonBuy` objects is only for :meth:`~pyrogram.Client.send_invoice`. + and only one needed in the first row. """ def __init__(self, inline_keyboard: List[List[Union["types.InlineKeyboardButton", "types.InlineKeyboardButtonBuy"]]]): diff --git a/pyrogram/types/bots_and_keyboards/pre_checkout_query.py b/pyrogram/types/bots_and_keyboards/pre_checkout_query.py index 2a5dc552..09f3bdaf 100644 --- a/pyrogram/types/bots_and_keyboards/pre_checkout_query.py +++ b/pyrogram/types/bots_and_keyboards/pre_checkout_query.py @@ -116,7 +116,7 @@ class PreCheckoutQuery(Object, Update): await client.answer_pre_checkout_query( pre_checkout_query.id, - ok=True + success=True ) Example: diff --git a/pyrogram/types/messages_and_media/labeled_price.py b/pyrogram/types/messages_and_media/labeled_price.py index 5ffc9237..5ea1c53c 100644 --- a/pyrogram/types/messages_and_media/labeled_price.py +++ b/pyrogram/types/messages_and_media/labeled_price.py @@ -28,6 +28,9 @@ class LabeledPrice(Object): amount (``int``): Price of the product in the smallest units of the currency (integer, not float/double). + The minimum amuont for telegram stars is 1. + The minimum amount for other currencies is US$1. + you need to add 2 extra zeros to the amount (except stars), example 100 for 1 usd. """ def __init__( diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index ee4e2187..c18fefca 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -792,17 +792,17 @@ class Message(Object, Update): elif isinstance(action, raw.types.MessageActionBotAllowed): bot_allowed = types.BotAllowed._parse(client, action) service_type = enums.MessageServiceType.BOT_ALLOWED - elif isinstance(action, raw.types.MessageActionRequestedPeer): + elif isinstance(action, raw.types.MessageActionRequestedPeer) or isinstance(action, raw.types.MessageActionRequestedPeerSentMe): chat_shared = [] user_shared = [] for peer in action.peers: - if isinstance(peer, raw.types.PeerChannel): + if isinstance(peer, raw.types.PeerChannel) or isinstance(peer, raw.types.RequestedPeerChannel): chat_shared.append(utils.get_channel_id(utils.get_raw_peer_id(peer))) service_type = enums.MessageServiceType.ChannelShared - elif isinstance(peer, raw.types.PeerChat): + elif isinstance(peer, raw.types.PeerChat) or isinstance(peer, raw.types.RequestedPeerChat): chat_shared.append(utils.get_channel_id(utils.get_raw_peer_id(peer))) service_type = enums.MessageServiceType.ChannelShared - elif isinstance(peer, raw.types.PeerUser): + elif isinstance(peer, raw.types.PeerUser) or isinstance(peer, raw.types.RequestedPeerUser): user_shared.append(peer.user_id) service_type = enums.MessageServiceType.UserShared elif isinstance(action, raw.types.MessageActionTopicCreate):