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 @@ -3,5 +3,6 @@ features = "Full Support for Bot API 9.3"
pull_requests = [
{ uid = "5078", author_uid = "aelkheir", closes_threads = ["5077"] },
{ uid = "5079", author_uid = "aelkheir" },
{ uid = "5084", author_uids = ["Bibo-Joshi"] },
{ uid = "5085", author_uids = ["Bibo-Joshi"] },
]
2 changes: 2 additions & 0 deletions docs/source/telegram.at-tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ Available Types
telegram.telegramobject
telegram.textquote
telegram.uniquegift
telegram.uniquegiftcolors
telegram.uniquegiftbackdrop
telegram.uniquegiftbackdropcolors
telegram.uniquegiftinfo
Expand All @@ -190,6 +191,7 @@ Available Types
telegram.user
telegram.userchatboosts
telegram.userprofilephotos
telegram.userrating
telegram.usersshared
telegram.venue
telegram.video
Expand Down
7 changes: 7 additions & 0 deletions docs/source/telegram.uniquegiftcolors.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
UniqueGiftColors
================

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

6 changes: 6 additions & 0 deletions docs/source/telegram.userrating.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
UserRating
==========

.. autoclass:: telegram.UserRating
:members:
:show-inheritance:
4 changes: 4 additions & 0 deletions src/telegram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,15 @@
"UniqueGift",
"UniqueGiftBackdrop",
"UniqueGiftBackdropColors",
"UniqueGiftColors",
"UniqueGiftInfo",
"UniqueGiftModel",
"UniqueGiftSymbol",
"Update",
"User",
"UserChatBoosts",
"UserProfilePhotos",
"UserRating",
"UsersShared",
"Venue",
"Video",
Expand Down Expand Up @@ -597,13 +599,15 @@
UniqueGift,
UniqueGiftBackdrop,
UniqueGiftBackdropColors,
UniqueGiftColors,
UniqueGiftInfo,
UniqueGiftModel,
UniqueGiftSymbol,
)
from ._update import Update
from ._user import User
from ._userprofilephotos import UserProfilePhotos
from ._userrating import UserRating
from ._videochat import (
VideoChatEnded,
VideoChatParticipantsInvited,
Expand Down
42 changes: 42 additions & 0 deletions src/telegram/_chatfullinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
from telegram._files.chatphoto import ChatPhoto
from telegram._gifts import AcceptedGiftTypes
from telegram._reaction import ReactionType
from telegram._uniquegift import UniqueGiftColors
from telegram._userrating import UserRating
from telegram._utils.argumentparsing import (
de_json_optional,
de_list_optional,
Expand Down Expand Up @@ -232,6 +234,19 @@ class ChatFullInfo(_ChatBase):
chat; for direct messages chats only.

.. versionadded:: 22.4
rating (:class:`telegram.UserRating`, optional): For private chats, the rating of the user
if any.

.. versionadded:: NEXT.VERSION
unique_gift_colors (:class:`telegram.UniqueGiftColors`, optional): The color scheme based
on a unique gift that must be used for the chat's name, message replies and link
previews

.. versionadded:: NEXT.VERSION
paid_message_star_count (:obj:`int`, optional): The number of Telegram Stars a general user
have to pay to send a message to the chat

.. versionadded:: NEXT.VERSION

Attributes:
id (:obj:`int`): Unique identifier for this chat.
Expand Down Expand Up @@ -404,6 +419,19 @@ class ChatFullInfo(_ChatBase):
chat; for direct messages chats only.

.. versionadded:: 22.4
rating (:class:`telegram.UserRating`): Optional. For private chats, the rating of the user
if any.

.. versionadded:: NEXT.VERSION
unique_gift_colors (:class:`telegram.UniqueGiftColors`): Optional. The color scheme based
on a unique gift that must be used for the chat's name, message replies and link
previews

.. versionadded:: NEXT.VERSION
paid_message_star_count (:obj:`int`): Optional. The number of Telegram Stars a general user
have to pay to send a message to the chat

.. versionadded:: NEXT.VERSION

.. _accent colors: https://core.telegram.org/bots/api#accent-colors
.. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups
Expand Down Expand Up @@ -440,14 +468,17 @@ class ChatFullInfo(_ChatBase):
"linked_chat_id",
"location",
"max_reaction_count",
"paid_message_star_count",
"parent_chat",
"permissions",
"personal_chat",
"photo",
"pinned_message",
"profile_accent_color_id",
"profile_background_custom_emoji_id",
"rating",
"sticker_set_name",
"unique_gift_colors",
"unrestrict_boost_count",
)

Expand Down Expand Up @@ -500,6 +531,9 @@ def __init__(
can_send_paid_media: bool | None = None,
is_direct_messages: bool | None = None,
parent_chat: Chat | None = None,
rating: UserRating | None = None,
unique_gift_colors: UniqueGiftColors | None = None,
paid_message_star_count: int | None = None,
*,
api_kwargs: JSONDict | None = None,
):
Expand Down Expand Up @@ -563,6 +597,9 @@ def __init__(
self.can_send_paid_media: bool | None = can_send_paid_media
self.accepted_gift_types: AcceptedGiftTypes = accepted_gift_types
self.parent_chat: Chat | None = parent_chat
self.rating: UserRating | None = rating
self.unique_gift_colors: UniqueGiftColors | None = unique_gift_colors
self.paid_message_star_count: int | None = paid_message_star_count

@property
def slow_mode_delay(self) -> int | dtm.timedelta | None:
Expand Down Expand Up @@ -615,4 +652,9 @@ def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "ChatFullInfo":
)
data["parent_chat"] = de_json_optional(data.get("parent_chat"), Chat, bot)

data["rating"] = de_json_optional(data.get("rating"), UserRating, bot)
data["unique_gift_colors"] = de_json_optional(
data.get("unique_gift_colors"), UniqueGiftColors, bot
)

return super().de_json(data=data, bot=bot)
76 changes: 75 additions & 1 deletion src/telegram/_uniquegift.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,88 @@
from telegram._files.sticker import Sticker
from telegram._telegramobject import TelegramObject
from telegram._utils import enum
from telegram._utils.argumentparsing import de_json_optional
from telegram._utils.argumentparsing import de_json_optional, parse_sequence_arg
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.types import JSONDict

if TYPE_CHECKING:
from telegram import Bot


class UniqueGiftColors(TelegramObject):
"""This object contains information about the color scheme for a user's name, message replies
and link previews based on a unique gift.

Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal if their :attr:`model_custom_emoji_id`, :attr:`symbol_custom_emoji_id`,
:attr:`light_theme_main_color`, :attr:`light_theme_other_colors`,
:attr:`dark_theme_main_color`, and :attr:`dark_theme_other_colors` are equal.

.. versionadded:: NEXT.VERSION

Args:
model_custom_emoji_id (:obj:`str`): Custom emoji identifier of the unique gift's model.
symbol_custom_emoji_id (:obj:`str`): Custom emoji identifier of the unique gift's symbol.
light_theme_main_color (:obj:`int`): Main color used in light themes; RGB format.
light_theme_other_colors (Sequence[:obj:`int`]): List of 1-3 additional colors used in
light themes; RGB format. |sequenceclassargs|
dark_theme_main_color (:obj:`int`): Main color used in dark themes; RGB format.
dark_theme_other_colors (Sequence[:obj:`int`]): List of 1-3 additional colors used in dark
themes; RGB format. |sequenceclassargs|

Attributes:
model_custom_emoji_id (:obj:`str`): Custom emoji identifier of the unique gift's model.
symbol_custom_emoji_id (:obj:`str`): Custom emoji identifier of the unique gift's symbol.
light_theme_main_color (:obj:`int`): Main color used in light themes; RGB format.
light_theme_other_colors (Tuple[:obj:`int`]): Tuple of 1-3 additional colors used in
light themes; RGB format.
dark_theme_main_color (:obj:`int`): Main color used in dark themes; RGB format.
dark_theme_other_colors (Tuple[:obj:`int`]): Tuple of 1-3 additional colors used in dark
themes; RGB format.
"""

__slots__ = (
"dark_theme_main_color",
"dark_theme_other_colors",
"light_theme_main_color",
"light_theme_other_colors",
"model_custom_emoji_id",
"symbol_custom_emoji_id",
)

def __init__(
self,
model_custom_emoji_id: str,
symbol_custom_emoji_id: str,
light_theme_main_color: int,
light_theme_other_colors: list[int],
dark_theme_main_color: int,
dark_theme_other_colors: list[int],
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
self.model_custom_emoji_id: str = model_custom_emoji_id
self.symbol_custom_emoji_id: str = symbol_custom_emoji_id
self.light_theme_main_color: int = light_theme_main_color
self.light_theme_other_colors: tuple[int, ...] = parse_sequence_arg(
light_theme_other_colors
)
self.dark_theme_main_color: int = dark_theme_main_color
self.dark_theme_other_colors: tuple[int, ...] = parse_sequence_arg(dark_theme_other_colors)

self._id_attrs = (
self.model_custom_emoji_id,
self.symbol_custom_emoji_id,
self.light_theme_main_color,
self.light_theme_other_colors,
self.dark_theme_main_color,
self.dark_theme_other_colors,
)

self._freeze()


class UniqueGiftModel(TelegramObject):
"""This object describes the model of a unique gift.

Expand Down
75 changes: 75 additions & 0 deletions src/telegram/_userrating.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2026
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram user rating."""

from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict


class UserRating(TelegramObject):
"""
This object describes the rating of a user based on their Telegram Star spendings.

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

.. versionadded:: NEXT.VERSION

Args:
level (:obj:`int`): Current level of the user, indicating their reliability when purchasing
digital goods and services. A higher level suggests a more trustworthy customer; a
negative level is likely reason for concern.
rating (:obj:`int`): Numerical value of the user's rating; the higher the rating, the
better
current_level_rating (:obj:`int`): The rating value required to get the current level
next_level_rating (:obj:`int`, optional): The rating value required to get to the next
level; omitted if the maximum level was reached

Attributes:
level (:obj:`int`): Current level of the user, indicating their reliability when purchasing
digital goods and services. A higher level suggests a more trustworthy customer; a
negative level is likely reason for concern.
rating (:obj:`int`): Numerical value of the user's rating; the higher the rating, the
better
current_level_rating (:obj:`int`): The rating value required to get the current level
next_level_rating (:obj:`int`): Optional. The rating value required to get to the next
level; omitted if the maximum level was reached

"""

__slots__ = ("current_level_rating", "level", "next_level_rating", "rating")

def __init__(
self,
level: int,
rating: int,
current_level_rating: int,
next_level_rating: int | None = None,
*,
api_kwargs: JSONDict | None = None,
) -> None:
super().__init__(api_kwargs=api_kwargs)
self.level: int = level
self.rating: int = rating
self.current_level_rating: int = current_level_rating
self.next_level_rating: int | None = next_level_rating

self._id_attrs = (self.level, self.rating)

self._freeze()
24 changes: 24 additions & 0 deletions tests/test_chatfullinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
Location,
ReactionTypeCustomEmoji,
ReactionTypeEmoji,
UniqueGiftColors,
UserRating,
)
from telegram._gifts import AcceptedGiftTypes
from telegram._utils.datetime import UTC, to_timestamp
Expand Down Expand Up @@ -89,6 +91,9 @@ def chat_full_info(bot):
can_send_paid_media=ChatFullInfoTestBase.can_send_paid_media,
is_direct_messages=ChatFullInfoTestBase.is_direct_messages,
parent_chat=ChatFullInfoTestBase.parent_chat,
rating=ChatFullInfoTestBase.rating,
unique_gift_colors=ChatFullInfoTestBase.unique_gift_colors,
paid_message_star_count=ChatFullInfoTestBase.paid_message_star_count,
)
chat.set_bot(bot)
chat._unfreeze()
Expand Down Expand Up @@ -150,6 +155,16 @@ class ChatFullInfoTestBase:
accepted_gift_types = AcceptedGiftTypes(True, True, True, True)
is_direct_messages = True
parent_chat = Chat(4, "channel", "channel")
rating = UserRating(level=1, rating=2, current_level_rating=3, next_level_rating=4)
unique_gift_colors = UniqueGiftColors(
model_custom_emoji_id="model_custom_emoji_id",
symbol_custom_emoji_id="symbol_custom_emoji_id",
light_theme_main_color=0xFF5733,
light_theme_other_colors=[0x33FF57, 0x3357FF],
dark_theme_main_color=0xC70039,
dark_theme_other_colors=[0x900C3F, 0x581845],
)
paid_message_star_count = 1234


class TestChatFullInfoWithoutRequest(ChatFullInfoTestBase):
Expand Down Expand Up @@ -207,6 +222,9 @@ def test_de_json(self, offline_bot):
"can_send_paid_media": self.can_send_paid_media,
"is_direct_messages": self.is_direct_messages,
"parent_chat": self.parent_chat.to_dict(),
"rating": self.rating.to_dict(),
"unique_gift_colors": self.unique_gift_colors.to_dict(),
"paid_message_star_count": self.paid_message_star_count,
}

cfi = ChatFullInfo.de_json(json_dict, offline_bot)
Expand Down Expand Up @@ -258,6 +276,9 @@ def test_de_json(self, offline_bot):
assert cfi.can_send_paid_media == self.can_send_paid_media
assert cfi.is_direct_messages == self.is_direct_messages
assert cfi.parent_chat == self.parent_chat
assert cfi.rating == self.rating
assert cfi.unique_gift_colors == self.unique_gift_colors
assert cfi.paid_message_star_count == self.paid_message_star_count

def test_de_json_localization(self, offline_bot, raw_bot, tz_bot):
json_dict = {
Expand Down Expand Up @@ -341,6 +362,9 @@ def test_to_dict(self, chat_full_info):
assert cfi_dict["max_reaction_count"] == cfi.max_reaction_count
assert cfi_dict["is_direct_messages"] == cfi.is_direct_messages
assert cfi_dict["parent_chat"] == cfi.parent_chat.to_dict()
assert cfi_dict["rating"] == cfi.rating.to_dict()
assert cfi_dict["unique_gift_colors"] == cfi.unique_gift_colors.to_dict()
assert cfi_dict["paid_message_star_count"] == cfi.paid_message_star_count

def test_time_period_properties(self, PTB_TIMEDELTA, chat_full_info):
cfi = chat_full_info
Expand Down
Loading
Loading