From d8b118bc6189bb607951883f628aecd1595b0daf Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 24 Nov 2024 13:55:19 +0100 Subject: [PATCH 1/2] Add `Bot.set_user_emoji_status` --- docs/source/inclusions/bot_methods.rst | 2 + docs/substitutions/global.rst | 2 + telegram/_bot.py | 72 ++++++++++++++++++++------ telegram/ext/_callbackdatacache.py | 4 +- telegram/ext/_extbot.py | 25 +++++++++ tests/test_bot.py | 33 ++++++++++++ 6 files changed, 120 insertions(+), 18 deletions(-) diff --git a/docs/source/inclusions/bot_methods.rst b/docs/source/inclusions/bot_methods.rst index 3189de1c1d3..4dbc5979a13 100644 --- a/docs/source/inclusions/bot_methods.rst +++ b/docs/source/inclusions/bot_methods.rst @@ -151,6 +151,8 @@ - Used for setting a chat title * - :meth:`~telegram.Bot.set_chat_description` - Used for setting the description of a chat + * - :meth:`~telegram.Bot.set_user_emoji_status` + - Used for setting the users status emoji * - :meth:`~telegram.Bot.pin_chat_message` - Used for pinning a message * - :meth:`~telegram.Bot.unpin_chat_message` diff --git a/docs/substitutions/global.rst b/docs/substitutions/global.rst index ab9c69249c9..b71ac1f0eac 100644 --- a/docs/substitutions/global.rst +++ b/docs/substitutions/global.rst @@ -95,3 +95,5 @@ .. |tg_stars| replace:: `Telegram Stars `__ .. |allow_paid_broadcast| replace:: Pass True to allow up to :tg-const:`telegram.constants.FloodLimit.PAID_MESSAGES_PER_SECOND` messages per second, ignoring `broadcasting limits `__ for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance. + +.. |tz-naive-dtms| replace:: For timezone naive :obj:`datetime.datetime` objects, the default timezone of the bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is used. \ No newline at end of file diff --git a/telegram/_bot.py b/telegram/_bot.py index cc2ba38fb3a..f90ff2941f4 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -3779,9 +3779,7 @@ async def ban_chat_member( be unbanned, unix time. If user is banned for more than 366 days or less than 30 seconds from the current time they are considered to be banned forever. Applied for supergroups and channels only. - For timezone naive :obj:`datetime.datetime` objects, the default timezone of the - bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is - used. + |tz-naive-dtms| revoke_messages (:obj:`bool`, optional): Pass :obj:`True` to delete all messages from the chat for the user that is being removed. If :obj:`False`, the user will be able to see messages in the group that were sent before the user was removed. @@ -5415,9 +5413,7 @@ async def restrict_chat_member( will be lifted for the user, unix time. If user is restricted for more than 366 days or less than 30 seconds from the current time, they are considered to be restricted forever. - For timezone naive :obj:`datetime.datetime` objects, the default timezone of the - bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is - used. + |tz-naive-dtms| permissions (:class:`telegram.ChatPermissions`): An object for new user permissions. use_independent_chat_permissions (:obj:`bool`, optional): Pass :obj:`True` if chat @@ -5761,9 +5757,7 @@ async def create_chat_invite_link( chat_id (:obj:`int` | :obj:`str`): |chat_id_channel| expire_date (:obj:`int` | :obj:`datetime.datetime`, optional): Date when the link will expire. Integer input will be interpreted as Unix timestamp. - For timezone naive :obj:`datetime.datetime` objects, the default timezone of the - bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is - used. + |tz-naive-dtms| member_limit (:obj:`int`, optional): Maximum number of users that can be members of the chat simultaneously after joining the chat via this invite link; :tg-const:`telegram.constants.ChatInviteLinkLimit.MIN_MEMBER_LIMIT`- @@ -5840,9 +5834,7 @@ async def edit_chat_invite_link( Now also accepts :class:`telegram.ChatInviteLink` instances. expire_date (:obj:`int` | :obj:`datetime.datetime`, optional): Date when the link will expire. - For timezone naive :obj:`datetime.datetime` objects, the default timezone of the - bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is - used. + |tz-naive-dtms| member_limit (:obj:`int`, optional): Maximum number of users that can be members of the chat simultaneously after joining the chat via this invite link; :tg-const:`telegram.constants.ChatInviteLinkLimit.MIN_MEMBER_LIMIT`- @@ -6176,6 +6168,56 @@ async def set_chat_description( api_kwargs=api_kwargs, ) + async def set_user_emoji_status( + self, + user_id: int, + emoji_status_custom_emoji_id: Optional[str], + emoji_status_expiration_date: Optional[Union[int, datetime]] = None, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Changes the emoji status for a given user that previously allowed the bot to manage + their emoji status via the Mini App method + `requestEmojiStatusAccess `_ + . + + .. versionadded:: NEXT.VERSION + + Args: + user_id (:obj:`int`): Unique identifier of the target user + emoji_status_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of the + emoji status to set. Pass an empty string to remove the status. + emoji_status_expiration_date (Union[:obj:`int`, :obj:`datetime.datetime`], optional): + Expiration date of the emoji status, if any, as unix timestamp or + :class:`datetime.datetime` object. + |tz-naive-dtms| + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + + Raises: + :class:`telegram.error.TelegramError` + + """ + data: JSONDict = { + "user_id": user_id, + "emoji_status_custom_emoji_id": emoji_status_custom_emoji_id, + "emoji_status_expiration_date": emoji_status_expiration_date, + } + return await self._post( + "setUserEmojiStatus", + data, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) + async def pin_chat_message( self, chat_id: Union[str, int], @@ -7127,9 +7169,7 @@ async def send_poll( :tg-const:`telegram.Poll.MIN_OPEN_PERIOD` and no more than :tg-const:`telegram.Poll.MAX_OPEN_PERIOD` seconds in the future. Can't be used together with :paramref:`open_period`. - For timezone naive :obj:`datetime.datetime` objects, the default timezone of the - bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is - used. + |tz-naive-dtms| is_closed (:obj:`bool`, optional): Pass :obj:`True`, if the poll needs to be immediately closed. This can be useful for poll preview. disable_notification (:obj:`bool`, optional): |disable_notification| @@ -9615,6 +9655,8 @@ def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002 """Alias for :meth:`set_chat_title`""" setChatDescription = set_chat_description """Alias for :meth:`set_chat_description`""" + setUserEmojiStatus = set_user_emoji_status + """Alias for :meth:`set_user_emoji_status`""" pinChatMessage = pin_chat_message """Alias for :meth:`pin_chat_message`""" unpinChatMessage = unpin_chat_message diff --git a/telegram/ext/_callbackdatacache.py b/telegram/ext/_callbackdatacache.py index 97649d2eb91..058a53e206e 100644 --- a/telegram/ext/_callbackdatacache.py +++ b/telegram/ext/_callbackdatacache.py @@ -437,9 +437,7 @@ def clear_callback_data(self, time_cutoff: Optional[Union[float, datetime]] = No Args: time_cutoff (:obj:`float` | :obj:`datetime.datetime`, optional): Pass a UNIX timestamp or a :obj:`datetime.datetime` to clear only entries which are older. - For timezone naive :obj:`datetime.datetime` objects, the default timezone of the - bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is - used. + |tz-naive-dtms| """ self.__clear(self._keyboard_data, time_cutoff=time_cutoff) diff --git a/telegram/ext/_extbot.py b/telegram/ext/_extbot.py index 66921e415df..519f6afaabe 100644 --- a/telegram/ext/_extbot.py +++ b/telegram/ext/_extbot.py @@ -3385,6 +3385,30 @@ async def set_chat_description( api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), ) + async def set_user_emoji_status( + self, + user_id: int, + emoji_status_custom_emoji_id: Optional[str], + emoji_status_expiration_date: Optional[Union[int, datetime]] = None, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + rate_limit_args: Optional[RLARGS] = None, + ) -> bool: + return await super().set_user_emoji_status( + user_id=user_id, + emoji_status_custom_emoji_id=emoji_status_custom_emoji_id, + emoji_status_expiration_date=emoji_status_expiration_date, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), + ) + async def set_chat_menu_button( self, chat_id: Optional[int] = None, @@ -4421,6 +4445,7 @@ async def edit_chat_subscription_invite_link( deleteChatPhoto = delete_chat_photo setChatTitle = set_chat_title setChatDescription = set_chat_description + setUserEmojiStatus = set_user_emoji_status pinChatMessage = pin_chat_message unpinChatMessage = unpin_chat_message unpinAllChatMessages = unpin_all_chat_messages diff --git a/tests/test_bot.py b/tests/test_bot.py index 8ff0dec8d7b..fbe1d64bac5 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -2336,6 +2336,39 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): await offline_bot.create_chat_subscription_invite_link(1234, 2592000, 6) + @pytest.mark.parametrize( + "expiration_date", [dtm.datetime(2024, 1, 1), 1704067200], ids=["datetime", "timestamp"] + ) + async def test_set_user_emoji_status_basic(self, offline_bot, monkeypatch, expiration_date): + async def make_assertion(url, request_data: RequestData, *args, **kwargs): + assert request_data.parameters.get("user_id") == 4242 + assert ( + request_data.parameters.get("emoji_status_custom_emoji_id") + == "emoji_status_custom_emoji_id" + ) + assert request_data.parameters.get("emoji_status_expiration_date") == 1704067200 + + monkeypatch.setattr(offline_bot.request, "post", make_assertion) + await offline_bot.set_user_emoji_status( + 4242, "emoji_status_custom_emoji_id", expiration_date + ) + + async def test_set_user_emoji_status_default_timezone(self, tz_bot, monkeypatch): + async def make_assertion(url, request_data: RequestData, *args, **kwargs): + assert request_data.parameters.get("user_id") == 4242 + assert ( + request_data.parameters.get("emoji_status_custom_emoji_id") + == "emoji_status_custom_emoji_id" + ) + assert request_data.parameters.get("emoji_status_expiration_date") == to_timestamp( + dtm.datetime(2024, 1, 1), tzinfo=tz_bot.defaults.tzinfo + ) + + monkeypatch.setattr(tz_bot.request, "post", make_assertion) + await tz_bot.set_user_emoji_status( + 4242, "emoji_status_custom_emoji_id", dtm.datetime(2024, 1, 1) + ) + class TestBotWithRequest: """ From 647217c80c63c6b198c9be58499874143469cfff Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Thu, 28 Nov 2024 19:31:24 +0100 Subject: [PATCH 2/2] fix a typo --- telegram/_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telegram/_bot.py b/telegram/_bot.py index e9c63186f4f..f291a508de6 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -6190,7 +6190,7 @@ async def set_user_emoji_status( Args: user_id (:obj:`int`): Unique identifier of the target user emoji_status_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of the - emoji status to set. Pass an empty string to remove the status. + emoji status to set. Pass an empty string to remove the status. emoji_status_expiration_date (Union[:obj:`int`, :obj:`datetime.datetime`], optional): Expiration date of the emoji status, if any, as unix timestamp or :class:`datetime.datetime` object.