From 14d4d2c3a301e7503d21f15997e0c3e6075d61ca Mon Sep 17 00:00:00 2001 From: aelkheir <90580077+aelkheir@users.noreply.github.com> Date: Sun, 8 Sep 2024 09:35:53 +0300 Subject: [PATCH 1/6] Add paid media payload. --- telegram/_bot.py | 7 +++++++ telegram/_chat.py | 2 ++ telegram/_payment/stars.py | 15 ++++++++------- telegram/constants.py | 2 ++ telegram/ext/_extbot.py | 2 ++ tests/test_chat.py | 5 ++++- tests/test_stars.py | 1 + 7 files changed, 26 insertions(+), 8 deletions(-) diff --git a/telegram/_bot.py b/telegram/_bot.py index b79df08ff17..94c4b1f0365 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -9193,6 +9193,7 @@ async def send_paid_media( reply_parameters: Optional["ReplyParameters"] = None, reply_markup: Optional[ReplyMarkup] = None, business_connection_id: Optional[str] = None, + payload: Optional[str] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -9214,6 +9215,11 @@ async def send_paid_media( to the media. media (Sequence[:class:`telegram.InputPaidMedia`]): A list describing the media to be sent; up to :tg-const:`telegram.constants.MediaGroupLimit.MAX_MEDIA_LENGTH` items. + payload (:obj:`str`, optional): Bot-defined paid media payload, + 0-:tg-const:`telegram.constants.InvoiceLimit.MAX_PAYLOAD_LENGTH` bytes. This will + not be displayed to the user, use it for your internal processes. + + .. versionadded:: NEXT.VERSION caption (:obj:`str`, optional): Caption of the media to be sent, 0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters. parse_mode (:obj:`str`, optional): |parse_mode| @@ -9252,6 +9258,7 @@ async def send_paid_media( "star_count": star_count, "media": media, "show_caption_above_media": show_caption_above_media, + "payload": payload, } return await self._send_message( diff --git a/telegram/_chat.py b/telegram/_chat.py index 6eb78978596..8c5f705248e 100644 --- a/telegram/_chat.py +++ b/telegram/_chat.py @@ -3350,6 +3350,7 @@ async def send_paid_media( reply_parameters: Optional["ReplyParameters"] = None, reply_markup: Optional[ReplyMarkup] = None, business_connection_id: Optional[str] = None, + payload: Optional[str] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -3391,6 +3392,7 @@ async def send_paid_media( pool_timeout=pool_timeout, api_kwargs=api_kwargs, business_connection_id=business_connection_id, + payload=payload, ) diff --git a/telegram/_payment/stars.py b/telegram/_payment/stars.py index 94f621d00e8..576e13f0328 100644 --- a/telegram/_payment/stars.py +++ b/telegram/_payment/stars.py @@ -326,8 +326,9 @@ class TransactionPartnerUser(TransactionPartner): invoice_payload (:obj:`str`, optional): Bot-specified invoice payload. paid_media (Sequence[:class:`telegram.PaidMedia`], optional): Information about the paid media bought by the user. + paid_media_payload (:obj:`str`, optional): Optional. Bot-specified paid media payload. - .. versionadded:: 21.5 + .. versionadded:: NEXT.VERSION Attributes: type (:obj:`str`): The type of the transaction partner, @@ -336,21 +337,20 @@ class TransactionPartnerUser(TransactionPartner): invoice_payload (:obj:`str`): Optional. Bot-specified invoice payload. paid_media (Tuple[:class:`telegram.PaidMedia`]): Optional. Information about the paid media bought by the user. + paid_media_payload (:obj:`str`): Optional. Optional. Bot-specified paid media payload. + + .. versionadded:: NEXT.VERSION - .. versionadded:: 21.5 """ - __slots__ = ( - "invoice_payload", - "paid_media", - "user", - ) + __slots__ = ("invoice_payload", "paid_media", "paid_media_payload", "user") def __init__( self, user: "User", invoice_payload: Optional[str] = None, paid_media: Optional[Sequence[PaidMedia]] = None, + paid_media_payload: Optional[str] = None, *, api_kwargs: Optional[JSONDict] = None, ) -> None: @@ -360,6 +360,7 @@ def __init__( self.user: User = user self.invoice_payload: Optional[str] = invoice_payload self.paid_media: Optional[Tuple[PaidMedia, ...]] = parse_sequence_arg(paid_media) + self.paid_media_payload: Optional[str] = paid_media_payload self._id_attrs = ( self.type, self.user, diff --git a/telegram/constants.py b/telegram/constants.py index 0f179b1a34d..58129b5ab68 100644 --- a/telegram/constants.py +++ b/telegram/constants.py @@ -2795,6 +2795,8 @@ class InvoiceLimit(IntEnum): :meth:`telegram.Bot.send_invoice`. * :paramref:`~telegram.Bot.create_invoice_link.payload` parameter of :meth:`telegram.Bot.create_invoice_link`. + * :paramref:`~telegram.Bot.send_paid_media.payload` parameter of + :meth:`telegram.Bot.send_paid_media`. """ MAX_TIP_AMOUNTS = 4 """:obj:`int`: Maximum length of a :obj:`Sequence` passed as: diff --git a/telegram/ext/_extbot.py b/telegram/ext/_extbot.py index 76b17bad02a..3d91acf0d4f 100644 --- a/telegram/ext/_extbot.py +++ b/telegram/ext/_extbot.py @@ -4235,6 +4235,7 @@ async def send_paid_media( reply_parameters: Optional["ReplyParameters"] = None, reply_markup: Optional[ReplyMarkup] = None, business_connection_id: Optional[str] = None, + payload: Optional[str] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -4265,6 +4266,7 @@ async def send_paid_media( pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), business_connection_id=business_connection_id, + payload=payload, ) async def create_chat_subscription_invite_link( diff --git a/tests/test_chat.py b/tests/test_chat.py index a3dcd6aa17f..72041c47b5c 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -1299,6 +1299,7 @@ async def make_assertion(*_, **kwargs): and kwargs["media"] == "media" and kwargs["star_count"] == 42 and kwargs["caption"] == "stars" + and kwargs["payload"] == "payload" ) assert check_shortcut_signature(Chat.send_paid_media, Bot.send_paid_media, ["chat_id"], []) @@ -1306,7 +1307,9 @@ async def make_assertion(*_, **kwargs): assert await check_defaults_handling(chat.send_paid_media, chat.get_bot()) monkeypatch.setattr(chat.get_bot(), "send_paid_media", make_assertion) - assert await chat.send_paid_media(media="media", star_count=42, caption="stars") + assert await chat.send_paid_media( + media="media", star_count=42, caption="stars", payload="payload" + ) def test_mention_html(self): chat = Chat(id=1, type="foo") diff --git a/tests/test_stars.py b/tests/test_stars.py index ef700ae392a..1a91a73cfc2 100644 --- a/tests/test_stars.py +++ b/tests/test_stars.py @@ -74,6 +74,7 @@ def transaction_partner_user(): ] ) ], + paid_media_payload="payload", ) From cf501a70302d5e5ba02b9507b5b219cfbfb5e6e7 Mon Sep 17 00:00:00 2001 From: aelkheir <90580077+aelkheir@users.noreply.github.com> Date: Sun, 8 Sep 2024 11:51:51 +0300 Subject: [PATCH 2/6] Add the field `star_prize_count`. --- telegram/_chatboost.py | 15 +++++++++++++-- telegram/_giveaway.py | 41 ++++++++++++++++++++++++++++++++++++++--- tests/test_chatboost.py | 2 ++ tests/test_giveaway.py | 41 +++++++++++++++++++++++++++++++++++++++-- tests/test_message.py | 2 +- 5 files changed, 93 insertions(+), 8 deletions(-) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index 7b972eec6d8..03ffd94e64c 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -188,7 +188,8 @@ def __init__(self, user: User, *, api_kwargs: Optional[JSONDict] = None): class ChatBoostSourceGiveaway(ChatBoostSource): """ The boost was obtained by the creation of a Telegram Premium giveaway. This boosts the chat 4 - times for the duration of the corresponding Telegram Premium subscription. + times for the duration of the corresponding Telegram Premium subscription for Telegram Premium + giveaways and prize_star_count / 500 times for one year for Telegram Star giveaways. .. versionadded:: 20.8 @@ -196,6 +197,10 @@ class ChatBoostSourceGiveaway(ChatBoostSource): giveaway_message_id (:obj:`int`): Identifier of a message in the chat with the giveaway; the message could have been deleted already. May be 0 if the message isn't sent yet. user (:class:`telegram.User`, optional): User that won the prize in the giveaway if any. + prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between + giveaway winners; for Telegram Star giveaways only. + + .. versionadded:: NEXT.VERSION is_unclaimed (:obj:`bool`, optional): :obj:`True`, if the giveaway was completed, but there was no user to win the prize. @@ -205,17 +210,22 @@ class ChatBoostSourceGiveaway(ChatBoostSource): giveaway_message_id (:obj:`int`): Identifier of a message in the chat with the giveaway; the message could have been deleted already. May be 0 if the message isn't sent yet. user (:class:`telegram.User`): Optional. User that won the prize in the giveaway if any. + prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between + giveaway winners; for Telegram Star giveaways only. + + .. versionadded:: NEXT.VERSION is_unclaimed (:obj:`bool`): Optional. :obj:`True`, if the giveaway was completed, but there was no user to win the prize. """ - __slots__ = ("giveaway_message_id", "is_unclaimed", "user") + __slots__ = ("giveaway_message_id", "is_unclaimed", "prize_star_count", "user") def __init__( self, giveaway_message_id: int, user: Optional[User] = None, is_unclaimed: Optional[bool] = None, + prize_star_count: Optional[int] = None, *, api_kwargs: Optional[JSONDict] = None, ): @@ -224,6 +234,7 @@ def __init__( with self._unfrozen(): self.giveaway_message_id: int = giveaway_message_id self.user: Optional[User] = user + self.prize_star_count: Optional[int] = prize_star_count self.is_unclaimed: Optional[bool] = is_unclaimed diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index b287433fe0b..5c189262f9e 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -56,6 +56,10 @@ class Giveaway(TelegramObject): country codes indicating the countries from which eligible users for the giveaway must come. If empty, then all users can participate in the giveaway. Users with a phone number that was bought on Fragment can always participate in giveaways. + prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between + giveaway winners; for Telegram Star giveaways only. + + .. versionadded:: NEXT.VERSION premium_subscription_month_count (:obj:`int`, optional): The number of months the Telegram Premium subscription won from the giveaway will be active for. @@ -75,6 +79,10 @@ class Giveaway(TelegramObject): country codes indicating the countries from which eligible users for the giveaway must come. If empty, then all users can participate in the giveaway. Users with a phone number that was bought on Fragment can always participate in giveaways. + prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between + giveaway winners; for Telegram Star giveaways only. + + .. versionadded:: NEXT.VERSION premium_subscription_month_count (:obj:`int`): Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for. """ @@ -86,6 +94,7 @@ class Giveaway(TelegramObject): "only_new_members", "premium_subscription_month_count", "prize_description", + "prize_star_count", "winner_count", "winners_selection_date", ) @@ -100,6 +109,7 @@ def __init__( prize_description: Optional[str] = None, country_codes: Optional[Sequence[str]] = None, premium_subscription_month_count: Optional[int] = None, + prize_star_count: Optional[int] = None, *, api_kwargs: Optional[JSONDict] = None, ): @@ -113,6 +123,7 @@ def __init__( self.prize_description: Optional[str] = prize_description self.country_codes: Tuple[str, ...] = parse_sequence_arg(country_codes) self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count + self.prize_star_count: Optional[int] = prize_star_count self._id_attrs = ( self.chats, @@ -145,13 +156,26 @@ def de_json( class GiveawayCreated(TelegramObject): """This object represents a service message about the creation of a scheduled giveaway. - Currently holds no information. + + Args: + prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be + split between giveaway winners; for Telegram Star giveaways only. + + .. versionadded:: NEXT.VERSION + + Attributes: + prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be + split between giveaway winners; for Telegram Star giveaways only. + + .. versionadded:: NEXT.VERSION + """ - __slots__ = () + __slots__ = ("prize_star_count",) - def __init__(self, *, api_kwargs: Optional[JSONDict] = None): + def __init__(self, prize_star_count: Optional[int], *, api_kwargs: Optional[JSONDict] = None): super().__init__(api_kwargs=api_kwargs) + self.prize_star_count: Optional[int] = prize_star_count self._freeze() @@ -173,6 +197,10 @@ class GiveawayWinners(TelegramObject): winner_count (:obj:`int`): Total number of winners in the giveaway winners (Sequence[:class:`telegram.User`]): List of up to :tg-const:`telegram.constants.GiveawayLimit.MAX_WINNERS` winners of the giveaway + prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between + giveaway winners; for Telegram Star giveaways only. + + .. versionadded:: NEXT.VERSION additional_chat_count (:obj:`int`, optional): The number of other chats the user had to join in order to be eligible for the giveaway premium_subscription_month_count (:obj:`int`, optional): The number of months the Telegram @@ -194,6 +222,10 @@ class GiveawayWinners(TelegramObject): :tg-const:`telegram.constants.GiveawayLimit.MAX_WINNERS` winners of the giveaway additional_chat_count (:obj:`int`): Optional. The number of other chats the user had to join in order to be eligible for the giveaway + prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between + giveaway winners; for Telegram Star giveaways only. + + .. versionadded:: NEXT.VERSION premium_subscription_month_count (:obj:`int`): Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for unclaimed_prize_count (:obj:`int`): Optional. Number of undistributed prizes @@ -211,6 +243,7 @@ class GiveawayWinners(TelegramObject): "only_new_members", "premium_subscription_month_count", "prize_description", + "prize_star_count", "unclaimed_prize_count", "was_refunded", "winner_count", @@ -231,6 +264,7 @@ def __init__( only_new_members: Optional[bool] = None, was_refunded: Optional[bool] = None, prize_description: Optional[str] = None, + prize_star_count: Optional[int] = None, *, api_kwargs: Optional[JSONDict] = None, ): @@ -247,6 +281,7 @@ def __init__( self.only_new_members: Optional[bool] = only_new_members self.was_refunded: Optional[bool] = was_refunded self.prize_description: Optional[str] = prize_description + self.prize_star_count: Optional[int] = prize_star_count self._id_attrs = ( self.chat, diff --git a/tests/test_chatboost.py b/tests/test_chatboost.py index f0ef143618a..dc393dc6043 100644 --- a/tests/test_chatboost.py +++ b/tests/test_chatboost.py @@ -50,6 +50,7 @@ class ChatBoostDefaults: user = User(1, "user", False) date = to_timestamp(datetime.datetime.utcnow()) default_source = ChatBoostSourcePremium(user) + prize_star_count = 99 @pytest.fixture(scope="module") @@ -91,6 +92,7 @@ def chat_boost_source_giveaway(): user=ChatBoostDefaults.user, giveaway_message_id=ChatBoostDefaults.giveaway_message_id, is_unclaimed=ChatBoostDefaults.is_unclaimed, + prize_star_count=ChatBoostDefaults.prize_star_count, ) diff --git a/tests/test_giveaway.py b/tests/test_giveaway.py index 35945118363..7578b3b0ae6 100644 --- a/tests/test_giveaway.py +++ b/tests/test_giveaway.py @@ -48,6 +48,7 @@ def giveaway(): premium_subscription_month_count=( TestGiveawayWithoutRequest.premium_subscription_month_count ), + prize_star_count=TestGiveawayWithoutRequest.prize_star_count, ) @@ -60,6 +61,7 @@ class TestGiveawayWithoutRequest: prize_description = "prize_description" country_codes = ["DE", "US"] premium_subscription_month_count = 3 + prize_star_count = 99 def test_slot_behaviour(self, giveaway): for attr in giveaway.__slots__: @@ -76,6 +78,7 @@ def test_de_json(self, bot): "prize_description": self.prize_description, "country_codes": self.country_codes, "premium_subscription_month_count": self.premium_subscription_month_count, + "prize_star_count": self.prize_star_count, } giveaway = Giveaway.de_json(json_dict, bot) @@ -89,6 +92,7 @@ def test_de_json(self, bot): assert giveaway.prize_description == self.prize_description assert giveaway.country_codes == tuple(self.country_codes) assert giveaway.premium_subscription_month_count == self.premium_subscription_month_count + assert giveaway.prize_star_count == self.prize_star_count assert Giveaway.de_json(None, bot) is None @@ -102,6 +106,7 @@ def test_de_json_localization(self, tz_bot, bot, raw_bot): "prize_description": self.prize_description, "country_codes": self.country_codes, "premium_subscription_month_count": self.premium_subscription_month_count, + "prize_star_count": self.prize_star_count, } giveaway_raw = Giveaway.de_json(json_dict, raw_bot) @@ -133,6 +138,7 @@ def test_to_dict(self, giveaway): giveaway_dict["premium_subscription_month_count"] == self.premium_subscription_month_count ) + assert giveaway_dict["prize_star_count"] == self.prize_star_count def test_equality(self, giveaway): a = giveaway @@ -164,15 +170,41 @@ def test_equality(self, giveaway): assert hash(a) != hash(e) +@pytest.fixture(scope="module") +def giveaway_created(): + return GiveawayCreated( + prize_star_count=TestGiveawayCreatedWithoutRequest.prize_star_count, + ) + + class TestGiveawayCreatedWithoutRequest: - def test_slot_behaviour(self): - giveaway_created = GiveawayCreated() + prize_star_count = 99 + + def test_slot_behaviour(self, giveaway_created): for attr in giveaway_created.__slots__: assert getattr(giveaway_created, attr, "err") != "err", f"got extra slot '{attr}'" assert len(mro_slots(giveaway_created)) == len( set(mro_slots(giveaway_created)) ), "duplicate slot" + def test_de_json(self, bot): + json_dict = { + "prize_star_count": self.prize_star_count, + } + + gac = GiveawayCreated.de_json(json_dict, bot) + assert gac.api_kwargs == {} + + assert gac.prize_star_count == self.prize_star_count + + assert Giveaway.de_json(None, bot) is None + + def test_to_dict(self, giveaway_created): + gac_dict = giveaway_created.to_dict() + + assert isinstance(gac_dict, dict) + assert gac_dict["prize_star_count"] == self.prize_star_count + @pytest.fixture(scope="module") def giveaway_winners(): @@ -190,6 +222,7 @@ def giveaway_winners(): additional_chat_count=TestGiveawayWinnersWithoutRequest.additional_chat_count, unclaimed_prize_count=TestGiveawayWinnersWithoutRequest.unclaimed_prize_count, was_refunded=TestGiveawayWinnersWithoutRequest.was_refunded, + prize_star_count=TestGiveawayWinnersWithoutRequest.prize_star_count, ) @@ -205,6 +238,7 @@ class TestGiveawayWinnersWithoutRequest: only_new_members = True was_refunded = True prize_description = "prize_description" + prize_star_count = 99 def test_slot_behaviour(self, giveaway_winners): for attr in giveaway_winners.__slots__: @@ -226,6 +260,7 @@ def test_de_json(self, bot): "only_new_members": self.only_new_members, "was_refunded": self.was_refunded, "prize_description": self.prize_description, + "prize_star_count": self.prize_star_count, } giveaway_winners = GiveawayWinners.de_json(json_dict, bot) @@ -245,6 +280,7 @@ def test_de_json(self, bot): assert giveaway_winners.only_new_members == self.only_new_members assert giveaway_winners.was_refunded == self.was_refunded assert giveaway_winners.prize_description == self.prize_description + assert giveaway_winners.prize_star_count == self.prize_star_count assert GiveawayWinners.de_json(None, bot) is None @@ -291,6 +327,7 @@ def test_to_dict(self, giveaway_winners): assert giveaway_winners_dict["only_new_members"] == self.only_new_members assert giveaway_winners_dict["was_refunded"] == self.was_refunded assert giveaway_winners_dict["prize_description"] == self.prize_description + assert giveaway_winners_dict["prize_star_count"] == self.prize_star_count def test_equality(self, giveaway_winners): a = giveaway_winners diff --git a/tests/test_message.py b/tests/test_message.py index 84b2b7c3929..9f085d3fca6 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -236,7 +236,7 @@ def message(bot): winner_count=5, ) }, - {"giveaway_created": GiveawayCreated()}, + {"giveaway_created": GiveawayCreated(prize_star_count=99)}, { "giveaway_winners": GiveawayWinners( chat=Chat(1, Chat.CHANNEL), From e25842d55f9a6ce7456dfaa3d67127ad3793a2c6 Mon Sep 17 00:00:00 2001 From: aelkheir <90580077+aelkheir@users.noreply.github.com> Date: Sun, 8 Sep 2024 12:03:35 +0300 Subject: [PATCH 3/6] Add the field `is_star_giveaway`. --- telegram/_giveaway.py | 8 +++++++- tests/test_giveaway.py | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index 5c189262f9e..8bf8f986c7b 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -330,21 +330,26 @@ class GiveawayCompleted(TelegramObject): unclaimed_prize_count (:obj:`int`, optional): Number of undistributed prizes giveaway_message (:class:`telegram.Message`, optional): Message with the giveaway that was completed, if it wasn't deleted + is_star_giveaway (:obj:`bool`, optional): True, if the giveaway is a Telegram Star + giveaway. Otherwise, currently, the giveaway is a Telegram Premium giveaway. Attributes: winner_count (:obj:`int`): Number of winners in the giveaway unclaimed_prize_count (:obj:`int`): Optional. Number of undistributed prizes giveaway_message (:class:`telegram.Message`): Optional. Message with the giveaway that was completed, if it wasn't deleted + is_star_giveaway (:obj:`bool`): Optional. True, if the giveaway is a Telegram Star + giveaway. Otherwise, currently, the giveaway is a Telegram Premium giveaway. """ - __slots__ = ("giveaway_message", "unclaimed_prize_count", "winner_count") + __slots__ = ("giveaway_message", "is_star_giveaway", "unclaimed_prize_count", "winner_count") def __init__( self, winner_count: int, unclaimed_prize_count: Optional[int] = None, giveaway_message: Optional["Message"] = None, + is_star_giveaway: Optional[bool] = None, *, api_kwargs: Optional[JSONDict] = None, ): @@ -353,6 +358,7 @@ def __init__( self.winner_count: int = winner_count self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count self.giveaway_message: Optional[Message] = giveaway_message + self.is_star_giveaway: Optional[bool] = is_star_giveaway self._id_attrs = ( self.winner_count, diff --git a/tests/test_giveaway.py b/tests/test_giveaway.py index 7578b3b0ae6..67888038ab0 100644 --- a/tests/test_giveaway.py +++ b/tests/test_giveaway.py @@ -373,12 +373,14 @@ def giveaway_completed(): winner_count=TestGiveawayCompletedWithoutRequest.winner_count, unclaimed_prize_count=TestGiveawayCompletedWithoutRequest.unclaimed_prize_count, giveaway_message=TestGiveawayCompletedWithoutRequest.giveaway_message, + is_star_giveaway=TestGiveawayCompletedWithoutRequest.is_star_giveaway, ) class TestGiveawayCompletedWithoutRequest: winner_count = 42 unclaimed_prize_count = 4 + is_star_giveaway = True giveaway_message = Message( message_id=1, date=dtm.datetime.now(dtm.timezone.utc), @@ -399,6 +401,7 @@ def test_de_json(self, bot): "winner_count": self.winner_count, "unclaimed_prize_count": self.unclaimed_prize_count, "giveaway_message": self.giveaway_message.to_dict(), + "is_star_giveaway": self.is_star_giveaway, } giveaway_completed = GiveawayCompleted.de_json(json_dict, bot) @@ -407,6 +410,7 @@ def test_de_json(self, bot): assert giveaway_completed.winner_count == self.winner_count assert giveaway_completed.unclaimed_prize_count == self.unclaimed_prize_count assert giveaway_completed.giveaway_message == self.giveaway_message + assert giveaway_completed.is_star_giveaway == self.is_star_giveaway assert GiveawayCompleted.de_json(None, bot) is None @@ -417,6 +421,7 @@ def test_to_dict(self, giveaway_completed): assert giveaway_completed_dict["winner_count"] == self.winner_count assert giveaway_completed_dict["unclaimed_prize_count"] == self.unclaimed_prize_count assert giveaway_completed_dict["giveaway_message"] == self.giveaway_message.to_dict() + assert giveaway_completed_dict["is_star_giveaway"] == self.is_star_giveaway def test_equality(self, giveaway_completed): a = giveaway_completed @@ -424,6 +429,7 @@ def test_equality(self, giveaway_completed): winner_count=self.winner_count, unclaimed_prize_count=self.unclaimed_prize_count, giveaway_message=self.giveaway_message, + is_star_giveaway=self.is_star_giveaway, ) c = GiveawayCompleted( winner_count=self.winner_count + 30, From f2cafec5e4cbaec43ab763251d78cafbe00ee1e4 Mon Sep 17 00:00:00 2001 From: aelkheir <90580077+aelkheir@users.noreply.github.com> Date: Mon, 9 Sep 2024 06:01:28 +0300 Subject: [PATCH 4/6] Address review comments. --- telegram/_chatboost.py | 11 ++++++----- telegram/_giveaway.py | 19 +++++++++++-------- telegram/_payment/stars.py | 4 ++++ tests/test_giveaway.py | 1 - 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index 03ffd94e64c..25944cda0f4 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -187,9 +187,10 @@ def __init__(self, user: User, *, api_kwargs: Optional[JSONDict] = None): class ChatBoostSourceGiveaway(ChatBoostSource): """ - The boost was obtained by the creation of a Telegram Premium giveaway. This boosts the chat 4 - times for the duration of the corresponding Telegram Premium subscription for Telegram Premium - giveaways and prize_star_count / 500 times for one year for Telegram Star giveaways. + The boost was obtained by the creation of a Telegram Premium giveaway or a Telegram Star. + This boosts the chat 4 times for the duration of the corresponding Telegram Premium + subscription for Telegram Premium giveaways and :attr:`prize_star_count` / 500 times for + one year for Telegram Star giveaways. .. versionadded:: 20.8 @@ -200,7 +201,7 @@ class ChatBoostSourceGiveaway(ChatBoostSource): prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only. - .. versionadded:: NEXT.VERSION + .. versionadded:: NEXT.VERSION is_unclaimed (:obj:`bool`, optional): :obj:`True`, if the giveaway was completed, but there was no user to win the prize. @@ -213,7 +214,7 @@ class ChatBoostSourceGiveaway(ChatBoostSource): prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only. - .. versionadded:: NEXT.VERSION + .. versionadded:: NEXT.VERSION is_unclaimed (:obj:`bool`): Optional. :obj:`True`, if the giveaway was completed, but there was no user to win the prize. """ diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index 8bf8f986c7b..1e3bbd5c7fb 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -59,7 +59,7 @@ class Giveaway(TelegramObject): prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only. - .. versionadded:: NEXT.VERSION + .. versionadded:: NEXT.VERSION premium_subscription_month_count (:obj:`int`, optional): The number of months the Telegram Premium subscription won from the giveaway will be active for. @@ -82,7 +82,7 @@ class Giveaway(TelegramObject): prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only. - .. versionadded:: NEXT.VERSION + .. versionadded:: NEXT.VERSION premium_subscription_month_count (:obj:`int`): Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for. """ @@ -161,13 +161,13 @@ class GiveawayCreated(TelegramObject): prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only. - .. versionadded:: NEXT.VERSION + .. versionadded:: NEXT.VERSION Attributes: prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only. - .. versionadded:: NEXT.VERSION + .. versionadded:: NEXT.VERSION """ @@ -200,7 +200,7 @@ class GiveawayWinners(TelegramObject): prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only. - .. versionadded:: NEXT.VERSION + .. versionadded:: NEXT.VERSION additional_chat_count (:obj:`int`, optional): The number of other chats the user had to join in order to be eligible for the giveaway premium_subscription_month_count (:obj:`int`, optional): The number of months the Telegram @@ -225,7 +225,7 @@ class GiveawayWinners(TelegramObject): prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only. - .. versionadded:: NEXT.VERSION + .. versionadded:: NEXT.VERSION premium_subscription_month_count (:obj:`int`): Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for unclaimed_prize_count (:obj:`int`): Optional. Number of undistributed prizes @@ -330,16 +330,19 @@ class GiveawayCompleted(TelegramObject): unclaimed_prize_count (:obj:`int`, optional): Number of undistributed prizes giveaway_message (:class:`telegram.Message`, optional): Message with the giveaway that was completed, if it wasn't deleted - is_star_giveaway (:obj:`bool`, optional): True, if the giveaway is a Telegram Star + is_star_giveaway (:obj:`bool`, optional): :obj:`True`, if the giveaway is a Telegram Star giveaway. Otherwise, currently, the giveaway is a Telegram Premium giveaway. + .. versionadded:: NEXT.VERSION Attributes: winner_count (:obj:`int`): Number of winners in the giveaway unclaimed_prize_count (:obj:`int`): Optional. Number of undistributed prizes giveaway_message (:class:`telegram.Message`): Optional. Message with the giveaway that was completed, if it wasn't deleted - is_star_giveaway (:obj:`bool`): Optional. True, if the giveaway is a Telegram Star + is_star_giveaway (:obj:`bool`): Optional. :obj:`True`, if the giveaway is a Telegram Star giveaway. Otherwise, currently, the giveaway is a Telegram Premium giveaway. + + .. versionadded:: NEXT.VERSION """ __slots__ = ("giveaway_message", "is_star_giveaway", "unclaimed_prize_count", "winner_count") diff --git a/telegram/_payment/stars.py b/telegram/_payment/stars.py index 576e13f0328..2a3f1dca280 100644 --- a/telegram/_payment/stars.py +++ b/telegram/_payment/stars.py @@ -326,6 +326,8 @@ class TransactionPartnerUser(TransactionPartner): invoice_payload (:obj:`str`, optional): Bot-specified invoice payload. paid_media (Sequence[:class:`telegram.PaidMedia`], optional): Information about the paid media bought by the user. + + .. versionadded:: 21.5 paid_media_payload (:obj:`str`, optional): Optional. Bot-specified paid media payload. .. versionadded:: NEXT.VERSION @@ -337,6 +339,8 @@ class TransactionPartnerUser(TransactionPartner): invoice_payload (:obj:`str`): Optional. Bot-specified invoice payload. paid_media (Tuple[:class:`telegram.PaidMedia`]): Optional. Information about the paid media bought by the user. + + .. versionadded:: 21.5 paid_media_payload (:obj:`str`): Optional. Optional. Bot-specified paid media payload. .. versionadded:: NEXT.VERSION diff --git a/tests/test_giveaway.py b/tests/test_giveaway.py index 67888038ab0..ce5f87a5053 100644 --- a/tests/test_giveaway.py +++ b/tests/test_giveaway.py @@ -194,7 +194,6 @@ def test_de_json(self, bot): gac = GiveawayCreated.de_json(json_dict, bot) assert gac.api_kwargs == {} - assert gac.prize_star_count == self.prize_star_count assert Giveaway.de_json(None, bot) is None From a7e90a21e6d0efceded51614d1f8db7625b6b16f Mon Sep 17 00:00:00 2001 From: aelkheir <90580077+aelkheir@users.noreply.github.com> Date: Mon, 9 Sep 2024 06:25:54 +0300 Subject: [PATCH 5/6] Fix test_ofiicial. --- telegram/_giveaway.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index 1e3bbd5c7fb..7c08fdcb26e 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -173,7 +173,9 @@ class GiveawayCreated(TelegramObject): __slots__ = ("prize_star_count",) - def __init__(self, prize_star_count: Optional[int], *, api_kwargs: Optional[JSONDict] = None): + def __init__( + self, prize_star_count: Optional[int] = None, *, api_kwargs: Optional[JSONDict] = None + ): super().__init__(api_kwargs=api_kwargs) self.prize_star_count: Optional[int] = prize_star_count From eaa3de42c0d63ee1e08d1828c0336bcdf26bd3e5 Mon Sep 17 00:00:00 2001 From: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> Date: Mon, 9 Sep 2024 22:03:39 +0200 Subject: [PATCH 6/6] Update telegram/_chatboost.py --- telegram/_chatboost.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index 25944cda0f4..c39537442e5 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -197,7 +197,8 @@ class ChatBoostSourceGiveaway(ChatBoostSource): Args: giveaway_message_id (:obj:`int`): Identifier of a message in the chat with the giveaway; the message could have been deleted already. May be 0 if the message isn't sent yet. - user (:class:`telegram.User`, optional): User that won the prize in the giveaway if any. + user (:class:`telegram.User`, optional): User that won the prize in the giveaway if any; + for Telegram Premium giveaways only. prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only.