Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/unreleased/5078.FoNwUYLbXQFRebTFhR6UPn.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ pull_requests = [
{ uid = "5079", author_uid = "aelkheir" },
{ uid = "5084", author_uids = ["Bibo-Joshi"] },
{ uid = "5085", author_uids = ["Bibo-Joshi"] },
{ uid = "5090", author_uids = ["Bibo-Joshi"] },
{ uid = "5089", author_uids = ["Bibo-Joshi"] },
]
1 change: 1 addition & 0 deletions docs/source/telegram.at-tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Available Types
telegram.forumtopicreopened
telegram.generalforumtopichidden
telegram.generalforumtopicunhidden
telegram.giftbackground
telegram.giftinfo
telegram.giveaway
telegram.giveawaycompleted
Expand Down
7 changes: 7 additions & 0 deletions docs/source/telegram.giftbackground.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
GiftBackground
==============

.. autoclass:: telegram.GiftBackground
:members:
:show-inheritance:

3 changes: 2 additions & 1 deletion src/telegram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
"GeneralForumTopicHidden",
"GeneralForumTopicUnhidden",
"Gift",
"GiftBackground",
"GiftInfo",
"Gifts",
"Giveaway",
Expand Down Expand Up @@ -455,7 +456,7 @@
from ._games.callbackgame import CallbackGame
from ._games.game import Game
from ._games.gamehighscore import GameHighScore
from ._gifts import AcceptedGiftTypes, Gift, GiftInfo, Gifts
from ._gifts import AcceptedGiftTypes, Gift, GiftBackground, GiftInfo, Gifts
from ._giveaway import Giveaway, GiveawayCompleted, GiveawayCreated, GiveawayWinners
from ._inline.inlinekeyboardbutton import InlineKeyboardButton
from ._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
Expand Down
114 changes: 114 additions & 0 deletions src/telegram/_gifts.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,55 @@
from telegram import Bot


class GiftBackground(TelegramObject):
"""This object describes the background of a gift.

Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal if their :attr:`center_color`, :attr:`edge_color` and :attr:`text_color` are
equal.

.. versionadded:: NEXT.VERSION

Args:
center_color (:obj:`int`): Center color of the background in RGB format.
edge_color (:obj:`int`): Edge color of the background in RGB format.
text_color (:obj:`int`): Text color of the background in RGB format.

Attributes:
center_color (:obj:`int`): Center color of the background in RGB format.
edge_color (:obj:`int`): Edge color of the background in RGB format.
text_color (:obj:`int`): Text color of the background in RGB format.

"""

__slots__ = (
"center_color",
"edge_color",
"text_color",
)

def __init__(
self,
center_color: int,
edge_color: int,
text_color: int,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
self.center_color: int = center_color
self.edge_color: int = edge_color
self.text_color: int = text_color

self._id_attrs = (
self.center_color,
self.edge_color,
self.text_color,
)

self._freeze()


class Gift(TelegramObject):
"""This object represents a gift that can be sent by the bot.

Expand All @@ -59,6 +108,29 @@ class Gift(TelegramObject):
published the gift.

.. versionadded:: 22.4
personal_total_count (:obj:`int`, optional): The total number of gifts of this type that
can be sent by the bot; for limited gifts only.

.. versionadded:: NEXT.VERSION
personal_remaining_count (:obj:`int`, optional): The number of remaining gifts of this type
that can be sent by the bot; for limited gifts only.

.. versionadded:: NEXT.VERSION
background (:class:`GiftBackground`, optional): Background of the gift.

.. versionadded:: NEXT.VERSION
is_premium (:obj:`bool`, optional): :obj:`True`, if the gift can only be purchased by
Telegram Premium subscribers.

.. versionadded:: NEXT.VERSION
has_colors (:obj:`bool`, optional): :obj:`True`, if the gift can be used (after being
upgraded) to customize a user's appearance.

.. versionadded:: NEXT.VERSION
unique_gift_variant_count (:obj:`int`, optional): The total number of different unique
gifts that can be obtained by upgrading the gift.

.. versionadded:: NEXT.VERSION

Attributes:
id (:obj:`str`): Unique identifier of the gift.
Expand All @@ -77,16 +149,45 @@ class Gift(TelegramObject):
published the gift.

.. versionadded:: 22.4
personal_total_count (:obj:`int`): Optional. The total number of gifts of this type that
can be sent by the bot; for limited gifts only.

.. versionadded:: NEXT.VERSION
personal_remaining_count (:obj:`int`): Optional. The number of remaining gifts of this type
that can be sent by the bot; for limited gifts only.

.. versionadded:: NEXT.VERSION
background (:class:`GiftBackground`): Optional. Background of the gift.

.. versionadded:: NEXT.VERSION
is_premium (:obj:`bool`): Optional. :obj:`True`, if the gift can only be purchased by
Telegram Premium subscribers.

.. versionadded:: NEXT.VERSION
has_colors (:obj:`bool`): Optional. :obj:`True`, if the gift can be used (after being
upgraded) to customize a user's appearance.

.. versionadded:: NEXT.VERSION
unique_gift_variant_count (:obj:`int`): Optional. The total number of different unique
gifts that can be obtained by upgrading the gift.

.. versionadded:: NEXT.VERSION

"""

__slots__ = (
"background",
"has_colors",
"id",
"is_premium",
"personal_remaining_count",
"personal_total_count",
"publisher_chat",
"remaining_count",
"star_count",
"sticker",
"total_count",
"unique_gift_variant_count",
"upgrade_star_count",
)

Expand All @@ -99,6 +200,12 @@ def __init__(
remaining_count: int | None = None,
upgrade_star_count: int | None = None,
publisher_chat: Chat | None = None,
personal_total_count: int | None = None,
personal_remaining_count: int | None = None,
background: GiftBackground | None = None,
is_premium: bool | None = None,
has_colors: bool | None = None,
unique_gift_variant_count: int | None = None,
*,
api_kwargs: JSONDict | None = None,
):
Expand All @@ -110,6 +217,12 @@ def __init__(
self.remaining_count: int | None = remaining_count
self.upgrade_star_count: int | None = upgrade_star_count
self.publisher_chat: Chat | None = publisher_chat
self.personal_total_count: int | None = personal_total_count
self.personal_remaining_count: int | None = personal_remaining_count
self.background: GiftBackground | None = background
self.is_premium: bool | None = is_premium
self.has_colors: bool | None = has_colors
self.unique_gift_variant_count: int | None = unique_gift_variant_count

self._id_attrs = (self.id,)

Expand All @@ -122,6 +235,7 @@ def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "Gift":

data["sticker"] = de_json_optional(data.get("sticker"), Sticker, bot)
data["publisher_chat"] = de_json_optional(data.get("publisher_chat"), Chat, bot)
data["background"] = de_json_optional(data.get("background"), GiftBackground, bot)
return super().de_json(data=data, bot=bot)


Expand Down
97 changes: 96 additions & 1 deletion tests/test_gifts.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,77 @@
import pytest

from telegram import BotCommand, Chat, Gift, GiftInfo, Gifts, MessageEntity, Sticker
from telegram._gifts import AcceptedGiftTypes
from telegram._gifts import AcceptedGiftTypes, GiftBackground
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram.request import RequestData
from tests.auxil.slots import mro_slots


@pytest.fixture
def gift_background():
return GiftBackground(
center_color=GiftBackgroundTestBase.center_color,
edge_color=GiftBackgroundTestBase.edge_color,
text_color=GiftBackgroundTestBase.text_color,
)


class GiftBackgroundTestBase:
center_color = 0xFFFFFF
edge_color = 0x000000
text_color = 0xFF0000


class TestGiftBackgroundWithoutRequest(GiftBackgroundTestBase):
def test_slot_behaviour(self, gift_background):
for attr in gift_background.__slots__:
assert getattr(gift_background, attr, "err") != "err", f"got extra slot '{attr}'"
assert len(mro_slots(gift_background)) == len(set(mro_slots(gift_background))), (
"duplicate slot"
)

def test_de_json(self, offline_bot):
json_dict = {
"center_color": self.center_color,
"edge_color": self.edge_color,
"text_color": self.text_color,
}
gift_background = GiftBackground.de_json(json_dict, offline_bot)
assert gift_background.api_kwargs == {}
assert gift_background.center_color == self.center_color
assert gift_background.edge_color == self.edge_color
assert gift_background.text_color == self.text_color

def test_to_dict(self, gift_background):
json_dict = gift_background.to_dict()
assert json_dict["center_color"] == self.center_color
assert json_dict["edge_color"] == self.edge_color
assert json_dict["text_color"] == self.text_color

def test_equality(self, gift_background):
a = gift_background
b = GiftBackground(
self.center_color,
self.edge_color,
self.text_color,
)
c = GiftBackground(
0x000000,
self.edge_color,
self.text_color,
)
d = BotCommand("start", "description")

assert a == b
assert hash(a) == hash(b)

assert a != c
assert hash(a) != hash(c)

assert a != d
assert hash(a) != hash(d)


@pytest.fixture
def gift(request):
return Gift(
Expand All @@ -37,6 +102,12 @@ def gift(request):
remaining_count=GiftTestBase.remaining_count,
upgrade_star_count=GiftTestBase.upgrade_star_count,
publisher_chat=GiftTestBase.publisher_chat,
personal_total_count=GiftTestBase.personal_total_count,
personal_remaining_count=GiftTestBase.personal_remaining_count,
background=GiftTestBase.background,
is_premium=GiftTestBase.is_premium,
has_colors=GiftTestBase.has_colors,
unique_gift_variant_count=GiftTestBase.unique_gift_variant_count,
)


Expand All @@ -56,6 +127,12 @@ class GiftTestBase:
remaining_count = 5
upgrade_star_count = 10
publisher_chat = Chat(1, Chat.PRIVATE)
personal_total_count = 37
personal_remaining_count = 23
background = GiftBackground(0xFFFFFF, 0x000000, 0xFF0000)
is_premium = True
has_colors = True
unique_gift_variant_count = 42


class TestGiftWithoutRequest(GiftTestBase):
Expand All @@ -73,6 +150,12 @@ def test_de_json(self, offline_bot, gift):
"remaining_count": self.remaining_count,
"upgrade_star_count": self.upgrade_star_count,
"publisher_chat": self.publisher_chat.to_dict(),
"personal_total_count": self.personal_total_count,
"personal_remaining_count": self.personal_remaining_count,
"background": self.background.to_dict(),
"is_premium": self.is_premium,
"has_colors": self.has_colors,
"unique_gift_variant_count": self.unique_gift_variant_count,
}
gift = Gift.de_json(json_dict, offline_bot)
assert gift.api_kwargs == {}
Expand All @@ -84,6 +167,12 @@ def test_de_json(self, offline_bot, gift):
assert gift.remaining_count == self.remaining_count
assert gift.upgrade_star_count == self.upgrade_star_count
assert gift.publisher_chat == self.publisher_chat
assert gift.personal_total_count == self.personal_total_count
assert gift.personal_remaining_count == self.personal_remaining_count
assert gift.background == self.background
assert gift.is_premium == self.is_premium
assert gift.has_colors == self.has_colors
assert gift.unique_gift_variant_count == self.unique_gift_variant_count

def test_to_dict(self, gift):
gift_dict = gift.to_dict()
Expand All @@ -96,6 +185,12 @@ def test_to_dict(self, gift):
assert gift_dict["remaining_count"] == self.remaining_count
assert gift_dict["upgrade_star_count"] == self.upgrade_star_count
assert gift_dict["publisher_chat"] == self.publisher_chat.to_dict()
assert gift_dict["personal_total_count"] == self.personal_total_count
assert gift_dict["personal_remaining_count"] == self.personal_remaining_count
assert gift_dict["background"] == self.background.to_dict()
assert gift_dict["is_premium"] == self.is_premium
assert gift_dict["has_colors"] == self.has_colors
assert gift_dict["unique_gift_variant_count"] == self.unique_gift_variant_count

def test_equality(self, gift):
a = gift
Expand Down
Loading