Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api 5.5 #2809

Merged
merged 12 commits into from Dec 11, 2021
90 changes: 89 additions & 1 deletion telegram/bot.py
Expand Up @@ -579,6 +579,14 @@ def forward_message(
) -> Message:
"""Use this method to forward messages of any kind. Service messages can't be forwarded.

Note:
Since the release of Bot API 5.5 it can be impossible to forward messages from
some chats. Use the attributes :attr:`telegram.Message.has_protected_content` and
:attr:`telegram.Chat.has_protected_content` to check this.

As a workaround, it is still possible to use :meth:`copy_message`. However, this
behaviour is undocumented and might be changed by Telegram.
harshil21 marked this conversation as resolved.
Show resolved Hide resolved

Args:
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target chat or username
of the target channel (in the format ``@channelusername``).
Expand Down Expand Up @@ -2408,6 +2416,45 @@ def ban_chat_member(

return result # type: ignore[return-value]

@log
def ban_chat_sender_chat(
self,
chat_id: Union[str, int],
sender_chat_id: int,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""
Use this method to ban a channel chat in a supergroup or a channel. Until the chat is
unbanned, the owner of the banned chat won't be able to send messages on behalf of **any of
their channels**. The bot must be an administrator in the supergroup or channel for this
to work and must have the appropriate administrator rights.

.. versionadded:: 13.9

Args:
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target group or username
of the target supergroup or channel (in the format ``@channelusername``).
sender_chat_id (:obj:`int`): Unique identifier of the target sender chat.
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.

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

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

"""
data: JSONDict = {'chat_id': chat_id, 'sender_chat_id': sender_chat_id}

result = self._post('banChatSenderChat', data, timeout=timeout, api_kwargs=api_kwargs)

return result # type: ignore[return-value]

@log
def unban_chat_member(
self,
Expand Down Expand Up @@ -2437,7 +2484,7 @@ def unban_chat_member(
Telegram API.

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

Raises:
:class:`telegram.error.TelegramError`
Expand All @@ -2452,6 +2499,43 @@ def unban_chat_member(

return result # type: ignore[return-value]

@log
def unban_chat_sender_chat(
self,
chat_id: Union[str, int],
sender_chat_id: int,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Use this method to unban a previously banned channel in a supergroup or channel.
The bot must be an administrator for this to work and must have the
appropriate administrator rights.

.. versionadded:: 13.9

Args:
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target chat or username
of the target supergroup or channel (in the format ``@channelusername``).
sender_chat_id (:obj:`int`): Unique identifier of the target sender chat.
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.

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

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

"""
data: JSONDict = {'chat_id': chat_id, 'sender_chat_id': sender_chat_id}

result = self._post('unbanChatSenderChat', data, timeout=timeout, api_kwargs=api_kwargs)

return result # type: ignore[return-value]

@log
def answer_callback_query(
self,
Expand Down Expand Up @@ -5499,10 +5583,14 @@ def __hash__(self) -> int:
"""Alias for :meth:`get_file`"""
banChatMember = ban_chat_member
"""Alias for :meth:`ban_chat_member`"""
banChatSenderChat = ban_chat_sender_chat
"""Alias for :meth:`ban_chat_sender_chat`"""
kickChatMember = kick_chat_member
"""Alias for :meth:`kick_chat_member`"""
unbanChatMember = unban_chat_member
"""Alias for :meth:`unban_chat_member`"""
unbanChatSenderChat = unban_chat_sender_chat
"""Alias for :meth:`unban_chat_sender_chat`"""
answerCallbackQuery = answer_callback_query
"""Alias for :meth:`answer_callback_query`"""
editMessageText = edit_message_text
Expand Down
116 changes: 116 additions & 0 deletions telegram/chat.py
Expand Up @@ -81,6 +81,11 @@ class Chat(TelegramObject):
Returned only in :meth:`telegram.Bot.get_chat`.
bio (:obj:`str`, optional): Bio of the other party in a private chat. Returned only in
:meth:`telegram.Bot.get_chat`.
has_private_forwards (:obj:`bool`, optional): :obj:`True`, if privacy settings of the other
party in the private chat allows to use ``tg://user?id=<user_id>`` links only in chats
with the user. Returned only in :meth:`telegram.Bot.get_chat`.

.. versionadded:: 13.9
description (:obj:`str`, optional): Description, for groups, supergroups and channel chats.
Returned only in :meth:`telegram.Bot.get_chat`.
invite_link (:obj:`str`, optional): Primary invite link, for groups, supergroups and
Expand All @@ -97,6 +102,10 @@ class Chat(TelegramObject):
:meth:`telegram.Bot.get_chat`.

.. versionadded:: 13.4
has_protected_content (:obj:`bool`, optional): :obj:`True`, if messages from the chat can't
be forwarded to other chats. Returned only in :meth:`telegram.Bot.get_chat`.

.. versionadded:: 13.9
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
sticker_set_name (:obj:`str`, optional): For supergroups, name of group sticker set.
Returned only in :meth:`telegram.Bot.get_chat`.
Expand All @@ -119,6 +128,11 @@ class Chat(TelegramObject):
photo (:class:`telegram.ChatPhoto`): Optional. Chat photo.
bio (:obj:`str`): Optional. Bio of the other party in a private chat. Returned only in
:meth:`telegram.Bot.get_chat`.
has_private_forwards (:obj:`bool`): Optional. :obj:`True`, if privacy settings of the other
party in the private chat allows to use ``tg://user?id=<user_id>`` links only in chats
with the user.

.. versionadded:: 13.9
description (:obj:`str`): Optional. Description, for groups, supergroups and channel chats.
invite_link (:obj:`str`): Optional. Primary invite link, for groups, supergroups and
channel. Returned only in :meth:`telegram.Bot.get_chat`.
Expand All @@ -134,6 +148,10 @@ class Chat(TelegramObject):
:meth:`telegram.Bot.get_chat`.

.. versionadded:: 13.4
has_protected_content (:obj:`bool`): Optional. :obj:`True`, if messages from the chat can't
be forwarded to other chats.

.. versionadded:: 13.9
sticker_set_name (:obj:`str`): Optional. For supergroups, name of Group sticker set.
can_set_sticker_set (:obj:`bool`): Optional. :obj:`True`, if the bot can change group the
sticker set.
Expand Down Expand Up @@ -166,6 +184,8 @@ class Chat(TelegramObject):
'linked_chat_id',
'all_members_are_administrators',
'message_auto_delete_time',
'has_protected_content',
'has_private_forwards',
'_id_attrs',
)

Expand Down Expand Up @@ -204,6 +224,8 @@ def __init__(
linked_chat_id: int = None,
location: ChatLocation = None,
message_auto_delete_time: int = None,
has_private_forwards: bool = None,
has_protected_content: bool = None,
**_kwargs: Any,
):
# Required
Expand All @@ -218,6 +240,7 @@ def __init__(
self.all_members_are_administrators = _kwargs.get('all_members_are_administrators')
self.photo = photo
self.bio = bio
self.has_private_forwards = has_private_forwards
self.description = description
self.invite_link = invite_link
self.pinned_message = pinned_message
Expand All @@ -226,6 +249,7 @@ def __init__(
self.message_auto_delete_time = (
int(message_auto_delete_time) if message_auto_delete_time is not None else None
)
self.has_protected_content = has_protected_content
self.sticker_set_name = sticker_set_name
self.can_set_sticker_set = can_set_sticker_set
self.linked_chat_id = linked_chat_id
Expand Down Expand Up @@ -433,6 +457,98 @@ def ban_member(
revoke_messages=revoke_messages,
)

def ban_sender_chat(
harshil21 marked this conversation as resolved.
Show resolved Hide resolved
self,
sender_chat_id: int,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::

bot.ban_chat_sender_chat(chat_id=update.effective_chat.id, *args, **kwargs)

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

.. versionadded:: 13.9

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

"""
return self.bot.ban_chat_sender_chat(
chat_id=self.id, sender_chat_id=sender_chat_id, timeout=timeout, api_kwargs=api_kwargs
)

def ban_chat(
self,
chat_id: Union[str, int],
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::

bot.ban_chat_sender_chat(sender_chat_id=update.effective_chat.id, *args, **kwargs)

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

.. versionadded:: 13.9

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

"""
return self.bot.ban_chat_sender_chat(
chat_id=chat_id, sender_chat_id=self.id, timeout=timeout, api_kwargs=api_kwargs
)

def unban_sender_chat(
self,
sender_chat_id: int,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::

bot.unban_chat_sender_chat(chat_id=update.effective_chat.id, *args, **kwargs)

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

.. versionadded:: 13.9

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

"""
return self.bot.unban_chat_sender_chat(
chat_id=self.id, sender_chat_id=sender_chat_id, timeout=timeout, api_kwargs=api_kwargs
)

def unban_chat(
self,
chat_id: Union[str, int],
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::

bot.unban_chat_sender_chat(sender_chat_id=update.effective_chat.id, *args, **kwargs)

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

.. versionadded:: 13.9

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

"""
return self.bot.unban_chat_sender_chat(
chat_id=chat_id, sender_chat_id=self.id, timeout=timeout, api_kwargs=api_kwargs
)

def unban_member(
self,
user_id: Union[str, int],
Expand Down
6 changes: 6 additions & 0 deletions telegram/chatjoinrequest.py
Expand Up @@ -36,6 +36,12 @@ class ChatJoinRequest(TelegramObject):

.. versionadded:: 13.8

Bots are now allowed to contact users who sent a join request to a chat where the bot is
an administrator with the can_invite_users administrator right – even if the user
never interacted with the bot before.

.. versionchanged:: 13.9

harshil21 marked this conversation as resolved.
Show resolved Hide resolved
Args:
chat (:class:`telegram.Chat`): Chat to which the request was sent.
from_user (:class:`telegram.User`): User that sent the join request.
Expand Down
37 changes: 33 additions & 4 deletions telegram/ext/filters.py
Expand Up @@ -1965,16 +1965,16 @@ def remove_chat_ids(self, chat_id: SLT[int]) -> None:

class sender_chat(_ChatUserBaseFilter):
# pylint: disable=W0235
"""Filters messages to allow only those which are from a specified sender chats chat ID or
"""Filters messages to allow only those which are from a specified sender chat's chat ID or
harshil21 marked this conversation as resolved.
Show resolved Hide resolved
username.

Examples:
* To filter for messages forwarded to a discussion group from a channel with ID
* To filter for messages sent to a group by a channel with ID
``-1234``, use ``MessageHandler(Filters.sender_chat(-1234), callback_method)``.
* To filter for messages of anonymous admins in a super group with username
``@anonymous``, use
``MessageHandler(Filters.sender_chat(username='anonymous'), callback_method)``.
* To filter for messages forwarded to a discussion group from *any* channel, use
* To filter for messages sent to a group by *any* channel, use
``MessageHandler(Filters.sender_chat.channel, callback_method)``.
* To filter for messages of anonymous admins in *any* super group, use
``MessageHandler(Filters.sender_chat.super_group, callback_method)``.
Expand All @@ -1983,7 +1983,10 @@ class sender_chat(_ChatUserBaseFilter):
Remember, ``sender_chat`` is also set for messages in a channel as the channel itself,
so when your bot is an admin in a channel and the linked discussion group, you would
receive the message twice (once from inside the channel, once inside the discussion
group).
group). Since v13.9, the field :attr:`telegram.Message.is_automatic_forward` will be
:obj:`True` for the discussion group message.

.. seealso:: :attr:`Filters.is_automatic_forward`

Warning:
:attr:`chat_ids` will return a *copy* of the saved chat ids as :class:`frozenset`. This
Expand Down Expand Up @@ -2089,6 +2092,32 @@ def filter(self, message: Message) -> bool:
super_group = _SuperGroup()
channel = _Channel()

class _IsAutomaticForward(MessageFilter):
__slots__ = ()
name = 'Filters.is_automatic_forward'

def filter(self, message: Message) -> bool:
return bool(message.is_automatic_forward)

is_automatic_forward = _IsAutomaticForward()
"""Messages that contain :attr:`telegram.Message.is_automatic_forward`.

.. versionadded:: 13.9
"""

class _HasProtectedContent(MessageFilter):
__slots__ = ()
name = 'Filters.has_protected_content'

def filter(self, message: Message) -> bool:
return bool(message.has_protected_content)

has_protected_content = _HasProtectedContent()
"""Messages that contain :attr:`telegram.Message.has_protected_content`.

.. versionadded:: 13.9
"""

class _Invoice(MessageFilter):
__slots__ = ()
name = 'Filters.invoice'
Expand Down