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
2 changes: 2 additions & 0 deletions changes/unreleased/5229.87PBN4GFkuAaDhhgFwCYkY.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ highlights = "Full Support for Bot API 10.0"
pull_requests = [
{ uid = "5229", author_uid = "aelkheir", closes_threads = ["5228"] },
{ uid = "5230", author_uid = "harshil21" },
{ uid = "5235", author_uid = "harshil21" },
{ uid = "5238", author_uid = "harshil21" },
]
6 changes: 6 additions & 0 deletions docs/source/inclusions/bot_methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@
- Used for unpinning a message
* - :meth:`~telegram.Bot.unpin_all_chat_messages`
- Used for unpinning all pinned chat messages
* - :meth:`~telegram.Bot.get_user_personal_chat_messages`
- Used for obtaining the personal chat messages of a user
* - :meth:`~telegram.Bot.get_user_profile_audios`
- Used for obtaining user's profile audios
* - :meth:`~telegram.Bot.get_user_profile_photos`
Expand Down Expand Up @@ -241,6 +243,10 @@
- Used for obtaining the menu button of a private chat or the default menu button
* - :meth:`~telegram.Bot.set_chat_menu_button`
- Used for setting the menu button of a private chat or the default menu button
* - :meth:`~telegram.Bot.set_managed_bot_access_settings`
- Used for changing the access settings of a managed bot
* - :meth:`~telegram.Bot.get_managed_bot_access_settings`
- Used for obtaining the access settings of a managed bot
Comment thread
harshil21 marked this conversation as resolved.
* - :meth:`~telegram.Bot.set_my_description`
- Used for setting the description of the bot
* - :meth:`~telegram.Bot.get_my_description`
Expand Down
1 change: 1 addition & 0 deletions docs/source/telegram.at-tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Available Types
telegram.animation
telegram.audio
telegram.birthdate
telegram.botaccesssettings
telegram.botcommand
telegram.botcommandscope
telegram.botcommandscopeallchatadministrators
Expand Down
6 changes: 6 additions & 0 deletions docs/source/telegram.botaccesssettings.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BotAccessSettings
=================

.. autoclass:: telegram.BotAccessSettings
:members:
:show-inheritance:
2 changes: 2 additions & 0 deletions src/telegram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"BackgroundTypeWallpaper",
"Birthdate",
"Bot",
"BotAccessSettings",
"BotCommand",
"BotCommandScope",
"BotCommandScopeAllChatAdministrators",
Expand Down Expand Up @@ -348,6 +349,7 @@
from . import _version, constants, error, helpers, request, warnings
from ._birthdate import Birthdate
from ._bot import Bot
from ._botaccesssettings import BotAccessSettings
from ._botcommand import BotCommand
from ._botcommandscope import (
BotCommandScope,
Expand Down
170 changes: 160 additions & 10 deletions src/telegram/_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
serialization = None # type: ignore[assignment]
CRYPTO_INSTALLED = False

from telegram._botcommand import BotCommand # pylint: disable=ungrouped-imports
from telegram._botaccesssettings import BotAccessSettings # pylint: disable=ungrouped-imports
from telegram._botcommand import BotCommand
from telegram._botcommandscope import BotCommandScope
from telegram._botdescription import BotDescription, BotShortDescription
from telegram._botname import BotName
Expand Down Expand Up @@ -1209,7 +1210,7 @@ async def send_message_draft(
self,
chat_id: int,
draft_id: int,
text: str,
text: str | None = None,
message_thread_id: int | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
entities: Sequence["MessageEntity"] | None = None,
Expand All @@ -1221,7 +1222,9 @@ async def send_message_draft(
api_kwargs: JSONDict | None = None,
) -> bool:
"""Use this method to stream a partial message to a user while the message is being
generated.
generated. Note that the streamed draft is ephemeral and acts as a temporary 30-second
preview - once the output is finalized, you must call :meth:`~Bot.send_message` with
the complete message to persist it in the user's chat.

.. versionadded:: 22.6

Expand All @@ -1233,19 +1236,21 @@ async def send_message_draft(
chat_id (:obj:`int`): Unique identifier for the target private chat.
draft_id (:obj:`int`): Unique identifier of the message draft; must be non-zero.
Changes of drafts with the same identifier are animated.
text (:obj:`str`): Text of the message to be sent,
:tg-const:`telegram.constants.MessageLimit.MIN_TEXT_LENGTH`-
:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters after
entities parsing.
text (:obj:`str`, optional): Text of the message to be sent,
0-:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters after
entities parsing. Pass an empty text to show a "Thinking..." placeholder.

.. versionchanged:: NEXT.VERSION
Bot API 10.0 now makes this an optional parameter.

message_thread_id (:obj:`int`, optional): Unique identifier for the target
message thread.
parse_mode (:obj:`str`): |parse_mode|
entities (Sequence[:class:`telegram.MessageEntity`], optional): Sequence of special
entities that appear in message text, which can be specified instead of
:paramref:`parse_mode`.

|sequenceargs|
message_thread_id (:obj:`int`, optional): Unique identifier for the target
message thread.


Returns:
:obj:`bool`: On success, :obj:`True` is returned.
Expand Down Expand Up @@ -11127,6 +11132,145 @@ async def edit_user_star_subscription(
api_kwargs=api_kwargs,
)

async def get_managed_bot_access_settings(
self,
user_id: int,
*,
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: JSONDict | None = None,
) -> BotAccessSettings:
"""
Use this method to get the access settings of a managed bot.

.. versionadded:: NEXT.VERSION

Args:
user_id (:obj:`int`): User identifier of the managed bot whose access settings will be
returned.

Returns:
:class:`telegram.BotAccessSettings`: The access settings of the managed bot.

Raises:
:class:`telegram.error.TelegramError`
"""

data: JSONDict = {
"user_id": user_id,
}

return BotAccessSettings.de_json(
await self._post(
"getManagedBotAccessSettings",
data,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
),
self,
)

async def set_managed_bot_access_settings(
self,
user_id: int,
is_access_restricted: bool,
added_user_ids: Sequence[int] | None = 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: JSONDict | None = None,
) -> bool:
"""
Use this method to change the access settings of a managed bot.

.. versionadded:: NEXT.VERSION

Args:
user_id (:obj:`int`): User identifier of the managed bot whose access settings will be
changed.
is_access_restricted (:obj:`bool`): Pass :obj:`True`, if only selected users can access
the bot. The bot's owner can always access it.
added_user_ids (Sequence[:obj:`int`], optional): A list of up to
:tg-const:`telegram.constants.ManagedBotAccessLimit.MAX_ALLOWED_USERS`
identifiers of users who will have access to the bot in addition to its owner.
Ignored if :paramref:`is_access_restricted` is :obj:`False`.

Returns:
:obj:`bool`: On success, :obj:`True` is returned.

Raises:
:class:`telegram.error.TelegramError`
"""

data: JSONDict = {
"user_id": user_id,
"is_access_restricted": is_access_restricted,
"added_user_ids": added_user_ids,
}

return await self._post(
"setManagedBotAccessSettings",
data,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)

async def get_user_personal_chat_messages(
self,
user_id: int,
limit: int,
*,
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: JSONDict | None = None,
) -> tuple[Message, ...]:
"""
Use this method to get the last messages from the personal chat (i.e., the chat currently
added to their profile) of a given user.

.. versionadded:: NEXT.VERSION

Args:
user_id (:obj:`int`): Unique identifier of the target user.
limit (:obj:`int`): The maximum number of messages to return;
:tg-const:`telegram.constants.PersonalChatMessagesLimit.MIN_LIMIT`-
:tg-const:`telegram.constants.PersonalChatMessagesLimit.MAX_LIMIT`.

Returns:
tuple[:class:`telegram.Message`, ...]: On success, a tuple of
:class:`telegram.Message` objects is returned.

Raises:
:class:`telegram.error.TelegramError`
"""

data: JSONDict = {"user_id": user_id, "limit": limit}

return Message.de_list(
await self._post(
"getUserPersonalChatMessages",
data,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
),
self,
)

async def send_paid_media(
self,
chat_id: str | int,
Expand Down Expand Up @@ -12733,6 +12877,12 @@ def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002
"""Alias for :meth:`replace_managed_bot_token`"""
savePreparedKeyboardButton = save_prepared_keyboard_button
"""Alias for :meth:`save_prepared_keyboard_button`"""
getManagedBotAccessSettings = get_managed_bot_access_settings
"""Alias for :meth:`get_managed_bot_access_settings`"""
setManagedBotAccessSettings = set_managed_bot_access_settings
"""Alias for :meth:`set_managed_bot_access_settings`"""
getUserPersonalChatMessages = get_user_personal_chat_messages
"""Alias for :meth:`get_user_personal_chat_messages`"""
deleteMessageReaction = delete_message_reaction
"""Alias for :meth:`delete_message_reaction`"""
deleteAllMessageReactions = delete_all_message_reactions
Expand Down
77 changes: 77 additions & 0 deletions src/telegram/_botaccesssettings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/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 Bot Access Settings."""

from collections.abc import Sequence
from typing import TYPE_CHECKING

from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.argumentparsing import de_list_optional, parse_sequence_arg
from telegram._utils.types import JSONDict

if TYPE_CHECKING:
from telegram import Bot


class BotAccessSettings(TelegramObject):
"""
This object describes the access settings of a bot.

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

.. versionadded:: NEXT.VERSION

Args:
is_access_restricted (:obj:`bool`): :obj:`True`, if only selected users can access the bot.
The bot's owner can always access it.
added_users (Sequence[:class:`telegram.User`], optional): The list of other users who
have access to the bot if the access is restricted.

Attributes:
is_access_restricted (:obj:`bool`): :obj:`True`, if only selected users can access the bot.
The bot's owner can always access it.
added_users (Sequence[:class:`telegram.User`]): Optional. The list of other users who
have access to the bot if the access is restricted.
"""

__slots__ = ("added_users", "is_access_restricted")

def __init__(
self,
is_access_restricted: bool,
added_users: Sequence[User] | None = None,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
self.is_access_restricted: bool = is_access_restricted
self.added_users: tuple[User, ...] = parse_sequence_arg(added_users)

self._id_attrs = (self.is_access_restricted, self.added_users)
self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BotAccessSettings":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
data["added_users"] = de_list_optional(data.get("added_users"), User, bot)

return super().de_json(data=data, bot=bot)
5 changes: 4 additions & 1 deletion src/telegram/_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ async def send_message(
async def send_message_draft(
self,
draft_id: int,
text: str,
text: str | None = None,
message_thread_id: int | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
entities: Sequence["MessageEntity"] | None = None,
Expand All @@ -1107,6 +1107,9 @@ async def send_message_draft(

For the documentation of the arguments, please see :meth:`telegram.Bot.send_message_draft`.

.. versionchanged:: NEXT.VERSION
Bot API 10.0 makes the ``text`` argument optional.

Returns:
:obj:`bool`: On success, :obj:`True` is returned.

Expand Down
5 changes: 4 additions & 1 deletion src/telegram/_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -2186,7 +2186,7 @@ async def reply_text(
async def reply_text_draft(
self,
draft_id: int,
text: str,
text: str | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
entities: Sequence["MessageEntity"] | None = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
Expand All @@ -2213,6 +2213,9 @@ async def reply_text_draft(

.. versionadded:: 22.6

.. versionchanged:: NEXT.VERSION
Bot API 10.0 makes the ``text`` argument optional.

Returns:
:obj:`bool`: On success, :obj:`True` is returned.

Expand Down
Loading
Loading