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):