diff --git a/Makefile b/Makefile
index c4570330..d4007f91 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,8 @@ base_python := python3
py := poetry run
python := $(py) python
+reports_dir := reports
+
.PHONY: help
help:
@echo "======================================================================================="
@@ -79,8 +81,8 @@ flake8:
.PHONY: flake8-report
flake8-report:
- mkdir -p reports/flake8
- $(py) flake8 --format=html --htmldir=reports/flake8 aiogram test
+ mkdir -p $(reports_dir)/flake8
+ $(py) flake8 --format=html --htmldir=$(reports_dir)/flake8 aiogram test
.PHONY: mypy
mypy:
@@ -88,7 +90,7 @@ mypy:
.PHONY: mypy-report
mypy-report:
- $(py) mypy aiogram tests --html-report reports/typechecking
+ $(py) mypy aiogram tests --html-report $(reports_dir)/typechecking
.PHONY: lint
lint: isort black flake8 mypy
@@ -99,13 +101,13 @@ lint: isort black flake8 mypy
.PHONY: test
test:
- $(py) pytest --cov=aiogram --cov-config .coveragerc -p no:warnings tests/
+ $(py) pytest --cov=aiogram --cov-config .coveragerc tests/
.PHONY: test-coverage
test-coverage:
- mkdir -p reports/tests/
- $(py) pytest --cov=aiogram --cov-config .coveragerc --html=reports/tests/index.html -p no:warnings tests/
- $(py) coverage html -d reports/coverage
+ mkdir -p $(reports_dir)/tests/
+ $(py) pytest --cov=aiogram --cov-config .coveragerc --html=$(reports_dir)/tests/index.html tests/
+ $(py) coverage html -d $(reports_dir)/coverage
# =================================================================================================
# Docs
@@ -121,7 +123,7 @@ docs-serve:
.PHONY: docs-copy-reports
docs-copy-reports:
- mv reports/* site/reports
+ mv $(reports_dir)/* site/reports
# =================================================================================================
@@ -129,7 +131,7 @@ docs-copy-reports:
# =================================================================================================
.PHONY: build
-build: clean tests test-coverage flake8-report mypy-report docs docs-copy-reports
+build: clean flake8-report mypy-report test-coverage docs docs-copy-reports
mkdir -p site/simple
poetry build
mv dist site/simple/aiogram
diff --git a/README.md b/README.md
index 8766e027..b1ca77ae 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
[](https://opensource.org/licenses/MIT)
[](https://pypi.python.org/pypi/aiogram)
-[](https://core.telegram.org/bots/api)
+[](https://core.telegram.org/bots/api)
[](https://pypi.python.org/pypi/aiogram)
[](https://pypi.python.org/pypi/aiogram)
[](https://pypi.python.org/pypi/aiogram)
diff --git a/aiogram/__init__.py b/aiogram/__init__.py
index 9af0a993..8a568996 100644
--- a/aiogram/__init__.py
+++ b/aiogram/__init__.py
@@ -26,5 +26,5 @@ __all__ = (
"handler",
)
-__version__ = "3.0.0a0"
-__api_version__ = "4.4"
+__version__ = "3.0.0a1"
+__api_version__ = "4.5"
diff --git a/aiogram/api/client/base.py b/aiogram/api/client/base.py
index 156125e7..4d8b7453 100644
--- a/aiogram/api/client/base.py
+++ b/aiogram/api/client/base.py
@@ -38,7 +38,7 @@ class BaseBot(ContextInstanceMixin, DataMixin):
"""
return extract_bot_id(self.__token)
- async def emit(self, method: TelegramMethod[T]) -> T:
+ async def __call__(self, method: TelegramMethod[T]) -> T:
"""
Call API method
diff --git a/aiogram/api/client/bot.py b/aiogram/api/client/bot.py
index 06d1af05..95dab879 100644
--- a/aiogram/api/client/bot.py
+++ b/aiogram/api/client/bot.py
@@ -55,6 +55,7 @@ from ..methods import (
SendVideo,
SendVideoNote,
SendVoice,
+ SetChatAdministratorCustomTitle,
SetChatDescription,
SetChatPermissions,
SetChatPhoto,
@@ -154,7 +155,7 @@ class Bot(BaseBot):
call = GetUpdates(
offset=offset, limit=limit, timeout=timeout, allowed_updates=allowed_updates
)
- return await self.emit(call)
+ return await self(call)
async def set_webhook(
self,
@@ -204,7 +205,7 @@ class Bot(BaseBot):
max_connections=max_connections,
allowed_updates=allowed_updates,
)
- return await self.emit(call)
+ return await self(call)
async def delete_webhook(self,) -> bool:
"""
@@ -216,7 +217,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = DeleteWebhook()
- return await self.emit(call)
+ return await self(call)
async def get_webhook_info(self,) -> WebhookInfo:
"""
@@ -230,7 +231,7 @@ class Bot(BaseBot):
return an object with the url field empty.
"""
call = GetWebhookInfo()
- return await self.emit(call)
+ return await self(call)
# =============================================================================================
# Group: Available methods
@@ -247,7 +248,7 @@ class Bot(BaseBot):
:return: Returns basic information about the bot in form of a User object.
"""
call = GetMe()
- return await self.emit(call)
+ return await self(call)
async def send_message(
self,
@@ -289,7 +290,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def forward_message(
self,
@@ -318,7 +319,7 @@ class Bot(BaseBot):
message_id=message_id,
disable_notification=disable_notification,
)
- return await self.emit(call)
+ return await self(call)
async def send_photo(
self,
@@ -364,7 +365,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_audio(
self,
@@ -431,7 +432,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_document(
self,
@@ -488,7 +489,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_video(
self,
@@ -557,7 +558,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_animation(
self,
@@ -623,7 +624,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_voice(
self,
@@ -675,7 +676,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_video_note(
self,
@@ -729,7 +730,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_media_group(
self,
@@ -759,7 +760,7 @@ class Bot(BaseBot):
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
)
- return await self.emit(call)
+ return await self(call)
async def send_location(
self,
@@ -801,7 +802,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def edit_message_live_location(
self,
@@ -841,7 +842,7 @@ class Bot(BaseBot):
inline_message_id=inline_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def stop_message_live_location(
self,
@@ -874,7 +875,7 @@ class Bot(BaseBot):
inline_message_id=inline_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_venue(
self,
@@ -927,7 +928,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_contact(
self,
@@ -971,7 +972,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_poll(
self,
@@ -1011,7 +1012,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def send_chat_action(self, chat_id: Union[int, str], action: str) -> bool:
"""
@@ -1037,7 +1038,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = SendChatAction(chat_id=chat_id, action=action)
- return await self.emit(call)
+ return await self(call)
async def get_user_profile_photos(
self, user_id: int, offset: Optional[int] = None, limit: Optional[int] = None
@@ -1056,7 +1057,7 @@ class Bot(BaseBot):
:return: Returns a UserProfilePhotos object.
"""
call = GetUserProfilePhotos(user_id=user_id, offset=offset, limit=limit)
- return await self.emit(call)
+ return await self(call)
async def get_file(self, file_id: str) -> File:
"""
@@ -1075,7 +1076,7 @@ class Bot(BaseBot):
:return: On success, a File object is returned.
"""
call = GetFile(file_id=file_id)
- return await self.emit(call)
+ return await self(call)
async def kick_chat_member(
self,
@@ -1101,7 +1102,7 @@ class Bot(BaseBot):
the group on their own using invite links, etc. Returns True on success.
"""
call = KickChatMember(chat_id=chat_id, user_id=user_id, until_date=until_date)
- return await self.emit(call)
+ return await self(call)
async def unban_chat_member(self, chat_id: Union[int, str], user_id: int) -> bool:
"""
@@ -1118,7 +1119,7 @@ class Bot(BaseBot):
to join via link, etc. Returns True on success.
"""
call = UnbanChatMember(chat_id=chat_id, user_id=user_id)
- return await self.emit(call)
+ return await self(call)
async def restrict_chat_member(
self,
@@ -1146,7 +1147,7 @@ class Bot(BaseBot):
call = RestrictChatMember(
chat_id=chat_id, user_id=user_id, permissions=permissions, until_date=until_date
)
- return await self.emit(call)
+ return await self(call)
async def promote_chat_member(
self,
@@ -1202,7 +1203,28 @@ class Bot(BaseBot):
can_pin_messages=can_pin_messages,
can_promote_members=can_promote_members,
)
- return await self.emit(call)
+ return await self(call)
+
+ async def set_chat_administrator_custom_title(
+ self, chat_id: Union[int, str], user_id: int, custom_title: str
+ ) -> bool:
+ """
+ Use this method to set a custom title for an administrator in a supergroup promoted by the
+ bot. Returns True on success.
+
+ Source: https://core.telegram.org/bots/api#setchatadministratorcustomtitle
+
+ :param chat_id: Unique identifier for the target chat or username of the target supergroup
+ (in the format @supergroupusername)
+ :param user_id: Unique identifier of the target user
+ :param custom_title: New custom title for the administrator; 0-16 characters, emoji are
+ not allowed
+ :return: Returns True on success.
+ """
+ call = SetChatAdministratorCustomTitle(
+ chat_id=chat_id, user_id=user_id, custom_title=custom_title
+ )
+ return await self(call)
async def set_chat_permissions(
self, chat_id: Union[int, str], permissions: ChatPermissions
@@ -1220,7 +1242,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = SetChatPermissions(chat_id=chat_id, permissions=permissions)
- return await self.emit(call)
+ return await self(call)
async def export_chat_invite_link(self, chat_id: Union[int, str]) -> str:
"""
@@ -1240,7 +1262,7 @@ class Bot(BaseBot):
:return: Returns the new invite link as String on success.
"""
call = ExportChatInviteLink(chat_id=chat_id)
- return await self.emit(call)
+ return await self(call)
async def set_chat_photo(self, chat_id: Union[int, str], photo: InputFile) -> bool:
"""
@@ -1256,7 +1278,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = SetChatPhoto(chat_id=chat_id, photo=photo)
- return await self.emit(call)
+ return await self(call)
async def delete_chat_photo(self, chat_id: Union[int, str]) -> bool:
"""
@@ -1271,7 +1293,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = DeleteChatPhoto(chat_id=chat_id)
- return await self.emit(call)
+ return await self(call)
async def set_chat_title(self, chat_id: Union[int, str], title: str) -> bool:
"""
@@ -1287,7 +1309,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = SetChatTitle(chat_id=chat_id, title=title)
- return await self.emit(call)
+ return await self(call)
async def set_chat_description(
self, chat_id: Union[int, str], description: Optional[str] = None
@@ -1305,7 +1327,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = SetChatDescription(chat_id=chat_id, description=description)
- return await self.emit(call)
+ return await self(call)
async def pin_chat_message(
self,
@@ -1332,7 +1354,7 @@ class Bot(BaseBot):
call = PinChatMessage(
chat_id=chat_id, message_id=message_id, disable_notification=disable_notification
)
- return await self.emit(call)
+ return await self(call)
async def unpin_chat_message(self, chat_id: Union[int, str]) -> bool:
"""
@@ -1348,7 +1370,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = UnpinChatMessage(chat_id=chat_id)
- return await self.emit(call)
+ return await self(call)
async def leave_chat(self, chat_id: Union[int, str]) -> bool:
"""
@@ -1362,7 +1384,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = LeaveChat(chat_id=chat_id)
- return await self.emit(call)
+ return await self(call)
async def get_chat(self, chat_id: Union[int, str]) -> Chat:
"""
@@ -1377,7 +1399,7 @@ class Bot(BaseBot):
:return: Returns a Chat object on success.
"""
call = GetChat(chat_id=chat_id)
- return await self.emit(call)
+ return await self(call)
async def get_chat_administrators(self, chat_id: Union[int, str]) -> List[ChatMember]:
"""
@@ -1396,7 +1418,7 @@ class Bot(BaseBot):
returned.
"""
call = GetChatAdministrators(chat_id=chat_id)
- return await self.emit(call)
+ return await self(call)
async def get_chat_members_count(self, chat_id: Union[int, str]) -> int:
"""
@@ -1409,7 +1431,7 @@ class Bot(BaseBot):
:return: Returns Int on success.
"""
call = GetChatMembersCount(chat_id=chat_id)
- return await self.emit(call)
+ return await self(call)
async def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> ChatMember:
"""
@@ -1424,7 +1446,7 @@ class Bot(BaseBot):
:return: Returns a ChatMember object on success.
"""
call = GetChatMember(chat_id=chat_id, user_id=user_id)
- return await self.emit(call)
+ return await self(call)
async def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: str) -> bool:
"""
@@ -1442,7 +1464,7 @@ class Bot(BaseBot):
check if the bot can use this method. Returns True on success.
"""
call = SetChatStickerSet(chat_id=chat_id, sticker_set_name=sticker_set_name)
- return await self.emit(call)
+ return await self(call)
async def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool:
"""
@@ -1459,7 +1481,7 @@ class Bot(BaseBot):
check if the bot can use this method. Returns True on success.
"""
call = DeleteChatStickerSet(chat_id=chat_id)
- return await self.emit(call)
+ return await self(call)
async def answer_callback_query(
self,
@@ -1500,7 +1522,7 @@ class Bot(BaseBot):
url=url,
cache_time=cache_time,
)
- return await self.emit(call)
+ return await self(call)
# =============================================================================================
# Group: Updating messages
@@ -1547,7 +1569,7 @@ class Bot(BaseBot):
disable_web_page_preview=disable_web_page_preview,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def edit_message_caption(
self,
@@ -1586,7 +1608,7 @@ class Bot(BaseBot):
parse_mode=parse_mode,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def edit_message_media(
self,
@@ -1625,7 +1647,7 @@ class Bot(BaseBot):
inline_message_id=inline_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def edit_message_reply_markup(
self,
@@ -1657,7 +1679,7 @@ class Bot(BaseBot):
inline_message_id=inline_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def stop_poll(
self,
@@ -1678,7 +1700,7 @@ class Bot(BaseBot):
:return: On success, the stopped Poll with the final results is returned.
"""
call = StopPoll(chat_id=chat_id, message_id=message_id, reply_markup=reply_markup)
- return await self.emit(call)
+ return await self(call)
async def delete_message(self, chat_id: Union[int, str], message_id: int) -> bool:
"""
@@ -1701,7 +1723,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = DeleteMessage(chat_id=chat_id, message_id=message_id)
- return await self.emit(call)
+ return await self(call)
# =============================================================================================
# Group: Stickers
@@ -1745,7 +1767,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def get_sticker_set(self, name: str) -> StickerSet:
"""
@@ -1757,7 +1779,7 @@ class Bot(BaseBot):
:return: On success, a StickerSet object is returned.
"""
call = GetStickerSet(name=name)
- return await self.emit(call)
+ return await self(call)
async def upload_sticker_file(self, user_id: int, png_sticker: InputFile) -> File:
"""
@@ -1774,7 +1796,7 @@ class Bot(BaseBot):
:return: Returns the uploaded File on success.
"""
call = UploadStickerFile(user_id=user_id, png_sticker=png_sticker)
- return await self.emit(call)
+ return await self(call)
async def create_new_sticker_set(
self,
@@ -1819,7 +1841,7 @@ class Bot(BaseBot):
contains_masks=contains_masks,
mask_position=mask_position,
)
- return await self.emit(call)
+ return await self(call)
async def add_sticker_to_set(
self,
@@ -1854,7 +1876,7 @@ class Bot(BaseBot):
emojis=emojis,
mask_position=mask_position,
)
- return await self.emit(call)
+ return await self(call)
async def set_sticker_position_in_set(self, sticker: str, position: int) -> bool:
"""
@@ -1868,7 +1890,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = SetStickerPositionInSet(sticker=sticker, position=position)
- return await self.emit(call)
+ return await self(call)
async def delete_sticker_from_set(self, sticker: str) -> bool:
"""
@@ -1881,7 +1903,7 @@ class Bot(BaseBot):
:return: Returns True on success.
"""
call = DeleteStickerFromSet(sticker=sticker)
- return await self.emit(call)
+ return await self(call)
# =============================================================================================
# Group: Inline mode
@@ -1932,7 +1954,7 @@ class Bot(BaseBot):
switch_pm_text=switch_pm_text,
switch_pm_parameter=switch_pm_parameter,
)
- return await self.emit(call)
+ return await self(call)
# =============================================================================================
# Group: Payments
@@ -2035,7 +2057,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def answer_shipping_query(
self,
@@ -2069,7 +2091,7 @@ class Bot(BaseBot):
shipping_options=shipping_options,
error_message=error_message,
)
- return await self.emit(call)
+ return await self(call)
async def answer_pre_checkout_query(
self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str] = None
@@ -2096,7 +2118,7 @@ class Bot(BaseBot):
call = AnswerPreCheckoutQuery(
pre_checkout_query_id=pre_checkout_query_id, ok=ok, error_message=error_message
)
- return await self.emit(call)
+ return await self(call)
# =============================================================================================
# Group: Telegram Passport
@@ -2125,7 +2147,7 @@ class Bot(BaseBot):
Returns True on success.
"""
call = SetPassportDataErrors(user_id=user_id, errors=errors)
- return await self.emit(call)
+ return await self(call)
# =============================================================================================
# Group: Games
@@ -2163,7 +2185,7 @@ class Bot(BaseBot):
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
)
- return await self.emit(call)
+ return await self(call)
async def set_game_score(
self,
@@ -2208,7 +2230,7 @@ class Bot(BaseBot):
message_id=message_id,
inline_message_id=inline_message_id,
)
- return await self.emit(call)
+ return await self(call)
async def get_game_high_scores(
self,
@@ -2246,4 +2268,4 @@ class Bot(BaseBot):
message_id=message_id,
inline_message_id=inline_message_id,
)
- return await self.emit(call)
+ return await self(call)
diff --git a/aiogram/api/methods/__init__.py b/aiogram/api/methods/__init__.py
index 39095df7..b1a1344e 100644
--- a/aiogram/api/methods/__init__.py
+++ b/aiogram/api/methods/__init__.py
@@ -50,6 +50,7 @@ from .send_venue import SendVenue
from .send_video import SendVideo
from .send_video_note import SendVideoNote
from .send_voice import SendVoice
+from .set_chat_administrator_custom_title import SetChatAdministratorCustomTitle
from .set_chat_description import SetChatDescription
from .set_chat_permissions import SetChatPermissions
from .set_chat_photo import SetChatPhoto
@@ -97,6 +98,7 @@ __all__ = (
"UnbanChatMember",
"RestrictChatMember",
"PromoteChatMember",
+ "SetChatAdministratorCustomTitle",
"SetChatPermissions",
"ExportChatInviteLink",
"SetChatPhoto",
diff --git a/aiogram/api/methods/base.py b/aiogram/api/methods/base.py
index ec4fc9f1..d1a7078e 100644
--- a/aiogram/api/methods/base.py
+++ b/aiogram/api/methods/base.py
@@ -54,7 +54,7 @@ class TelegramMethod(abc.ABC, BaseModel, Generic[T]):
return Response[self.__returning__](**data) # type: ignore
async def emit(self, bot: Bot) -> T:
- return await bot.emit(self)
+ return await bot(self)
def __await__(self):
from aiogram.api.client.bot import Bot
diff --git a/aiogram/api/methods/set_chat_administrator_custom_title.py b/aiogram/api/methods/set_chat_administrator_custom_title.py
new file mode 100644
index 00000000..a153212a
--- /dev/null
+++ b/aiogram/api/methods/set_chat_administrator_custom_title.py
@@ -0,0 +1,27 @@
+from typing import Any, Dict, Union
+
+from .base import Request, TelegramMethod
+
+
+class SetChatAdministratorCustomTitle(TelegramMethod[bool]):
+ """
+ Use this method to set a custom title for an administrator in a supergroup promoted by the
+ bot. Returns True on success.
+
+ Source: https://core.telegram.org/bots/api#setchatadministratorcustomtitle
+ """
+
+ __returning__ = bool
+
+ chat_id: Union[int, str]
+ """Unique identifier for the target chat or username of the target supergroup (in the format
+ @supergroupusername)"""
+ user_id: int
+ """Unique identifier of the target user"""
+ custom_title: str
+ """New custom title for the administrator; 0-16 characters, emoji are not allowed"""
+
+ def build_request(self) -> Request:
+ data: Dict[str, Any] = self.dict()
+
+ return Request(method="setChatAdministratorCustomTitle", data=data)
diff --git a/aiogram/api/types/animation.py b/aiogram/api/types/animation.py
index 9f9c8db4..ffa3141b 100644
--- a/aiogram/api/types/animation.py
+++ b/aiogram/api/types/animation.py
@@ -16,7 +16,10 @@ class Animation(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
width: int
"""Video width as defined by sender"""
height: int
diff --git a/aiogram/api/types/audio.py b/aiogram/api/types/audio.py
index ce690e9b..4b496d06 100644
--- a/aiogram/api/types/audio.py
+++ b/aiogram/api/types/audio.py
@@ -16,7 +16,10 @@ class Audio(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
duration: int
"""Duration of the audio in seconds as defined by sender"""
performer: Optional[str] = None
diff --git a/aiogram/api/types/chat.py b/aiogram/api/types/chat.py
index 23b79f31..f56cc9df 100644
--- a/aiogram/api/types/chat.py
+++ b/aiogram/api/types/chat.py
@@ -5,8 +5,8 @@ from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING: # pragma: no cover
- from .chat_photo import ChatPhoto
from .message import Message
+ from .chat_photo import ChatPhoto
from .chat_permissions import ChatPermissions
@@ -44,6 +44,9 @@ class Chat(TelegramObject):
"""Pinned message, for groups, supergroups and channels. Returned only in getChat."""
permissions: Optional[ChatPermissions] = None
"""Default chat member permissions, for groups and supergroups. Returned only in getChat."""
+ slow_mode_delay: Optional[int] = None
+ """For supergroups, the minimum allowed delay between consecutive messages sent by each
+ unpriviledged user. Returned only in getChat."""
sticker_set_name: Optional[str] = None
"""For supergroups, name of group sticker set. Returned only in getChat."""
can_set_sticker_set: Optional[bool] = None
diff --git a/aiogram/api/types/chat_member.py b/aiogram/api/types/chat_member.py
index b7662e5a..2708b073 100644
--- a/aiogram/api/types/chat_member.py
+++ b/aiogram/api/types/chat_member.py
@@ -21,6 +21,8 @@ class ChatMember(TelegramObject):
status: str
"""The member's status in the chat. Can be 'creator', 'administrator', 'member', 'restricted',
'left' or 'kicked'"""
+ custom_title: Optional[str] = None
+ """Owner and administrators only. Custom title for this user"""
until_date: Optional[Union[int, datetime.datetime, datetime.timedelta]] = None
"""Restricted and kicked only. Date when restrictions will be lifted for this user; unix time"""
can_be_edited: Optional[bool] = None
diff --git a/aiogram/api/types/chat_photo.py b/aiogram/api/types/chat_photo.py
index 87429764..9fd53d32 100644
--- a/aiogram/api/types/chat_photo.py
+++ b/aiogram/api/types/chat_photo.py
@@ -13,6 +13,12 @@ class ChatPhoto(TelegramObject):
small_file_id: str
"""File identifier of small (160x160) chat photo. This file_id can be used only for photo
download and only for as long as the photo is not changed."""
+ small_file_unique_id: str
+ """Unique file identifier of small (160x160) chat photo, which is supposed to be the same over
+ time and for different bots. Can't be used to download or reuse the file."""
big_file_id: str
"""File identifier of big (640x640) chat photo. This file_id can be used only for photo
download and only for as long as the photo is not changed."""
+ big_file_unique_id: str
+ """Unique file identifier of big (640x640) chat photo, which is supposed to be the same over
+ time and for different bots. Can't be used to download or reuse the file."""
diff --git a/aiogram/api/types/document.py b/aiogram/api/types/document.py
index 39ed3552..7939cd9a 100644
--- a/aiogram/api/types/document.py
+++ b/aiogram/api/types/document.py
@@ -16,7 +16,10 @@ class Document(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
thumb: Optional[PhotoSize] = None
"""Document thumbnail as defined by sender"""
file_name: Optional[str] = None
diff --git a/aiogram/api/types/file.py b/aiogram/api/types/file.py
index 25551a8c..f914fe00 100644
--- a/aiogram/api/types/file.py
+++ b/aiogram/api/types/file.py
@@ -17,7 +17,10 @@ class File(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
file_size: Optional[int] = None
"""File size, if known"""
file_path: Optional[str] = None
diff --git a/aiogram/api/types/message_entity.py b/aiogram/api/types/message_entity.py
index b8166b3f..a08e4306 100644
--- a/aiogram/api/types/message_entity.py
+++ b/aiogram/api/types/message_entity.py
@@ -17,10 +17,12 @@ class MessageEntity(TelegramObject):
"""
type: str
- """Type of the entity. Can be mention (@username), hashtag, cashtag, bot_command, url, email,
- phone_number, bold (bold text), italic (italic text), code (monowidth string), pre
- (monowidth block), text_link (for clickable text URLs), text_mention (for users without
- usernames)"""
+ """Type of the entity. Can be 'mention' (@username), 'hashtag' (#hashtag), 'cashtag' ($USD),
+ 'bot_command' (/start@jobs_bot), 'url' (https://telegram.org), 'email'
+ (do-not-reply@telegram.org), 'phone_number' (+1-212-555-0123), 'bold' (bold text), 'italic'
+ (italic text), 'underline' (underlined text), 'strikethrough' (strikethrough text), 'code'
+ (monowidth string), 'pre' (monowidth block), 'text_link' (for clickable text URLs),
+ 'text_mention' (for users without usernames)"""
offset: int
"""Offset in UTF-16 code units to the start of the entity"""
length: int
diff --git a/aiogram/api/types/passport_file.py b/aiogram/api/types/passport_file.py
index ed02e7e1..9b7185f2 100644
--- a/aiogram/api/types/passport_file.py
+++ b/aiogram/api/types/passport_file.py
@@ -12,7 +12,10 @@ class PassportFile(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
file_size: int
"""File size"""
file_date: int
diff --git a/aiogram/api/types/photo_size.py b/aiogram/api/types/photo_size.py
index e0d18ac9..7aeb89fd 100644
--- a/aiogram/api/types/photo_size.py
+++ b/aiogram/api/types/photo_size.py
@@ -13,7 +13,10 @@ class PhotoSize(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
width: int
"""Photo width"""
height: int
diff --git a/aiogram/api/types/shipping_query.py b/aiogram/api/types/shipping_query.py
index 8129e1a4..a219be7c 100644
--- a/aiogram/api/types/shipping_query.py
+++ b/aiogram/api/types/shipping_query.py
@@ -7,8 +7,8 @@ from pydantic import Field
from .base import TelegramObject
if TYPE_CHECKING: # pragma: no cover
- from .user import User
from .shipping_address import ShippingAddress
+ from .user import User
class ShippingQuery(TelegramObject):
diff --git a/aiogram/api/types/sticker.py b/aiogram/api/types/sticker.py
index 1eb98599..1743de6b 100644
--- a/aiogram/api/types/sticker.py
+++ b/aiogram/api/types/sticker.py
@@ -5,8 +5,8 @@ from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING: # pragma: no cover
- from .photo_size import PhotoSize
from .mask_position import MaskPosition
+ from .photo_size import PhotoSize
class Sticker(TelegramObject):
@@ -17,7 +17,10 @@ class Sticker(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
width: int
"""Sticker width"""
height: int
diff --git a/aiogram/api/types/video.py b/aiogram/api/types/video.py
index acd3a303..647333b5 100644
--- a/aiogram/api/types/video.py
+++ b/aiogram/api/types/video.py
@@ -16,7 +16,10 @@ class Video(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
width: int
"""Video width as defined by sender"""
height: int
diff --git a/aiogram/api/types/video_note.py b/aiogram/api/types/video_note.py
index 184087ba..b33baa39 100644
--- a/aiogram/api/types/video_note.py
+++ b/aiogram/api/types/video_note.py
@@ -16,7 +16,10 @@ class VideoNote(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
length: int
"""Video width and height (diameter of the video message) as defined by sender"""
duration: int
diff --git a/aiogram/api/types/voice.py b/aiogram/api/types/voice.py
index 634571ec..52e5bb71 100644
--- a/aiogram/api/types/voice.py
+++ b/aiogram/api/types/voice.py
@@ -13,7 +13,10 @@ class Voice(TelegramObject):
"""
file_id: str
- """Identifier for this file"""
+ """Identifier for this file, which can be used to download or reuse the file"""
+ file_unique_id: str
+ """Unique identifier for this file, which is supposed to be the same over time and for
+ different bots. Can't be used to download or reuse the file."""
duration: int
"""Duration of the audio in seconds as defined by sender"""
mime_type: Optional[str] = None
diff --git a/aiogram/utils/markdown.py b/aiogram/utils/markdown.py
index e934fe14..7b217b4f 100644
--- a/aiogram/utils/markdown.py
+++ b/aiogram/utils/markdown.py
@@ -1,4 +1,4 @@
-from .text_decorations import html, markdown
+from .text_decorations import html_decoration, markdown_decoration
LIST_MD_SYMBOLS = "*_`["
@@ -41,7 +41,7 @@ def bold(*content, sep=" "):
:param sep:
:return:
"""
- return markdown.bold.format(value=html.quote(_join(*content, sep=sep)))
+ return markdown_decoration.bold.format(value=html_decoration.quote(_join(*content, sep=sep)))
def hbold(*content, sep=" "):
@@ -52,7 +52,7 @@ def hbold(*content, sep=" "):
:param sep:
:return:
"""
- return html.bold.format(value=html.quote(_join(*content, sep=sep)))
+ return html_decoration.bold.format(value=html_decoration.quote(_join(*content, sep=sep)))
def italic(*content, sep=" "):
@@ -63,7 +63,7 @@ def italic(*content, sep=" "):
:param sep:
:return:
"""
- return markdown.italic.format(value=html.quote(_join(*content, sep=sep)))
+ return markdown_decoration.italic.format(value=html_decoration.quote(_join(*content, sep=sep)))
def hitalic(*content, sep=" "):
@@ -74,7 +74,7 @@ def hitalic(*content, sep=" "):
:param sep:
:return:
"""
- return html.italic.format(value=html.quote(_join(*content, sep=sep)))
+ return html_decoration.italic.format(value=html_decoration.quote(_join(*content, sep=sep)))
def code(*content, sep=" "):
@@ -85,7 +85,7 @@ def code(*content, sep=" "):
:param sep:
:return:
"""
- return markdown.code.format(value=html.quote(_join(*content, sep=sep)))
+ return markdown_decoration.code.format(value=html_decoration.quote(_join(*content, sep=sep)))
def hcode(*content, sep=" "):
@@ -96,7 +96,7 @@ def hcode(*content, sep=" "):
:param sep:
:return:
"""
- return html.code.format(value=html.quote(_join(*content, sep=sep)))
+ return html_decoration.code.format(value=html_decoration.quote(_join(*content, sep=sep)))
def pre(*content, sep="\n"):
@@ -107,7 +107,7 @@ def pre(*content, sep="\n"):
:param sep:
:return:
"""
- return markdown.pre.format(value=html.quote(_join(*content, sep=sep)))
+ return markdown_decoration.pre.format(value=html_decoration.quote(_join(*content, sep=sep)))
def hpre(*content, sep="\n"):
@@ -118,7 +118,7 @@ def hpre(*content, sep="\n"):
:param sep:
:return:
"""
- return html.pre.format(value=html.quote(_join(*content, sep=sep)))
+ return html_decoration.pre.format(value=html_decoration.quote(_join(*content, sep=sep)))
def underline(*content, sep=" "):
@@ -129,7 +129,9 @@ def underline(*content, sep=" "):
:param sep:
:return:
"""
- return markdown.underline.format(value=markdown.quote(_join(*content, sep=sep)))
+ return markdown_decoration.underline.format(
+ value=markdown_decoration.quote(_join(*content, sep=sep))
+ )
def hunderline(*content, sep=" "):
@@ -140,7 +142,7 @@ def hunderline(*content, sep=" "):
:param sep:
:return:
"""
- return html.underline.format(value=html.quote(_join(*content, sep=sep)))
+ return html_decoration.underline.format(value=html_decoration.quote(_join(*content, sep=sep)))
def strikethrough(*content, sep=" "):
@@ -151,7 +153,9 @@ def strikethrough(*content, sep=" "):
:param sep:
:return:
"""
- return markdown.strikethrough.format(value=markdown.quote(_join(*content, sep=sep)))
+ return markdown_decoration.strikethrough.format(
+ value=markdown_decoration.quote(_join(*content, sep=sep))
+ )
def hstrikethrough(*content, sep=" "):
@@ -162,7 +166,9 @@ def hstrikethrough(*content, sep=" "):
:param sep:
:return:
"""
- return html.strikethrough.format(value=html.quote(_join(*content, sep=sep)))
+ return html_decoration.strikethrough.format(
+ value=html_decoration.quote(_join(*content, sep=sep))
+ )
def link(title: str, url: str) -> str:
@@ -173,7 +179,7 @@ def link(title: str, url: str) -> str:
:param url:
:return:
"""
- return markdown.link.format(value=html.quote(title), link=url)
+ return markdown_decoration.link.format(value=html_decoration.quote(title), link=url)
def hlink(title: str, url: str) -> str:
@@ -184,7 +190,7 @@ def hlink(title: str, url: str) -> str:
:param url:
:return:
"""
- return html.link.format(value=html.quote(title), link=url)
+ return html_decoration.link.format(value=html_decoration.quote(title), link=url)
def hide_link(url: str) -> str:
diff --git a/aiogram/utils/text_decorations.py b/aiogram/utils/text_decorations.py
index 3ca73bc9..5b9502b7 100644
--- a/aiogram/utils/text_decorations.py
+++ b/aiogram/utils/text_decorations.py
@@ -6,7 +6,13 @@ from typing import AnyStr, Callable, Generator, Iterable, List, Optional
from aiogram.api.types import MessageEntity
-__all__ = ("TextDecoration", "html", "markdown", "add_surrogate", "remove_surrogate")
+__all__ = (
+ "TextDecoration",
+ "html_decoration",
+ "markdown_decoration",
+ "add_surrogate",
+ "remove_surrogate",
+)
@dataclass
@@ -82,7 +88,7 @@ class TextDecoration:
yield self.quote(text[offset:length])
-html = TextDecoration(
+html_decoration = TextDecoration(
link='{value}',
bold="{value}",
italic="{value}",
@@ -93,18 +99,18 @@ html = TextDecoration(
quote=html.escape,
)
-markdown = TextDecoration(
+MARKDOWN_QUOTE_PATTERN = re.compile(r"([_*\[\]()~`>#+\-|{}.!])")
+
+markdown_decoration = TextDecoration(
link="[{value}]({link})",
bold="*{value}*",
- italic="_{value}_",
+ italic="_{value}_\r",
code="`{value}`",
pre="```{value}```",
- underline="--{value}--", # Is not supported
- strikethrough="~~{value}~~", # Is not supported
- quote=lambda text: re.sub(
- pattern=r"([*_`\[])", repl=r"\\\1", string=text
- ), # Is not always helpful
-) # Markdown is not recommended for usage. Use HTML instead
+ underline="__{value}__",
+ strikethrough="~{value}~",
+ quote=lambda text: re.sub(pattern=MARKDOWN_QUOTE_PATTERN, repl=r"\\\1", string=text),
+)
def add_surrogate(text: str) -> str:
diff --git a/docs/api/methods/add_sticker_to_set.md b/docs/api/methods/add_sticker_to_set.md
index f7cdb803..b98b85d5 100644
--- a/docs/api/methods/add_sticker_to_set.md
+++ b/docs/api/methods/add_sticker_to_set.md
@@ -41,24 +41,25 @@ Imports:
- `from aiogram.api.methods import AddStickerToSet`
- `from aiogram.api.methods.add_sticker_to_set import AddStickerToSet`
-#### As reply into Webhook
-```python3
-return AddStickerToSet(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(AddStickerToSet(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await AddStickerToSet(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(AddStickerToSet(...))
+```
+#### As reply into Webhook in handler
+```python3
+return AddStickerToSet(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#addstickertoset)
- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.MaskPosition](../types/mask_position.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/answer_callback_query.md b/docs/api/methods/answer_callback_query.md
index b9c49ef7..14fe48ff 100644
--- a/docs/api/methods/answer_callback_query.md
+++ b/docs/api/methods/answer_callback_query.md
@@ -43,21 +43,21 @@ Imports:
- `from aiogram.api.methods import AnswerCallbackQuery`
- `from aiogram.api.methods.answer_callback_query import AnswerCallbackQuery`
-#### As reply into Webhook
-```python3
-return AnswerCallbackQuery(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(AnswerCallbackQuery(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await AnswerCallbackQuery(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(AnswerCallbackQuery(...))
+```
+#### As reply into Webhook in handler
+```python3
+return AnswerCallbackQuery(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/answer_inline_query.md b/docs/api/methods/answer_inline_query.md
index e84bdcb2..819544b1 100644
--- a/docs/api/methods/answer_inline_query.md
+++ b/docs/api/methods/answer_inline_query.md
@@ -45,21 +45,21 @@ Imports:
- `from aiogram.api.methods import AnswerInlineQuery`
- `from aiogram.api.methods.answer_inline_query import AnswerInlineQuery`
-#### As reply into Webhook
-```python3
-return AnswerInlineQuery(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(AnswerInlineQuery(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await AnswerInlineQuery(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(AnswerInlineQuery(...))
+```
+#### As reply into Webhook in handler
+```python3
+return AnswerInlineQuery(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/answer_pre_checkout_query.md b/docs/api/methods/answer_pre_checkout_query.md
index 7833030f..cbc8cbcd 100644
--- a/docs/api/methods/answer_pre_checkout_query.md
+++ b/docs/api/methods/answer_pre_checkout_query.md
@@ -39,21 +39,21 @@ Imports:
- `from aiogram.api.methods import AnswerPreCheckoutQuery`
- `from aiogram.api.methods.answer_pre_checkout_query import AnswerPreCheckoutQuery`
-#### As reply into Webhook
-```python3
-return AnswerPreCheckoutQuery(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(AnswerPreCheckoutQuery(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await AnswerPreCheckoutQuery(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(AnswerPreCheckoutQuery(...))
+```
+#### As reply into Webhook in handler
+```python3
+return AnswerPreCheckoutQuery(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/answer_shipping_query.md b/docs/api/methods/answer_shipping_query.md
index d1197cc7..ddf25f0f 100644
--- a/docs/api/methods/answer_shipping_query.md
+++ b/docs/api/methods/answer_shipping_query.md
@@ -40,21 +40,21 @@ Imports:
- `from aiogram.api.methods import AnswerShippingQuery`
- `from aiogram.api.methods.answer_shipping_query import AnswerShippingQuery`
-#### As reply into Webhook
-```python3
-return AnswerShippingQuery(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(AnswerShippingQuery(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await AnswerShippingQuery(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(AnswerShippingQuery(...))
+```
+#### As reply into Webhook in handler
+```python3
+return AnswerShippingQuery(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/create_new_sticker_set.md b/docs/api/methods/create_new_sticker_set.md
index 3f25c14e..8e9ada88 100644
--- a/docs/api/methods/create_new_sticker_set.md
+++ b/docs/api/methods/create_new_sticker_set.md
@@ -43,24 +43,25 @@ Imports:
- `from aiogram.api.methods import CreateNewStickerSet`
- `from aiogram.api.methods.create_new_sticker_set import CreateNewStickerSet`
-#### As reply into Webhook
-```python3
-return CreateNewStickerSet(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(CreateNewStickerSet(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await CreateNewStickerSet(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(CreateNewStickerSet(...))
+```
+#### As reply into Webhook in handler
+```python3
+return CreateNewStickerSet(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#createnewstickerset)
- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.MaskPosition](../types/mask_position.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/delete_chat_photo.md b/docs/api/methods/delete_chat_photo.md
index 0eedbe36..cfe0b7d4 100644
--- a/docs/api/methods/delete_chat_photo.md
+++ b/docs/api/methods/delete_chat_photo.md
@@ -37,21 +37,21 @@ Imports:
- `from aiogram.api.methods import DeleteChatPhoto`
- `from aiogram.api.methods.delete_chat_photo import DeleteChatPhoto`
-#### As reply into Webhook
-```python3
-return DeleteChatPhoto(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(DeleteChatPhoto(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await DeleteChatPhoto(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(DeleteChatPhoto(...))
+```
+#### As reply into Webhook in handler
+```python3
+return DeleteChatPhoto(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/delete_chat_sticker_set.md b/docs/api/methods/delete_chat_sticker_set.md
index 266a53b7..083f4bdd 100644
--- a/docs/api/methods/delete_chat_sticker_set.md
+++ b/docs/api/methods/delete_chat_sticker_set.md
@@ -37,21 +37,21 @@ Imports:
- `from aiogram.api.methods import DeleteChatStickerSet`
- `from aiogram.api.methods.delete_chat_sticker_set import DeleteChatStickerSet`
-#### As reply into Webhook
-```python3
-return DeleteChatStickerSet(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(DeleteChatStickerSet(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await DeleteChatStickerSet(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(DeleteChatStickerSet(...))
+```
+#### As reply into Webhook in handler
+```python3
+return DeleteChatStickerSet(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/delete_message.md b/docs/api/methods/delete_message.md
index 273c07de..fc50f66e 100644
--- a/docs/api/methods/delete_message.md
+++ b/docs/api/methods/delete_message.md
@@ -52,21 +52,21 @@ Imports:
- `from aiogram.api.methods import DeleteMessage`
- `from aiogram.api.methods.delete_message import DeleteMessage`
-#### As reply into Webhook
-```python3
-return DeleteMessage(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(DeleteMessage(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await DeleteMessage(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(DeleteMessage(...))
+```
+#### As reply into Webhook in handler
+```python3
+return DeleteMessage(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/delete_sticker_from_set.md b/docs/api/methods/delete_sticker_from_set.md
index 40f99276..4b6dcfd3 100644
--- a/docs/api/methods/delete_sticker_from_set.md
+++ b/docs/api/methods/delete_sticker_from_set.md
@@ -37,21 +37,21 @@ Imports:
- `from aiogram.api.methods import DeleteStickerFromSet`
- `from aiogram.api.methods.delete_sticker_from_set import DeleteStickerFromSet`
-#### As reply into Webhook
-```python3
-return DeleteStickerFromSet(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(DeleteStickerFromSet(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await DeleteStickerFromSet(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(DeleteStickerFromSet(...))
+```
+#### As reply into Webhook in handler
+```python3
+return DeleteStickerFromSet(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/delete_webhook.md b/docs/api/methods/delete_webhook.md
index cfc78ac2..e4584685 100644
--- a/docs/api/methods/delete_webhook.md
+++ b/docs/api/methods/delete_webhook.md
@@ -33,18 +33,18 @@ Imports:
#### As reply into Webhook
```python3
-return DeleteWebhook(...)
+result: bool = await DeleteWebhook(...)
```
#### With specific bot
```python3
-result: bool = await bot.emit(DeleteWebhook(...))
+result: bool = await bot(DeleteWebhook(...))
+```
+#### As reply into Webhook in handler
+```python3
+return DeleteWebhook(...)
```
-#### In handlers with current bot
-```python3
-result: bool = await DeleteWebhook(...)
-```
## Related pages:
diff --git a/docs/api/methods/edit_message_caption.md b/docs/api/methods/edit_message_caption.md
index 06f1f31e..cdaecdae 100644
--- a/docs/api/methods/edit_message_caption.md
+++ b/docs/api/methods/edit_message_caption.md
@@ -42,21 +42,21 @@ Imports:
- `from aiogram.api.methods import EditMessageCaption`
- `from aiogram.api.methods.edit_message_caption import EditMessageCaption`
-#### As reply into Webhook
-```python3
-return EditMessageCaption(...)
-```
-
-#### With specific bot
-```python3
-result: Union[Message, bool] = await bot.emit(EditMessageCaption(...))
-```
-
#### In handlers with current bot
```python3
result: Union[Message, bool] = await EditMessageCaption(...)
```
+#### With specific bot
+```python3
+result: Union[Message, bool] = await bot(EditMessageCaption(...))
+```
+#### As reply into Webhook in handler
+```python3
+return EditMessageCaption(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/edit_message_live_location.md b/docs/api/methods/edit_message_live_location.md
index 2ffaab42..e3a9ff39 100644
--- a/docs/api/methods/edit_message_live_location.md
+++ b/docs/api/methods/edit_message_live_location.md
@@ -42,21 +42,21 @@ Imports:
- `from aiogram.api.methods import EditMessageLiveLocation`
- `from aiogram.api.methods.edit_message_live_location import EditMessageLiveLocation`
-#### As reply into Webhook
-```python3
-return EditMessageLiveLocation(...)
-```
-
-#### With specific bot
-```python3
-result: Union[Message, bool] = await bot.emit(EditMessageLiveLocation(...))
-```
-
#### In handlers with current bot
```python3
result: Union[Message, bool] = await EditMessageLiveLocation(...)
```
+#### With specific bot
+```python3
+result: Union[Message, bool] = await bot(EditMessageLiveLocation(...))
+```
+#### As reply into Webhook in handler
+```python3
+return EditMessageLiveLocation(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/edit_message_media.md b/docs/api/methods/edit_message_media.md
index 60b255db..5d25baa5 100644
--- a/docs/api/methods/edit_message_media.md
+++ b/docs/api/methods/edit_message_media.md
@@ -41,21 +41,21 @@ Imports:
- `from aiogram.api.methods import EditMessageMedia`
- `from aiogram.api.methods.edit_message_media import EditMessageMedia`
-#### As reply into Webhook
-```python3
-return EditMessageMedia(...)
-```
-
-#### With specific bot
-```python3
-result: Union[Message, bool] = await bot.emit(EditMessageMedia(...))
-```
-
#### In handlers with current bot
```python3
result: Union[Message, bool] = await EditMessageMedia(...)
```
+#### With specific bot
+```python3
+result: Union[Message, bool] = await bot(EditMessageMedia(...))
+```
+#### As reply into Webhook in handler
+```python3
+return EditMessageMedia(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/edit_message_reply_markup.md b/docs/api/methods/edit_message_reply_markup.md
index 16cb8b37..efbda5aa 100644
--- a/docs/api/methods/edit_message_reply_markup.md
+++ b/docs/api/methods/edit_message_reply_markup.md
@@ -40,21 +40,21 @@ Imports:
- `from aiogram.api.methods import EditMessageReplyMarkup`
- `from aiogram.api.methods.edit_message_reply_markup import EditMessageReplyMarkup`
-#### As reply into Webhook
-```python3
-return EditMessageReplyMarkup(...)
-```
-
-#### With specific bot
-```python3
-result: Union[Message, bool] = await bot.emit(EditMessageReplyMarkup(...))
-```
-
#### In handlers with current bot
```python3
result: Union[Message, bool] = await EditMessageReplyMarkup(...)
```
+#### With specific bot
+```python3
+result: Union[Message, bool] = await bot(EditMessageReplyMarkup(...))
+```
+#### As reply into Webhook in handler
+```python3
+return EditMessageReplyMarkup(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/edit_message_text.md b/docs/api/methods/edit_message_text.md
index 7d65e8c5..6fa574c9 100644
--- a/docs/api/methods/edit_message_text.md
+++ b/docs/api/methods/edit_message_text.md
@@ -43,21 +43,21 @@ Imports:
- `from aiogram.api.methods import EditMessageText`
- `from aiogram.api.methods.edit_message_text import EditMessageText`
-#### As reply into Webhook
-```python3
-return EditMessageText(...)
-```
-
-#### With specific bot
-```python3
-result: Union[Message, bool] = await bot.emit(EditMessageText(...))
-```
-
#### In handlers with current bot
```python3
result: Union[Message, bool] = await EditMessageText(...)
```
+#### With specific bot
+```python3
+result: Union[Message, bool] = await bot(EditMessageText(...))
+```
+#### As reply into Webhook in handler
+```python3
+return EditMessageText(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/export_chat_invite_link.md b/docs/api/methods/export_chat_invite_link.md
index 4c696a28..8fc0d888 100644
--- a/docs/api/methods/export_chat_invite_link.md
+++ b/docs/api/methods/export_chat_invite_link.md
@@ -39,21 +39,21 @@ Imports:
- `from aiogram.api.methods import ExportChatInviteLink`
- `from aiogram.api.methods.export_chat_invite_link import ExportChatInviteLink`
-#### As reply into Webhook
-```python3
-return ExportChatInviteLink(...)
-```
-
-#### With specific bot
-```python3
-result: str = await bot.emit(ExportChatInviteLink(...))
-```
-
#### In handlers with current bot
```python3
result: str = await ExportChatInviteLink(...)
```
+#### With specific bot
+```python3
+result: str = await bot(ExportChatInviteLink(...))
+```
+#### As reply into Webhook in handler
+```python3
+return ExportChatInviteLink(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/forward_message.md b/docs/api/methods/forward_message.md
index 60e5bf20..755d4b43 100644
--- a/docs/api/methods/forward_message.md
+++ b/docs/api/methods/forward_message.md
@@ -40,21 +40,21 @@ Imports:
- `from aiogram.api.methods import ForwardMessage`
- `from aiogram.api.methods.forward_message import ForwardMessage`
-#### As reply into Webhook
-```python3
-return ForwardMessage(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(ForwardMessage(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await ForwardMessage(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(ForwardMessage(...))
+```
+#### As reply into Webhook in handler
+```python3
+return ForwardMessage(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_chat.md b/docs/api/methods/get_chat.md
index fa55a5f5..c216afa2 100644
--- a/docs/api/methods/get_chat.md
+++ b/docs/api/methods/get_chat.md
@@ -37,17 +37,17 @@ Imports:
- `from aiogram.api.methods import GetChat`
- `from aiogram.api.methods.get_chat import GetChat`
-
-#### With specific bot
-```python3
-result: Chat = await bot.emit(GetChat(...))
-```
-
#### In handlers with current bot
```python3
result: Chat = await GetChat(...)
```
+#### With specific bot
+```python3
+result: Chat = await bot(GetChat(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_chat_administrators.md b/docs/api/methods/get_chat_administrators.md
index 37481883..d7047f7e 100644
--- a/docs/api/methods/get_chat_administrators.md
+++ b/docs/api/methods/get_chat_administrators.md
@@ -37,17 +37,17 @@ Imports:
- `from aiogram.api.methods import GetChatAdministrators`
- `from aiogram.api.methods.get_chat_administrators import GetChatAdministrators`
-
-#### With specific bot
-```python3
-result: List[ChatMember] = await bot.emit(GetChatAdministrators(...))
-```
-
#### In handlers with current bot
```python3
result: List[ChatMember] = await GetChatAdministrators(...)
```
+#### With specific bot
+```python3
+result: List[ChatMember] = await bot(GetChatAdministrators(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_chat_member.md b/docs/api/methods/get_chat_member.md
index 761c253b..2198e1fe 100644
--- a/docs/api/methods/get_chat_member.md
+++ b/docs/api/methods/get_chat_member.md
@@ -38,17 +38,17 @@ Imports:
- `from aiogram.api.methods import GetChatMember`
- `from aiogram.api.methods.get_chat_member import GetChatMember`
-
-#### With specific bot
-```python3
-result: ChatMember = await bot.emit(GetChatMember(...))
-```
-
#### In handlers with current bot
```python3
result: ChatMember = await GetChatMember(...)
```
+#### With specific bot
+```python3
+result: ChatMember = await bot(GetChatMember(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_chat_members_count.md b/docs/api/methods/get_chat_members_count.md
index 6c85e74d..e1cb3312 100644
--- a/docs/api/methods/get_chat_members_count.md
+++ b/docs/api/methods/get_chat_members_count.md
@@ -37,17 +37,17 @@ Imports:
- `from aiogram.api.methods import GetChatMembersCount`
- `from aiogram.api.methods.get_chat_members_count import GetChatMembersCount`
-
-#### With specific bot
-```python3
-result: int = await bot.emit(GetChatMembersCount(...))
-```
-
#### In handlers with current bot
```python3
result: int = await GetChatMembersCount(...)
```
+#### With specific bot
+```python3
+result: int = await bot(GetChatMembersCount(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_file.md b/docs/api/methods/get_file.md
index b89910d9..c449135b 100644
--- a/docs/api/methods/get_file.md
+++ b/docs/api/methods/get_file.md
@@ -39,17 +39,17 @@ Imports:
- `from aiogram.api.methods import GetFile`
- `from aiogram.api.methods.get_file import GetFile`
-
-#### With specific bot
-```python3
-result: File = await bot.emit(GetFile(...))
-```
-
#### In handlers with current bot
```python3
result: File = await GetFile(...)
```
+#### With specific bot
+```python3
+result: File = await bot(GetFile(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_game_high_scores.md b/docs/api/methods/get_game_high_scores.md
index 1055d672..b97514c6 100644
--- a/docs/api/methods/get_game_high_scores.md
+++ b/docs/api/methods/get_game_high_scores.md
@@ -42,17 +42,17 @@ Imports:
- `from aiogram.api.methods import GetGameHighScores`
- `from aiogram.api.methods.get_game_high_scores import GetGameHighScores`
-
-#### With specific bot
-```python3
-result: List[GameHighScore] = await bot.emit(GetGameHighScores(...))
-```
-
#### In handlers with current bot
```python3
result: List[GameHighScore] = await GetGameHighScores(...)
```
+#### With specific bot
+```python3
+result: List[GameHighScore] = await bot(GetGameHighScores(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_me.md b/docs/api/methods/get_me.md
index d57ccf11..b2994f25 100644
--- a/docs/api/methods/get_me.md
+++ b/docs/api/methods/get_me.md
@@ -31,17 +31,17 @@ Imports:
- `from aiogram.api.methods import GetMe`
- `from aiogram.api.methods.get_me import GetMe`
-
-#### With specific bot
-```python3
-result: User = await bot.emit(GetMe(...))
-```
-
#### In handlers with current bot
```python3
result: User = await GetMe(...)
```
+#### With specific bot
+```python3
+result: User = await bot(GetMe(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_sticker_set.md b/docs/api/methods/get_sticker_set.md
index 7c4fed19..983f1331 100644
--- a/docs/api/methods/get_sticker_set.md
+++ b/docs/api/methods/get_sticker_set.md
@@ -37,17 +37,17 @@ Imports:
- `from aiogram.api.methods import GetStickerSet`
- `from aiogram.api.methods.get_sticker_set import GetStickerSet`
-
-#### With specific bot
-```python3
-result: StickerSet = await bot.emit(GetStickerSet(...))
-```
-
#### In handlers with current bot
```python3
result: StickerSet = await GetStickerSet(...)
```
+#### With specific bot
+```python3
+result: StickerSet = await bot(GetStickerSet(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_updates.md b/docs/api/methods/get_updates.md
index 3ca4ac18..ed5481b7 100644
--- a/docs/api/methods/get_updates.md
+++ b/docs/api/methods/get_updates.md
@@ -46,17 +46,17 @@ Imports:
- `from aiogram.api.methods import GetUpdates`
- `from aiogram.api.methods.get_updates import GetUpdates`
-
-#### With specific bot
-```python3
-result: List[Update] = await bot.emit(GetUpdates(...))
-```
-
#### In handlers with current bot
```python3
result: List[Update] = await GetUpdates(...)
```
+#### With specific bot
+```python3
+result: List[Update] = await bot(GetUpdates(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_user_profile_photos.md b/docs/api/methods/get_user_profile_photos.md
index 082cb73c..0b69b59d 100644
--- a/docs/api/methods/get_user_profile_photos.md
+++ b/docs/api/methods/get_user_profile_photos.md
@@ -39,17 +39,17 @@ Imports:
- `from aiogram.api.methods import GetUserProfilePhotos`
- `from aiogram.api.methods.get_user_profile_photos import GetUserProfilePhotos`
-
-#### With specific bot
-```python3
-result: UserProfilePhotos = await bot.emit(GetUserProfilePhotos(...))
-```
-
#### In handlers with current bot
```python3
result: UserProfilePhotos = await GetUserProfilePhotos(...)
```
+#### With specific bot
+```python3
+result: UserProfilePhotos = await bot(GetUserProfilePhotos(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/get_webhook_info.md b/docs/api/methods/get_webhook_info.md
index c6868a40..2428a6af 100644
--- a/docs/api/methods/get_webhook_info.md
+++ b/docs/api/methods/get_webhook_info.md
@@ -31,17 +31,17 @@ Imports:
- `from aiogram.api.methods import GetWebhookInfo`
- `from aiogram.api.methods.get_webhook_info import GetWebhookInfo`
-
-#### With specific bot
-```python3
-result: WebhookInfo = await bot.emit(GetWebhookInfo(...))
-```
-
#### In handlers with current bot
```python3
result: WebhookInfo = await GetWebhookInfo(...)
```
+#### With specific bot
+```python3
+result: WebhookInfo = await bot(GetWebhookInfo(...))
+```
+
+
## Related pages:
diff --git a/docs/api/methods/kick_chat_member.md b/docs/api/methods/kick_chat_member.md
index c8d0b811..0a475e03 100644
--- a/docs/api/methods/kick_chat_member.md
+++ b/docs/api/methods/kick_chat_member.md
@@ -39,21 +39,21 @@ Imports:
- `from aiogram.api.methods import KickChatMember`
- `from aiogram.api.methods.kick_chat_member import KickChatMember`
-#### As reply into Webhook
-```python3
-return KickChatMember(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(KickChatMember(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await KickChatMember(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(KickChatMember(...))
+```
+#### As reply into Webhook in handler
+```python3
+return KickChatMember(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/leave_chat.md b/docs/api/methods/leave_chat.md
index b8f980f3..284c72f1 100644
--- a/docs/api/methods/leave_chat.md
+++ b/docs/api/methods/leave_chat.md
@@ -37,21 +37,21 @@ Imports:
- `from aiogram.api.methods import LeaveChat`
- `from aiogram.api.methods.leave_chat import LeaveChat`
-#### As reply into Webhook
-```python3
-return LeaveChat(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(LeaveChat(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await LeaveChat(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(LeaveChat(...))
+```
+#### As reply into Webhook in handler
+```python3
+return LeaveChat(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/pin_chat_message.md b/docs/api/methods/pin_chat_message.md
index b94f86ed..1d9fd53e 100644
--- a/docs/api/methods/pin_chat_message.md
+++ b/docs/api/methods/pin_chat_message.md
@@ -39,21 +39,21 @@ Imports:
- `from aiogram.api.methods import PinChatMessage`
- `from aiogram.api.methods.pin_chat_message import PinChatMessage`
-#### As reply into Webhook
-```python3
-return PinChatMessage(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(PinChatMessage(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await PinChatMessage(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(PinChatMessage(...))
+```
+#### As reply into Webhook in handler
+```python3
+return PinChatMessage(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/promote_chat_member.md b/docs/api/methods/promote_chat_member.md
index 8b031cec..e2fd6202 100644
--- a/docs/api/methods/promote_chat_member.md
+++ b/docs/api/methods/promote_chat_member.md
@@ -46,21 +46,21 @@ Imports:
- `from aiogram.api.methods import PromoteChatMember`
- `from aiogram.api.methods.promote_chat_member import PromoteChatMember`
-#### As reply into Webhook
-```python3
-return PromoteChatMember(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(PromoteChatMember(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await PromoteChatMember(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(PromoteChatMember(...))
+```
+#### As reply into Webhook in handler
+```python3
+return PromoteChatMember(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/restrict_chat_member.md b/docs/api/methods/restrict_chat_member.md
index a03725cc..fa438eb9 100644
--- a/docs/api/methods/restrict_chat_member.md
+++ b/docs/api/methods/restrict_chat_member.md
@@ -40,21 +40,21 @@ Imports:
- `from aiogram.api.methods import RestrictChatMember`
- `from aiogram.api.methods.restrict_chat_member import RestrictChatMember`
-#### As reply into Webhook
-```python3
-return RestrictChatMember(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(RestrictChatMember(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await RestrictChatMember(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(RestrictChatMember(...))
+```
+#### As reply into Webhook in handler
+```python3
+return RestrictChatMember(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/send_animation.md b/docs/api/methods/send_animation.md
index fac7d9c3..3ea76968 100644
--- a/docs/api/methods/send_animation.md
+++ b/docs/api/methods/send_animation.md
@@ -47,28 +47,29 @@ Imports:
- `from aiogram.api.methods import SendAnimation`
- `from aiogram.api.methods.send_animation import SendAnimation`
-#### As reply into Webhook
-```python3
-return SendAnimation(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendAnimation(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendAnimation(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendAnimation(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendAnimation(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendanimation)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/send_audio.md b/docs/api/methods/send_audio.md
index fdeb29f1..1aadc59d 100644
--- a/docs/api/methods/send_audio.md
+++ b/docs/api/methods/send_audio.md
@@ -49,28 +49,29 @@ Imports:
- `from aiogram.api.methods import SendAudio`
- `from aiogram.api.methods.send_audio import SendAudio`
-#### As reply into Webhook
-```python3
-return SendAudio(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendAudio(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendAudio(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendAudio(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendAudio(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendaudio)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/send_chat_action.md b/docs/api/methods/send_chat_action.md
index 1dfab03b..59e23a75 100644
--- a/docs/api/methods/send_chat_action.md
+++ b/docs/api/methods/send_chat_action.md
@@ -42,21 +42,21 @@ Imports:
- `from aiogram.api.methods import SendChatAction`
- `from aiogram.api.methods.send_chat_action import SendChatAction`
-#### As reply into Webhook
-```python3
-return SendChatAction(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SendChatAction(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SendChatAction(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SendChatAction(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendChatAction(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/send_contact.md b/docs/api/methods/send_contact.md
index 3f67e608..b9de4bcf 100644
--- a/docs/api/methods/send_contact.md
+++ b/docs/api/methods/send_contact.md
@@ -44,27 +44,27 @@ Imports:
- `from aiogram.api.methods import SendContact`
- `from aiogram.api.methods.send_contact import SendContact`
-#### As reply into Webhook
-```python3
-return SendContact(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendContact(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendContact(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendContact(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendContact(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendcontact)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
diff --git a/docs/api/methods/send_document.md b/docs/api/methods/send_document.md
index 9fd71e38..9b0134b8 100644
--- a/docs/api/methods/send_document.md
+++ b/docs/api/methods/send_document.md
@@ -44,28 +44,29 @@ Imports:
- `from aiogram.api.methods import SendDocument`
- `from aiogram.api.methods.send_document import SendDocument`
-#### As reply into Webhook
-```python3
-return SendDocument(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendDocument(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendDocument(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendDocument(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendDocument(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#senddocument)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/send_game.md b/docs/api/methods/send_game.md
index 85901bff..47b66405 100644
--- a/docs/api/methods/send_game.md
+++ b/docs/api/methods/send_game.md
@@ -41,21 +41,21 @@ Imports:
- `from aiogram.api.methods import SendGame`
- `from aiogram.api.methods.send_game import SendGame`
-#### As reply into Webhook
-```python3
-return SendGame(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendGame(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendGame(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendGame(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendGame(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/send_invoice.md b/docs/api/methods/send_invoice.md
index f9cc8023..ce8d6346 100644
--- a/docs/api/methods/send_invoice.md
+++ b/docs/api/methods/send_invoice.md
@@ -59,25 +59,25 @@ Imports:
- `from aiogram.api.methods import SendInvoice`
- `from aiogram.api.methods.send_invoice import SendInvoice`
-#### As reply into Webhook
-```python3
-return SendInvoice(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendInvoice(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendInvoice(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendInvoice(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendInvoice(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendinvoice)
-- [aiogram.types.LabeledPrice](../types/labeled_price.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.LabeledPrice](../types/labeled_price.md)
- [aiogram.types.Message](../types/message.md)
diff --git a/docs/api/methods/send_location.md b/docs/api/methods/send_location.md
index eaa88ed7..26b6d72b 100644
--- a/docs/api/methods/send_location.md
+++ b/docs/api/methods/send_location.md
@@ -43,27 +43,27 @@ Imports:
- `from aiogram.api.methods import SendLocation`
- `from aiogram.api.methods.send_location import SendLocation`
-#### As reply into Webhook
-```python3
-return SendLocation(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendLocation(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendLocation(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendLocation(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendLocation(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendlocation)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
diff --git a/docs/api/methods/send_media_group.md b/docs/api/methods/send_media_group.md
index a291d489..522a849b 100644
--- a/docs/api/methods/send_media_group.md
+++ b/docs/api/methods/send_media_group.md
@@ -40,21 +40,21 @@ Imports:
- `from aiogram.api.methods import SendMediaGroup`
- `from aiogram.api.methods.send_media_group import SendMediaGroup`
-#### As reply into Webhook
-```python3
-return SendMediaGroup(...)
-```
-
-#### With specific bot
-```python3
-result: List[Message] = await bot.emit(SendMediaGroup(...))
-```
-
#### In handlers with current bot
```python3
result: List[Message] = await SendMediaGroup(...)
```
+#### With specific bot
+```python3
+result: List[Message] = await bot(SendMediaGroup(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendMediaGroup(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/send_message.md b/docs/api/methods/send_message.md
index c3a8bfbc..bb1137df 100644
--- a/docs/api/methods/send_message.md
+++ b/docs/api/methods/send_message.md
@@ -43,27 +43,27 @@ Imports:
- `from aiogram.api.methods import SendMessage`
- `from aiogram.api.methods.send_message import SendMessage`
-#### As reply into Webhook
-```python3
-return SendMessage(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendMessage(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendMessage(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendMessage(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendMessage(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendmessage)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
diff --git a/docs/api/methods/send_photo.md b/docs/api/methods/send_photo.md
index 275c4b8b..e52f8bf8 100644
--- a/docs/api/methods/send_photo.md
+++ b/docs/api/methods/send_photo.md
@@ -43,28 +43,29 @@ Imports:
- `from aiogram.api.methods import SendPhoto`
- `from aiogram.api.methods.send_photo import SendPhoto`
-#### As reply into Webhook
-```python3
-return SendPhoto(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendPhoto(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendPhoto(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendPhoto(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendPhoto(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendphoto)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/send_poll.md b/docs/api/methods/send_poll.md
index cc3c4f58..7583603b 100644
--- a/docs/api/methods/send_poll.md
+++ b/docs/api/methods/send_poll.md
@@ -42,27 +42,27 @@ Imports:
- `from aiogram.api.methods import SendPoll`
- `from aiogram.api.methods.send_poll import SendPoll`
-#### As reply into Webhook
-```python3
-return SendPoll(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendPoll(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendPoll(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendPoll(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendPoll(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendpoll)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
diff --git a/docs/api/methods/send_sticker.md b/docs/api/methods/send_sticker.md
index ccbb5638..2195256d 100644
--- a/docs/api/methods/send_sticker.md
+++ b/docs/api/methods/send_sticker.md
@@ -41,28 +41,29 @@ Imports:
- `from aiogram.api.methods import SendSticker`
- `from aiogram.api.methods.send_sticker import SendSticker`
-#### As reply into Webhook
-```python3
-return SendSticker(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendSticker(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendSticker(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendSticker(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendSticker(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendsticker)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/send_venue.md b/docs/api/methods/send_venue.md
index a83ba2db..95509b55 100644
--- a/docs/api/methods/send_venue.md
+++ b/docs/api/methods/send_venue.md
@@ -46,27 +46,27 @@ Imports:
- `from aiogram.api.methods import SendVenue`
- `from aiogram.api.methods.send_venue import SendVenue`
-#### As reply into Webhook
-```python3
-return SendVenue(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendVenue(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendVenue(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendVenue(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendVenue(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendvenue)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
diff --git a/docs/api/methods/send_video.md b/docs/api/methods/send_video.md
index 76582afb..1cd459f8 100644
--- a/docs/api/methods/send_video.md
+++ b/docs/api/methods/send_video.md
@@ -48,28 +48,29 @@ Imports:
- `from aiogram.api.methods import SendVideo`
- `from aiogram.api.methods.send_video import SendVideo`
-#### As reply into Webhook
-```python3
-return SendVideo(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendVideo(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendVideo(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendVideo(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendVideo(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendvideo)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/send_video_note.md b/docs/api/methods/send_video_note.md
index 04fb05c3..d2e60ff9 100644
--- a/docs/api/methods/send_video_note.md
+++ b/docs/api/methods/send_video_note.md
@@ -44,28 +44,29 @@ Imports:
- `from aiogram.api.methods import SendVideoNote`
- `from aiogram.api.methods.send_video_note import SendVideoNote`
-#### As reply into Webhook
-```python3
-return SendVideoNote(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendVideoNote(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendVideoNote(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendVideoNote(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendVideoNote(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendvideonote)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/send_voice.md b/docs/api/methods/send_voice.md
index f99655b0..f71790fd 100644
--- a/docs/api/methods/send_voice.md
+++ b/docs/api/methods/send_voice.md
@@ -44,28 +44,29 @@ Imports:
- `from aiogram.api.methods import SendVoice`
- `from aiogram.api.methods.send_voice import SendVoice`
-#### As reply into Webhook
-```python3
-return SendVoice(...)
-```
-
-#### With specific bot
-```python3
-result: Message = await bot.emit(SendVoice(...))
-```
-
#### In handlers with current bot
```python3
result: Message = await SendVoice(...)
```
+#### With specific bot
+```python3
+result: Message = await bot(SendVoice(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SendVoice(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#sendvoice)
- [aiogram.types.ForceReply](../types/force_reply.md)
-- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
-- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.ReplyKeyboardMarkup](../types/reply_keyboard_markup.md)
+- [aiogram.types.ReplyKeyboardRemove](../types/reply_keyboard_remove.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/set_chat_administrator_custom_title.md b/docs/api/methods/set_chat_administrator_custom_title.md
new file mode 100644
index 00000000..dd301d2f
--- /dev/null
+++ b/docs/api/methods/set_chat_administrator_custom_title.md
@@ -0,0 +1,60 @@
+# setChatAdministratorCustomTitle
+
+## Description
+
+Use this method to set a custom title for an administrator in a supergroup promoted by the bot. Returns True on success.
+
+
+## Arguments
+
+| Name | Type | Description |
+| - | - | - |
+| `chat_id` | `#!python3 Union[int, str]` | Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) |
+| `user_id` | `#!python3 int` | Unique identifier of the target user |
+| `custom_title` | `#!python3 str` | New custom title for the administrator; 0-16 characters, emoji are not allowed |
+
+
+
+## Response
+
+Type: `#!python3 bool`
+
+Description: Returns True on success.
+
+
+## Usage
+
+
+### As bot method bot
+
+```python3
+result: bool = await bot.set_chat_administrator_custom_title(...)
+```
+
+### Method as object
+
+Imports:
+
+- `from aiogram.methods import SetChatAdministratorCustomTitle`
+- `from aiogram.api.methods import SetChatAdministratorCustomTitle`
+- `from aiogram.api.methods.set_chat_administrator_custom_title import SetChatAdministratorCustomTitle`
+
+#### In handlers with current bot
+```python3
+result: bool = await SetChatAdministratorCustomTitle(...)
+```
+
+#### With specific bot
+```python3
+result: bool = await bot(SetChatAdministratorCustomTitle(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetChatAdministratorCustomTitle(...)
+```
+
+
+
+## Related pages:
+
+- [Official documentation](https://core.telegram.org/bots/api#setchatadministratorcustomtitle)
diff --git a/docs/api/methods/set_chat_description.md b/docs/api/methods/set_chat_description.md
index 837a100b..ce555f3f 100644
--- a/docs/api/methods/set_chat_description.md
+++ b/docs/api/methods/set_chat_description.md
@@ -38,21 +38,21 @@ Imports:
- `from aiogram.api.methods import SetChatDescription`
- `from aiogram.api.methods.set_chat_description import SetChatDescription`
-#### As reply into Webhook
-```python3
-return SetChatDescription(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SetChatDescription(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SetChatDescription(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SetChatDescription(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetChatDescription(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/set_chat_permissions.md b/docs/api/methods/set_chat_permissions.md
index d97c23ad..3f975e51 100644
--- a/docs/api/methods/set_chat_permissions.md
+++ b/docs/api/methods/set_chat_permissions.md
@@ -38,21 +38,21 @@ Imports:
- `from aiogram.api.methods import SetChatPermissions`
- `from aiogram.api.methods.set_chat_permissions import SetChatPermissions`
-#### As reply into Webhook
-```python3
-return SetChatPermissions(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SetChatPermissions(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SetChatPermissions(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SetChatPermissions(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetChatPermissions(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/set_chat_photo.md b/docs/api/methods/set_chat_photo.md
index 5c9c8167..8d17dc21 100644
--- a/docs/api/methods/set_chat_photo.md
+++ b/docs/api/methods/set_chat_photo.md
@@ -38,19 +38,20 @@ Imports:
- `from aiogram.api.methods import SetChatPhoto`
- `from aiogram.api.methods.set_chat_photo import SetChatPhoto`
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SetChatPhoto(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SetChatPhoto(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SetChatPhoto(...))
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#setchatphoto)
- [aiogram.types.InputFile](../types/input_file.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/set_chat_sticker_set.md b/docs/api/methods/set_chat_sticker_set.md
index 375742f2..dda34637 100644
--- a/docs/api/methods/set_chat_sticker_set.md
+++ b/docs/api/methods/set_chat_sticker_set.md
@@ -38,21 +38,21 @@ Imports:
- `from aiogram.api.methods import SetChatStickerSet`
- `from aiogram.api.methods.set_chat_sticker_set import SetChatStickerSet`
-#### As reply into Webhook
-```python3
-return SetChatStickerSet(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SetChatStickerSet(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SetChatStickerSet(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SetChatStickerSet(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetChatStickerSet(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/set_chat_title.md b/docs/api/methods/set_chat_title.md
index 7ac44236..d4162ce5 100644
--- a/docs/api/methods/set_chat_title.md
+++ b/docs/api/methods/set_chat_title.md
@@ -38,21 +38,21 @@ Imports:
- `from aiogram.api.methods import SetChatTitle`
- `from aiogram.api.methods.set_chat_title import SetChatTitle`
-#### As reply into Webhook
-```python3
-return SetChatTitle(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SetChatTitle(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SetChatTitle(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SetChatTitle(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetChatTitle(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/set_game_score.md b/docs/api/methods/set_game_score.md
index a56a5ac3..ff09795c 100644
--- a/docs/api/methods/set_game_score.md
+++ b/docs/api/methods/set_game_score.md
@@ -43,21 +43,21 @@ Imports:
- `from aiogram.api.methods import SetGameScore`
- `from aiogram.api.methods.set_game_score import SetGameScore`
-#### As reply into Webhook
-```python3
-return SetGameScore(...)
-```
-
-#### With specific bot
-```python3
-result: Union[Message, bool] = await bot.emit(SetGameScore(...))
-```
-
#### In handlers with current bot
```python3
result: Union[Message, bool] = await SetGameScore(...)
```
+#### With specific bot
+```python3
+result: Union[Message, bool] = await bot(SetGameScore(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetGameScore(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/set_passport_data_errors.md b/docs/api/methods/set_passport_data_errors.md
index 6924dc90..e00d2e89 100644
--- a/docs/api/methods/set_passport_data_errors.md
+++ b/docs/api/methods/set_passport_data_errors.md
@@ -40,21 +40,21 @@ Imports:
- `from aiogram.api.methods import SetPassportDataErrors`
- `from aiogram.api.methods.set_passport_data_errors import SetPassportDataErrors`
-#### As reply into Webhook
-```python3
-return SetPassportDataErrors(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SetPassportDataErrors(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SetPassportDataErrors(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SetPassportDataErrors(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetPassportDataErrors(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/set_sticker_position_in_set.md b/docs/api/methods/set_sticker_position_in_set.md
index 32c59daa..7a67dab9 100644
--- a/docs/api/methods/set_sticker_position_in_set.md
+++ b/docs/api/methods/set_sticker_position_in_set.md
@@ -38,21 +38,21 @@ Imports:
- `from aiogram.api.methods import SetStickerPositionInSet`
- `from aiogram.api.methods.set_sticker_position_in_set import SetStickerPositionInSet`
-#### As reply into Webhook
-```python3
-return SetStickerPositionInSet(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SetStickerPositionInSet(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SetStickerPositionInSet(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SetStickerPositionInSet(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetStickerPositionInSet(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/set_webhook.md b/docs/api/methods/set_webhook.md
index 5271cf3f..2db3433a 100644
--- a/docs/api/methods/set_webhook.md
+++ b/docs/api/methods/set_webhook.md
@@ -52,23 +52,24 @@ Imports:
- `from aiogram.api.methods import SetWebhook`
- `from aiogram.api.methods.set_webhook import SetWebhook`
-#### As reply into Webhook
-```python3
-return SetWebhook(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(SetWebhook(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await SetWebhook(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(SetWebhook(...))
+```
+#### As reply into Webhook in handler
+```python3
+return SetWebhook(...)
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#setwebhook)
- [aiogram.types.InputFile](../types/input_file.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/methods/stop_message_live_location.md b/docs/api/methods/stop_message_live_location.md
index 4a9fbc18..32dbaa19 100644
--- a/docs/api/methods/stop_message_live_location.md
+++ b/docs/api/methods/stop_message_live_location.md
@@ -40,21 +40,21 @@ Imports:
- `from aiogram.api.methods import StopMessageLiveLocation`
- `from aiogram.api.methods.stop_message_live_location import StopMessageLiveLocation`
-#### As reply into Webhook
-```python3
-return StopMessageLiveLocation(...)
-```
-
-#### With specific bot
-```python3
-result: Union[Message, bool] = await bot.emit(StopMessageLiveLocation(...))
-```
-
#### In handlers with current bot
```python3
result: Union[Message, bool] = await StopMessageLiveLocation(...)
```
+#### With specific bot
+```python3
+result: Union[Message, bool] = await bot(StopMessageLiveLocation(...))
+```
+#### As reply into Webhook in handler
+```python3
+return StopMessageLiveLocation(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/stop_poll.md b/docs/api/methods/stop_poll.md
index 826fc114..797da7ec 100644
--- a/docs/api/methods/stop_poll.md
+++ b/docs/api/methods/stop_poll.md
@@ -39,21 +39,21 @@ Imports:
- `from aiogram.api.methods import StopPoll`
- `from aiogram.api.methods.stop_poll import StopPoll`
-#### As reply into Webhook
-```python3
-return StopPoll(...)
-```
-
-#### With specific bot
-```python3
-result: Poll = await bot.emit(StopPoll(...))
-```
-
#### In handlers with current bot
```python3
result: Poll = await StopPoll(...)
```
+#### With specific bot
+```python3
+result: Poll = await bot(StopPoll(...))
+```
+#### As reply into Webhook in handler
+```python3
+return StopPoll(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/unban_chat_member.md b/docs/api/methods/unban_chat_member.md
index b054cbac..2c18ed5e 100644
--- a/docs/api/methods/unban_chat_member.md
+++ b/docs/api/methods/unban_chat_member.md
@@ -38,21 +38,21 @@ Imports:
- `from aiogram.api.methods import UnbanChatMember`
- `from aiogram.api.methods.unban_chat_member import UnbanChatMember`
-#### As reply into Webhook
-```python3
-return UnbanChatMember(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(UnbanChatMember(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await UnbanChatMember(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(UnbanChatMember(...))
+```
+#### As reply into Webhook in handler
+```python3
+return UnbanChatMember(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/unpin_chat_message.md b/docs/api/methods/unpin_chat_message.md
index 4b76b651..b49bf991 100644
--- a/docs/api/methods/unpin_chat_message.md
+++ b/docs/api/methods/unpin_chat_message.md
@@ -37,21 +37,21 @@ Imports:
- `from aiogram.api.methods import UnpinChatMessage`
- `from aiogram.api.methods.unpin_chat_message import UnpinChatMessage`
-#### As reply into Webhook
-```python3
-return UnpinChatMessage(...)
-```
-
-#### With specific bot
-```python3
-result: bool = await bot.emit(UnpinChatMessage(...))
-```
-
#### In handlers with current bot
```python3
result: bool = await UnpinChatMessage(...)
```
+#### With specific bot
+```python3
+result: bool = await bot(UnpinChatMessage(...))
+```
+#### As reply into Webhook in handler
+```python3
+return UnpinChatMessage(...)
+```
+
+
## Related pages:
diff --git a/docs/api/methods/upload_sticker_file.md b/docs/api/methods/upload_sticker_file.md
index 7a4ff16e..b14b250e 100644
--- a/docs/api/methods/upload_sticker_file.md
+++ b/docs/api/methods/upload_sticker_file.md
@@ -38,20 +38,21 @@ Imports:
- `from aiogram.api.methods import UploadStickerFile`
- `from aiogram.api.methods.upload_sticker_file import UploadStickerFile`
-
-#### With specific bot
-```python3
-result: File = await bot.emit(UploadStickerFile(...))
-```
-
#### In handlers with current bot
```python3
result: File = await UploadStickerFile(...)
```
+#### With specific bot
+```python3
+result: File = await bot(UploadStickerFile(...))
+```
+
+
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#uploadstickerfile)
-- [aiogram.types.InputFile](../types/input_file.md)
- [aiogram.types.File](../types/file.md)
+- [aiogram.types.InputFile](../types/input_file.md)
+- [How to upload file?](../sending_files.md)
diff --git a/docs/api/types/animation.md b/docs/api/types/animation.md
index 75f57efd..db527991 100644
--- a/docs/api/types/animation.md
+++ b/docs/api/types/animation.md
@@ -9,7 +9,8 @@ This object represents an animation file (GIF or H.264/MPEG-4 AVC video without
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `width` | `#!python int` | Video width as defined by sender |
| `height` | `#!python int` | Video height as defined by sender |
| `duration` | `#!python int` | Duration of the video in seconds as defined by sender |
diff --git a/docs/api/types/audio.md b/docs/api/types/audio.md
index e56505b8..694f883c 100644
--- a/docs/api/types/audio.md
+++ b/docs/api/types/audio.md
@@ -9,7 +9,8 @@ This object represents an audio file to be treated as music by the Telegram clie
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `duration` | `#!python int` | Duration of the audio in seconds as defined by sender |
| `performer` | `#!python Optional[str]` | Optional. Performer of the audio as defined by sender or by audio tags |
| `title` | `#!python Optional[str]` | Optional. Title of the audio as defined by sender or by audio tags |
diff --git a/docs/api/types/callback_query.md b/docs/api/types/callback_query.md
index 5fc09499..1a7c5312 100644
--- a/docs/api/types/callback_query.md
+++ b/docs/api/types/callback_query.md
@@ -30,5 +30,5 @@ NOTE: After the user presses a callback button, Telegram clients will display a
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#callbackquery)
-- [aiogram.types.User](../types/user.md)
- [aiogram.types.Message](../types/message.md)
+- [aiogram.types.User](../types/user.md)
diff --git a/docs/api/types/chat.md b/docs/api/types/chat.md
index b2aacbdf..c269927c 100644
--- a/docs/api/types/chat.md
+++ b/docs/api/types/chat.md
@@ -20,6 +20,7 @@ This object represents a chat.
| `invite_link` | `#!python Optional[str]` | Optional. Chat invite link, for groups, supergroups and channel chats. Each administrator in a chat generates their own invite links, so the bot must first generate the link using exportChatInviteLink. Returned only in getChat. |
| `pinned_message` | `#!python Optional[Message]` | Optional. Pinned message, for groups, supergroups and channels. Returned only in getChat. |
| `permissions` | `#!python Optional[ChatPermissions]` | Optional. Default chat member permissions, for groups and supergroups. Returned only in getChat. |
+| `slow_mode_delay` | `#!python Optional[int]` | Optional. For supergroups, the minimum allowed delay between consecutive messages sent by each unpriviledged user. Returned only in getChat. |
| `sticker_set_name` | `#!python Optional[str]` | Optional. For supergroups, name of group sticker set. Returned only in getChat. |
| `can_set_sticker_set` | `#!python Optional[bool]` | Optional. True, if the bot can change the group sticker set. Returned only in getChat. |
diff --git a/docs/api/types/chat_member.md b/docs/api/types/chat_member.md
index 08b4f9a4..d475c33d 100644
--- a/docs/api/types/chat_member.md
+++ b/docs/api/types/chat_member.md
@@ -11,6 +11,7 @@ This object contains information about one member of a chat.
| - | - | - |
| `user` | `#!python User` | Information about the user |
| `status` | `#!python str` | The member's status in the chat. Can be 'creator', 'administrator', 'member', 'restricted', 'left' or 'kicked' |
+| `custom_title` | `#!python Optional[str]` | Optional. Owner and administrators only. Custom title for this user |
| `until_date` | `#!python Optional[Union[int, datetime.datetime, datetime.timedelta]]` | Optional. Restricted and kicked only. Date when restrictions will be lifted for this user; unix time |
| `can_be_edited` | `#!python Optional[bool]` | Optional. Administrators only. True, if the bot is allowed to edit administrator privileges of that user |
| `can_post_messages` | `#!python Optional[bool]` | Optional. Administrators only. True, if the administrator can post in the channel; channels only |
diff --git a/docs/api/types/chat_photo.md b/docs/api/types/chat_photo.md
index 954ceb0c..2098d4da 100644
--- a/docs/api/types/chat_photo.md
+++ b/docs/api/types/chat_photo.md
@@ -10,7 +10,9 @@ This object represents a chat photo.
| Name | Type | Description |
| - | - | - |
| `small_file_id` | `#!python str` | File identifier of small (160x160) chat photo. This file_id can be used only for photo download and only for as long as the photo is not changed. |
+| `small_file_unique_id` | `#!python str` | Unique file identifier of small (160x160) chat photo, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `big_file_id` | `#!python str` | File identifier of big (640x640) chat photo. This file_id can be used only for photo download and only for as long as the photo is not changed. |
+| `big_file_unique_id` | `#!python str` | Unique file identifier of big (640x640) chat photo, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
diff --git a/docs/api/types/document.md b/docs/api/types/document.md
index 316f4d19..bed757d9 100644
--- a/docs/api/types/document.md
+++ b/docs/api/types/document.md
@@ -9,7 +9,8 @@ This object represents a general file (as opposed to photos, voice messages and
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `thumb` | `#!python Optional[PhotoSize]` | Optional. Document thumbnail as defined by sender |
| `file_name` | `#!python Optional[str]` | Optional. Original filename as defined by sender |
| `mime_type` | `#!python Optional[str]` | Optional. MIME type of the file as defined by sender |
diff --git a/docs/api/types/file.md b/docs/api/types/file.md
index 32fb6cb3..7f914b41 100644
--- a/docs/api/types/file.md
+++ b/docs/api/types/file.md
@@ -11,7 +11,8 @@ Maximum file size to download is 20 MB
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `file_size` | `#!python Optional[int]` | Optional. File size, if known |
| `file_path` | `#!python Optional[str]` | Optional. File path. Use https://api.telegram.org/file/bot/ to get the file. |
diff --git a/docs/api/types/game.md b/docs/api/types/game.md
index 95f02332..52e5af79 100644
--- a/docs/api/types/game.md
+++ b/docs/api/types/game.md
@@ -27,6 +27,6 @@ This object represents a game. Use BotFather to create and edit games, their sho
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#game)
-- [aiogram.types.MessageEntity](../types/message_entity.md)
- [aiogram.types.Animation](../types/animation.md)
+- [aiogram.types.MessageEntity](../types/message_entity.md)
- [aiogram.types.PhotoSize](../types/photo_size.md)
diff --git a/docs/api/types/inline_keyboard_button.md b/docs/api/types/inline_keyboard_button.md
index 38de8c65..173ddb4e 100644
--- a/docs/api/types/inline_keyboard_button.md
+++ b/docs/api/types/inline_keyboard_button.md
@@ -29,5 +29,5 @@ This object represents one button of an inline keyboard. You must use exactly on
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinekeyboardbutton)
-- [aiogram.types.LoginUrl](../types/login_url.md)
- [aiogram.types.CallbackGame](../types/callback_game.md)
+- [aiogram.types.LoginUrl](../types/login_url.md)
diff --git a/docs/api/types/inline_query_result_article.md b/docs/api/types/inline_query_result_article.md
index 3b0e6f06..e8829c4e 100644
--- a/docs/api/types/inline_query_result_article.md
+++ b/docs/api/types/inline_query_result_article.md
@@ -32,5 +32,5 @@ Represents a link to an article or web page.
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultarticle)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_audio.md b/docs/api/types/inline_query_result_audio.md
index 93ded16e..38d1bb91 100644
--- a/docs/api/types/inline_query_result_audio.md
+++ b/docs/api/types/inline_query_result_audio.md
@@ -33,5 +33,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultaudio)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_cached_audio.md b/docs/api/types/inline_query_result_cached_audio.md
index cfc938d9..c1110f8e 100644
--- a/docs/api/types/inline_query_result_cached_audio.md
+++ b/docs/api/types/inline_query_result_cached_audio.md
@@ -30,5 +30,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcachedaudio)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_cached_document.md b/docs/api/types/inline_query_result_cached_document.md
index 3b7898c7..7401235f 100644
--- a/docs/api/types/inline_query_result_cached_document.md
+++ b/docs/api/types/inline_query_result_cached_document.md
@@ -32,5 +32,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcacheddocument)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_cached_gif.md b/docs/api/types/inline_query_result_cached_gif.md
index 93c18449..44c4820d 100644
--- a/docs/api/types/inline_query_result_cached_gif.md
+++ b/docs/api/types/inline_query_result_cached_gif.md
@@ -29,5 +29,5 @@ Represents a link to an animated GIF file stored on the Telegram servers. By def
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcachedgif)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_cached_mpeg4_gif.md b/docs/api/types/inline_query_result_cached_mpeg4_gif.md
index bef9c476..0ae5bbf6 100644
--- a/docs/api/types/inline_query_result_cached_mpeg4_gif.md
+++ b/docs/api/types/inline_query_result_cached_mpeg4_gif.md
@@ -29,5 +29,5 @@ Represents a link to a video animation (H.264/MPEG-4 AVC video without sound) st
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcachedmpeg4gif)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_cached_photo.md b/docs/api/types/inline_query_result_cached_photo.md
index ed7a9331..1ce40aa8 100644
--- a/docs/api/types/inline_query_result_cached_photo.md
+++ b/docs/api/types/inline_query_result_cached_photo.md
@@ -30,5 +30,5 @@ Represents a link to a photo stored on the Telegram servers. By default, this ph
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcachedphoto)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_cached_sticker.md b/docs/api/types/inline_query_result_cached_sticker.md
index 6231bfc5..39c66b0a 100644
--- a/docs/api/types/inline_query_result_cached_sticker.md
+++ b/docs/api/types/inline_query_result_cached_sticker.md
@@ -28,5 +28,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016 for
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcachedsticker)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_cached_video.md b/docs/api/types/inline_query_result_cached_video.md
index 395a3736..6e12fbbc 100644
--- a/docs/api/types/inline_query_result_cached_video.md
+++ b/docs/api/types/inline_query_result_cached_video.md
@@ -30,5 +30,5 @@ Represents a link to a video file stored on the Telegram servers. By default, th
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcachedvideo)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_cached_voice.md b/docs/api/types/inline_query_result_cached_voice.md
index e809f3a6..aadcbd0e 100644
--- a/docs/api/types/inline_query_result_cached_voice.md
+++ b/docs/api/types/inline_query_result_cached_voice.md
@@ -31,5 +31,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcachedvoice)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_contact.md b/docs/api/types/inline_query_result_contact.md
index 71f9a972..65088d5f 100644
--- a/docs/api/types/inline_query_result_contact.md
+++ b/docs/api/types/inline_query_result_contact.md
@@ -34,5 +34,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultcontact)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_document.md b/docs/api/types/inline_query_result_document.md
index f71b317f..05c783d7 100644
--- a/docs/api/types/inline_query_result_document.md
+++ b/docs/api/types/inline_query_result_document.md
@@ -36,5 +36,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultdocument)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_gif.md b/docs/api/types/inline_query_result_gif.md
index 17af669c..4365c243 100644
--- a/docs/api/types/inline_query_result_gif.md
+++ b/docs/api/types/inline_query_result_gif.md
@@ -33,5 +33,5 @@ Represents a link to an animated GIF file. By default, this animated GIF file wi
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultgif)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_location.md b/docs/api/types/inline_query_result_location.md
index 334365c1..e4c35ef8 100644
--- a/docs/api/types/inline_query_result_location.md
+++ b/docs/api/types/inline_query_result_location.md
@@ -34,5 +34,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultlocation)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_mpeg4_gif.md b/docs/api/types/inline_query_result_mpeg4_gif.md
index 52ee96d0..934611ab 100644
--- a/docs/api/types/inline_query_result_mpeg4_gif.md
+++ b/docs/api/types/inline_query_result_mpeg4_gif.md
@@ -33,5 +33,5 @@ Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). B
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultmpeg4gif)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_photo.md b/docs/api/types/inline_query_result_photo.md
index 77b2dddc..96d71636 100644
--- a/docs/api/types/inline_query_result_photo.md
+++ b/docs/api/types/inline_query_result_photo.md
@@ -33,5 +33,5 @@ Represents a link to a photo. By default, this photo will be sent by the user wi
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultphoto)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_venue.md b/docs/api/types/inline_query_result_venue.md
index 539e163a..a2e545a1 100644
--- a/docs/api/types/inline_query_result_venue.md
+++ b/docs/api/types/inline_query_result_venue.md
@@ -36,5 +36,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultvenue)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_video.md b/docs/api/types/inline_query_result_video.md
index e4f50f97..b212f03a 100644
--- a/docs/api/types/inline_query_result_video.md
+++ b/docs/api/types/inline_query_result_video.md
@@ -37,5 +37,5 @@ If an InlineQueryResultVideo message contains an embedded video (e.g., YouTube),
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultvideo)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/inline_query_result_voice.md b/docs/api/types/inline_query_result_voice.md
index f13a2bd8..f7725c5a 100644
--- a/docs/api/types/inline_query_result_voice.md
+++ b/docs/api/types/inline_query_result_voice.md
@@ -32,5 +32,5 @@ Note: This will only work in Telegram versions released after 9 April, 2016. Old
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#inlinequeryresultvoice)
-- [aiogram.types.InputMessageContent](../types/input_message_content.md)
- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.InputMessageContent](../types/input_message_content.md)
diff --git a/docs/api/types/input_file.md b/docs/api/types/input_file.md
index ca034c7f..d062e1d7 100644
--- a/docs/api/types/input_file.md
+++ b/docs/api/types/input_file.md
@@ -14,5 +14,6 @@ This object represents the contents of a file to be uploaded. Must be posted usi
- `from aiogram.api.types.input_file import InputFile`
## Related pages:
+
- [Official documentation](https://core.telegram.org/bots/api#inputfile)
- [How to upload file?](../sending_files.md)
diff --git a/docs/api/types/message.md b/docs/api/types/message.md
index c12879c9..976b54e1 100644
--- a/docs/api/types/message.md
+++ b/docs/api/types/message.md
@@ -68,23 +68,23 @@ This object represents a message.
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#message)
-- [aiogram.types.Poll](../types/poll.md)
-- [aiogram.types.PassportData](../types/passport_data.md)
-- [aiogram.types.Video](../types/video.md)
-- [aiogram.types.MessageEntity](../types/message_entity.md)
-- [aiogram.types.PhotoSize](../types/photo_size.md)
+- [aiogram.types.Animation](../types/animation.md)
+- [aiogram.types.Audio](../types/audio.md)
+- [aiogram.types.Chat](../types/chat.md)
- [aiogram.types.Contact](../types/contact.md)
- [aiogram.types.Document](../types/document.md)
-- [aiogram.types.Animation](../types/animation.md)
-- [aiogram.types.SuccessfulPayment](../types/successful_payment.md)
-- [aiogram.types.Chat](../types/chat.md)
-- [aiogram.types.Audio](../types/audio.md)
- [aiogram.types.Game](../types/game.md)
-- [aiogram.types.Voice](../types/voice.md)
-- [aiogram.types.VideoNote](../types/video_note.md)
+- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
- [aiogram.types.Invoice](../types/invoice.md)
- [aiogram.types.Location](../types/location.md)
+- [aiogram.types.MessageEntity](../types/message_entity.md)
+- [aiogram.types.PassportData](../types/passport_data.md)
+- [aiogram.types.PhotoSize](../types/photo_size.md)
+- [aiogram.types.Poll](../types/poll.md)
- [aiogram.types.Sticker](../types/sticker.md)
-- [aiogram.types.InlineKeyboardMarkup](../types/inline_keyboard_markup.md)
+- [aiogram.types.SuccessfulPayment](../types/successful_payment.md)
- [aiogram.types.User](../types/user.md)
- [aiogram.types.Venue](../types/venue.md)
+- [aiogram.types.Video](../types/video.md)
+- [aiogram.types.VideoNote](../types/video_note.md)
+- [aiogram.types.Voice](../types/voice.md)
diff --git a/docs/api/types/message_entity.md b/docs/api/types/message_entity.md
index 48282a71..702d7701 100644
--- a/docs/api/types/message_entity.md
+++ b/docs/api/types/message_entity.md
@@ -9,7 +9,7 @@ This object represents one special entity in a text message. For example, hashta
| Name | Type | Description |
| - | - | - |
-| `type` | `#!python str` | Type of the entity. Can be mention (@username), hashtag, cashtag, bot_command, url, email, phone_number, bold (bold text), italic (italic text), code (monowidth string), pre (monowidth block), text_link (for clickable text URLs), text_mention (for users without usernames) |
+| `type` | `#!python str` | Type of the entity. Can be 'mention' (@username), 'hashtag' (#hashtag), 'cashtag' ($USD), 'bot_command' (/start@jobs_bot), 'url' (https://telegram.org), 'email' (do-not-reply@telegram.org), 'phone_number' (+1-212-555-0123), 'bold' (bold text), 'italic' (italic text), 'underline' (underlined text), 'strikethrough' (strikethrough text), 'code' (monowidth string), 'pre' (monowidth block), 'text_link' (for clickable text URLs), 'text_mention' (for users without usernames) |
| `offset` | `#!python int` | Offset in UTF-16 code units to the start of the entity |
| `length` | `#!python int` | Length of the entity in UTF-16 code units |
| `url` | `#!python Optional[str]` | Optional. For 'text_link' only, url that will be opened after user taps on the text |
diff --git a/docs/api/types/passport_data.md b/docs/api/types/passport_data.md
index 5cf9694f..ac165be0 100644
--- a/docs/api/types/passport_data.md
+++ b/docs/api/types/passport_data.md
@@ -23,5 +23,5 @@ Contains information about Telegram Passport data shared with the bot by the use
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#passportdata)
-- [aiogram.types.EncryptedPassportElement](../types/encrypted_passport_element.md)
- [aiogram.types.EncryptedCredentials](../types/encrypted_credentials.md)
+- [aiogram.types.EncryptedPassportElement](../types/encrypted_passport_element.md)
diff --git a/docs/api/types/passport_file.md b/docs/api/types/passport_file.md
index 2883c6cf..ed8a7561 100644
--- a/docs/api/types/passport_file.md
+++ b/docs/api/types/passport_file.md
@@ -9,7 +9,8 @@ This object represents a file uploaded to Telegram Passport. Currently all Teleg
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `file_size` | `#!python int` | File size |
| `file_date` | `#!python int` | Unix time when the file was uploaded |
diff --git a/docs/api/types/photo_size.md b/docs/api/types/photo_size.md
index 42f5fe14..ee13b2cf 100644
--- a/docs/api/types/photo_size.md
+++ b/docs/api/types/photo_size.md
@@ -9,7 +9,8 @@ This object represents one size of a photo or a file / sticker thumbnail.
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `width` | `#!python int` | Photo width |
| `height` | `#!python int` | Photo height |
| `file_size` | `#!python Optional[int]` | Optional. File size |
diff --git a/docs/api/types/sticker.md b/docs/api/types/sticker.md
index ff945b24..dde51a74 100644
--- a/docs/api/types/sticker.md
+++ b/docs/api/types/sticker.md
@@ -9,7 +9,8 @@ This object represents a sticker.
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `width` | `#!python int` | Sticker width |
| `height` | `#!python int` | Sticker height |
| `is_animated` | `#!python bool` | True, if the sticker is animated |
diff --git a/docs/api/types/update.md b/docs/api/types/update.md
index b1f95eba..78a8d241 100644
--- a/docs/api/types/update.md
+++ b/docs/api/types/update.md
@@ -34,10 +34,10 @@ At most one of the optional parameters can be present in any given update.
## Related pages:
- [Official documentation](https://core.telegram.org/bots/api#update)
-- [aiogram.types.Poll](../types/poll.md)
- [aiogram.types.CallbackQuery](../types/callback_query.md)
-- [aiogram.types.InlineQuery](../types/inline_query.md)
- [aiogram.types.ChosenInlineResult](../types/chosen_inline_result.md)
+- [aiogram.types.InlineQuery](../types/inline_query.md)
- [aiogram.types.Message](../types/message.md)
-- [aiogram.types.ShippingQuery](../types/shipping_query.md)
+- [aiogram.types.Poll](../types/poll.md)
- [aiogram.types.PreCheckoutQuery](../types/pre_checkout_query.md)
+- [aiogram.types.ShippingQuery](../types/shipping_query.md)
diff --git a/docs/api/types/video.md b/docs/api/types/video.md
index 9e368de2..2e43020b 100644
--- a/docs/api/types/video.md
+++ b/docs/api/types/video.md
@@ -9,7 +9,8 @@ This object represents a video file.
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `width` | `#!python int` | Video width as defined by sender |
| `height` | `#!python int` | Video height as defined by sender |
| `duration` | `#!python int` | Duration of the video in seconds as defined by sender |
diff --git a/docs/api/types/video_note.md b/docs/api/types/video_note.md
index 9222b6be..34387929 100644
--- a/docs/api/types/video_note.md
+++ b/docs/api/types/video_note.md
@@ -9,7 +9,8 @@ This object represents a video message (available in Telegram apps as of v.4.0).
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `length` | `#!python int` | Video width and height (diameter of the video message) as defined by sender |
| `duration` | `#!python int` | Duration of the video in seconds as defined by sender |
| `thumb` | `#!python Optional[PhotoSize]` | Optional. Video thumbnail |
diff --git a/docs/api/types/voice.md b/docs/api/types/voice.md
index 776e920b..f108efcb 100644
--- a/docs/api/types/voice.md
+++ b/docs/api/types/voice.md
@@ -9,7 +9,8 @@ This object represents a voice note.
| Name | Type | Description |
| - | - | - |
-| `file_id` | `#!python str` | Identifier for this file |
+| `file_id` | `#!python str` | Identifier for this file, which can be used to download or reuse the file |
+| `file_unique_id` | `#!python str` | Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. |
| `duration` | `#!python int` | Duration of the audio in seconds as defined by sender |
| `mime_type` | `#!python Optional[str]` | Optional. MIME type of the file as defined by sender |
| `file_size` | `#!python Optional[int]` | Optional. File size |
diff --git a/docs/dispatcher/router.md b/docs/dispatcher/router.md
index f22136c1..c08df6b8 100644
--- a/docs/dispatcher/router.md
+++ b/docs/dispatcher/router.md
@@ -28,77 +28,77 @@ Here is list of available observers and examples how to register handlers (In ex
### Update
```python3
-@router.update_handler():
+@router.update_handler()
async def message_handler(update: types.Update) -> Any: pass
```
Should be used for handling [updates](../api/types/update.md). By default Router is already have an update handler which route all event types to another observers.
### Message
```python3
-@router.message_handler():
+@router.message_handler()
async def message_handler(message: types.Message) -> Any: pass
```
Is useful for handling [message](../api/types/message.md)
### Edited message
```python3
-@router.edited_message_handler():
+@router.edited_message_handler()
async def edited_message_handler(edited_message: types.Message) -> Any: pass
```
Is useful for handling [edited messages](../api/types/message.md)
### Channel post
```python3
-@router.channel_post_handler():
+@router.channel_post_handler()
async def channel_post_handler(channel_post: types.Message) -> Any: pass
```
Is useful for handling [channel posts](../api/types/message.md)
### Edited channel post
```python3
-@router.edited_channel_post_handler():
+@router.edited_channel_post_handler()
async def edited_channel_post_handler(edited_channel_post: types.Message) -> Any: pass
```
Is useful for handling [edited channel posts](../api/types/message.md)
### Inline query
```python3
-@router.inline_query_handler():
+@router.inline_query_handler()
async def inline_query_handler(inline_query: types.Message) -> Any: pass
```
Is useful for handling [inline query](../api/types/inline_query.md)
### Chosen inline query
```python3
-@router.chosen_inline_result_handler():
+@router.chosen_inline_result_handler()
async def chosen_inline_result_handler(chosen_inline_result: types.ChosenInlineResult) -> Any: pass
```
Is useful for handling [chosen inline query](../api/types/chosen_inline_result.md)
### Callback query
```python3
-@router.callback_query_handler():
+@router.callback_query_handler()
async def callback_query_handler(callback_query: types.CallbackQuery) -> Any: pass
```
Is useful for handling [callback query's](../api/types/callback_query.md)
### Shipping query
```python3
-@router.shipping_query_handler():
+@router.shipping_query_handler()
async def shipping_query_handler(shipping_query: types.ShippingQuery) -> Any: pass
```
Is useful for handling [shipping query](../api/types/shipping_query.md)
### Pre checkout query
```python3
-@router.pre_checkout_query_handler():
+@router.pre_checkout_query_handler()
async def pre_checkout_query_handler(pre_checkout_query: types.PreCheckoutQuery) -> Any: pass
```
Is useful for handling [pre-checkout query](../api/types/pre_checkout_query.md)
### Poll
```python3
-@router.poll_handler():
+@router.poll_handler()
async def poll_handler(poll: types.Poll) -> Any: pass
```
Is useful for handling [polls](../api/types/poll.md)
diff --git a/docs/index.md b/docs/index.md
index 5bd98ffe..073f8d61 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -4,7 +4,7 @@ Documentation for version 3.0 [WIP] [^1]
[](https://opensource.org/licenses/MIT)
[](https://pypi.python.org/pypi/aiogram)
-[](https://core.telegram.org/bots/api)
+[](https://core.telegram.org/bots/api)
[](https://pypi.python.org/pypi/aiogram)
[](https://pypi.python.org/pypi/aiogram)
[](https://pypi.python.org/pypi/aiogram)
@@ -16,7 +16,7 @@ Documentation for version 3.0 [WIP] [^1]
## Features
- Asynchronous
-- [Supports Telegram Bot API v4.4](api/index.md)
+- [Supports Telegram Bot API v4.5](api/index.md)
- Finite State Machine
- [Replies into Webhook](https://core.telegram.org/bots/faq#how-can-i-make-requests-in-response-to-updates)
- Middlewares
diff --git a/mkdocs.yml b/mkdocs.yml
index c74954ac..3d5d70b4 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,11 +1,11 @@
site_name: aiogram
site_description: 'Documentations of aiogram framework'
site_author: 'Alex Root Junior'
-site_url: 'https://aiogram.2038.io'
+site_url: 'https://docs.aiogram.dev'
repo_name: 'aiogram/aiogram'
repo_url: 'https://github.com/aiogram/aiogram'
-google_analytics: ['UA-63525804-7', 'aiogram.2038.io']
+google_analytics: ['UA-63525804-7', 'dev-docs.aiogram.dev']
theme:
name: 'material'
@@ -70,6 +70,7 @@ nav:
- api/methods/unban_chat_member.md
- api/methods/restrict_chat_member.md
- api/methods/promote_chat_member.md
+ - api/methods/set_chat_administrator_custom_title.md
- api/methods/set_chat_permissions.md
- api/methods/export_chat_invite_link.md
- api/methods/set_chat_photo.md
diff --git a/poetry.lock b/poetry.lock
index 303ee594..09f53fba 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -33,7 +33,7 @@ python-versions = "*"
version = "1.4.3"
[[package]]
-category = "main"
+category = "dev"
description = "Disable App Nap on OS X 10.9"
marker = "sys_platform == \"darwin\""
name = "appnope"
@@ -72,6 +72,7 @@ version = "3.0.1"
[[package]]
category = "dev"
description = "Enhance the standard unittest package with features for testing asyncio libraries"
+marker = "python_version < \"3.8\""
name = "asynctest"
optional = false
python-versions = ">=3.5"
@@ -106,13 +107,13 @@ description = "Internationalization utilities"
name = "babel"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "2.7.0"
+version = "2.8.0"
[package.dependencies]
pytz = ">=2015.7"
[[package]]
-category = "main"
+category = "dev"
description = "Specifications for callback functions passed in to an API"
name = "backcall"
optional = false
@@ -153,7 +154,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "7.0"
[[package]]
-category = "main"
+category = "dev"
description = "Cross-platform colored terminal text."
marker = "python_version >= \"3.5\" and sys_platform == \"win32\" or sys_platform == \"win32\""
name = "colorama"
@@ -167,13 +168,13 @@ description = "Code coverage measurement for Python"
name = "coverage"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
-version = "5.0.1"
+version = "5.0.2"
[package.extras]
toml = ["toml"]
[[package]]
-category = "main"
+category = "dev"
description = "Decorators for Humans"
name = "decorator"
optional = false
@@ -238,7 +239,7 @@ marker = "python_version >= \"3.5\" and python_version < \"3.8\" or python_versi
name = "importlib-metadata"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-version = "1.3.0"
+version = "1.4.0"
[package.dependencies]
zipp = ">=0.5"
@@ -248,12 +249,12 @@ docs = ["sphinx", "rst.linker"]
testing = ["packaging", "importlib-resources"]
[[package]]
-category = "main"
+category = "dev"
description = "IPython: Productive Interactive Computing"
name = "ipython"
optional = false
python-versions = ">=3.6"
-version = "7.10.2"
+version = "7.11.1"
[package.dependencies]
appnope = "*"
@@ -269,7 +270,7 @@ setuptools = ">=18.5"
traitlets = ">=4.2"
[package.extras]
-all = ["nose (>=0.10.1)", "qtconsole", "pygments", "nbconvert", "Sphinx (>=1.3)", "nbformat", "requests", "testpath", "ipykernel", "notebook", "ipyparallel", "ipywidgets", "numpy (>=1.14)"]
+all = ["ipywidgets", "ipyparallel", "qtconsole", "ipykernel", "nbconvert", "notebook", "nbformat", "testpath", "pygments", "requests", "numpy (>=1.14)", "nose (>=0.10.1)", "Sphinx (>=1.3)"]
doc = ["Sphinx (>=1.3)"]
kernel = ["ipykernel"]
nbconvert = ["nbconvert"]
@@ -280,7 +281,7 @@ qtconsole = ["qtconsole"]
test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.14)"]
[[package]]
-category = "main"
+category = "dev"
description = "Vestigial utilities from IPython"
name = "ipython-genutils"
optional = false
@@ -302,7 +303,7 @@ requirements = ["pipreqs", "pip-api"]
xdg_home = ["appdirs (>=1.4.0)"]
[[package]]
-category = "main"
+category = "dev"
description = "An autocompletion tool for Python that can be used for text editors."
name = "jedi"
optional = false
@@ -451,7 +452,7 @@ description = "More routines for operating on iterables, beyond itertools"
name = "more-itertools"
optional = false
python-versions = ">=3.5"
-version = "8.0.2"
+version = "8.1.0"
[[package]]
category = "main"
@@ -459,7 +460,7 @@ description = "multidict implementation"
name = "multidict"
optional = false
python-versions = ">=3.5"
-version = "4.7.2"
+version = "4.7.4"
[[package]]
category = "dev"
@@ -467,10 +468,10 @@ description = "Optional static typing for Python"
name = "mypy"
optional = false
python-versions = ">=3.5"
-version = "0.750"
+version = "0.761"
[package.dependencies]
-mypy-extensions = ">=0.4.0,<0.5.0"
+mypy-extensions = ">=0.4.3,<0.5.0"
typed-ast = ">=1.4.0,<1.5.0"
typing-extensions = ">=3.7.4"
@@ -491,14 +492,14 @@ description = "Core utilities for Python packages"
name = "packaging"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "19.2"
+version = "20.0"
[package.dependencies]
pyparsing = ">=2.0.2"
six = "*"
[[package]]
-category = "main"
+category = "dev"
description = "A Python Parser"
name = "parso"
optional = false
@@ -517,7 +518,7 @@ python-versions = "*"
version = "1.0"
[[package]]
-category = "main"
+category = "dev"
description = "Pexpect allows easy control of interactive console applications."
marker = "sys_platform != \"win32\""
name = "pexpect"
@@ -529,7 +530,7 @@ version = "4.7.0"
ptyprocess = ">=0.5"
[[package]]
-category = "main"
+category = "dev"
description = "Tiny 'shelve'-like database with concurrency support"
name = "pickleshare"
optional = false
@@ -553,7 +554,7 @@ version = ">=0.12"
dev = ["pre-commit", "tox"]
[[package]]
-category = "main"
+category = "dev"
description = "Library for building powerful interactive command lines in Python"
name = "prompt-toolkit"
optional = false
@@ -564,7 +565,7 @@ version = "3.0.2"
wcwidth = "*"
[[package]]
-category = "main"
+category = "dev"
description = "Run a subprocess in a pseudo terminal"
marker = "sys_platform != \"win32\""
name = "ptyprocess"
@@ -578,7 +579,7 @@ description = "library with cross-python path, ini-parsing, io, code, log facili
name = "py"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.8.0"
+version = "1.8.1"
[[package]]
category = "dev"
@@ -609,7 +610,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.1.1"
[[package]]
-category = "main"
+category = "dev"
description = "Pygments is a syntax highlighting package written in Python."
name = "pygments"
optional = false
@@ -719,7 +720,7 @@ description = "Thin-wrapper around the mock package for easier use with py.test"
name = "pytest-mock"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.13.0"
+version = "2.0.0"
[package.dependencies]
pytest = ">=2.7"
@@ -761,11 +762,11 @@ category = "dev"
description = "YAML parser and emitter for Python"
name = "pyyaml"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "5.2"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "5.3"
[[package]]
-category = "main"
+category = "dev"
description = "Python 2 and 3 compatibility utilities"
name = "six"
optional = false
@@ -789,7 +790,7 @@ python-versions = ">= 3.5"
version = "6.0.3"
[[package]]
-category = "main"
+category = "dev"
description = "Traitlets Python config system"
name = "traitlets"
optional = false
@@ -829,12 +830,12 @@ python-versions = "*"
version = "0.14.0"
[[package]]
-category = "main"
+category = "dev"
description = "Measures number of Terminal column cells of wide-character codes"
name = "wcwidth"
optional = false
python-versions = "*"
-version = "0.1.7"
+version = "0.1.8"
[[package]]
category = "main"
@@ -868,7 +869,7 @@ testing = ["pathlib2", "contextlib2", "unittest2"]
fast = ["uvloop"]
[metadata]
-content-hash = "6740ebe6e8395a46b6c5b0590632cee2cb1b0712556cb7c89c9fe8a1e1270dc1"
+content-hash = "ab163ac1d239335c7e8d9cb1e9c02e878b17609ab3639fe3c2ad37c3fec5b462"
python-versions = "^3.7"
[metadata.files]
@@ -922,8 +923,8 @@ attrs = [
{file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
]
babel = [
- {file = "Babel-2.7.0-py2.py3-none-any.whl", hash = "sha256:af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab"},
- {file = "Babel-2.7.0.tar.gz", hash = "sha256:e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"},
+ {file = "Babel-2.8.0-py2.py3-none-any.whl", hash = "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"},
+ {file = "Babel-2.8.0.tar.gz", hash = "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38"},
]
backcall = [
{file = "backcall-0.1.0.tar.gz", hash = "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4"},
@@ -946,37 +947,37 @@ colorama = [
{file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"},
]
coverage = [
- {file = "coverage-5.0.1-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:c90bda74e16bcd03861b09b1d37c0a4158feda5d5a036bb2d6e58de6ff65793e"},
- {file = "coverage-5.0.1-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:bb3d29df5d07d5399d58a394d0ef50adf303ab4fbf66dfd25b9ef258effcb692"},
- {file = "coverage-5.0.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1ca43dbd739c0fc30b0a3637a003a0d2c7edc1dd618359d58cc1e211742f8bd1"},
- {file = "coverage-5.0.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:591506e088901bdc25620c37aec885e82cc896528f28c57e113751e3471fc314"},
- {file = "coverage-5.0.1-cp27-cp27m-win32.whl", hash = "sha256:a50b0888d8a021a3342d36a6086501e30de7d840ab68fca44913e97d14487dc1"},
- {file = "coverage-5.0.1-cp27-cp27m-win_amd64.whl", hash = "sha256:c792d3707a86c01c02607ae74364854220fb3e82735f631cd0a345dea6b4cee5"},
- {file = "coverage-5.0.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f425f50a6dd807cb9043d15a4fcfba3b5874a54d9587ccbb748899f70dc18c47"},
- {file = "coverage-5.0.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:25b8f60b5c7da71e64c18888f3067d5b6f1334b9681876b2fb41eea26de881ae"},
- {file = "coverage-5.0.1-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:7362a7f829feda10c7265b553455de596b83d1623b3d436b6d3c51c688c57bf6"},
- {file = "coverage-5.0.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:fcd4459fe35a400b8f416bc57906862693c9f88b66dc925e7f2a933e77f6b18b"},
- {file = "coverage-5.0.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:40fbfd6b044c9db13aeec1daf5887d322c710d811f944011757526ef6e323fd9"},
- {file = "coverage-5.0.1-cp35-cp35m-win32.whl", hash = "sha256:7f2675750c50151f806070ec11258edf4c328340916c53bac0adbc465abd6b1e"},
- {file = "coverage-5.0.1-cp35-cp35m-win_amd64.whl", hash = "sha256:24bcfa86fd9ce86b73a8368383c39d919c497a06eebb888b6f0c12f13e920b1a"},
- {file = "coverage-5.0.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:eeafb646f374988c22c8e6da5ab9fb81367ecfe81c70c292623373d2a021b1a1"},
- {file = "coverage-5.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:2ca2cd5264e84b2cafc73f0045437f70c6378c0d7dbcddc9ee3fe192c1e29e5d"},
- {file = "coverage-5.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2cc707fc9aad2592fc686d63ef72dc0031fc98b6fb921d2f5395d9ab84fbc3ef"},
- {file = "coverage-5.0.1-cp36-cp36m-win32.whl", hash = "sha256:04b961862334687549eb91cd5178a6fbe977ad365bddc7c60f2227f2f9880cf4"},
- {file = "coverage-5.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:232f0b52a5b978288f0bbc282a6c03fe48cd19a04202df44309919c142b3bb9c"},
- {file = "coverage-5.0.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:cfce79ce41cc1a1dc7fc85bb41eeeb32d34a4cf39a645c717c0550287e30ff06"},
- {file = "coverage-5.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c9c6a1d1190c0b75ec7c0f339088309952b82ae8d67a79ff1319eb4e749b96"},
- {file = "coverage-5.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1cbb88b34187bdb841f2599770b7e6ff8e259dc3bb64fc7893acf44998acf5f8"},
- {file = "coverage-5.0.1-cp37-cp37m-win32.whl", hash = "sha256:ff3936dd5feaefb4f91c8c1f50a06c588b5dc69fba4f7d9c79a6617ad80bb7df"},
- {file = "coverage-5.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:65bead1ac8c8930cf92a1ccaedcce19a57298547d5d1db5c9d4d068a0675c38b"},
- {file = "coverage-5.0.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:348630edea485f4228233c2f310a598abf8afa5f8c716c02a9698089687b6085"},
- {file = "coverage-5.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:960d7f42277391e8b1c0b0ae427a214e1b31a1278de6b73f8807b20c2e913bba"},
- {file = "coverage-5.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0101888bd1592a20ccadae081ba10e8b204d20235d18d05c6f7d5e904a38fc10"},
- {file = "coverage-5.0.1-cp38-cp38m-win32.whl", hash = "sha256:c0fff2733f7c2950f58a4fd09b5db257b00c6fec57bf3f68c5bae004d804b407"},
- {file = "coverage-5.0.1-cp38-cp38m-win_amd64.whl", hash = "sha256:5f622f19abda4e934938e24f1d67599249abc201844933a6f01aaa8663094489"},
- {file = "coverage-5.0.1-cp39-cp39m-win32.whl", hash = "sha256:2714160a63da18aed9340c70ed514973971ee7e665e6b336917ff4cca81a25b1"},
- {file = "coverage-5.0.1-cp39-cp39m-win_amd64.whl", hash = "sha256:b7dbc5e8c39ea3ad3db22715f1b5401cd698a621218680c6daf42c2f9d36e205"},
- {file = "coverage-5.0.1.tar.gz", hash = "sha256:5ac71bba1e07eab403b082c4428f868c1c9e26a21041436b4905c4c3d4e49b08"},
+ {file = "coverage-5.0.2-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:511ec0c00840e12fb4e852e4db58fa6a01ca4da72f36a9766fae344c3d502033"},
+ {file = "coverage-5.0.2-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:d22b4297e7e4225ccf01f1aa55e7a96412ea0796b532dd614c3fcbafa341128e"},
+ {file = "coverage-5.0.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:593853aa1ac6dcc6405324d877544c596c9d948ef20d2e9512a0f5d2d3202356"},
+ {file = "coverage-5.0.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:e65a5aa1670db6263f19fdc03daee1d7dbbadb5cb67fd0a1f16033659db13c1d"},
+ {file = "coverage-5.0.2-cp27-cp27m-win32.whl", hash = "sha256:d4a2b578a7a70e0c71f662705262f87a456f1e6c1e40ada7ea699abaf070a76d"},
+ {file = "coverage-5.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:28f7f73b34a05e23758e860a89a7f649b85c6749e252eff60ebb05532d180e86"},
+ {file = "coverage-5.0.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7d1cc7acc9ce55179616cf72154f9e648136ea55987edf84addbcd9886ffeba2"},
+ {file = "coverage-5.0.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:2d0cb9b1fe6ad0d915d45ad3d87f03a38e979093a98597e755930db1f897afae"},
+ {file = "coverage-5.0.2-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:bfe102659e2ec13b86c7f3b1db6c9a4e7beea4255058d006351339e6b342d5d2"},
+ {file = "coverage-5.0.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:23688ff75adfa8bfa2a67254d889f9bdf9302c27241d746e17547c42c732d3f4"},
+ {file = "coverage-5.0.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1bf7ba2af1d373a1750888724f84cffdfc697738f29a353c98195f98fc011509"},
+ {file = "coverage-5.0.2-cp35-cp35m-win32.whl", hash = "sha256:569f9ee3025682afda6e9b0f5bb14897c0db03f1a1dc088b083dd36e743f92bb"},
+ {file = "coverage-5.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:cf908840896f7aa62d0ec693beb53264b154f972eb8226fb864ac38975590c4f"},
+ {file = "coverage-5.0.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:eaad65bd20955131bcdb3967a4dea66b4e4d4ca488efed7c00d91ee0173387e8"},
+ {file = "coverage-5.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:225e79a5d485bc1642cb7ba02281419c633c216cdc6b26c26494ba959f09e69f"},
+ {file = "coverage-5.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bd82b684bb498c60ef47bb1541a50e6d006dde8579934dcbdbc61d67d1ea70d9"},
+ {file = "coverage-5.0.2-cp36-cp36m-win32.whl", hash = "sha256:7ca3db38a61f3655a2613ee2c190d63639215a7a736d3c64cc7bbdb002ce6310"},
+ {file = "coverage-5.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:47874b4711c5aeb295c31b228a758ce3d096be83dc37bd56da48ed99efb8813b"},
+ {file = "coverage-5.0.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:955ec084f549128fa2702f0b2dc696392001d986b71acd8fd47424f28289a9c3"},
+ {file = "coverage-5.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1f4ee8e2e4243971618bc16fcc4478317405205f135e95226c2496e2a3b8dbbf"},
+ {file = "coverage-5.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f45fba420b94165c17896861bb0e8b27fb7abdcedfeb154895d8553df90b7b00"},
+ {file = "coverage-5.0.2-cp37-cp37m-win32.whl", hash = "sha256:cca38ded59105f7705ef6ffe1e960b8db6c7d8279c1e71654a4775ab4454ca15"},
+ {file = "coverage-5.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:cb2b74c123f65e8166f7e1265829a6c8ed755c3cd16d7f50e75a83456a5f3fd7"},
+ {file = "coverage-5.0.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:53e7438fef0c97bc248f88ba1edd10268cd94d5609970aaf87abbe493691af87"},
+ {file = "coverage-5.0.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c1e4e39e43057396a5e9d069bfbb6ffeee892e40c5d2effbd8cd71f34ee66c4d"},
+ {file = "coverage-5.0.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5b0a07158360d22492f9abd02a0f2ee7981b33f0646bf796598b7673f6bbab14"},
+ {file = "coverage-5.0.2-cp38-cp38m-win32.whl", hash = "sha256:88b51153657612aea68fa684a5b88037597925260392b7bb4509d4f9b0bdd889"},
+ {file = "coverage-5.0.2-cp38-cp38m-win_amd64.whl", hash = "sha256:189aac76d6e0d7af15572c51892e7326ee451c076c5a50a9d266406cd6c49708"},
+ {file = "coverage-5.0.2-cp39-cp39m-win32.whl", hash = "sha256:d095a7b473f8a95f7efe821f92058c8a2ecfb18f8db6677ae3819e15dc11aaae"},
+ {file = "coverage-5.0.2-cp39-cp39m-win_amd64.whl", hash = "sha256:ddeb42a3d5419434742bf4cc71c9eaa22df3b76808e23a82bd0b0bd360f1a9f1"},
+ {file = "coverage-5.0.2.tar.gz", hash = "sha256:b251c7092cbb6d789d62dc9c9e7c4fb448c9138b51285c36aeb72462cad3600e"},
]
decorator = [
{file = "decorator-4.4.1-py2.py3-none-any.whl", hash = "sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"},
@@ -1002,12 +1003,12 @@ idna = [
{file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"},
]
importlib-metadata = [
- {file = "importlib_metadata-1.3.0-py2.py3-none-any.whl", hash = "sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f"},
- {file = "importlib_metadata-1.3.0.tar.gz", hash = "sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45"},
+ {file = "importlib_metadata-1.4.0-py2.py3-none-any.whl", hash = "sha256:bdd9b7c397c273bcc9a11d6629a38487cd07154fa255a467bf704cd2c258e359"},
+ {file = "importlib_metadata-1.4.0.tar.gz", hash = "sha256:f17c015735e1a88296994c0697ecea7e11db24290941983b08c9feb30921e6d8"},
]
ipython = [
- {file = "ipython-7.10.2-py3-none-any.whl", hash = "sha256:190a279bd3d4fc585a611e9358a88f1048cc57fd688254a86f9461889ee152a6"},
- {file = "ipython-7.10.2.tar.gz", hash = "sha256:762d79a62b6aa96b04971e920543f558dfbeedc0468b899303c080c8068d4ac2"},
+ {file = "ipython-7.11.1-py3-none-any.whl", hash = "sha256:387686dd7fc9caf29d2fddcf3116c4b07a11d9025701d220c589a430b0171d8a"},
+ {file = "ipython-7.11.1.tar.gz", hash = "sha256:0f4bcf18293fb666df8511feec0403bdb7e061a5842ea6e88a3177b0ceb34ead"},
]
ipython-genutils = [
{file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"},
@@ -1114,51 +1115,51 @@ mkdocs-minify-plugin = [
{file = "mkdocs_minify_plugin-0.2.1-py2-none-any.whl", hash = "sha256:d54fdd5be6843dd29fd7af2f7fdd20a9eb4db46f1f6bed914e03b2f58d2d488e"},
]
more-itertools = [
- {file = "more-itertools-8.0.2.tar.gz", hash = "sha256:b84b238cce0d9adad5ed87e745778d20a3f8487d0f0cb8b8a586816c7496458d"},
- {file = "more_itertools-8.0.2-py3-none-any.whl", hash = "sha256:c833ef592a0324bcc6a60e48440da07645063c453880c9477ceb22490aec1564"},
+ {file = "more-itertools-8.1.0.tar.gz", hash = "sha256:c468adec578380b6281a114cb8a5db34eb1116277da92d7c46f904f0b52d3288"},
+ {file = "more_itertools-8.1.0-py3-none-any.whl", hash = "sha256:1a2a32c72400d365000412fe08eb4a24ebee89997c18d3d147544f70f5403b39"},
]
multidict = [
- {file = "multidict-4.7.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:8f30ead697c2e37147d82ba8019952b5ea99bd3d1052f1f1ebff951eaa953209"},
- {file = "multidict-4.7.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:824716bba5a4efd74ddd36a3830efb9e49860149514ef7c41aac0144757ebb5d"},
- {file = "multidict-4.7.2-cp35-cp35m-win32.whl", hash = "sha256:63d9a3d93a514549760cb68c82864966bddb6ab53a3326931c8db9ad29414603"},
- {file = "multidict-4.7.2-cp35-cp35m-win_amd64.whl", hash = "sha256:a03efe8b7591c77d9ad4b9d81dcfb9c96e538ae25eb114385f35f4d7ffa3bac2"},
- {file = "multidict-4.7.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:7dd6f6a51b64d0a6473bc30c53e1d73fcb461c437f43662b7d6d701bd90db253"},
- {file = "multidict-4.7.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:77264002c184538df5dcb4fc1de5df6803587fa30bbe12203a7a3436b8aafc0f"},
- {file = "multidict-4.7.2-cp36-cp36m-win32.whl", hash = "sha256:b86e8e33a0a24240b293e7fad233a7e886bae6e51ca6923d39f4e313dd1d5578"},
- {file = "multidict-4.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:daf6d89e47418e38af98e1f2beb3fe0c8aa34806f681d04df314c0f131dcf01d"},
- {file = "multidict-4.7.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:7f4e591ec80619e74c50b7800f9db9b0e01d2099094767050dfe2e78e1c41839"},
- {file = "multidict-4.7.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:335344a3c3b19845c73a7826f359c51c4a12a1ccd2392b5f572a63b452bfc771"},
- {file = "multidict-4.7.2-cp37-cp37m-win32.whl", hash = "sha256:615a282acd530a1bc1b01f069a8c5874cb7c2780c287a2895ad5ab7407540e9d"},
- {file = "multidict-4.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:20081b14c923d2c5122c13e060d0ee334e078e1802c36006b20c8d7a59ee6a52"},
- {file = "multidict-4.7.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:49e80c53659c7ac50ec1c4b5fa50f045b67fffeb5b735dccb6205e4ff122e8b6"},
- {file = "multidict-4.7.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ff53a434890a16356bc45c0b90557efd89d0e5a820dbab37015d7ee630c6707a"},
- {file = "multidict-4.7.2-cp38-cp38-win32.whl", hash = "sha256:c1c64c93b8754a5cebd495d136f47a5ca93cbfceba532e306a768c27a0c1292b"},
- {file = "multidict-4.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:e03b7addca96b9eb24d6eabbdc3041e8f71fd47b316e0f3c0fa993fc7b99002c"},
- {file = "multidict-4.7.2.tar.gz", hash = "sha256:d4dafdcfbf0ac80fc5f00603f0ce43e487c654ae34a656e4749f175d9832b1b5"},
+ {file = "multidict-4.7.4-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:93166e0f5379cf6cd29746989f8a594fa7204dcae2e9335ddba39c870a287e1c"},
+ {file = "multidict-4.7.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a8ed33e8f9b67e3b592c56567135bb42e7e0e97417a4b6a771e60898dfd5182b"},
+ {file = "multidict-4.7.4-cp35-cp35m-win32.whl", hash = "sha256:a38baa3046cce174a07a59952c9f876ae8875ef3559709639c17fdf21f7b30dd"},
+ {file = "multidict-4.7.4-cp35-cp35m-win_amd64.whl", hash = "sha256:9a7b115ee0b9b92d10ebc246811d8f55d0c57e82dbb6a26b23c9a9a6ad40ce0c"},
+ {file = "multidict-4.7.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:dcfed56aa085b89d644af17442cdc2debaa73388feba4b8026446d168ca8dad7"},
+ {file = "multidict-4.7.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f29b885e4903bd57a7789f09fe9d60b6475a6c1a4c0eca874d8558f00f9d4b51"},
+ {file = "multidict-4.7.4-cp36-cp36m-win32.whl", hash = "sha256:13f3ebdb5693944f52faa7b2065b751cb7e578b8dd0a5bb8e4ab05ad0188b85e"},
+ {file = "multidict-4.7.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4fba5204d32d5c52439f88437d33ad14b5f228e25072a192453f658bddfe45a7"},
+ {file = "multidict-4.7.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a6d219f49821f4b2c85c6d426346a5d84dab6daa6f85ca3da6c00ed05b54022d"},
+ {file = "multidict-4.7.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:63810343ea07f5cd86ba66ab66706243a6f5af075eea50c01e39b4ad6bc3c57a"},
+ {file = "multidict-4.7.4-cp37-cp37m-win32.whl", hash = "sha256:26502cefa86d79b86752e96639352c7247846515c864d7c2eb85d036752b643c"},
+ {file = "multidict-4.7.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5eee66f882ab35674944dfa0d28b57fa51e160b4dce0ce19e47f495fdae70703"},
+ {file = "multidict-4.7.4-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:527124ef435f39a37b279653ad0238ff606b58328ca7989a6df372fd75d7fe26"},
+ {file = "multidict-4.7.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:83c6ddf0add57c6b8a7de0bc7e2d656be3eefeff7c922af9a9aae7e49f225625"},
+ {file = "multidict-4.7.4-cp38-cp38-win32.whl", hash = "sha256:6bd10adf9f0d6a98ccc792ab6f83d18674775986ba9bacd376b643fe35633357"},
+ {file = "multidict-4.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:5414f388ffd78c57e77bd253cf829373721f450613de53dc85a08e34d806e8eb"},
+ {file = "multidict-4.7.4.tar.gz", hash = "sha256:d7d428488c67b09b26928950a395e41cc72bb9c3d5abfe9f0521940ee4f796d4"},
]
mypy = [
- {file = "mypy-0.750-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:de9ec8dba773b78c49e7bec9a35c9b6fc5235682ad1fc2105752ae7c22f4b931"},
- {file = "mypy-0.750-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3294821b5840d51a3cd7a2bb63b40fc3f901f6a3cfb3c6046570749c4c7ef279"},
- {file = "mypy-0.750-cp35-cp35m-win_amd64.whl", hash = "sha256:6992133c95a2847d309b4b0c899d7054adc60481df6f6b52bb7dee3d5fd157f7"},
- {file = "mypy-0.750-cp36-cp36m-macosx_10_6_x86_64.whl", hash = "sha256:41696a7d912ce16fdc7c141d87e8db5144d4be664a0c699a2b417d393994b0c2"},
- {file = "mypy-0.750-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c87ac7233c629f305602f563db07f5221950fe34fe30af072ac838fa85395f78"},
- {file = "mypy-0.750-cp36-cp36m-win_amd64.whl", hash = "sha256:83fa87f556e60782c0fc3df1b37b7b4a840314ba1ac27f3e1a1e10cb37c89c17"},
- {file = "mypy-0.750-cp37-cp37m-macosx_10_6_x86_64.whl", hash = "sha256:30e123b24931f02c5d99307406658ac8f9cd6746f0d45a3dcac2fe5fbdd60939"},
- {file = "mypy-0.750-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:02d9bdd3398b636723ecb6c5cfe9773025a9ab7f34612c1cde5c7f2292e2d768"},
- {file = "mypy-0.750-cp37-cp37m-win_amd64.whl", hash = "sha256:088f758a50af31cf8b42688118077292370c90c89232c783ba7979f39ea16646"},
- {file = "mypy-0.750-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4f42675fa278f3913340bb8c3371d191319704437758d7c4a8440346c293ecb2"},
- {file = "mypy-0.750-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:f385a0accf353ca1bca4bbf473b9d83ed18d923fdb809d3a70a385da23e25b6a"},
- {file = "mypy-0.750-cp38-cp38-win_amd64.whl", hash = "sha256:54d205ccce6ed930a8a2ccf48404896d456e8b87812e491cb907a355b1a9c640"},
- {file = "mypy-0.750-py3-none-any.whl", hash = "sha256:28e9fbc96d13397a7ddb7fad7b14f373f91b5cff538e0772e77c270468df083c"},
- {file = "mypy-0.750.tar.gz", hash = "sha256:6ecbd0e8e371333027abca0922b0c2c632a5b4739a0c61ffbd0733391e39144c"},
+ {file = "mypy-0.761-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:7f672d02fffcbace4db2b05369142e0506cdcde20cea0e07c7c2171c4fd11dd6"},
+ {file = "mypy-0.761-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:87c556fb85d709dacd4b4cb6167eecc5bbb4f0a9864b69136a0d4640fdc76a36"},
+ {file = "mypy-0.761-cp35-cp35m-win_amd64.whl", hash = "sha256:c6d27bd20c3ba60d5b02f20bd28e20091d6286a699174dfad515636cb09b5a72"},
+ {file = "mypy-0.761-cp36-cp36m-macosx_10_6_x86_64.whl", hash = "sha256:4b9365ade157794cef9685791032521233729cb00ce76b0ddc78749abea463d2"},
+ {file = "mypy-0.761-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:634aef60b4ff0f650d3e59d4374626ca6153fcaff96ec075b215b568e6ee3cb0"},
+ {file = "mypy-0.761-cp36-cp36m-win_amd64.whl", hash = "sha256:53ea810ae3f83f9c9b452582261ea859828a9ed666f2e1ca840300b69322c474"},
+ {file = "mypy-0.761-cp37-cp37m-macosx_10_6_x86_64.whl", hash = "sha256:0a9a45157e532da06fe56adcfef8a74629566b607fa2c1ac0122d1ff995c748a"},
+ {file = "mypy-0.761-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7eadc91af8270455e0d73565b8964da1642fe226665dd5c9560067cd64d56749"},
+ {file = "mypy-0.761-cp37-cp37m-win_amd64.whl", hash = "sha256:e2bb577d10d09a2d8822a042a23b8d62bc3b269667c9eb8e60a6edfa000211b1"},
+ {file = "mypy-0.761-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c35cae79ceb20d47facfad51f952df16c2ae9f45db6cb38405a3da1cf8fc0a7"},
+ {file = "mypy-0.761-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:f97a605d7c8bc2c6d1172c2f0d5a65b24142e11a58de689046e62c2d632ca8c1"},
+ {file = "mypy-0.761-cp38-cp38-win_amd64.whl", hash = "sha256:a6bd44efee4dc8c3324c13785a9dc3519b3ee3a92cada42d2b57762b7053b49b"},
+ {file = "mypy-0.761-py3-none-any.whl", hash = "sha256:7e396ce53cacd5596ff6d191b47ab0ea18f8e0ec04e15d69728d530e86d4c217"},
+ {file = "mypy-0.761.tar.gz", hash = "sha256:85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf"},
]
mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
]
packaging = [
- {file = "packaging-19.2-py2.py3-none-any.whl", hash = "sha256:d9551545c6d761f3def1677baf08ab2a3ca17c56879e70fecba2fc4dde4ed108"},
- {file = "packaging-19.2.tar.gz", hash = "sha256:28b924174df7a2fa32c1953825ff29c61e2f5e082343165438812f00d3a7fc47"},
+ {file = "packaging-20.0-py2.py3-none-any.whl", hash = "sha256:aec3fdbb8bc9e4bb65f0634b9f551ced63983a529d6a8931817d52fdd0816ddb"},
+ {file = "packaging-20.0.tar.gz", hash = "sha256:fe1d8331dfa7cc0a883b49d75fc76380b2ab2734b220fbb87d774e4fd4b851f8"},
]
parso = [
{file = "parso-0.5.2-py2.py3-none-any.whl", hash = "sha256:5c1f7791de6bd5dbbeac8db0ef5594b36799de198b3f7f7014643b0c5536b9d3"},
@@ -1189,8 +1190,8 @@ ptyprocess = [
{file = "ptyprocess-0.6.0.tar.gz", hash = "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0"},
]
py = [
- {file = "py-1.8.0-py2.py3-none-any.whl", hash = "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa"},
- {file = "py-1.8.0.tar.gz", hash = "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"},
+ {file = "py-1.8.1-py2.py3-none-any.whl", hash = "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"},
+ {file = "py-1.8.1.tar.gz", hash = "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa"},
]
pycodestyle = [
{file = "pycodestyle-2.5.0-py2.py3-none-any.whl", hash = "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56"},
@@ -1249,8 +1250,8 @@ pytest-metadata = [
{file = "pytest_metadata-1.8.0-py2.py3-none-any.whl", hash = "sha256:c29a1fb470424926c63154c1b632c02585f2ba4282932058a71d35295ff8c96d"},
]
pytest-mock = [
- {file = "pytest-mock-1.13.0.tar.gz", hash = "sha256:e24a911ec96773022ebcc7030059b57cd3480b56d4f5d19b7c370ec635e6aed5"},
- {file = "pytest_mock-1.13.0-py2.py3-none-any.whl", hash = "sha256:67e414b3caef7bff6fc6bd83b22b5bc39147e4493f483c2679bc9d4dc485a94d"},
+ {file = "pytest-mock-2.0.0.tar.gz", hash = "sha256:b35eb281e93aafed138db25c8772b95d3756108b601947f89af503f8c629413f"},
+ {file = "pytest_mock-2.0.0-py2.py3-none-any.whl", hash = "sha256:cb67402d87d5f53c579263d37971a164743dc33c159dfb4fb4a86f37c5552307"},
]
pytest-mypy = [
{file = "pytest-mypy-0.4.2.tar.gz", hash = "sha256:5a5338cecff17f005b181546a13e282761754b481225df37f33d37f86ac5b304"},
@@ -1261,17 +1262,17 @@ pytz = [
{file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"},
]
pyyaml = [
- {file = "PyYAML-5.2-cp27-cp27m-win32.whl", hash = "sha256:35ace9b4147848cafac3db142795ee42deebe9d0dad885ce643928e88daebdcc"},
- {file = "PyYAML-5.2-cp27-cp27m-win_amd64.whl", hash = "sha256:ebc4ed52dcc93eeebeae5cf5deb2ae4347b3a81c3fa12b0b8c976544829396a4"},
- {file = "PyYAML-5.2-cp35-cp35m-win32.whl", hash = "sha256:38a4f0d114101c58c0f3a88aeaa44d63efd588845c5a2df5290b73db8f246d15"},
- {file = "PyYAML-5.2-cp35-cp35m-win_amd64.whl", hash = "sha256:483eb6a33b671408c8529106df3707270bfacb2447bf8ad856a4b4f57f6e3075"},
- {file = "PyYAML-5.2-cp36-cp36m-win32.whl", hash = "sha256:7f38e35c00e160db592091751d385cd7b3046d6d51f578b29943225178257b31"},
- {file = "PyYAML-5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0e7f69397d53155e55d10ff68fdfb2cf630a35e6daf65cf0bdeaf04f127c09dc"},
- {file = "PyYAML-5.2-cp37-cp37m-win32.whl", hash = "sha256:e4c015484ff0ff197564917b4b4246ca03f411b9bd7f16e02a2f586eb48b6d04"},
- {file = "PyYAML-5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:4b6be5edb9f6bb73680f5bf4ee08ff25416d1400fbd4535fe0069b2994da07cd"},
- {file = "PyYAML-5.2-cp38-cp38-win32.whl", hash = "sha256:8100c896ecb361794d8bfdb9c11fce618c7cf83d624d73d5ab38aef3bc82d43f"},
- {file = "PyYAML-5.2-cp38-cp38-win_amd64.whl", hash = "sha256:2e9f0b7c5914367b0916c3c104a024bb68f269a486b9d04a2e8ac6f6597b7803"},
- {file = "PyYAML-5.2.tar.gz", hash = "sha256:c0ee8eca2c582d29c3c2ec6e2c4f703d1b7f1fb10bc72317355a746057e7346c"},
+ {file = "PyYAML-5.3-cp27-cp27m-win32.whl", hash = "sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d"},
+ {file = "PyYAML-5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6"},
+ {file = "PyYAML-5.3-cp35-cp35m-win32.whl", hash = "sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e"},
+ {file = "PyYAML-5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689"},
+ {file = "PyYAML-5.3-cp36-cp36m-win32.whl", hash = "sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994"},
+ {file = "PyYAML-5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e"},
+ {file = "PyYAML-5.3-cp37-cp37m-win32.whl", hash = "sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5"},
+ {file = "PyYAML-5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf"},
+ {file = "PyYAML-5.3-cp38-cp38-win32.whl", hash = "sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811"},
+ {file = "PyYAML-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20"},
+ {file = "PyYAML-5.3.tar.gz", hash = "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615"},
]
six = [
{file = "six-1.13.0-py2.py3-none-any.whl", hash = "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd"},
@@ -1334,8 +1335,8 @@ uvloop = [
{file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"},
]
wcwidth = [
- {file = "wcwidth-0.1.7-py2.py3-none-any.whl", hash = "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"},
- {file = "wcwidth-0.1.7.tar.gz", hash = "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e"},
+ {file = "wcwidth-0.1.8-py2.py3-none-any.whl", hash = "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603"},
+ {file = "wcwidth-0.1.8.tar.gz", hash = "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8"},
]
yarl = [
{file = "yarl-1.4.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b"},
diff --git a/pyproject.toml b/pyproject.toml
index b1259432..692704ac 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "aiogram"
-version = "3.0.0-alpha.0"
+version = "3.0.0-alpha.1"
description = "modern and fully asynchronous framework for Telegram Bot API"
authors = ["Alex Root Junior "]
license = "MIT"
@@ -17,6 +17,7 @@ classifiers = [
"Intended Audience :: System Administrators",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
"Topic :: Software Development :: Libraries :: Application Frameworks",
]
@@ -28,7 +29,6 @@ Babel = "^2.7"
aiofiles = "^0.4.0"
uvloop = {version = "^0.14.0", optional = true}
async_lru = "^1.0"
-ipython = "^7.10"
[tool.poetry.dev-dependencies]
uvloop = "^0.14.0"
@@ -36,21 +36,22 @@ pytest = "^5.3"
pytest-html = "^2.0"
pytest-asyncio = "^0.10.0"
pytest-mypy = "^0.4.2"
-pytest-mock = "^1.13"
+pytest-mock = "^2.0"
pytest-cov = "^2.8"
aresponses = "^1.1"
-asynctest = "^0.13.0"
+asynctest = {version = "^0.13.0", python = "<3.8"}
black = {version = "^18.3-alpha.0", allow-prereleases = true}
isort = "^4.3"
flake8 = "^3.7"
flake8-html = "^0.4.0"
-mypy = "^0.750"
+mypy = "^0.761"
mkdocs = "^1.0"
mkdocs-material = "^4.6"
mkautodoc = "^0.1.0"
pygments = "^2.4"
pymdown-extensions = "^6.1"
lxml = "^4.4"
+ipython = "^7.10"
[tool.poetry.extras]
fast = ["uvloop"]
diff --git a/tests/test_api/test_client/test_base_bot.py b/tests/test_api/test_client/test_base_bot.py
index 04c46668..652f0918 100644
--- a/tests/test_api/test_client/test_base_bot.py
+++ b/tests/test_api/test_client/test_base_bot.py
@@ -1,12 +1,14 @@
-import copy
-
import pytest
-from asynctest import CoroutineMock, patch
from aiogram.api.client.base import BaseBot
from aiogram.api.client.session.aiohttp import AiohttpSession
from aiogram.api.methods import GetMe
+try:
+ from asynctest import CoroutineMock, patch
+except ImportError:
+ from unittest.mock import AsyncMock as CoroutineMock, patch # type: ignore
+
class TestBaseBot:
def test_init(self):
@@ -33,7 +35,7 @@ class TestBaseBot:
"aiogram.api.client.session.aiohttp.AiohttpSession.make_request",
new_callable=CoroutineMock,
) as mocked_make_request:
- await base_bot.emit(method)
+ await base_bot(method)
mocked_make_request.assert_awaited_with("42:TEST", method)
@pytest.mark.asyncio
diff --git a/tests/test_api/test_client/test_session/test_aiohttp_session.py b/tests/test_api/test_client/test_session/test_aiohttp_session.py
index 85d9e67c..ac93b1a7 100644
--- a/tests/test_api/test_client/test_session/test_aiohttp_session.py
+++ b/tests/test_api/test_client/test_session/test_aiohttp_session.py
@@ -4,12 +4,16 @@ from typing import AsyncContextManager
import aiohttp
import pytest
from aresponses import ResponsesMockServer
-from asynctest import CoroutineMock, patch
from aiogram.api.client.session.aiohttp import AiohttpSession
from aiogram.api.methods import Request, TelegramMethod
from aiogram.api.types import InputFile
+try:
+ from asynctest import CoroutineMock, patch
+except ImportError:
+ from unittest.mock import AsyncMock as CoroutineMock, patch # type: ignore
+
class BareInputFile(InputFile):
async def read(self, chunk_size: int):
diff --git a/tests/test_api/test_client/test_session/test_base_session.py b/tests/test_api/test_client/test_session/test_base_session.py
index 91cb5508..f5004b68 100644
--- a/tests/test_api/test_client/test_session/test_base_session.py
+++ b/tests/test_api/test_client/test_session/test_base_session.py
@@ -2,13 +2,17 @@ import datetime
from typing import AsyncContextManager
import pytest
-from asynctest import CoroutineMock, patch
from aiogram.api.client.session.base import BaseSession, T
from aiogram.api.client.telegram import PRODUCTION, TelegramAPIServer
from aiogram.api.methods import GetMe, Response, TelegramMethod
from aiogram.utils.mixins import DataMixin
+try:
+ from asynctest import CoroutineMock, patch
+except ImportError:
+ from unittest.mock import AsyncMock as CoroutineMock, patch # type: ignore
+
class CustomSession(BaseSession):
async def close(self):
diff --git a/tests/test_api/test_methods/test_get_file.py b/tests/test_api/test_methods/test_get_file.py
index 6b8e2ff0..1b8fe22a 100644
--- a/tests/test_api/test_methods/test_get_file.py
+++ b/tests/test_api/test_methods/test_get_file.py
@@ -8,7 +8,9 @@ from tests.mocked_bot import MockedBot
class TestGetFile:
@pytest.mark.asyncio
async def test_method(self, bot: MockedBot):
- prepare_result = bot.add_result_for(GetFile, ok=True, result=File(file_id="file id"))
+ prepare_result = bot.add_result_for(
+ GetFile, ok=True, result=File(file_id="file id", file_unique_id="file id")
+ )
response: File = await GetFile(file_id="file id")
request: Request = bot.get_request()
@@ -17,7 +19,9 @@ class TestGetFile:
@pytest.mark.asyncio
async def test_bot_method(self, bot: MockedBot):
- prepare_result = bot.add_result_for(GetFile, ok=True, result=File(file_id="file id"))
+ prepare_result = bot.add_result_for(
+ GetFile, ok=True, result=File(file_id="file id", file_unique_id="file id")
+ )
response: File = await bot.get_file(file_id="file id")
request: Request = bot.get_request()
diff --git a/tests/test_api/test_methods/test_get_sticker_set.py b/tests/test_api/test_methods/test_get_sticker_set.py
index 236116ce..130de89a 100644
--- a/tests/test_api/test_methods/test_get_sticker_set.py
+++ b/tests/test_api/test_methods/test_get_sticker_set.py
@@ -16,7 +16,15 @@ class TestGetStickerSet:
title="test",
is_animated=False,
contains_masks=False,
- stickers=[Sticker(file_id="file if", width=42, height=42, is_animated=False)],
+ stickers=[
+ Sticker(
+ file_id="file if",
+ width=42,
+ height=42,
+ is_animated=False,
+ file_unique_id="file id",
+ )
+ ],
),
)
@@ -35,7 +43,15 @@ class TestGetStickerSet:
title="test",
is_animated=False,
contains_masks=False,
- stickers=[Sticker(file_id="file if", width=42, height=42, is_animated=False)],
+ stickers=[
+ Sticker(
+ file_id="file if",
+ width=42,
+ height=42,
+ is_animated=False,
+ file_unique_id="file id",
+ )
+ ],
),
)
diff --git a/tests/test_api/test_methods/test_get_user_profile_photos.py b/tests/test_api/test_methods/test_get_user_profile_photos.py
index d30ee6dd..093dea82 100644
--- a/tests/test_api/test_methods/test_get_user_profile_photos.py
+++ b/tests/test_api/test_methods/test_get_user_profile_photos.py
@@ -12,7 +12,10 @@ class TestGetUserProfilePhotos:
GetUserProfilePhotos,
ok=True,
result=UserProfilePhotos(
- total_count=1, photos=[[PhotoSize(file_id="file_id", width=42, height=42)]]
+ total_count=1,
+ photos=[
+ [PhotoSize(file_id="file_id", width=42, height=42, file_unique_id="file id")]
+ ],
),
)
@@ -27,7 +30,10 @@ class TestGetUserProfilePhotos:
GetUserProfilePhotos,
ok=True,
result=UserProfilePhotos(
- total_count=1, photos=[[PhotoSize(file_id="file_id", width=42, height=42)]]
+ total_count=1,
+ photos=[
+ [PhotoSize(file_id="file_id", width=42, height=42, file_unique_id="file id")]
+ ],
),
)
diff --git a/tests/test_api/test_methods/test_send_animation.py b/tests/test_api/test_methods/test_send_animation.py
index 06af5218..b02bad5f 100644
--- a/tests/test_api/test_methods/test_send_animation.py
+++ b/tests/test_api/test_methods/test_send_animation.py
@@ -16,7 +16,9 @@ class TestSendAnimation:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- animation=Animation(file_id="file id", width=42, height=42, duration=0),
+ animation=Animation(
+ file_id="file id", width=42, height=42, duration=0, file_unique_id="file id"
+ ),
chat=Chat(id=42, type="private"),
),
)
@@ -34,7 +36,9 @@ class TestSendAnimation:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- animation=Animation(file_id="file id", width=42, height=42, duration=0),
+ animation=Animation(
+ file_id="file id", width=42, height=42, duration=0, file_unique_id="file id"
+ ),
chat=Chat(id=42, type="private"),
),
)
diff --git a/tests/test_api/test_methods/test_send_audio.py b/tests/test_api/test_methods/test_send_audio.py
index c15d6728..fdc06bdb 100644
--- a/tests/test_api/test_methods/test_send_audio.py
+++ b/tests/test_api/test_methods/test_send_audio.py
@@ -16,7 +16,7 @@ class TestSendAudio:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- audio=Audio(file_id="file id", duration=42),
+ audio=Audio(file_id="file id", duration=42, file_unique_id="file id"),
chat=Chat(id=42, type="private"),
),
)
@@ -34,7 +34,7 @@ class TestSendAudio:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- audio=Audio(file_id="file id", duration=42),
+ audio=Audio(file_id="file id", duration=42, file_unique_id="file id"),
chat=Chat(id=42, type="private"),
),
)
diff --git a/tests/test_api/test_methods/test_send_document.py b/tests/test_api/test_methods/test_send_document.py
index aebccc1f..5ddd2e6a 100644
--- a/tests/test_api/test_methods/test_send_document.py
+++ b/tests/test_api/test_methods/test_send_document.py
@@ -16,7 +16,7 @@ class TestSendDocument:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- document=Document(file_id="file id"),
+ document=Document(file_id="file id", file_unique_id="file id"),
chat=Chat(id=42, type="private"),
),
)
@@ -34,7 +34,7 @@ class TestSendDocument:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- document=Document(file_id="file id"),
+ document=Document(file_id="file id", file_unique_id="file id"),
chat=Chat(id=42, type="private"),
),
)
diff --git a/tests/test_api/test_methods/test_send_game.py b/tests/test_api/test_methods/test_send_game.py
index a26a1cc1..7728c079 100644
--- a/tests/test_api/test_methods/test_send_game.py
+++ b/tests/test_api/test_methods/test_send_game.py
@@ -19,7 +19,9 @@ class TestSendGame:
game=Game(
title="title",
description="description",
- photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ photo=[
+ PhotoSize(file_id="file id", width=42, height=42, file_unique_id="file id")
+ ],
),
chat=Chat(id=42, type="private"),
),
@@ -41,7 +43,9 @@ class TestSendGame:
game=Game(
title="title",
description="description",
- photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ photo=[
+ PhotoSize(file_id="file id", width=42, height=42, file_unique_id="file id")
+ ],
),
chat=Chat(id=42, type="private"),
),
diff --git a/tests/test_api/test_methods/test_send_media_group.py b/tests/test_api/test_methods/test_send_media_group.py
index 4a3c495c..14a30ccb 100644
--- a/tests/test_api/test_methods/test_send_media_group.py
+++ b/tests/test_api/test_methods/test_send_media_group.py
@@ -26,14 +26,22 @@ class TestSendMediaGroup:
Message(
message_id=42,
date=datetime.datetime.now(),
- photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ photo=[
+ PhotoSize(file_id="file id", width=42, height=42, file_unique_id="file id")
+ ],
media_group_id="media group",
chat=Chat(id=42, type="private"),
),
Message(
message_id=43,
date=datetime.datetime.now(),
- video=Video(file_id="file id", width=42, height=42, duration=0),
+ video=Video(
+ file_id="file id",
+ width=42,
+ height=42,
+ duration=0,
+ file_unique_id="file id",
+ ),
media_group_id="media group",
chat=Chat(id=42, type="private"),
),
@@ -60,14 +68,22 @@ class TestSendMediaGroup:
Message(
message_id=42,
date=datetime.datetime.now(),
- photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ photo=[
+ PhotoSize(file_id="file id", width=42, height=42, file_unique_id="file id")
+ ],
media_group_id="media group",
chat=Chat(id=42, type="private"),
),
Message(
message_id=43,
date=datetime.datetime.now(),
- video=Video(file_id="file id", width=42, height=42, duration=0),
+ video=Video(
+ file_id="file id",
+ width=42,
+ height=42,
+ duration=0,
+ file_unique_id="file id",
+ ),
media_group_id="media group",
chat=Chat(id=42, type="private"),
),
diff --git a/tests/test_api/test_methods/test_send_photo.py b/tests/test_api/test_methods/test_send_photo.py
index 82ef4a84..2ff2b7c6 100644
--- a/tests/test_api/test_methods/test_send_photo.py
+++ b/tests/test_api/test_methods/test_send_photo.py
@@ -16,7 +16,9 @@ class TestSendPhoto:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ photo=[
+ PhotoSize(file_id="file id", width=42, height=42, file_unique_id="file id")
+ ],
chat=Chat(id=42, type="private"),
),
)
@@ -34,7 +36,9 @@ class TestSendPhoto:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ photo=[
+ PhotoSize(file_id="file id", width=42, height=42, file_unique_id="file id")
+ ],
chat=Chat(id=42, type="private"),
),
)
diff --git a/tests/test_api/test_methods/test_send_sticker.py b/tests/test_api/test_methods/test_send_sticker.py
index 8ed2fe46..8475581e 100644
--- a/tests/test_api/test_methods/test_send_sticker.py
+++ b/tests/test_api/test_methods/test_send_sticker.py
@@ -16,7 +16,13 @@ class TestSendSticker:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- sticker=Sticker(file_id="file id", width=42, height=42, is_animated=False),
+ sticker=Sticker(
+ file_id="file id",
+ width=42,
+ height=42,
+ is_animated=False,
+ file_unique_id="file id",
+ ),
chat=Chat(id=42, type="private"),
),
)
@@ -34,7 +40,13 @@ class TestSendSticker:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- sticker=Sticker(file_id="file id", width=42, height=42, is_animated=False),
+ sticker=Sticker(
+ file_id="file id",
+ width=42,
+ height=42,
+ is_animated=False,
+ file_unique_id="file id",
+ ),
chat=Chat(id=42, type="private"),
),
)
diff --git a/tests/test_api/test_methods/test_send_video.py b/tests/test_api/test_methods/test_send_video.py
index 7d6e9c8c..6d52f109 100644
--- a/tests/test_api/test_methods/test_send_video.py
+++ b/tests/test_api/test_methods/test_send_video.py
@@ -16,7 +16,9 @@ class TestSendVideo:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- video=Video(file_id="file id", width=42, height=42, duration=0),
+ video=Video(
+ file_id="file id", width=42, height=42, duration=0, file_unique_id="file id"
+ ),
chat=Chat(id=42, type="private"),
),
)
@@ -34,7 +36,9 @@ class TestSendVideo:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- video=Video(file_id="file id", width=42, height=42, duration=0),
+ video=Video(
+ file_id="file id", width=42, height=42, duration=0, file_unique_id="file id"
+ ),
chat=Chat(id=42, type="private"),
),
)
diff --git a/tests/test_api/test_methods/test_send_video_note.py b/tests/test_api/test_methods/test_send_video_note.py
index 704d13f3..bb235bed 100644
--- a/tests/test_api/test_methods/test_send_video_note.py
+++ b/tests/test_api/test_methods/test_send_video_note.py
@@ -16,7 +16,9 @@ class TestSendVideoNote:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- video_note=VideoNote(file_id="file id", length=0, duration=0),
+ video_note=VideoNote(
+ file_id="file id", length=0, duration=0, file_unique_id="file id"
+ ),
chat=Chat(id=42, type="private"),
),
)
@@ -36,7 +38,9 @@ class TestSendVideoNote:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- video_note=VideoNote(file_id="file id", length=0, duration=0),
+ video_note=VideoNote(
+ file_id="file id", length=0, duration=0, file_unique_id="file id"
+ ),
chat=Chat(id=42, type="private"),
),
)
diff --git a/tests/test_api/test_methods/test_send_voice.py b/tests/test_api/test_methods/test_send_voice.py
index 1a7804e1..6dcab09d 100644
--- a/tests/test_api/test_methods/test_send_voice.py
+++ b/tests/test_api/test_methods/test_send_voice.py
@@ -16,7 +16,7 @@ class TestSendVoice:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- voice=Voice(file_id="file id", duration=0),
+ voice=Voice(file_id="file id", duration=0, file_unique_id="file id"),
chat=Chat(id=42, type="private"),
),
)
@@ -34,7 +34,7 @@ class TestSendVoice:
result=Message(
message_id=42,
date=datetime.datetime.now(),
- voice=Voice(file_id="file id", duration=0),
+ voice=Voice(file_id="file id", duration=0, file_unique_id="file id"),
chat=Chat(id=42, type="private"),
),
)
diff --git a/tests/test_api/test_methods/test_set_chat_administrator_custom_title.py b/tests/test_api/test_methods/test_set_chat_administrator_custom_title.py
new file mode 100644
index 00000000..e4372c3d
--- /dev/null
+++ b/tests/test_api/test_methods/test_set_chat_administrator_custom_title.py
@@ -0,0 +1,28 @@
+import pytest
+
+from aiogram.api.methods import Request, SetChatAdministratorCustomTitle, SetChatTitle
+from tests.mocked_bot import MockedBot
+
+
+class TestSetChatTitle:
+ @pytest.mark.asyncio
+ async def test_method(self, bot: MockedBot):
+ prepare_result = bot.add_result_for(SetChatAdministratorCustomTitle, ok=True, result=True)
+
+ response: bool = await SetChatAdministratorCustomTitle(
+ chat_id=-42, user_id=42, custom_title="test chat"
+ )
+ request: Request = bot.get_request()
+ assert request.method == "setChatAdministratorCustomTitle"
+ assert response == prepare_result.result
+
+ @pytest.mark.asyncio
+ async def test_bot_method(self, bot: MockedBot):
+ prepare_result = bot.add_result_for(SetChatAdministratorCustomTitle, ok=True, result=True)
+
+ response: bool = await bot.set_chat_administrator_custom_title(
+ chat_id=-42, user_id=42, custom_title="test chat"
+ )
+ request: Request = bot.get_request()
+ assert request.method == "setChatAdministratorCustomTitle"
+ assert response == prepare_result.result
diff --git a/tests/test_api/test_methods/test_upload_sticker_file.py b/tests/test_api/test_methods/test_upload_sticker_file.py
index 6ab48c6f..a90b395b 100644
--- a/tests/test_api/test_methods/test_upload_sticker_file.py
+++ b/tests/test_api/test_methods/test_upload_sticker_file.py
@@ -9,7 +9,7 @@ class TestUploadStickerFile:
@pytest.mark.asyncio
async def test_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(
- UploadStickerFile, ok=True, result=File(file_id="file id")
+ UploadStickerFile, ok=True, result=File(file_id="file id", file_unique_id="file id")
)
response: File = await UploadStickerFile(
@@ -22,7 +22,7 @@ class TestUploadStickerFile:
@pytest.mark.asyncio
async def test_bot_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(
- UploadStickerFile, ok=True, result=File(file_id="file id")
+ UploadStickerFile, ok=True, result=File(file_id="file id", file_unique_id="file id")
)
response: File = await bot.upload_sticker_file(
diff --git a/tests/test_api/test_types/test_message.py b/tests/test_api/test_types/test_message.py
index f1497be8..cd6c1cb6 100644
--- a/tests/test_api/test_types/test_message.py
+++ b/tests/test_api/test_types/test_message.py
@@ -45,7 +45,7 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- audio=Audio(file_id="file id", duration=42),
+ audio=Audio(file_id="file id", file_unique_id="file id", duration=42),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
@@ -55,7 +55,13 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- animation=Animation(file_id="file id", width=42, height=42, duration=0),
+ animation=Animation(
+ file_id="file id",
+ file_unique_id="file id",
+ width=42,
+ height=42,
+ duration=0,
+ ),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
@@ -65,7 +71,7 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- document=Document(file_id="file id"),
+ document=Document(file_id="file id", file_unique_id="file id"),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
@@ -78,7 +84,11 @@ class TestMessage:
game=Game(
title="title",
description="description",
- photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ photo=[
+ PhotoSize(
+ file_id="file id", file_unique_id="file id", width=42, height=42
+ )
+ ],
),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
@@ -89,7 +99,9 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ photo=[
+ PhotoSize(file_id="file id", file_unique_id="file id", width=42, height=42)
+ ],
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
@@ -99,7 +111,13 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- sticker=Sticker(file_id="file id", width=42, height=42, is_animated=False),
+ sticker=Sticker(
+ file_id="file id",
+ file_unique_id="file id",
+ width=42,
+ height=42,
+ is_animated=False,
+ ),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
@@ -109,7 +127,13 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- video=Video(file_id="file id", width=42, height=42, duration=0),
+ video=Video(
+ file_id="file id",
+ file_unique_id="file id",
+ width=42,
+ height=42,
+ duration=0,
+ ),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
@@ -119,7 +143,9 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- video_note=VideoNote(file_id="file id", length=0, duration=0),
+ video_note=VideoNote(
+ file_id="file id", file_unique_id="file id", length=0, duration=0
+ ),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
@@ -129,7 +155,7 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- voice=Voice(file_id="file id", duration=0),
+ voice=Voice(file_id="file id", file_unique_id="file id", duration=0),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
@@ -282,7 +308,9 @@ class TestMessage:
Message(
message_id=42,
date=datetime.datetime.now(),
- new_chat_photo=[PhotoSize(file_id="file id", width=42, height=42)],
+ new_chat_photo=[
+ PhotoSize(file_id="file id", file_unique_id="file id", width=42, height=42)
+ ],
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
),
diff --git a/tests/test_dispatcher/test_dispatcher.py b/tests/test_dispatcher/test_dispatcher.py
index b1c333d1..5e210c08 100644
--- a/tests/test_dispatcher/test_dispatcher.py
+++ b/tests/test_dispatcher/test_dispatcher.py
@@ -2,7 +2,6 @@ import datetime
import time
import pytest
-from asynctest import CoroutineMock, patch
from aiogram import Bot
from aiogram.api.methods import GetMe, GetUpdates, SendMessage
@@ -11,6 +10,11 @@ from aiogram.dispatcher.dispatcher import Dispatcher
from aiogram.dispatcher.router import Router
from tests.mocked_bot import MockedBot
+try:
+ from asynctest import CoroutineMock, patch
+except ImportError:
+ from unittest.mock import AsyncMock as CoroutineMock, patch # type: ignore
+
class TestDispatcher:
def test_parent_router(self):
diff --git a/tests/test_dispatcher/test_filters/test_base.py b/tests/test_dispatcher/test_filters/test_base.py
index dd183fb5..688b13ab 100644
--- a/tests/test_dispatcher/test_filters/test_base.py
+++ b/tests/test_dispatcher/test_filters/test_base.py
@@ -1,11 +1,14 @@
from typing import Awaitable
-from unittest.mock import patch
import pytest
-from asynctest import CoroutineMock
from aiogram.dispatcher.filters.base import BaseFilter
+try:
+ from asynctest import CoroutineMock, patch
+except ImportError:
+ from unittest.mock import AsyncMock as CoroutineMock, patch # type: ignore
+
class MyFilter(BaseFilter):
foo: str
diff --git a/tests/test_utils/test_markdown.py b/tests/test_utils/test_markdown.py
index 79b22c97..b9da8f46 100644
--- a/tests/test_utils/test_markdown.py
+++ b/tests/test_utils/test_markdown.py
@@ -14,15 +14,15 @@ class TestMarkdown:
[markdown.text, ("test", "test"), None, "test test"],
[markdown.bold, ("test", "test"), " ", "*test test*"],
[markdown.hbold, ("test", "test"), " ", "test test"],
- [markdown.italic, ("test", "test"), " ", "_test test_"],
+ [markdown.italic, ("test", "test"), " ", "_test test_\r"],
[markdown.hitalic, ("test", "test"), " ", "test test"],
[markdown.code, ("test", "test"), " ", "`test test`"],
[markdown.hcode, ("test", "test"), " ", "test test"],
[markdown.pre, ("test", "test"), " ", "```test test```"],
[markdown.hpre, ("test", "test"), " ", "test test
"],
- [markdown.underline, ("test", "test"), " ", "--test test--"],
+ [markdown.underline, ("test", "test"), " ", "__test test__"],
[markdown.hunderline, ("test", "test"), " ", "test test"],
- [markdown.strikethrough, ("test", "test"), " ", "~~test test~~"],
+ [markdown.strikethrough, ("test", "test"), " ", "~test test~"],
[markdown.hstrikethrough, ("test", "test"), " ", "test test"],
[markdown.link, ("test", "https://aiogram.dev"), None, "[test](https://aiogram.dev)"],
[
diff --git a/tests/test_utils/test_text_decorations.py b/tests/test_utils/test_text_decorations.py
index 40694a0a..babe0a58 100644
--- a/tests/test_utils/test_text_decorations.py
+++ b/tests/test_utils/test_text_decorations.py
@@ -3,32 +3,36 @@ from typing import List, Optional
import pytest
from aiogram.api.types import MessageEntity, User
-from aiogram.utils.text_decorations import TextDecoration, html, markdown
+from aiogram.utils.text_decorations import TextDecoration, html_decoration, markdown_decoration
class TestTextDecoration:
@pytest.mark.parametrize(
"decorator,entity,result",
[
- [html, MessageEntity(type="url", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="url", offset=0, length=5), "test"],
[
- html,
+ html_decoration,
MessageEntity(type="text_link", offset=0, length=5, url="https://aiogram.dev"),
'test',
],
- [html, MessageEntity(type="bold", offset=0, length=5), "test"],
- [html, MessageEntity(type="italic", offset=0, length=5), "test"],
- [html, MessageEntity(type="code", offset=0, length=5), "test"],
- [html, MessageEntity(type="pre", offset=0, length=5), "test
"],
- [html, MessageEntity(type="underline", offset=0, length=5), "test"],
- [html, MessageEntity(type="strikethrough", offset=0, length=5), "test"],
- [html, MessageEntity(type="hashtag", offset=0, length=5), "test"],
- [html, MessageEntity(type="cashtag", offset=0, length=5), "test"],
- [html, MessageEntity(type="bot_command", offset=0, length=5), "test"],
- [html, MessageEntity(type="email", offset=0, length=5), "test"],
- [html, MessageEntity(type="phone_number", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="bold", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="italic", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="code", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="pre", offset=0, length=5), "test
"],
+ [html_decoration, MessageEntity(type="underline", offset=0, length=5), "test"],
[
- html,
+ html_decoration,
+ MessageEntity(type="strikethrough", offset=0, length=5),
+ "test",
+ ],
+ [html_decoration, MessageEntity(type="hashtag", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="cashtag", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="bot_command", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="email", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="phone_number", offset=0, length=5), "test"],
+ [
+ html_decoration,
MessageEntity(
type="text_mention",
offset=0,
@@ -37,25 +41,29 @@ class TestTextDecoration:
),
'test',
],
- [html, MessageEntity(type="url", offset=0, length=5), "test"],
+ [html_decoration, MessageEntity(type="url", offset=0, length=5), "test"],
[
- html,
+ html_decoration,
MessageEntity(type="text_link", offset=0, length=5, url="https://aiogram.dev"),
'test',
],
- [markdown, MessageEntity(type="bold", offset=0, length=5), "*test*"],
- [markdown, MessageEntity(type="italic", offset=0, length=5), "_test_"],
- [markdown, MessageEntity(type="code", offset=0, length=5), "`test`"],
- [markdown, MessageEntity(type="pre", offset=0, length=5), "```test```"],
- [markdown, MessageEntity(type="underline", offset=0, length=5), "--test--"],
- [markdown, MessageEntity(type="strikethrough", offset=0, length=5), "~~test~~"],
- [markdown, MessageEntity(type="hashtag", offset=0, length=5), "test"],
- [markdown, MessageEntity(type="cashtag", offset=0, length=5), "test"],
- [markdown, MessageEntity(type="bot_command", offset=0, length=5), "test"],
- [markdown, MessageEntity(type="email", offset=0, length=5), "test"],
- [markdown, MessageEntity(type="phone_number", offset=0, length=5), "test"],
+ [markdown_decoration, MessageEntity(type="bold", offset=0, length=5), "*test*"],
+ [markdown_decoration, MessageEntity(type="italic", offset=0, length=5), "_test_\r"],
+ [markdown_decoration, MessageEntity(type="code", offset=0, length=5), "`test`"],
+ [markdown_decoration, MessageEntity(type="pre", offset=0, length=5), "```test```"],
+ [markdown_decoration, MessageEntity(type="underline", offset=0, length=5), "__test__"],
[
- markdown,
+ markdown_decoration,
+ MessageEntity(type="strikethrough", offset=0, length=5),
+ "~test~",
+ ],
+ [markdown_decoration, MessageEntity(type="hashtag", offset=0, length=5), "test"],
+ [markdown_decoration, MessageEntity(type="cashtag", offset=0, length=5), "test"],
+ [markdown_decoration, MessageEntity(type="bot_command", offset=0, length=5), "test"],
+ [markdown_decoration, MessageEntity(type="email", offset=0, length=5), "test"],
+ [markdown_decoration, MessageEntity(type="phone_number", offset=0, length=5), "test"],
+ [
+ markdown_decoration,
MessageEntity(
type="text_mention",
offset=0,
@@ -74,16 +82,16 @@ class TestTextDecoration:
@pytest.mark.parametrize(
"decorator,before,after",
[
- [html, "test", "test"],
- [html, "test < test", "test < test"],
- [html, "test > test", "test > test"],
- [html, "test & test", "test & test"],
- [html, "test @ test", "test @ test"],
- [markdown, "test", "test"],
- [markdown, "[test]", "\\[test]"],
- [markdown, "test ` test", "test \\` test"],
- [markdown, "test * test", "test \\* test"],
- [markdown, "test _ test", "test \\_ test"],
+ [html_decoration, "test", "test"],
+ [html_decoration, "test < test", "test < test"],
+ [html_decoration, "test > test", "test > test"],
+ [html_decoration, "test & test", "test & test"],
+ [html_decoration, "test @ test", "test @ test"],
+ [markdown_decoration, "test", "test"],
+ [markdown_decoration, "[test]", "\\[test\\]"],
+ [markdown_decoration, "test ` test", "test \\` test"],
+ [markdown_decoration, "test * test", "test \\* test"],
+ [markdown_decoration, "test _ test", "test \\_ test"],
],
)
def test_quote(self, decorator: TextDecoration, before: str, after: str):
@@ -92,10 +100,10 @@ class TestTextDecoration:
@pytest.mark.parametrize(
"decorator,text,entities,result",
[
- [html, "test", None, "test"],
- [html, "test", [], "test"],
+ [html_decoration, "test", None, "test"],
+ [html_decoration, "test", [], "test"],
[
- html,
+ html_decoration,
"test1 test2 test3 test4 test5 test6 test7",
[
MessageEntity(type="bold", offset=6, length=29),
@@ -105,7 +113,7 @@ class TestTextDecoration:
"test1 test2 test3 test4 test5 test6 test7",
],
[
- html,
+ html_decoration,
"test1 test2 test3 test4 test5",
[
MessageEntity(type="bold", offset=6, length=17),
@@ -114,7 +122,7 @@ class TestTextDecoration:
"test1 test2 test3 test4 test5",
],
[
- html,
+ html_decoration,
"test1 test2 test3 test4",
[
MessageEntity(type="bold", offset=6, length=11),
@@ -123,19 +131,19 @@ class TestTextDecoration:
"test1 test2 test3 test4",
],
[
- html,
+ html_decoration,
"test1 test2 test3",
[MessageEntity(type="bold", offset=6, length=5)],
"test1 test2 test3",
],
[
- html,
+ html_decoration,
"test1 test2",
[MessageEntity(type="bold", offset=0, length=5)],
"test1 test2",
],
[
- html,
+ html_decoration,
"strike bold",
[
MessageEntity(type="strikethrough", offset=0, length=6),
@@ -144,7 +152,7 @@ class TestTextDecoration:
"strike bold",
],
[
- html,
+ html_decoration,
"test",
[
MessageEntity(type="strikethrough", offset=0, length=5),
@@ -153,7 +161,7 @@ class TestTextDecoration:
"test",
],
[
- html,
+ html_decoration,
"strikeboldunder",
[
MessageEntity(type="strikethrough", offset=0, length=15),