From 81b6465340ebaf2cea8133028f8e65bddd4b648b Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Mon, 14 Aug 2023 22:44:36 +0300 Subject: [PATCH] Prepare for Bot API 6.8 --- .../entity.json | 25 +++++++ .butcher/schema/schema.json | 71 +++++++++++++++++-- .butcher/types/Chat/aliases.yml | 4 ++ .butcher/types/Chat/entity.json | 8 +++ .butcher/types/Message/entity.json | 8 +++ .butcher/types/Message/replace.yml | 4 ++ .butcher/types/PollAnswer/entity.json | 22 ++++-- .butcher/types/Story/entity.json | 16 +++++ aiogram/client/bot.py | 21 ++++++ aiogram/enums/content_type.py | 1 + aiogram/methods/__init__.py | 2 + .../unpin_all_general_forum_topic_messages.py | 30 ++++++++ aiogram/types/__init__.py | 2 + aiogram/types/chat.py | 31 ++++++++ aiogram/types/message.py | 11 ++- aiogram/types/poll_answer.py | 20 ++++-- aiogram/types/story.py | 9 +++ docs/api/methods/index.rst | 8 +++ ...unpin_all_general_forum_topic_messages.rst | 51 +++++++++++++ docs/api/types/index.rst | 8 +++ docs/api/types/story.rst | 10 +++ examples/context_addition_from_filter.py | 5 +- examples/multibot.py | 2 +- ..._unpin_all_general_forum_topic_messages.py | 15 ++++ tests/test_api/test_types/test_chat.py | 6 ++ tests/test_api/test_types/test_message.py | 11 +++ 26 files changed, 374 insertions(+), 27 deletions(-) create mode 100644 .butcher/methods/unpinAllGeneralForumTopicMessages/entity.json create mode 100644 .butcher/types/Story/entity.json create mode 100644 aiogram/methods/unpin_all_general_forum_topic_messages.py create mode 100644 aiogram/types/story.py create mode 100644 docs/api/methods/unpin_all_general_forum_topic_messages.rst create mode 100644 docs/api/types/story.rst create mode 100644 tests/test_api/test_methods/test_unpin_all_general_forum_topic_messages.py diff --git a/.butcher/methods/unpinAllGeneralForumTopicMessages/entity.json b/.butcher/methods/unpinAllGeneralForumTopicMessages/entity.json new file mode 100644 index 00000000..6dd2f5a3 --- /dev/null +++ b/.butcher/methods/unpinAllGeneralForumTopicMessages/entity.json @@ -0,0 +1,25 @@ +{ + "meta": {}, + "group": { + "title": "Upcoming update", + "anchor": "upcoming-update" + }, + "object": { + "anchor": "unpinallgeneralforumtopicmessages", + "name": "unpinAllGeneralForumTopicMessages", + "description": "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.", + "html_description": "

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.

", + "rst_description": "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 :code:`True` on success.", + "annotations": [ + { + "type": "Integer or String", + "required": true, + "description": "Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)", + "html_description": "Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)", + "rst_description": "Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)\n", + "name": "chat_id" + } + ], + "category": "methods" + } +} diff --git a/.butcher/schema/schema.json b/.butcher/schema/schema.json index fa7a76d3..621e98c0 100644 --- a/.butcher/schema/schema.json +++ b/.butcher/schema/schema.json @@ -690,6 +690,14 @@ "rst_description": "*Optional*. For supergroups, the location to which the supergroup is connected. Returned only in :class:`aiogram.methods.get_chat.GetChat`.\n", "name": "location", "required": false + }, + { + "type": "Integer", + "description": "Expiration date of the emoji status of the other party in a private chat, if any. Returned only in getChat.", + "html_description": "Optional. Expiration date of the emoji status of the other party in a private chat, if any. Returned only in getChat.", + "rst_description": "*Optional*. Expiration date of the emoji status of the other party in a private chat, if any. Returned only in :class:`aiogram.methods.get_chat.GetChat`.\n", + "name": "emoji_status_expiration_date", + "required": false } ], "category": "types" @@ -1268,6 +1276,14 @@ "rst_description": "*Optional*. Inline keyboard attached to the message. :code:`login_url` buttons are represented as ordinary :code:`url` buttons.\n", "name": "reply_markup", "required": false + }, + { + "type": "Story", + "description": "Message is a forwarded story", + "html_description": "Optional. Message is a forwarded story", + "rst_description": "*Optional*. Message is a forwarded story\n", + "name": "story", + "required": false } ], "category": "types" @@ -1937,19 +1953,27 @@ }, { "type": "User", - "description": "The user, who changed the answer to the poll", - "html_description": "The user, who changed the answer to the poll", - "rst_description": "The user, who changed the answer to the poll\n", + "description": "The user that changed the answer to the poll, if the voter isn't anonymous", + "html_description": "Optional. The user that changed the answer to the poll, if the voter isn't anonymous", + "rst_description": "*Optional*. The user that changed the answer to the poll, if the voter isn't anonymous\n", "name": "user", - "required": true + "required": false }, { "type": "Array of Integer", - "description": "0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.", - "html_description": "0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.", - "rst_description": "0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.\n", + "description": "0-based identifiers of chosen answer options. May be empty if the vote was retracted.", + "html_description": "0-based identifiers of chosen answer options. May be empty if the vote was retracted.", + "rst_description": "0-based identifiers of chosen answer options. May be empty if the vote was retracted.\n", "name": "option_ids", "required": true + }, + { + "type": "Chat", + "description": "The chat that changed the answer to the poll, if the voter is anonymous", + "html_description": "Optional. The chat that changed the answer to the poll, if the voter is anonymous", + "rst_description": "*Optional*. The chat that changed the answer to the poll, if the voter is anonymous\n", + "name": "voter_chat", + "required": false } ], "category": "types" @@ -13855,6 +13879,39 @@ } ], "description": "Your bot can offer users HTML5 games to play solo or to compete against each other in groups and one-on-one chats. Create games via @BotFather using the /newgame command. Please note that this kind of power requires responsibility: you will need to accept the terms for each game that your bots will be offering.\n - Games are a new type of content on Telegram, represented by the Game and InlineQueryResultGame objects.\n - Once you've created a game via BotFather, you can send games to chats as regular messages using the sendGame method, or use inline mode with InlineQueryResultGame.\n - If you send the game message without any buttons, it will automatically have a 'Play GameName' button. When this button is pressed, your bot gets a CallbackQuery with the game_short_name of the requested game. You provide the correct URL for this particular user and the app opens the game in the in-app browser.\n - You can manually add multiple buttons to your game message. Please note that the first button in the first row must always launch the game, using the field callback_game in InlineKeyboardButton. You can add extra buttons according to taste: e.g., for a description of the rules, or to open the game's official community.\n - To make your game more attractive, you can upload a GIF animation that demostrates the game to the users via BotFather (see Lumberjack for example).\n - A game message will also display high scores for the current chat. Use setGameScore to post high scores to the chat with the game, add the edit_message parameter to automatically update the message with the current scoreboard.\n - Use getGameHighScores to get data for in-game high score tables.\n - You can also add an extra sharing button for users to share their best score to different chats.\n - For examples of what can be done using this new stuff, check the @gamebot and @gamee bots." + }, + { + "title": "Upcoming update", + "anchor": "upcoming-update", + "children": [ + { + "anchor": "story", + "name": "Story", + "description": "This object represents a message about a forwarded story in the chat. Currently holds no information.", + "html_description": "

This object represents a message about a forwarded story in the chat. Currently holds no information.

", + "rst_description": "This object represents a message about a forwarded story in the chat. Currently holds no information.", + "annotations": [], + "category": "types" + }, + { + "anchor": "unpinallgeneralforumtopicmessages", + "name": "unpinAllGeneralForumTopicMessages", + "description": "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.", + "html_description": "

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.

", + "rst_description": "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 :code:`True` on success.", + "annotations": [ + { + "type": "Integer or String", + "required": true, + "description": "Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)", + "html_description": "Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)", + "rst_description": "Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)\n", + "name": "chat_id" + } + ], + "category": "methods" + } + ] } ] } diff --git a/.butcher/types/Chat/aliases.yml b/.butcher/types/Chat/aliases.yml index 4538f7e1..89b5843c 100644 --- a/.butcher/types/Chat/aliases.yml +++ b/.butcher/types/Chat/aliases.yml @@ -106,3 +106,7 @@ delete_photo: set_photo: method: setChatPhoto fill: *self + +unpin_all_general_forum_topic_messages: + method: unpinAllGeneralForumTopicMessages + fill: *self diff --git a/.butcher/types/Chat/entity.json b/.butcher/types/Chat/entity.json index 7aa42c18..362e827a 100644 --- a/.butcher/types/Chat/entity.json +++ b/.butcher/types/Chat/entity.json @@ -234,6 +234,14 @@ "rst_description": "*Optional*. For supergroups, the location to which the supergroup is connected. Returned only in :class:`aiogram.methods.get_chat.GetChat`.\n", "name": "location", "required": false + }, + { + "type": "Integer", + "description": "Expiration date of the emoji status of the other party in a private chat, if any. Returned only in getChat.", + "html_description": "Optional. Expiration date of the emoji status of the other party in a private chat, if any. Returned only in getChat.", + "rst_description": "*Optional*. Expiration date of the emoji status of the other party in a private chat, if any. Returned only in :class:`aiogram.methods.get_chat.GetChat`.\n", + "name": "emoji_status_expiration_date", + "required": false } ], "category": "types" diff --git a/.butcher/types/Message/entity.json b/.butcher/types/Message/entity.json index cd5e27cb..47116105 100644 --- a/.butcher/types/Message/entity.json +++ b/.butcher/types/Message/entity.json @@ -578,6 +578,14 @@ "rst_description": "*Optional*. Inline keyboard attached to the message. :code:`login_url` buttons are represented as ordinary :code:`url` buttons.\n", "name": "reply_markup", "required": false + }, + { + "type": "Story", + "description": "Message is a forwarded story", + "html_description": "Optional. Message is a forwarded story", + "rst_description": "*Optional*. Message is a forwarded story\n", + "name": "story", + "required": false } ], "category": "types" diff --git a/.butcher/types/Message/replace.yml b/.butcher/types/Message/replace.yml index 9a3a2842..93a8f17e 100644 --- a/.butcher/types/Message/replace.yml +++ b/.butcher/types/Message/replace.yml @@ -3,3 +3,7 @@ annotations: parsed_type: type: std name: datetime.datetime + forward_date: + parsed_type: + type: std + name: datetime.datetime diff --git a/.butcher/types/PollAnswer/entity.json b/.butcher/types/PollAnswer/entity.json index 9081b30c..5cf20ed7 100644 --- a/.butcher/types/PollAnswer/entity.json +++ b/.butcher/types/PollAnswer/entity.json @@ -21,19 +21,27 @@ }, { "type": "User", - "description": "The user, who changed the answer to the poll", - "html_description": "The user, who changed the answer to the poll", - "rst_description": "The user, who changed the answer to the poll\n", + "description": "The user that changed the answer to the poll, if the voter isn't anonymous", + "html_description": "Optional. The user that changed the answer to the poll, if the voter isn't anonymous", + "rst_description": "*Optional*. The user that changed the answer to the poll, if the voter isn't anonymous\n", "name": "user", - "required": true + "required": false }, { "type": "Array of Integer", - "description": "0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.", - "html_description": "0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.", - "rst_description": "0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.\n", + "description": "0-based identifiers of chosen answer options. May be empty if the vote was retracted.", + "html_description": "0-based identifiers of chosen answer options. May be empty if the vote was retracted.", + "rst_description": "0-based identifiers of chosen answer options. May be empty if the vote was retracted.\n", "name": "option_ids", "required": true + }, + { + "type": "Chat", + "description": "The chat that changed the answer to the poll, if the voter is anonymous", + "html_description": "Optional. The chat that changed the answer to the poll, if the voter is anonymous", + "rst_description": "*Optional*. The chat that changed the answer to the poll, if the voter is anonymous\n", + "name": "voter_chat", + "required": false } ], "category": "types" diff --git a/.butcher/types/Story/entity.json b/.butcher/types/Story/entity.json new file mode 100644 index 00000000..50407967 --- /dev/null +++ b/.butcher/types/Story/entity.json @@ -0,0 +1,16 @@ +{ + "meta": {}, + "group": { + "title": "Upcoming update", + "anchor": "upcoming-update" + }, + "object": { + "anchor": "story", + "name": "Story", + "description": "This object represents a message about a forwarded story in the chat. Currently holds no information.", + "html_description": "

This object represents a message about a forwarded story in the chat. Currently holds no information.

", + "rst_description": "This object represents a message about a forwarded story in the chat. Currently holds no information.", + "annotations": [], + "category": "types" + } +} diff --git a/aiogram/client/bot.py b/aiogram/client/bot.py index b7cda3ea..1bf48356 100644 --- a/aiogram/client/bot.py +++ b/aiogram/client/bot.py @@ -134,6 +134,7 @@ from ..methods import ( UnhideGeneralForumTopic, UnpinAllChatMessages, UnpinAllForumTopicMessages, + UnpinAllGeneralForumTopicMessages, UnpinChatMessage, UploadStickerFile, ) @@ -4086,3 +4087,23 @@ class Bot: language_code=language_code, ) return await self(call, request_timeout=request_timeout) + + async def unpin_all_general_forum_topic_messages( + self, + chat_id: Union[int, str], + request_timeout: Optional[int] = 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 the *can_pin_messages* administrator right in the supergroup. Returns :code:`True` on success. + + Source: https://core.telegram.org/bots/api#unpinallgeneralforumtopicmessages + + :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`) + :param request_timeout: Request timeout + :return: Returns :code:`True` on success. + """ + + call = UnpinAllGeneralForumTopicMessages( + chat_id=chat_id, + ) + return await self(call, request_timeout=request_timeout) diff --git a/aiogram/enums/content_type.py b/aiogram/enums/content_type.py index 52a9bfed..41ae59c1 100644 --- a/aiogram/enums/content_type.py +++ b/aiogram/enums/content_type.py @@ -55,3 +55,4 @@ class ContentType(str, Enum): VIDEO_CHAT_ENDED = "video_chat_ended" VIDEO_CHAT_PARTICIPANTS_INVITED = "video_chat_participants_invited" WEB_APP_DATA = "web_app_data" + STORY = "story" diff --git a/aiogram/methods/__init__.py b/aiogram/methods/__init__.py index fd887d7e..32909f4a 100644 --- a/aiogram/methods/__init__.py +++ b/aiogram/methods/__init__.py @@ -110,6 +110,7 @@ from .unban_chat_sender_chat import UnbanChatSenderChat from .unhide_general_forum_topic import UnhideGeneralForumTopic from .unpin_all_chat_messages import UnpinAllChatMessages from .unpin_all_forum_topic_messages import UnpinAllForumTopicMessages +from .unpin_all_general_forum_topic_messages import UnpinAllGeneralForumTopicMessages from .unpin_chat_message import UnpinChatMessage from .upload_sticker_file import UploadStickerFile @@ -228,6 +229,7 @@ __all__ = ( "UnhideGeneralForumTopic", "UnpinAllChatMessages", "UnpinAllForumTopicMessages", + "UnpinAllGeneralForumTopicMessages", "UnpinChatMessage", "UploadStickerFile", ) diff --git a/aiogram/methods/unpin_all_general_forum_topic_messages.py b/aiogram/methods/unpin_all_general_forum_topic_messages.py new file mode 100644 index 00000000..be76c198 --- /dev/null +++ b/aiogram/methods/unpin_all_general_forum_topic_messages.py @@ -0,0 +1,30 @@ +from typing import TYPE_CHECKING, Any, Union + +from aiogram.methods import TelegramMethod + + +class UnpinAllGeneralForumTopicMessages(TelegramMethod[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 :code:`True` on success. + + Source: https://core.telegram.org/bots/api#unpinallgeneralforumtopicmessages + """ + + __returning__ = bool + __api_method__ = "unpinAllGeneralForumTopicMessages" + + chat_id: Union[int, str] + """Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)""" + + if TYPE_CHECKING: + # DO NOT EDIT MANUALLY!!! + # This section was auto-generated via `butcher` + + def __init__( + __pydantic__self__, *, chat_id: Union[int, str], **__pydantic_kwargs: Any + ) -> None: + # DO NOT EDIT MANUALLY!!! + # This method was auto-generated via `butcher` + # Is needed only for type checking and IDE support without any additional plugins + + super().__init__(chat_id=chat_id, **__pydantic_kwargs) diff --git a/aiogram/types/__init__.py b/aiogram/types/__init__.py index a669cbe8..bf9c02ee 100644 --- a/aiogram/types/__init__.py +++ b/aiogram/types/__init__.py @@ -140,6 +140,7 @@ from .shipping_option import ShippingOption from .shipping_query import ShippingQuery from .sticker import Sticker from .sticker_set import StickerSet +from .story import Story from .successful_payment import SuccessfulPayment from .switch_inline_query_chosen_chat import SwitchInlineQueryChosenChat from .update import Update @@ -298,6 +299,7 @@ __all__ = ( "ShippingQuery", "Sticker", "StickerSet", + "Story", "SuccessfulPayment", "SwitchInlineQueryChosenChat", "TelegramObject", diff --git a/aiogram/types/chat.py b/aiogram/types/chat.py index 6c36ae5a..8045354b 100644 --- a/aiogram/types/chat.py +++ b/aiogram/types/chat.py @@ -34,6 +34,7 @@ if TYPE_CHECKING: UnbanChatSenderChat, UnpinAllChatMessages, UnpinChatMessage, + UnpinAllGeneralForumTopicMessages, ) from .chat_location import ChatLocation from .chat_permissions import ChatPermissions @@ -105,6 +106,8 @@ class Chat(TelegramObject): """*Optional*. Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa; for supergroups and channel chats. This identifier may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. Returned only in :class:`aiogram.methods.get_chat.GetChat`.""" location: Optional[ChatLocation] = None """*Optional*. For supergroups, the location to which the supergroup is connected. Returned only in :class:`aiogram.methods.get_chat.GetChat`.""" + emoji_status_expiration_date: Optional[int] = None + """*Optional*. Expiration date of the emoji status of the other party in a private chat, if any. Returned only in :class:`aiogram.methods.get_chat.GetChat`.""" if TYPE_CHECKING: # DO NOT EDIT MANUALLY!!! @@ -141,6 +144,7 @@ class Chat(TelegramObject): can_set_sticker_set: Optional[bool] = None, linked_chat_id: Optional[int] = None, location: Optional[ChatLocation] = None, + emoji_status_expiration_date: Optional[int] = None, **__pydantic_kwargs: Any, ) -> None: # DO NOT EDIT MANUALLY!!! @@ -176,6 +180,7 @@ class Chat(TelegramObject): can_set_sticker_set=can_set_sticker_set, linked_chat_id=linked_chat_id, location=location, + emoji_status_expiration_date=emoji_status_expiration_date, **__pydantic_kwargs, ) @@ -1082,3 +1087,29 @@ class Chat(TelegramObject): photo=photo, **kwargs, ).as_(self._bot) + + def unpin_all_general_forum_topic_messages( + self, + **kwargs: Any, + ) -> UnpinAllGeneralForumTopicMessages: + """ + Shortcut for method :class:`aiogram.methods.unpin_all_general_forum_topic_messages.UnpinAllGeneralForumTopicMessages` + will automatically fill method attributes: + + - :code:`chat_id` + + 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 :code:`True` on success. + + Source: https://core.telegram.org/bots/api#unpinallgeneralforumtopicmessages + + :return: instance of method :class:`aiogram.methods.unpin_all_general_forum_topic_messages.UnpinAllGeneralForumTopicMessages` + """ + # DO NOT EDIT MANUALLY!!! + # This method was auto-generated via `butcher` + + from aiogram.methods import UnpinAllGeneralForumTopicMessages + + return UnpinAllGeneralForumTopicMessages( + chat_id=self.id, + **kwargs, + ).as_(self._bot) diff --git a/aiogram/types/message.py b/aiogram/types/message.py index c8fd7c5a..052bd3af 100644 --- a/aiogram/types/message.py +++ b/aiogram/types/message.py @@ -84,6 +84,7 @@ if TYPE_CHECKING: from .reply_keyboard_markup import ReplyKeyboardMarkup from .reply_keyboard_remove import ReplyKeyboardRemove from .sticker import Sticker + from .story import Story from .successful_payment import SuccessfulPayment from .user import User from .user_shared import UserShared @@ -128,7 +129,7 @@ class Message(TelegramObject): """*Optional*. For forwarded messages that were originally sent in channels or by an anonymous chat administrator, signature of the message sender if present""" forward_sender_name: Optional[str] = None """*Optional*. Sender's name for messages forwarded from users who disallow adding a link to their account in forwarded messages""" - forward_date: Optional[int] = None + forward_date: Optional[datetime.datetime] = None """*Optional*. For forwarded messages, date the original message was sent in Unix time""" is_topic_message: Optional[bool] = None """*Optional*. :code:`True`, if the message is sent to a forum topic""" @@ -248,6 +249,8 @@ class Message(TelegramObject): """*Optional*. Service message: data sent by a Web App""" reply_markup: Optional[InlineKeyboardMarkup] = None """*Optional*. Inline keyboard attached to the message. :code:`login_url` buttons are represented as ordinary :code:`url` buttons.""" + story: Optional[Story] = None + """*Optional*. Message is a forwarded story""" if TYPE_CHECKING: # DO NOT EDIT MANUALLY!!! @@ -267,7 +270,7 @@ class Message(TelegramObject): forward_from_message_id: Optional[int] = None, forward_signature: Optional[str] = None, forward_sender_name: Optional[str] = None, - forward_date: Optional[int] = None, + forward_date: Optional[datetime.datetime] = None, is_topic_message: Optional[bool] = None, is_automatic_forward: Optional[bool] = None, reply_to_message: Optional[Message] = None, @@ -327,6 +330,7 @@ class Message(TelegramObject): video_chat_participants_invited: Optional[VideoChatParticipantsInvited] = None, web_app_data: Optional[WebAppData] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + story: Optional[Story] = None, **__pydantic_kwargs: Any, ) -> None: # DO NOT EDIT MANUALLY!!! @@ -405,6 +409,7 @@ class Message(TelegramObject): video_chat_participants_invited=video_chat_participants_invited, web_app_data=web_app_data, reply_markup=reply_markup, + story=story, **__pydantic_kwargs, ) @@ -496,6 +501,8 @@ class Message(TelegramObject): return ContentType.USER_SHARED if self.chat_shared: return ContentType.CHAT_SHARED + if self.story: + return ContentType.STORY return ContentType.UNKNOWN diff --git a/aiogram/types/poll_answer.py b/aiogram/types/poll_answer.py index beb6ef09..f9ed18e1 100644 --- a/aiogram/types/poll_answer.py +++ b/aiogram/types/poll_answer.py @@ -1,10 +1,11 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, List +from typing import TYPE_CHECKING, Any, List, Optional from .base import TelegramObject if TYPE_CHECKING: + from .chat import Chat from .user import User @@ -17,10 +18,12 @@ class PollAnswer(TelegramObject): poll_id: str """Unique poll identifier""" - user: User - """The user, who changed the answer to the poll""" option_ids: List[int] - """0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.""" + """0-based identifiers of chosen answer options. May be empty if the vote was retracted.""" + user: Optional[User] = None + """*Optional*. The user that changed the answer to the poll, if the voter isn't anonymous""" + voter_chat: Optional[Chat] = None + """*Optional*. The chat that changed the answer to the poll, if the voter is anonymous""" if TYPE_CHECKING: # DO NOT EDIT MANUALLY!!! @@ -30,8 +33,9 @@ class PollAnswer(TelegramObject): __pydantic__self__, *, poll_id: str, - user: User, option_ids: List[int], + user: Optional[User] = None, + voter_chat: Optional[Chat] = None, **__pydantic_kwargs: Any, ) -> None: # DO NOT EDIT MANUALLY!!! @@ -39,5 +43,9 @@ class PollAnswer(TelegramObject): # Is needed only for type checking and IDE support without any additional plugins super().__init__( - poll_id=poll_id, user=user, option_ids=option_ids, **__pydantic_kwargs + poll_id=poll_id, + option_ids=option_ids, + user=user, + voter_chat=voter_chat, + **__pydantic_kwargs, ) diff --git a/aiogram/types/story.py b/aiogram/types/story.py new file mode 100644 index 00000000..dc92c575 --- /dev/null +++ b/aiogram/types/story.py @@ -0,0 +1,9 @@ +from aiogram.types import TelegramObject + + +class Story(TelegramObject): + """ + This object represents a message about a forwarded story in the chat. Currently holds no information. + + Source: https://core.telegram.org/bots/api#story + """ diff --git a/docs/api/methods/index.rst b/docs/api/methods/index.rst index 4a7f4b01..7ac61f6c 100644 --- a/docs/api/methods/index.rst +++ b/docs/api/methods/index.rst @@ -165,6 +165,14 @@ Updating messages stop_message_live_location stop_poll +Upcoming update +=============== + +.. toctree:: + :maxdepth: 1 + + unpin_all_general_forum_topic_messages + Inline mode =========== diff --git a/docs/api/methods/unpin_all_general_forum_topic_messages.rst b/docs/api/methods/unpin_all_general_forum_topic_messages.rst new file mode 100644 index 00000000..b71da566 --- /dev/null +++ b/docs/api/methods/unpin_all_general_forum_topic_messages.rst @@ -0,0 +1,51 @@ +################################# +unpinAllGeneralForumTopicMessages +################################# + +Returns: :obj:`bool` + +.. automodule:: aiogram.methods.unpin_all_general_forum_topic_messages + :members: + :member-order: bysource + :undoc-members: True + :exclude-members: model_config,model_fields + + +Usage +===== + +As bot method +------------- + +.. code-block:: + + result: bool = await bot.unpin_all_general_forum_topic_messages(...) + + +Method as object +---------------- + +Imports: + +- :code:`from aiogram.methods.unpin_all_general_forum_topic_messages import UnpinAllGeneralForumTopicMessages` +- alias: :code:`from aiogram.methods import UnpinAllGeneralForumTopicMessages` + +With specific bot +~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + result: bool = await bot(UnpinAllGeneralForumTopicMessages(...)) + +As reply into Webhook in handler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + return UnpinAllGeneralForumTopicMessages(...) + + +As shortcut from received object +-------------------------------- + +- :meth:`aiogram.types.chat.Chat.unpin_all_general_forum_topic_messages` diff --git a/docs/api/types/index.rst b/docs/api/types/index.rst index 930e9354..7ff71075 100644 --- a/docs/api/types/index.rst +++ b/docs/api/types/index.rst @@ -204,3 +204,11 @@ Games callback_game game game_high_score + +Upcoming update +=============== + +.. toctree:: + :maxdepth: 1 + + story diff --git a/docs/api/types/story.rst b/docs/api/types/story.rst new file mode 100644 index 00000000..68565b39 --- /dev/null +++ b/docs/api/types/story.rst @@ -0,0 +1,10 @@ +##### +Story +##### + + +.. automodule:: aiogram.types.story + :members: + :member-order: bysource + :undoc-members: True + :exclude-members: model_config,model_fields diff --git a/examples/context_addition_from_filter.py b/examples/context_addition_from_filter.py index e4eca517..40338940 100644 --- a/examples/context_addition_from_filter.py +++ b/examples/context_addition_from_filter.py @@ -4,7 +4,6 @@ from aiogram import Router from aiogram.filters import Filter from aiogram.types import Message, User - router = Router(name=__name__) @@ -28,6 +27,4 @@ class HelloFilter(Filter): async def my_handler( message: Message, name: str # Now we can accept "name" as named parameter ) -> Any: - return message.answer( - "Hello, {name}!".format(name=name) - ) + return message.answer("Hello, {name}!".format(name=name)) diff --git a/examples/multibot.py b/examples/multibot.py index 82fac4a1..d5dbe5fc 100644 --- a/examples/multibot.py +++ b/examples/multibot.py @@ -4,6 +4,7 @@ from os import getenv from typing import Any, Dict, Union from aiohttp import web +from finite_state_machine import form_router from aiogram import Bot, Dispatcher, F, Router from aiogram.client.session.aiohttp import AiohttpSession @@ -18,7 +19,6 @@ from aiogram.webhook.aiohttp_server import ( TokenBasedRequestHandler, setup_application, ) -from finite_state_machine import form_router main_router = Router() diff --git a/tests/test_api/test_methods/test_unpin_all_general_forum_topic_messages.py b/tests/test_api/test_methods/test_unpin_all_general_forum_topic_messages.py new file mode 100644 index 00000000..406a98a7 --- /dev/null +++ b/tests/test_api/test_methods/test_unpin_all_general_forum_topic_messages.py @@ -0,0 +1,15 @@ +from aiogram.methods import Request, UnpinAllForumTopicMessages, UnpinAllGeneralForumTopicMessages +from tests.mocked_bot import MockedBot + + +class TestUnpinAllForumTopicMessages: + async def test_bot_method(self, bot: MockedBot): + prepare_result = bot.add_result_for( + UnpinAllGeneralForumTopicMessages, ok=True, result=True + ) + + response: bool = await bot.unpin_all_general_forum_topic_messages( + chat_id=42, + ) + request = bot.get_request() + assert response == prepare_result.result diff --git a/tests/test_api/test_types/test_chat.py b/tests/test_api/test_types/test_chat.py index 03cb8963..14cc3dc2 100644 --- a/tests/test_api/test_types/test_chat.py +++ b/tests/test_api/test_types/test_chat.py @@ -207,3 +207,9 @@ class TestChat: ): chat = Chat(id=42, first_name=first, last_name=last, title=title, type=chat_type) assert chat.full_name == result + + def test_unpin_all_general_forum_topic_messages(self): + chat = Chat(id=-42, type="supergroup") + + method = chat.unpin_all_general_forum_topic_messages() + assert method.chat_id == chat.id diff --git a/tests/test_api/test_types/test_message.py b/tests/test_api/test_types/test_message.py index f0a34b09..9d3835b6 100644 --- a/tests/test_api/test_types/test_message.py +++ b/tests/test_api/test_types/test_message.py @@ -73,6 +73,7 @@ from aiogram.types import ( VideoNote, Voice, WebAppData, + Story, ) from aiogram.types.message import ContentType, Message @@ -455,6 +456,15 @@ TEST_CHAT_SHARED = Message( from_user=User(id=42, is_bot=False, first_name="Test"), chat_shared=ChatShared(request_id=42, chat_id=42), ) +TEST_MESSAGE_STORY = Message( + message_id=42, + date=datetime.datetime.now(), + chat=Chat(id=42, type="private"), + from_user=User(id=42, is_bot=False, first_name="Test"), + story=Story(), + forward_signature="Test", + forward_date=datetime.datetime.now(), +) TEST_MESSAGE_UNKNOWN = Message( message_id=42, date=datetime.datetime.now(), @@ -516,6 +526,7 @@ class TestMessage: [TEST_FORUM_TOPIC_REOPENED, ContentType.FORUM_TOPIC_REOPENED], [TEST_USER_SHARED, ContentType.USER_SHARED], [TEST_CHAT_SHARED, ContentType.CHAT_SHARED], + [TEST_MESSAGE_STORY, ContentType.STORY], [TEST_MESSAGE_UNKNOWN, ContentType.UNKNOWN], ], )