From cf3a6c3d596df9956b5f95d2d526d4d2e340fa4f Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Fri, 9 Aug 2024 19:10:39 +0300 Subject: [PATCH] Added full support of Bot API 7.8 (#1551) * Added full support of Bot API 7.8 * Added changelog * Try to fix tests on Windows * scope=session? * Try another way * Just try to set custom event loop policy manually * Revert "Just try to set custom event loop policy manually" This reverts commit 04ee60d8783d7e084cfcb3b89b2d3f998fa42f5f. * Just try to set custom event loop policy manually --- .apiversion | 2 +- .butcher/methods/pinChatMessage/entity.json | 8 ++++ .../setStickerSetThumbnail/entity.json | 6 +-- .butcher/methods/unpinChatMessage/entity.json | 14 +++++-- .butcher/schema/schema.json | 42 +++++++++++++++---- .butcher/types/User/entity.json | 8 ++++ CHANGES/1551.feature.rst | 8 ++++ Makefile | 4 +- README.rst | 2 +- aiogram/__meta__.py | 2 +- aiogram/client/bot.py | 10 ++++- aiogram/methods/pin_chat_message.py | 4 ++ aiogram/methods/set_sticker_set_thumbnail.py | 2 +- aiogram/methods/unpin_chat_message.py | 12 +++++- aiogram/types/chat.py | 8 +++- aiogram/types/message.py | 6 +++ aiogram/types/user.py | 4 ++ docs/api/methods/send_paid_media.rst | 1 + examples/multibot.py | 2 +- tests/conftest.py | 17 ++++++-- 20 files changed, 132 insertions(+), 30 deletions(-) create mode 100644 CHANGES/1551.feature.rst diff --git a/.apiversion b/.apiversion index 25b629b0..a95c9963 100644 --- a/.apiversion +++ b/.apiversion @@ -1 +1 @@ -7.7 +7.8 diff --git a/.butcher/methods/pinChatMessage/entity.json b/.butcher/methods/pinChatMessage/entity.json index dd6e7609..1dede200 100644 --- a/.butcher/methods/pinChatMessage/entity.json +++ b/.butcher/methods/pinChatMessage/entity.json @@ -11,6 +11,14 @@ "html_description": "

Use this method to add a message to the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns True on success.

", "rst_description": "Use this method to add a message to the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns :code:`True` on success.", "annotations": [ + { + "type": "String", + "required": false, + "description": "Unique identifier of the business connection on behalf of which the message will be pinned", + "html_description": "Unique identifier of the business connection on behalf of which the message will be pinned", + "rst_description": "Unique identifier of the business connection on behalf of which the message will be pinned\n", + "name": "business_connection_id" + }, { "type": "Integer or String", "required": true, diff --git a/.butcher/methods/setStickerSetThumbnail/entity.json b/.butcher/methods/setStickerSetThumbnail/entity.json index aa49f0de..b334490d 100644 --- a/.butcher/methods/setStickerSetThumbnail/entity.json +++ b/.butcher/methods/setStickerSetThumbnail/entity.json @@ -30,9 +30,9 @@ { "type": "InputFile or String", "required": false, - "description": "A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.", - "html_description": "A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.", - "rst_description": "A **.WEBP** or **.PNG** image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a **.TGS** animation with a thumbnail up to 32 kilobytes in size (see `https://core.telegram.org/stickers#animated-sticker-requirements `_`https://core.telegram.org/stickers#animated-sticker-requirements `_ for animated sticker technical requirements), or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-sticker-requirements `_`https://core.telegram.org/stickers#video-sticker-requirements `_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More information on Sending Files » `. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.\n", + "description": "A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animation-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.", + "html_description": "A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animation-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.", + "rst_description": "A **.WEBP** or **.PNG** image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a **.TGS** animation with a thumbnail up to 32 kilobytes in size (see `https://core.telegram.org/stickers#animation-requirements `_`https://core.telegram.org/stickers#animation-requirements `_ for animated sticker technical requirements), or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-requirements `_`https://core.telegram.org/stickers#video-requirements `_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More information on Sending Files » `. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.\n", "name": "thumbnail" }, { diff --git a/.butcher/methods/unpinChatMessage/entity.json b/.butcher/methods/unpinChatMessage/entity.json index 90c2dc11..273ffeac 100644 --- a/.butcher/methods/unpinChatMessage/entity.json +++ b/.butcher/methods/unpinChatMessage/entity.json @@ -11,6 +11,14 @@ "html_description": "

Use this method to remove a message from the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns True on success.

", "rst_description": "Use this method to remove a message from the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns :code:`True` on success.", "annotations": [ + { + "type": "String", + "required": false, + "description": "Unique identifier of the business connection on behalf of which the message will be unpinned", + "html_description": "Unique identifier of the business connection on behalf of which the message will be unpinned", + "rst_description": "Unique identifier of the business connection on behalf of which the message will be unpinned\n", + "name": "business_connection_id" + }, { "type": "Integer or String", "required": true, @@ -22,9 +30,9 @@ { "type": "Integer", "required": false, - "description": "Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned.", - "html_description": "Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned.", - "rst_description": "Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned.\n", + "description": "Identifier of the message to unpin. Required if business_connection_id is specified. If not specified, the most recent pinned message (by sending date) will be unpinned.", + "html_description": "Identifier of the message to unpin. Required if business_connection_id is specified. If not specified, the most recent pinned message (by sending date) will be unpinned.", + "rst_description": "Identifier of the message to unpin. Required if *business_connection_id* is specified. If not specified, the most recent pinned message (by sending date) will be unpinned.\n", "name": "message_id" } ], diff --git a/.butcher/schema/schema.json b/.butcher/schema/schema.json index 9edf51c8..e076f99c 100644 --- a/.butcher/schema/schema.json +++ b/.butcher/schema/schema.json @@ -1,7 +1,7 @@ { "api": { - "version": "7.7", - "release_date": "2024-07-07" + "version": "7.8", + "release_date": "2024-07-31" }, "items": [ { @@ -528,6 +528,14 @@ "rst_description": "*Optional*. :code:`True`, if the bot can be connected to a Telegram Business account to receive its messages. Returned only in :class:`aiogram.methods.get_me.GetMe`.\n", "name": "can_connect_to_business", "required": false + }, + { + "type": "Boolean", + "description": "True, if the bot has a main Web App. Returned only in getMe.", + "html_description": "Optional. True, if the bot has a main Web App. Returned only in getMe.", + "rst_description": "*Optional*. :code:`True`, if the bot has a main Web App. Returned only in :class:`aiogram.methods.get_me.GetMe`.\n", + "name": "has_main_web_app", + "required": false } ], "category": "types" @@ -10570,6 +10578,14 @@ "html_description": "

Use this method to add a message to the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns True on success.

", "rst_description": "Use this method to add a message to the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns :code:`True` on success.", "annotations": [ + { + "type": "String", + "required": false, + "description": "Unique identifier of the business connection on behalf of which the message will be pinned", + "html_description": "Unique identifier of the business connection on behalf of which the message will be pinned", + "rst_description": "Unique identifier of the business connection on behalf of which the message will be pinned\n", + "name": "business_connection_id" + }, { "type": "Integer or String", "required": true, @@ -10604,6 +10620,14 @@ "html_description": "

Use this method to remove a message from the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns True on success.

", "rst_description": "Use this method to remove a message from the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns :code:`True` on success.", "annotations": [ + { + "type": "String", + "required": false, + "description": "Unique identifier of the business connection on behalf of which the message will be unpinned", + "html_description": "Unique identifier of the business connection on behalf of which the message will be unpinned", + "rst_description": "Unique identifier of the business connection on behalf of which the message will be unpinned\n", + "name": "business_connection_id" + }, { "type": "Integer or String", "required": true, @@ -10615,9 +10639,9 @@ { "type": "Integer", "required": false, - "description": "Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned.", - "html_description": "Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned.", - "rst_description": "Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned.\n", + "description": "Identifier of the message to unpin. Required if business_connection_id is specified. If not specified, the most recent pinned message (by sending date) will be unpinned.", + "html_description": "Identifier of the message to unpin. Required if business_connection_id is specified. If not specified, the most recent pinned message (by sending date) will be unpinned.", + "rst_description": "Identifier of the message to unpin. Required if *business_connection_id* is specified. If not specified, the most recent pinned message (by sending date) will be unpinned.\n", "name": "message_id" } ], @@ -12764,9 +12788,9 @@ { "type": "InputFile or String", "required": false, - "description": "A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.", - "html_description": "A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.", - "rst_description": "A **.WEBP** or **.PNG** image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a **.TGS** animation with a thumbnail up to 32 kilobytes in size (see `https://core.telegram.org/stickers#animated-sticker-requirements `_`https://core.telegram.org/stickers#animated-sticker-requirements `_ for animated sticker technical requirements), or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-sticker-requirements `_`https://core.telegram.org/stickers#video-sticker-requirements `_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More information on Sending Files » `. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.\n", + "description": "A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animation-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.", + "html_description": "A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animation-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.", + "rst_description": "A **.WEBP** or **.PNG** image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a **.TGS** animation with a thumbnail up to 32 kilobytes in size (see `https://core.telegram.org/stickers#animation-requirements `_`https://core.telegram.org/stickers#animation-requirements `_ for animated sticker technical requirements), or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-requirements `_`https://core.telegram.org/stickers#video-requirements `_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More information on Sending Files » `. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.\n", "name": "thumbnail" }, { @@ -17615,7 +17639,7 @@ "category": "types" } ], - "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." + "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 demonstrates 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 disable_edit_message parameter to disable automatic update of 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." } ] } diff --git a/.butcher/types/User/entity.json b/.butcher/types/User/entity.json index f502c62b..820d7563 100644 --- a/.butcher/types/User/entity.json +++ b/.butcher/types/User/entity.json @@ -106,6 +106,14 @@ "rst_description": "*Optional*. :code:`True`, if the bot can be connected to a Telegram Business account to receive its messages. Returned only in :class:`aiogram.methods.get_me.GetMe`.\n", "name": "can_connect_to_business", "required": false + }, + { + "type": "Boolean", + "description": "True, if the bot has a main Web App. Returned only in getMe.", + "html_description": "Optional. True, if the bot has a main Web App. Returned only in getMe.", + "rst_description": "*Optional*. :code:`True`, if the bot has a main Web App. Returned only in :class:`aiogram.methods.get_me.GetMe`.\n", + "name": "has_main_web_app", + "required": false } ], "category": "types" diff --git a/CHANGES/1551.feature.rst b/CHANGES/1551.feature.rst new file mode 100644 index 00000000..a7731f32 --- /dev/null +++ b/CHANGES/1551.feature.rst @@ -0,0 +1,8 @@ +Added full support of `Bot API 7.8 `_ + +- Added the field :code:`has_main_web_app` to the class :class:`aiogram.types.user.User`, + which is returned in the response to :class:`aiogram.methods.get_me.GetMe`. +- Added the parameter :code:`business_connection_id` to the methods + :class:`aiogram.methods.pin_chat_message.PinChatMessage` + and :class:`aiogram.methods.unpin_chat_message.UnpinChatMessage`, + allowing bots to manage pinned messages on behalf of a business account. diff --git a/Makefile b/Makefile index d08d0742..d079bb16 100644 --- a/Makefile +++ b/Makefile @@ -111,12 +111,12 @@ towncrier-build: .PHONY: towncrier-draft towncrier-draft: - towncrier build --draft + hatch run docs:towncrier build --draft .PHONY: towncrier-draft-github towncrier-draft-github: mkdir -p dist - towncrier build --draft | pandoc - -o dist/release.md + hatch run docs:towncrier build --draft | pandoc - -o dist/release.md .PHONY: prepare-release prepare-release: bump towncrier-build diff --git a/README.rst b/README.rst index dad0b5e2..736cbda1 100644 --- a/README.rst +++ b/README.rst @@ -52,7 +52,7 @@ Features - Asynchronous (`asyncio docs `_, :pep:`492`) - Has type hints (:pep:`484`) and can be used with `mypy `_ - Supports `PyPy `_ -- Supports `Telegram Bot API 7.7 `_ and gets fast updates to the latest versions of the Bot API +- Supports `Telegram Bot API 7.8 `_ and gets fast updates to the latest versions of the Bot API - Telegram Bot API integration code was `autogenerated `_ and can be easily re-generated when API gets updated - Updates router (Blueprints) - Has Finite State Machine diff --git a/aiogram/__meta__.py b/aiogram/__meta__.py index 869c5c7b..607a9731 100644 --- a/aiogram/__meta__.py +++ b/aiogram/__meta__.py @@ -1,2 +1,2 @@ __version__ = "3.10.0" -__api_version__ = "7.7" +__api_version__ = "7.8" diff --git a/aiogram/client/bot.py b/aiogram/client/bot.py index 0981bbf5..c51a7d62 100644 --- a/aiogram/client/bot.py +++ b/aiogram/client/bot.py @@ -2033,6 +2033,7 @@ class Bot: self, chat_id: Union[int, str], message_id: int, + business_connection_id: Optional[str] = None, disable_notification: Optional[bool] = None, request_timeout: Optional[int] = None, ) -> bool: @@ -2043,6 +2044,7 @@ class Bot: :param chat_id: Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`) :param message_id: Identifier of a message to pin + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be pinned :param disable_notification: Pass :code:`True` if it is not necessary to send a notification to all chat members about the new pinned message. Notifications are always disabled in channels and private chats. :param request_timeout: Request timeout :return: Returns :code:`True` on success. @@ -2051,6 +2053,7 @@ class Bot: call = PinChatMessage( chat_id=chat_id, message_id=message_id, + business_connection_id=business_connection_id, disable_notification=disable_notification, ) return await self(call, request_timeout=request_timeout) @@ -3934,6 +3937,7 @@ class Bot: async def unpin_chat_message( self, chat_id: Union[int, str], + business_connection_id: Optional[str] = None, message_id: Optional[int] = None, request_timeout: Optional[int] = None, ) -> bool: @@ -3943,13 +3947,15 @@ class Bot: Source: https://core.telegram.org/bots/api#unpinchatmessage :param chat_id: Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`) - :param message_id: Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned. + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be unpinned + :param message_id: Identifier of the message to unpin. Required if *business_connection_id* is specified. If not specified, the most recent pinned message (by sending date) will be unpinned. :param request_timeout: Request timeout :return: Returns :code:`True` on success. """ call = UnpinChatMessage( chat_id=chat_id, + business_connection_id=business_connection_id, message_id=message_id, ) return await self(call, request_timeout=request_timeout) @@ -4297,7 +4303,7 @@ class Bot: :param name: Sticker set name :param user_id: User identifier of the sticker set owner :param format: Format of the thumbnail, must be one of 'static' for a **.WEBP** or **.PNG** image, 'animated' for a **.TGS** animation, or 'video' for a **WEBM** video - :param thumbnail: A **.WEBP** or **.PNG** image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a **.TGS** animation with a thumbnail up to 32 kilobytes in size (see `https://core.telegram.org/stickers#animated-sticker-requirements `_`https://core.telegram.org/stickers#animated-sticker-requirements `_ for animated sticker technical requirements), or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-sticker-requirements `_`https://core.telegram.org/stickers#video-sticker-requirements `_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More information on Sending Files » `. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail. + :param thumbnail: A **.WEBP** or **.PNG** image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a **.TGS** animation with a thumbnail up to 32 kilobytes in size (see `https://core.telegram.org/stickers#animation-requirements `_`https://core.telegram.org/stickers#animation-requirements `_ for animated sticker technical requirements), or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-requirements `_`https://core.telegram.org/stickers#video-requirements `_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More information on Sending Files » `. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail. :param request_timeout: Request timeout :return: Returns :code:`True` on success. """ diff --git a/aiogram/methods/pin_chat_message.py b/aiogram/methods/pin_chat_message.py index fe99cc25..47c28f1c 100644 --- a/aiogram/methods/pin_chat_message.py +++ b/aiogram/methods/pin_chat_message.py @@ -19,6 +19,8 @@ class PinChatMessage(TelegramMethod[bool]): """Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`)""" message_id: int """Identifier of a message to pin""" + business_connection_id: Optional[str] = None + """Unique identifier of the business connection on behalf of which the message will be pinned""" disable_notification: Optional[bool] = None """Pass :code:`True` if it is not necessary to send a notification to all chat members about the new pinned message. Notifications are always disabled in channels and private chats.""" @@ -31,6 +33,7 @@ class PinChatMessage(TelegramMethod[bool]): *, chat_id: Union[int, str], message_id: int, + business_connection_id: Optional[str] = None, disable_notification: Optional[bool] = None, **__pydantic_kwargs: Any, ) -> None: @@ -41,6 +44,7 @@ class PinChatMessage(TelegramMethod[bool]): super().__init__( chat_id=chat_id, message_id=message_id, + business_connection_id=business_connection_id, disable_notification=disable_notification, **__pydantic_kwargs, ) diff --git a/aiogram/methods/set_sticker_set_thumbnail.py b/aiogram/methods/set_sticker_set_thumbnail.py index 38492f37..ef83f701 100644 --- a/aiogram/methods/set_sticker_set_thumbnail.py +++ b/aiogram/methods/set_sticker_set_thumbnail.py @@ -23,7 +23,7 @@ class SetStickerSetThumbnail(TelegramMethod[bool]): format: str """Format of the thumbnail, must be one of 'static' for a **.WEBP** or **.PNG** image, 'animated' for a **.TGS** animation, or 'video' for a **WEBM** video""" thumbnail: Optional[Union[InputFile, str]] = None - """A **.WEBP** or **.PNG** image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a **.TGS** animation with a thumbnail up to 32 kilobytes in size (see `https://core.telegram.org/stickers#animated-sticker-requirements `_`https://core.telegram.org/stickers#animated-sticker-requirements `_ for animated sticker technical requirements), or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-sticker-requirements `_`https://core.telegram.org/stickers#video-sticker-requirements `_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More information on Sending Files » `. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.""" + """A **.WEBP** or **.PNG** image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a **.TGS** animation with a thumbnail up to 32 kilobytes in size (see `https://core.telegram.org/stickers#animation-requirements `_`https://core.telegram.org/stickers#animation-requirements `_ for animated sticker technical requirements), or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-requirements `_`https://core.telegram.org/stickers#video-requirements `_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More information on Sending Files » `. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.""" if TYPE_CHECKING: # DO NOT EDIT MANUALLY!!! diff --git a/aiogram/methods/unpin_chat_message.py b/aiogram/methods/unpin_chat_message.py index 90547140..249aee6d 100644 --- a/aiogram/methods/unpin_chat_message.py +++ b/aiogram/methods/unpin_chat_message.py @@ -17,8 +17,10 @@ class UnpinChatMessage(TelegramMethod[bool]): chat_id: Union[int, str] """Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`)""" + business_connection_id: Optional[str] = None + """Unique identifier of the business connection on behalf of which the message will be unpinned""" message_id: Optional[int] = None - """Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned.""" + """Identifier of the message to unpin. Required if *business_connection_id* is specified. If not specified, the most recent pinned message (by sending date) will be unpinned.""" if TYPE_CHECKING: # DO NOT EDIT MANUALLY!!! @@ -28,6 +30,7 @@ class UnpinChatMessage(TelegramMethod[bool]): __pydantic__self__, *, chat_id: Union[int, str], + business_connection_id: Optional[str] = None, message_id: Optional[int] = None, **__pydantic_kwargs: Any, ) -> None: @@ -35,4 +38,9 @@ class UnpinChatMessage(TelegramMethod[bool]): # 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, message_id=message_id, **__pydantic_kwargs) + super().__init__( + chat_id=chat_id, + business_connection_id=business_connection_id, + message_id=message_id, + **__pydantic_kwargs, + ) diff --git a/aiogram/types/chat.py b/aiogram/types/chat.py index f44b01bf..278b656c 100644 --- a/aiogram/types/chat.py +++ b/aiogram/types/chat.py @@ -871,6 +871,7 @@ class Chat(TelegramObject): def unpin_message( self, + business_connection_id: Optional[str] = None, message_id: Optional[int] = None, **kwargs: Any, ) -> UnpinChatMessage: @@ -884,7 +885,8 @@ class Chat(TelegramObject): Source: https://core.telegram.org/bots/api#unpinchatmessage - :param message_id: Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned. + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be unpinned + :param message_id: Identifier of the message to unpin. Required if *business_connection_id* is specified. If not specified, the most recent pinned message (by sending date) will be unpinned. :return: instance of method :class:`aiogram.methods.unpin_chat_message.UnpinChatMessage` """ # DO NOT EDIT MANUALLY!!! @@ -894,6 +896,7 @@ class Chat(TelegramObject): return UnpinChatMessage( chat_id=self.id, + business_connection_id=business_connection_id, message_id=message_id, **kwargs, ).as_(self._bot) @@ -901,6 +904,7 @@ class Chat(TelegramObject): def pin_message( self, message_id: int, + business_connection_id: Optional[str] = None, disable_notification: Optional[bool] = None, **kwargs: Any, ) -> PinChatMessage: @@ -915,6 +919,7 @@ class Chat(TelegramObject): Source: https://core.telegram.org/bots/api#pinchatmessage :param message_id: Identifier of a message to pin + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be pinned :param disable_notification: Pass :code:`True` if it is not necessary to send a notification to all chat members about the new pinned message. Notifications are always disabled in channels and private chats. :return: instance of method :class:`aiogram.methods.pin_chat_message.PinChatMessage` """ @@ -926,6 +931,7 @@ class Chat(TelegramObject): return PinChatMessage( chat_id=self.id, message_id=message_id, + business_connection_id=business_connection_id, disable_notification=disable_notification, **kwargs, ).as_(self._bot) diff --git a/aiogram/types/message.py b/aiogram/types/message.py index 652c3e3c..d04f3317 100644 --- a/aiogram/types/message.py +++ b/aiogram/types/message.py @@ -3956,6 +3956,7 @@ class Message(MaybeInaccessibleMessage): def pin( self, + business_connection_id: Optional[str] = None, disable_notification: Optional[bool] = None, **kwargs: Any, ) -> PinChatMessage: @@ -3970,6 +3971,7 @@ class Message(MaybeInaccessibleMessage): Source: https://core.telegram.org/bots/api#pinchatmessage + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be pinned :param disable_notification: Pass :code:`True` if it is not necessary to send a notification to all chat members about the new pinned message. Notifications are always disabled in channels and private chats. :return: instance of method :class:`aiogram.methods.pin_chat_message.PinChatMessage` """ @@ -3985,12 +3987,14 @@ class Message(MaybeInaccessibleMessage): return PinChatMessage( chat_id=self.chat.id, message_id=self.message_id, + business_connection_id=business_connection_id, disable_notification=disable_notification, **kwargs, ).as_(self._bot) def unpin( self, + business_connection_id: Optional[str] = None, **kwargs: Any, ) -> UnpinChatMessage: """ @@ -4004,6 +4008,7 @@ class Message(MaybeInaccessibleMessage): Source: https://core.telegram.org/bots/api#unpinchatmessage + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be unpinned :return: instance of method :class:`aiogram.methods.unpin_chat_message.UnpinChatMessage` """ # DO NOT EDIT MANUALLY!!! @@ -4018,6 +4023,7 @@ class Message(MaybeInaccessibleMessage): return UnpinChatMessage( chat_id=self.chat.id, message_id=self.message_id, + business_connection_id=business_connection_id, **kwargs, ).as_(self._bot) diff --git a/aiogram/types/user.py b/aiogram/types/user.py index 7236effc..56782f2f 100644 --- a/aiogram/types/user.py +++ b/aiogram/types/user.py @@ -41,6 +41,8 @@ class User(TelegramObject): """*Optional*. :code:`True`, if the bot supports inline queries. Returned only in :class:`aiogram.methods.get_me.GetMe`.""" can_connect_to_business: Optional[bool] = None """*Optional*. :code:`True`, if the bot can be connected to a Telegram Business account to receive its messages. Returned only in :class:`aiogram.methods.get_me.GetMe`.""" + has_main_web_app: Optional[bool] = None + """*Optional*. :code:`True`, if the bot has a main Web App. Returned only in :class:`aiogram.methods.get_me.GetMe`.""" if TYPE_CHECKING: # DO NOT EDIT MANUALLY!!! @@ -61,6 +63,7 @@ class User(TelegramObject): can_read_all_group_messages: Optional[bool] = None, supports_inline_queries: Optional[bool] = None, can_connect_to_business: Optional[bool] = None, + has_main_web_app: Optional[bool] = None, **__pydantic_kwargs: Any, ) -> None: # DO NOT EDIT MANUALLY!!! @@ -80,6 +83,7 @@ class User(TelegramObject): can_read_all_group_messages=can_read_all_group_messages, supports_inline_queries=supports_inline_queries, can_connect_to_business=can_connect_to_business, + has_main_web_app=has_main_web_app, **__pydantic_kwargs, ) diff --git a/docs/api/methods/send_paid_media.rst b/docs/api/methods/send_paid_media.rst index 1916511d..ada3f2bb 100644 --- a/docs/api/methods/send_paid_media.rst +++ b/docs/api/methods/send_paid_media.rst @@ -49,3 +49,4 @@ As shortcut from received object -------------------------------- - :meth:`aiogram.types.message.Message.answer_paid_media` +- :meth:`aiogram.types.message.Message.reply_paid_media` 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/conftest.py b/tests/conftest.py index 497dd50f..fe5c3d22 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,5 @@ +import asyncio +import sys from pathlib import Path import pytest @@ -36,6 +38,11 @@ def pytest_configure(config): config.addinivalue_line("markers", "redis: marked tests require redis connection to run") config.addinivalue_line("markers", "mongo: marked tests require mongo connection to run") + if sys.platform == "win32": + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + else: + asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy()) + @pytest.fixture() def redis_server(request): @@ -47,7 +54,6 @@ def redis_server(request): @pytest.fixture() -@pytest.mark.redis async def redis_storage(redis_server): try: parse_redis_url(redis_server) @@ -76,7 +82,6 @@ def mongo_server(request): @pytest.fixture() -@pytest.mark.mongo async def mongo_storage(mongo_server): try: parse_mongo_url(mongo_server) @@ -107,7 +112,6 @@ async def memory_storage(): @pytest.fixture() -@pytest.mark.redis async def redis_isolation(redis_storage): isolation = redis_storage.create_isolation() return isolation @@ -149,3 +153,10 @@ async def dispatcher(): yield dp finally: await dp.emit_shutdown() + + +# @pytest.fixture(scope="session") +# def event_loop_policy(request): +# if sys.platform == "win32": +# return asyncio.WindowsSelectorEventLoopPolicy() +# return asyncio.DefaultEventLoopPolicy()