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 6.8 #3853

Merged
merged 20 commits into from Sep 3, 2023
Merged

API 6.8 #3853

Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.rst
Expand Up @@ -14,7 +14,7 @@
:target: https://pypi.org/project/python-telegram-bot/
:alt: Supported Python versions

.. image:: https://img.shields.io/badge/Bot%20API-6.7-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-6.8-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API versions

Expand Down Expand Up @@ -93,7 +93,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
Telegram API support
====================

All types and methods of the Telegram Bot API **6.7** are supported.
All types and methods of the Telegram Bot API **6.8** are supported.

Installing
==========
Expand Down
4 changes: 2 additions & 2 deletions README_RAW.rst
Expand Up @@ -14,7 +14,7 @@
:target: https://pypi.org/project/python-telegram-bot-raw/
:alt: Supported Python versions

.. image:: https://img.shields.io/badge/Bot%20API-6.7-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-6.8-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API versions

Expand Down Expand Up @@ -89,7 +89,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
Telegram API support
====================

All types and methods of the Telegram Bot API **6.7** are supported.
All types and methods of the Telegram Bot API **6.8** are supported.

Installing
==========
Expand Down
2 changes: 2 additions & 0 deletions docs/source/inclusions/bot_methods.rst
Expand Up @@ -328,6 +328,8 @@
- Used to reopen the general topic
* - :meth:`~telegram.Bot.unpin_all_forum_topic_messages`
- Used to unpin all messages in a forum topic
* - :meth:`~telegram.Bot.unpin_all_general_forum_topic_messages`
- Used to unpin all messages in the general forum topic

.. raw:: html

Expand Down
1 change: 1 addition & 0 deletions docs/source/telegram.at-tree.rst
Expand Up @@ -79,6 +79,7 @@ Available Types
telegram.replykeyboardmarkup
telegram.replykeyboardremove
telegram.sentwebappmessage
telegram.story
telegram.switchinlinequerychosenchat
telegram.telegramobject
telegram.update
Expand Down
6 changes: 6 additions & 0 deletions docs/source/telegram.story.rst
@@ -0,0 +1,6 @@
Story
=====

.. autoclass:: telegram.Story
:members:
:show-inheritance:
2 changes: 2 additions & 0 deletions telegram/__init__.py
Expand Up @@ -170,6 +170,7 @@
"ShippingQuery",
"Sticker",
"StickerSet",
"Story",
"SuccessfulPayment",
"SwitchInlineQueryChosenChat",
"TelegramObject",
Expand Down Expand Up @@ -341,6 +342,7 @@
from ._replykeyboardremove import ReplyKeyboardRemove
from ._sentwebappmessage import SentWebAppMessage
from ._shared import ChatShared, UserShared
from ._story import Story
from ._switchinlinequerychosenchat import SwitchInlineQueryChosenChat
from ._telegramobject import TelegramObject
from ._update import Update
Expand Down
42 changes: 42 additions & 0 deletions telegram/_bot.py
Expand Up @@ -7814,6 +7814,46 @@ async def unpin_all_forum_topic_messages(
api_kwargs=api_kwargs,
)

@_log
async def unpin_all_general_forum_topic_messages(
self,
chat_id: Union[str, 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: Optional[JSONDict] = None,
) -> bool:
"""
Use this method to clear the list of pinned messages in a General forum topic. The bot must
be an administrator in the chat for this to work and must have
:paramref:`~telegram.ChatAdministratorRights.can_pin_messages` administrator rights in the
supergroup.

.. versionadded:: NEXT.VERSION

Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_group|

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

Raises:
:class:`telegram.error.TelegramError`
"""
data: JSONDict = {"chat_id": chat_id}

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

@_log
async def edit_general_forum_topic(
self,
Expand Down Expand Up @@ -8527,3 +8567,5 @@ def __hash__(self) -> int:
"""Alias for :meth:`set_my_name`"""
getMyName = get_my_name
"""Alias for :meth:`get_my_name`"""
unpinAllGeneralForumTopicMessages = unpin_all_general_forum_topic_messages
"""Alias for :meth:`unpin_all_general_forum_topic_messages`"""
44 changes: 44 additions & 0 deletions telegram/_chat.py
Expand Up @@ -172,6 +172,11 @@ class Chat(TelegramObject):
:meth:`telegram.Bot.get_chat`.

.. versionadded:: 20.0
emoji_status_expiration_date (:obj:`int`, optional): Expiration date of emoji status of
the other party in a private chat, in seconds. Returned only in
:meth:`telegram.Bot.get_chat`.
Bibo-Joshi marked this conversation as resolved.
Show resolved Hide resolved

.. versionadded:: NEXT.VERSION
has_aggressive_anti_spam_enabled (:obj:`bool`, optional): :obj:`True`, if aggressive
anti-spam checks are enabled in the supergroup. The field is only available to chat
administrators. Returned only in :meth:`telegram.Bot.get_chat`.
Expand Down Expand Up @@ -265,6 +270,11 @@ class Chat(TelegramObject):
:meth:`telegram.Bot.get_chat`.

.. versionadded:: 20.0
emoji_status_expiration_date (:obj:`int`, optional): Expiration date of emoji status of
the other party in a private chat, in seconds. Returned only in
:meth:`telegram.Bot.get_chat`.
Bibo-Joshi marked this conversation as resolved.
Show resolved Hide resolved

.. versionadded:: NEXT.VERSION
has_aggressive_anti_spam_enabled (:obj:`bool`): Optional. :obj:`True`, if aggressive
anti-spam checks are enabled in the supergroup. The field is only available to chat
administrators. Returned only in :meth:`telegram.Bot.get_chat`.
Expand Down Expand Up @@ -306,6 +316,7 @@ class Chat(TelegramObject):
"is_forum",
"active_usernames",
"emoji_status_custom_emoji_id",
"emoji_status_expiration_date",
"has_hidden_members",
"has_aggressive_anti_spam_enabled",
)
Expand Down Expand Up @@ -352,6 +363,7 @@ def __init__(
is_forum: Optional[bool] = None,
active_usernames: Optional[Sequence[str]] = None,
emoji_status_custom_emoji_id: Optional[str] = None,
emoji_status_expiration_date: Optional[int] = None,
has_aggressive_anti_spam_enabled: Optional[bool] = None,
has_hidden_members: Optional[bool] = None,
*,
Expand Down Expand Up @@ -390,6 +402,7 @@ def __init__(
self.is_forum: Optional[bool] = is_forum
self.active_usernames: Tuple[str, ...] = parse_sequence_arg(active_usernames)
self.emoji_status_custom_emoji_id: Optional[str] = emoji_status_custom_emoji_id
self.emoji_status_expiration_date: Optional[int] = emoji_status_expiration_date
self.has_aggressive_anti_spam_enabled: Optional[bool] = has_aggressive_anti_spam_enabled
self.has_hidden_members: Optional[bool] = has_hidden_members

Expand Down Expand Up @@ -2904,6 +2917,37 @@ async def unpin_all_forum_topic_messages(
api_kwargs=api_kwargs,
)

async def unpin_all_general_forum_topic_messages(
self,
*,
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:
"""Shortcut for::

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

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

.. versionadded:: NEXT.VERSION

Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return await self.get_bot().unpin_all_general_forum_topic_messages(
chat_id=self.id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)

async def edit_general_forum_topic(
self,
name: str,
Expand Down
11 changes: 11 additions & 0 deletions telegram/_message.py
Expand Up @@ -53,6 +53,7 @@
from telegram._poll import Poll
from telegram._proximityalerttriggered import ProximityAlertTriggered
from telegram._shared import ChatShared, UserShared
from telegram._story import Story
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.argumentparsing import parse_sequence_arg
Expand Down Expand Up @@ -201,6 +202,9 @@ class Message(TelegramObject):

sticker (:class:`telegram.Sticker`, optional): Message is a sticker, information
about the sticker.
story (:class:`telegram.Story`, optional): Message is a forwarded story.
harshil21 marked this conversation as resolved.
Show resolved Hide resolved

.. versionadded:: NEXT.VERSION
video (:class:`telegram.Video`, optional): Message is a video, information about the
video.
voice (:class:`telegram.Voice`, optional): Message is a voice message, information about
Expand Down Expand Up @@ -435,6 +439,9 @@ class Message(TelegramObject):
about the sticker.

.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
story (:class:`telegram.Story`): Optional. Message is a forwarded story.

.. versionadded:: NEXT.VERSION
video (:class:`telegram.Video`): Optional. Message is a video, information about the
video.

Expand Down Expand Up @@ -671,6 +678,7 @@ class Message(TelegramObject):
"has_media_spoiler",
"user_shared",
"chat_shared",
"story",
)

def __init__(
Expand Down Expand Up @@ -746,6 +754,7 @@ def __init__(
has_media_spoiler: Optional[bool] = None,
user_shared: Optional[UserShared] = None,
chat_shared: Optional[ChatShared] = None,
story: Optional[Story] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
Expand Down Expand Up @@ -834,6 +843,7 @@ def __init__(
self.has_media_spoiler: Optional[bool] = has_media_spoiler
self.user_shared: Optional[UserShared] = user_shared
self.chat_shared: Optional[ChatShared] = chat_shared
self.story: Optional[Story] = story

self._effective_attachment = DEFAULT_NONE

Expand Down Expand Up @@ -903,6 +913,7 @@ def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["Message"]:
data["game"] = Game.de_json(data.get("game"), bot)
data["photo"] = PhotoSize.de_list(data.get("photo"), bot)
data["sticker"] = Sticker.de_json(data.get("sticker"), bot)
data["story"] = Story.de_json(data.get("story"), bot)
data["video"] = Video.de_json(data.get("video"), bot)
data["voice"] = Voice.de_json(data.get("voice"), bot)
data["video_note"] = VideoNote.de_json(data.get("video_note"), bot)
Expand Down
70 changes: 58 additions & 12 deletions telegram/_poll.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice backwards compatibility change

Expand Up @@ -21,13 +21,15 @@
from typing import TYPE_CHECKING, Dict, Final, List, Optional, Sequence, Tuple

from telegram import constants
from telegram._chat import Chat
from telegram._messageentity import MessageEntity
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils import enum
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.types import JSONDict
from telegram._utils.warnings import warn

if TYPE_CHECKING:
from telegram import Bot
Expand Down Expand Up @@ -84,42 +86,85 @@ class PollAnswer(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`poll_id`, :attr:`user` and :attr:`option_ids` are equal.

.. versionchanged:: NEXT.VERSION
The order of :paramref:`option_ids` and :paramref:`user` is changed in
NEXT.VERSION as the latter one became optional. We currently provide
backward compatibility for this but it will be removed in the future.
Please update your code to use the new order.

Args:
poll_id (:obj:`str`): Unique poll identifier.
user (:class:`telegram.User`): The user, who changed the answer to the poll.
option_ids (Sequence[:obj:`int`]): 0-based identifiers of answer options, chosen by the
user. May be empty if the user retracted their vote.
option_ids (Sequence[:obj:`int`]): Identifiers of answer options, chosen by the user. May
be empty if the user retracted their vote.

.. versionchanged:: 20.0
|sequenceclassargs|
user (:class:`telegram.User`, optional): The user that changed the answer to the poll,
if the voter isn't anonymous. If the voter is anonymous, this field will contain the
user :tg-const:`telegram.constants.ChatID.FAKE_CHANNEL` for backwards compatibility.

.. versionchanged:: NEXT.VERSION
:paramref:`user` became optional.
voter_chat (:class:`telegram.Chat`, optional): The chat that changed the answer to the
poll, if the voter is anonymous.

.. versionadded:: NEXT.VERSION

Attributes:
poll_id (:obj:`str`): Unique poll identifier.
user (:class:`telegram.User`): The user, who changed the answer to the poll.
option_ids (Tuple[:obj:`int`]): Identifiers of answer options, chosen by the user. May be
empty if the user retracted their vote.
option_ids (Tuple[:obj:`int`]): Identifiers of answer options, chosen by the user. May
be empty if the user retracted their vote.

.. versionchanged:: 20.0
|tupleclassattrs|
user (:class:`telegram.User`): Optional. The user, who changed the answer to the
poll, if the voter isn't anonymous. If the voter is anonymous, this field will contain
the user :tg-const:`telegram.constants.ChatID.FAKE_CHANNEL` for backwards compatibility

.. versionchanged:: NEXT.VERSION
:paramref:`user` became optional.
voter_chat (:class:`telegram.Chat`): Optional. The chat that changed the answer to the
poll, if the voter is anonymous.

.. versionadded:: NEXT.VERSION

"""

__slots__ = ("option_ids", "user", "poll_id")
__slots__ = ("option_ids", "poll_id", "user", "voter_chat")

def __init__(
self,
poll_id: str,
user: User,
option_ids: Sequence[int],
user: Optional[User] = None,
voter_chat: Optional[Chat] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.poll_id: str = poll_id
self.user: User = user
self.option_ids: Tuple[int, ...] = parse_sequence_arg(option_ids)

self._id_attrs = (self.poll_id, self.user, tuple(self.option_ids))
self.voter_chat: Optional[Chat] = voter_chat

if isinstance(option_ids, User) or isinstance(user, tuple):
warn(
"From v20.5 the order of `option_ids` and `user` is changed as the latter one"
clot27 marked this conversation as resolved.
Show resolved Hide resolved
" became optional. Please update your code to use the new order.",
stacklevel=2,
)
self.option_ids: Tuple[int, ...] = parse_sequence_arg(user)
self.user: Optional[User] = option_ids
else:
self.option_ids: Tuple[int, ...] = parse_sequence_arg( # type: ignore[no-redef]
option_ids
)
self.user: Optional[User] = user # type: ignore[no-redef]

self._id_attrs = (
self.poll_id,
self.option_ids,
self.user,
self.voter_chat,
)

self._freeze()

Expand All @@ -132,6 +177,7 @@ def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["PollAnswer"]
return None

data["user"] = User.de_json(data.get("user"), bot)
data["voter_chat"] = Chat.de_json(data.get("voter_chat"), bot)

return super().de_json(data=data, bot=bot)

Expand Down