diff --git a/README.md b/README.md index cf6e75fa9..c37a19eb4 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 6.7! +##

Supported Bot API version: 6.8!

Official documentation

Official ru documentation

diff --git a/telebot/__init__.py b/telebot/__init__.py index 77cdd0ded..e4377d2a0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4571,6 +4571,24 @@ def answer_inline_query( return apihelper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset, button) + def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> 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 the + can_pin_messages administrator right in the supergroup. + Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#unpinAllGeneralForumTopicMessages + + :param chat_id: Unique identifier for the target chat or username of chat + :type chat_id: :obj:`int` | :obj:`str` + + :return: On success, True is returned. + :rtype: :obj:`bool` + """ + + return apihelper.unpin_all_general_forum_topic_messages(self.token, chat_id) + def answer_callback_query( self, callback_query_id: int, text: Optional[str]=None, show_alert: Optional[bool]=None, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index a07f1ef91..cf8a03faf 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1585,6 +1585,11 @@ def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_message=No return _make_request(token, method_url, params=payload) +def unpin_all_general_forum_topic_messages(token, chat_id): + method_url = 'unpinAllGeneralForumTopicMessages' + payload = {'chat_id': chat_id} + return _make_request(token, method_url, params=payload, method='post') + # InlineQuery def answer_callback_query(token, callback_query_id, text=None, show_alert=None, url=None, cache_time=None): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index b3f189e16..91d0709c6 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -5432,6 +5432,24 @@ async def answer_inline_query( return await asyncio_helper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset, button) + async def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> 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 the + can_pin_messages administrator right in the supergroup. + Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#unpinAllGeneralForumTopicMessages + + :param chat_id: Unique identifier for the target chat or username of chat + :type chat_id: :obj:`int` | :obj:`str` + + :return: On success, True is returned. + :rtype: :obj:`bool` + """ + + return await asyncio_helper.unpin_all_general_forum_topic_messages(self.token, chat_id) + async def answer_callback_query( self, callback_query_id: int, text: Optional[str]=None, show_alert: Optional[bool]=None, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 5a615b397..894b62be5 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1575,6 +1575,11 @@ async def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_mess return await _process_request(token, method_url, params=payload) +async def unpin_all_general_forum_topic_messages(token, chat_id): + method_url = 'unpinAllGeneralForumTopicMessages' + payload = {'chat_id': chat_id} + return await _process_request(token, method_url, params=payload, method='post') + # InlineQuery async def answer_callback_query(token, callback_query_id, text=None, show_alert=None, url=None, cache_time=None): diff --git a/telebot/types.py b/telebot/types.py index 7f5fc3035..a81fad42e 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -543,6 +543,10 @@ class Chat(JsonDeserializable): Returned only in getChat. :type emoji_status_custom_emoji_id: :obj:`str` + :param emoji_status_expiration_date: Optional. Expiration date of the emoji status of the other party in a private chat, + if any. Returned only in getChat. + :type emoji_status_expiration_date: :obj:`int` + :param bio: Optional. Bio of the other party in a private chat. Returned only in getChat. :type bio: :obj:`str` @@ -638,7 +642,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, can_set_sticker_set=None, linked_chat_id=None, location=None, join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None, is_forum=None, active_usernames=None, emoji_status_custom_emoji_id=None, - has_hidden_members=None, has_aggressive_anti_spam_enabled=None, **kwargs): + has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -667,6 +671,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.emoji_status_custom_emoji_id: str = emoji_status_custom_emoji_id self.has_hidden_members: bool = has_hidden_members self.has_aggressive_anti_spam_enabled: bool = has_aggressive_anti_spam_enabled + self.emoji_status_expiration_date: int = emoji_status_expiration_date class MessageID(JsonDeserializable): @@ -821,6 +826,9 @@ class Message(JsonDeserializable): :param sticker: Optional. Message is a sticker, information about the sticker :type sticker: :class:`telebot.types.Sticker` + :param story: Optional. Message is a forwarded story + :type story: :class:`telebot.types.Story` + :param video: Optional. Message is a video, information about the video :type video: :class:`telebot.types.Video` @@ -1177,6 +1185,9 @@ def de_json(cls, json_string): if 'chat_shared' in obj: opts['chat_shared'] = ChatShared.de_json(obj['chat_shared']) content_type = 'chat_shared' + if 'story' in obj: + opts['story'] = Story.de_json(obj['story']) + content_type = 'story' return cls(message_id, from_user, date, chat, content_type, opts, json_string) @classmethod @@ -1274,10 +1285,12 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.write_access_allowed: Optional[WriteAccessAllowed] = None self.user_shared: Optional[UserShared] = None self.chat_shared: Optional[ChatShared] = None + self.story: Optional[Story] = None for key in options: setattr(self, key, options[key]) self.json = json_string + def __html_text(self, text, entities): """ Author: @sviat9440 @@ -6680,7 +6693,10 @@ class PollAnswer(JsonSerializable, JsonDeserializable, Dictionaryable): :param poll_id: Unique poll identifier :type poll_id: :obj:`str` - :param user: The user, who changed the answer to the poll + :param voter_chat: Optional. The chat that changed the answer to the poll, if the voter is anonymous + :type voter_chat: :class:`telebot.types.Chat` + + :param user: Optional. The user, who changed the answer to the poll :type user: :class:`telebot.types.User` :param option_ids: 0-based identifiers of answer options, chosen by the user. May be empty if the user retracted @@ -6694,21 +6710,34 @@ class PollAnswer(JsonSerializable, JsonDeserializable, Dictionaryable): def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) - obj['user'] = User.de_json(obj['user']) + if 'user' in obj: + obj['user'] = User.de_json(obj['user']) + if 'voter_chat' in obj: + obj['voter_chat'] = Chat.de_json(obj['voter_chat']) return cls(**obj) - def __init__(self, poll_id, user, option_ids, **kwargs): + def __init__(self, poll_id, option_ids, user=None, voter_chat=None, **kwargs): self.poll_id: str = poll_id - self.user: User = user + self.user: Optional[User] = user self.option_ids: List[int] = option_ids + self.voter_chat: Optional[Chat] = voter_chat + def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): - return {'poll_id': self.poll_id, - 'user': self.user.to_dict(), - 'option_ids': self.option_ids} + # Left for backward compatibility, but with no support for voter_chat + json_dict = { + "poll_id": self.poll_id, + "option_ids": self.option_ids + } + if self.user: + json_dict["user"] = self.user.to_dict() + if self.voter_chat: + json_dict["voter_chat"] = self.voter_chat + return json_dict + class ChatLocation(JsonSerializable, JsonDeserializable, Dictionaryable): @@ -7743,3 +7772,21 @@ def to_dict(self) -> dict: def to_json(self) -> str: return json.dumps(self.to_dict()) + + +class Story(JsonDeserializable): + """ + This object represents a message about a forwarded story in the chat. + Currently holds no information. + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self) -> None: + pass +