From 5715e4466f0d5a5ed6717540a51c1cc48cd09690 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 17 Mar 2021 15:28:42 +0300 Subject: [PATCH 01/10] Added alias to from_user field, fixed TypeError (#527) --- aiogram/types/chat_member_updated.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiogram/types/chat_member_updated.py b/aiogram/types/chat_member_updated.py index 7c6a124f..67c75616 100644 --- a/aiogram/types/chat_member_updated.py +++ b/aiogram/types/chat_member_updated.py @@ -15,7 +15,7 @@ class ChatMemberUpdated(base.TelegramObject): https://core.telegram.org/bots/api#chatmemberupdated """ chat: Chat = fields.Field(base=Chat) - from_user: User = fields.Field(base=User) + from_user: User = fields.Field(alias="from", base=User) date: datetime.datetime = fields.DateTimeField() old_chat_member: ChatMember = fields.Field(base=ChatMember) new_chat_member: ChatMember = fields.Field(base=ChatMember) From c153d681fb3b6af4dd1bde5e494cbd4f7497c3a8 Mon Sep 17 00:00:00 2001 From: Oleg A Date: Sat, 20 Mar 2021 17:49:17 +0300 Subject: [PATCH 02/10] fix: add Chat.message_auto_delete_time field (#535) --- aiogram/types/chat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aiogram/types/chat.py b/aiogram/types/chat.py index b9e03983..0a444fd8 100644 --- a/aiogram/types/chat.py +++ b/aiogram/types/chat.py @@ -35,6 +35,7 @@ class Chat(base.TelegramObject): pinned_message: 'Message' = fields.Field(base='Message') permissions: ChatPermissions = fields.Field(base=ChatPermissions) slow_mode_delay: base.Integer = fields.Field() + message_auto_delete_time: base.Integer = fields.Field() sticker_set_name: base.String = fields.Field() can_set_sticker_set: base.Boolean = fields.Field() linked_chat_id: base.Integer = fields.Field() From 901270449f5a9a52a546da0eaba9b9d4bdee6d16 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Sat, 20 Mar 2021 20:23:30 +0300 Subject: [PATCH 03/10] Changed ChatType from CHANNEL to SUPERGROUP to avoid confusion (#533) Channels require a separate channel_post_handler, so this example is currently broken and confusing --- examples/chat_type_filter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/chat_type_filter.py b/examples/chat_type_filter.py index e57f8825..9db13cb8 100644 --- a/examples/chat_type_filter.py +++ b/examples/chat_type_filter.py @@ -19,12 +19,12 @@ bot = Bot(token=API_TOKEN) dp = Dispatcher(bot) -@dp.message_handler(chat_type=[ChatType.PRIVATE, ChatType.CHANNEL]) +@dp.message_handler(chat_type=[ChatType.PRIVATE, ChatType.SUPERGROUP]) async def send_welcome(message: types.Message): """ - This handler will be called when user sends message in private chat or channel + This handler will be called when user sends message in private chat or supergroup """ - await message.reply("Hi!\nI'm hearing your messages in private chats and channels") + await message.reply("Hi!\nI'm hearing your messages in private chats and supergroups") # propagate message to the next handler raise SkipHandler From b287a9f5f525eb4e036775130ce287fcc56d3b31 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sat, 20 Mar 2021 19:37:39 +0200 Subject: [PATCH 04/10] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index c4430ef6..d643b3f0 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ open_collective: aiogram +patreon: aiogram From 7cce8b63976d1d87461643d8d7f52433e57fa257 Mon Sep 17 00:00:00 2001 From: JWSong Date: Sun, 21 Mar 2021 02:51:32 +0900 Subject: [PATCH 05/10] Removed redundant definitions (#531) This closes #456. Co-authored-by: Jungwoo Song --- aiogram/bot/bot.py | 114 ++++++++++-------------------- aiogram/dispatcher/handler.py | 3 +- aiogram/dispatcher/webhook.py | 3 +- aiogram/utils/text_decorations.py | 3 +- 4 files changed, 41 insertions(+), 82 deletions(-) diff --git a/aiogram/bot/bot.py b/aiogram/bot/bot.py index 85be7fd0..4b6c4c0b 100644 --- a/aiogram/bot/bot.py +++ b/aiogram/bot/bot.py @@ -161,8 +161,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): files = {} prepare_file(payload, files, 'certificate', certificate) - result = await self.request(api.Methods.SET_WEBHOOK, payload, files) - return result + return await self.request(api.Methods.SET_WEBHOOK, payload, files) async def delete_webhook(self, drop_pending_updates: typing.Optional[base.Boolean] = None, @@ -181,8 +180,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.DELETE_WEBHOOK, payload) - return result + return await self.request(api.Methods.DELETE_WEBHOOK, payload) async def get_webhook_info(self) -> types.WebhookInfo: """ @@ -232,8 +230,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.LOG_OUT, payload) - return result + return await self.request(api.Methods.LOG_OUT, payload) @deprecated("This method will be renamed to `close` in aiogram v3.0") async def close_bot(self) -> base.Boolean: @@ -251,8 +248,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.CLOSE, payload) - return result + return await self.request(api.Methods.CLOSE, payload) async def send_message(self, chat_id: typing.Union[base.Integer, base.String], @@ -1506,8 +1502,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.SEND_CHAT_ACTION, payload) - return result + return await self.request(api.Methods.SEND_CHAT_ACTION, payload) async def get_user_profile_photos(self, user_id: base.Integer, offset: typing.Optional[base.Integer] = None, limit: typing.Optional[base.Integer] = None) -> types.UserProfilePhotos: @@ -1593,8 +1588,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): until_date = prepare_arg(until_date) payload = generate_payload(**locals()) - result = await self.request(api.Methods.KICK_CHAT_MEMBER, payload) - return result + return await self.request(api.Methods.KICK_CHAT_MEMBER, payload) async def unban_chat_member(self, chat_id: typing.Union[base.Integer, base.String], @@ -1627,8 +1621,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.UNBAN_CHAT_MEMBER, payload) - return result + return await self.request(api.Methods.UNBAN_CHAT_MEMBER, payload) async def restrict_chat_member(self, chat_id: typing.Union[base.Integer, base.String], user_id: base.Integer, @@ -1683,8 +1676,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): f"passing regular argument {payload[permission]}", DeprecationWarning, stacklevel=2) - result = await self.request(api.Methods.RESTRICT_CHAT_MEMBER, payload) - return result + return await self.request(api.Methods.RESTRICT_CHAT_MEMBER, payload) async def promote_chat_member(self, chat_id: typing.Union[base.Integer, base.String], @@ -1756,8 +1748,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.PROMOTE_CHAT_MEMBER, payload) - return result + return await self.request(api.Methods.PROMOTE_CHAT_MEMBER, payload) async def set_chat_administrator_custom_title(self, chat_id: typing.Union[base.Integer, base.String], user_id: base.Integer, custom_title: base.String) -> base.Boolean: @@ -1775,8 +1766,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.SET_CHAT_ADMINISTRATOR_CUSTOM_TITLE, payload) - return result + return await self.request(api.Methods.SET_CHAT_ADMINISTRATOR_CUSTOM_TITLE, payload) async def set_chat_permissions(self, chat_id: typing.Union[base.Integer, base.String], permissions: types.ChatPermissions) -> base.Boolean: @@ -1794,8 +1784,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): permissions = prepare_arg(permissions) payload = generate_payload(**locals()) - result = await self.request(api.Methods.SET_CHAT_PERMISSIONS, payload) - return result + return await self.request(api.Methods.SET_CHAT_PERMISSIONS, payload) async def export_chat_invite_link(self, chat_id: typing.Union[base.Integer, base.String]) -> base.String: """ @@ -1811,8 +1800,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.EXPORT_CHAT_INVITE_LINK, payload) - return result + return await self.request(api.Methods.EXPORT_CHAT_INVITE_LINK, payload) async def create_chat_invite_link(self, chat_id: typing.Union[base.Integer, base.String], @@ -1846,8 +1834,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): expire_date = prepare_arg(expire_date) payload = generate_payload(**locals()) - result = await self.request(api.Methods.CREATE_CHAT_INVITE_LINK, payload) - return result + return await self.request(api.Methods.CREATE_CHAT_INVITE_LINK, payload) async def edit_chat_invite_link(self, chat_id: typing.Union[base.Integer, base.String], @@ -1883,8 +1870,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): expire_date = prepare_arg(expire_date) payload = generate_payload(**locals()) - result = await self.request(api.Methods.EDIT_CHAT_INVITE_LINK, payload) - return result + return await self.request(api.Methods.EDIT_CHAT_INVITE_LINK, payload) async def revoke_chat_invite_link(self, chat_id: typing.Union[base.Integer, base.String], @@ -1905,8 +1891,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.REVOKE_CHAT_INVITE_LINK, payload) - return result + return await self.request(api.Methods.REVOKE_CHAT_INVITE_LINK, payload) async def set_chat_photo(self, chat_id: typing.Union[base.Integer, base.String], photo: base.InputFile) -> base.Boolean: @@ -1931,8 +1916,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): files = {} prepare_file(payload, files, 'photo', photo) - result = await self.request(api.Methods.SET_CHAT_PHOTO, payload, files) - return result + return await self.request(api.Methods.SET_CHAT_PHOTO, payload, files) async def delete_chat_photo(self, chat_id: typing.Union[base.Integer, base.String]) -> base.Boolean: """ @@ -1951,8 +1935,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.DELETE_CHAT_PHOTO, payload) - return result + return await self.request(api.Methods.DELETE_CHAT_PHOTO, payload) async def set_chat_title(self, chat_id: typing.Union[base.Integer, base.String], title: base.String) -> base.Boolean: @@ -1974,8 +1957,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.SET_CHAT_TITLE, payload) - return result + return await self.request(api.Methods.SET_CHAT_TITLE, payload) async def set_chat_description(self, chat_id: typing.Union[base.Integer, base.String], description: typing.Optional[base.String] = None) -> base.Boolean: @@ -1994,8 +1976,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.SET_CHAT_DESCRIPTION, payload) - return result + return await self.request(api.Methods.SET_CHAT_DESCRIPTION, payload) async def pin_chat_message(self, chat_id: typing.Union[base.Integer, base.String], @@ -2027,8 +2008,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.PIN_CHAT_MESSAGE, payload) - return result + return await self.request(api.Methods.PIN_CHAT_MESSAGE, payload) async def unpin_chat_message(self, chat_id: typing.Union[base.Integer, base.String], @@ -2056,8 +2036,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.UNPIN_CHAT_MESSAGE, payload) - return result + return await self.request(api.Methods.UNPIN_CHAT_MESSAGE, payload) async def unpin_all_chat_messages(self, chat_id: typing.Union[base.Integer, base.String], @@ -2079,8 +2058,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.UNPIN_ALL_CHAT_MESSAGES, payload) - return result + return await self.request(api.Methods.UNPIN_ALL_CHAT_MESSAGES, payload) async def leave_chat(self, chat_id: typing.Union[base.Integer, base.String]) -> base.Boolean: """ @@ -2095,8 +2073,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.LEAVE_CHAT, payload) - return result + return await self.request(api.Methods.LEAVE_CHAT, payload) async def get_chat(self, chat_id: typing.Union[base.Integer, base.String]) -> types.Chat: """ @@ -2148,8 +2125,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.GET_CHAT_MEMBERS_COUNT, payload) - return result + return await self.request(api.Methods.GET_CHAT_MEMBERS_COUNT, payload) async def get_chat_member(self, chat_id: typing.Union[base.Integer, base.String], user_id: base.Integer) -> types.ChatMember: @@ -2190,8 +2166,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.SET_CHAT_STICKER_SET, payload) - return result + return await self.request(api.Methods.SET_CHAT_STICKER_SET, payload) async def delete_chat_sticker_set(self, chat_id: typing.Union[base.Integer, base.String]) -> base.Boolean: """ @@ -2210,8 +2185,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.DELETE_CHAT_STICKER_SET, payload) - return result + return await self.request(api.Methods.DELETE_CHAT_STICKER_SET, payload) async def answer_callback_query(self, callback_query_id: base.String, text: typing.Optional[base.String] = None, @@ -2245,8 +2219,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.ANSWER_CALLBACK_QUERY, payload) - return result + return await self.request(api.Methods.ANSWER_CALLBACK_QUERY, payload) async def set_my_commands(self, commands: typing.List[types.BotCommand]) -> base.Boolean: """ @@ -2263,8 +2236,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): commands = prepare_arg(commands) payload = generate_payload(**locals()) - result = await self.request(api.Methods.SET_MY_COMMANDS, payload) - return result + return await self.request(api.Methods.SET_MY_COMMANDS, payload) async def get_my_commands(self) -> typing.List[types.BotCommand]: """ @@ -2510,8 +2482,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.DELETE_MESSAGE, payload) - return result + return await self.request(api.Methods.DELETE_MESSAGE, payload) # === Stickers === # https://core.telegram.org/bots/api#stickers @@ -2652,8 +2623,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): prepare_file(payload, files, 'png_sticker', png_sticker) prepare_file(payload, files, 'tgs_sticker', tgs_sticker) - result = await self.request(api.Methods.CREATE_NEW_STICKER_SET, payload, files) - return result + return await self.request(api.Methods.CREATE_NEW_STICKER_SET, payload, files) async def add_sticker_to_set(self, user_id: base.Integer, @@ -2698,8 +2668,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): prepare_file(payload, files, 'png_sticker', png_sticker) prepare_file(payload, files, 'tgs_sticker', tgs_sticker) - result = await self.request(api.Methods.ADD_STICKER_TO_SET, payload, files) - return result + return await self.request(api.Methods.ADD_STICKER_TO_SET, payload, files) async def set_sticker_position_in_set(self, sticker: base.String, position: base.Integer) -> base.Boolean: """ @@ -2715,9 +2684,8 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): :rtype: :obj:`base.Boolean` """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.SET_STICKER_POSITION_IN_SET, payload) - return result + return await self.request(api.Methods.SET_STICKER_POSITION_IN_SET, payload) async def delete_sticker_from_set(self, sticker: base.String) -> base.Boolean: """ @@ -2732,8 +2700,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.DELETE_STICKER_FROM_SET, payload) - return result + return await self.request(api.Methods.DELETE_STICKER_FROM_SET, payload) async def set_sticker_set_thumb(self, name: base.String, @@ -2765,8 +2732,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): files = {} prepare_file(payload, files, 'thumb', thumb) - result = await self.request(api.Methods.SET_STICKER_SET_THUMB, payload, files) - return result + return await self.request(api.Methods.SET_STICKER_SET_THUMB, payload, files) async def answer_inline_query(self, inline_query_id: base.String, results: typing.List[types.InlineQueryResult], @@ -2809,8 +2775,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): results = prepare_arg(results) payload = generate_payload(**locals()) - result = await self.request(api.Methods.ANSWER_INLINE_QUERY, payload) - return result + return await self.request(api.Methods.ANSWER_INLINE_QUERY, payload) # === Payments === # https://core.telegram.org/bots/api#payments @@ -2958,8 +2923,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): for shipping_option in shipping_options]) payload = generate_payload(**locals()) - result = await self.request(api.Methods.ANSWER_SHIPPING_QUERY, payload) - return result + return await self.request(api.Methods.ANSWER_SHIPPING_QUERY, payload) async def answer_pre_checkout_query(self, pre_checkout_query_id: base.String, ok: base.Boolean, error_message: typing.Optional[base.String] = None) -> base.Boolean: @@ -2986,8 +2950,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): """ payload = generate_payload(**locals()) - result = await self.request(api.Methods.ANSWER_PRE_CHECKOUT_QUERY, payload) - return result + return await self.request(api.Methods.ANSWER_PRE_CHECKOUT_QUERY, payload) # === Games === # https://core.telegram.org/bots/api#games @@ -3018,8 +2981,7 @@ class Bot(BaseBot, DataMixin, ContextInstanceMixin): errors = prepare_arg(errors) payload = generate_payload(**locals()) - result = await self.request(api.Methods.SET_PASSPORT_DATA_ERRORS, payload) - return result + return await self.request(api.Methods.SET_PASSPORT_DATA_ERRORS, payload) # === Games === # https://core.telegram.org/bots/api#games diff --git a/aiogram/dispatcher/handler.py b/aiogram/dispatcher/handler.py index 38219012..10a94924 100644 --- a/aiogram/dispatcher/handler.py +++ b/aiogram/dispatcher/handler.py @@ -25,8 +25,7 @@ class CancelHandler(Exception): def _get_spec(func: callable): while hasattr(func, '__wrapped__'): # Try to resolve decorated callbacks func = func.__wrapped__ - spec = inspect.getfullargspec(func) - return spec + return inspect.getfullargspec(func) def _check_spec(spec: inspect.FullArgSpec, kwargs: dict): diff --git a/aiogram/dispatcher/webhook.py b/aiogram/dispatcher/webhook.py index b6280ed1..52191870 100644 --- a/aiogram/dispatcher/webhook.py +++ b/aiogram/dispatcher/webhook.py @@ -116,8 +116,7 @@ class WebhookRequestHandler(web.View): :return: :class:`aiogram.types.Update` """ data = await self.request.json() - update = types.Update(**data) - return update + return types.Update(**data) async def post(self): """ diff --git a/aiogram/utils/text_decorations.py b/aiogram/utils/text_decorations.py index 4de8d69a..09484e3c 100644 --- a/aiogram/utils/text_decorations.py +++ b/aiogram/utils/text_decorations.py @@ -55,12 +55,11 @@ class TextDecoration(ABC): :param entities: Array of MessageEntities :return: """ - result = "".join( + return "".join( self._unparse_entities( self._add_surrogates(text), sorted(entities, key=lambda item: item.offset) if entities else [] ) ) - return result def _unparse_entities( self, From eed147e2e35a6186dad957207c42ed69b90eea29 Mon Sep 17 00:00:00 2001 From: Daniil Kovalenko <40635760+WhiteMemory99@users.noreply.github.com> Date: Sun, 21 Mar 2021 00:52:35 +0700 Subject: [PATCH 06/10] Add MediaGroup Filter (#528) * Add MediaGroupFilter * Update __init__.py * Register MediaGroupFilter * Update docs * Fix a typo --- aiogram/dispatcher/dispatcher.py | 8 +++++++- aiogram/dispatcher/filters/__init__.py | 3 ++- aiogram/dispatcher/filters/builtin.py | 17 +++++++++++++++++ docs/source/dispatcher/filters.rst | 8 ++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/aiogram/dispatcher/dispatcher.py b/aiogram/dispatcher/dispatcher.py index a2736cf7..d471fe86 100644 --- a/aiogram/dispatcher/dispatcher.py +++ b/aiogram/dispatcher/dispatcher.py @@ -11,7 +11,7 @@ from aiohttp.helpers import sentinel from aiogram.utils.deprecated import renamed_argument from .filters import Command, ContentTypeFilter, ExceptionsFilter, FiltersFactory, HashTag, Regexp, \ RegexpCommandsFilter, StateFilter, Text, IDFilter, AdminFilter, IsReplyFilter, ForwardedMessageFilter, \ - IsSenderContact, ChatTypeFilter, AbstractFilter + IsSenderContact, ChatTypeFilter, MediaGroupFilter, AbstractFilter from .handler import Handler from .middlewares import MiddlewareManager from .storage import BaseStorage, DELTA, DisabledStorage, EXCEEDED_COUNT, FSMContext, \ @@ -204,6 +204,12 @@ class Dispatcher(DataMixin, ContextInstanceMixin): self.my_chat_member_handlers, self.chat_member_handlers ]) + filters_factory.bind(MediaGroupFilter, event_handlers=[ + self.message_handlers, + self.edited_channel_post_handlers, + self.channel_post_handlers, + self.edited_channel_post_handlers + ]) def __del__(self): self.stop_polling() diff --git a/aiogram/dispatcher/filters/__init__.py b/aiogram/dispatcher/filters/__init__.py index d64a2667..d07d953b 100644 --- a/aiogram/dispatcher/filters/__init__.py +++ b/aiogram/dispatcher/filters/__init__.py @@ -1,7 +1,7 @@ from .builtin import Command, CommandHelp, CommandPrivacy, CommandSettings, CommandStart, ContentTypeFilter, \ ExceptionsFilter, HashTag, Regexp, RegexpCommandsFilter, StateFilter, \ Text, IDFilter, AdminFilter, IsReplyFilter, IsSenderContact, ForwardedMessageFilter, \ - ChatTypeFilter + ChatTypeFilter, MediaGroupFilter from .factory import FiltersFactory from .filters import AbstractFilter, BoundFilter, Filter, FilterNotPassed, FilterRecord, execute_filter, \ check_filters, get_filter_spec, get_filters_spec @@ -25,6 +25,7 @@ __all__ = ( 'IsSenderContact', 'ForwardedMessageFilter', 'ChatTypeFilter', + 'MediaGroupFilter', 'FiltersFactory', 'AbstractFilter', 'BoundFilter', diff --git a/aiogram/dispatcher/filters/builtin.py b/aiogram/dispatcher/filters/builtin.py index 762c8505..c32c53be 100644 --- a/aiogram/dispatcher/filters/builtin.py +++ b/aiogram/dispatcher/filters/builtin.py @@ -738,3 +738,20 @@ class ChatTypeFilter(BoundFilter): return False return obj.type in self.chat_type + + +class MediaGroupFilter(BoundFilter): + """ + Check if message is part of a media group. + + `is_media_group=True` - the message is part of a media group + `is_media_group=False` - the message is NOT part of a media group + """ + + key = "is_media_group" + + def __init__(self, is_media_group: bool): + self.is_media_group = is_media_group + + async def check(self, message: types.Message) -> bool: + return bool(getattr(message, "media_group_id")) is self.is_media_group diff --git a/docs/source/dispatcher/filters.rst b/docs/source/dispatcher/filters.rst index b8f4962e..a47e396e 100644 --- a/docs/source/dispatcher/filters.rst +++ b/docs/source/dispatcher/filters.rst @@ -155,6 +155,14 @@ ChatTypeFilter .. autoclass:: aiogram.dispatcher.filters.ChatTypeFilter :members: :show-inheritance: + + +MediaGroupFilter +------------- + +.. autoclass:: aiogram.dispatcher.filters.MediaGroupFilter + :members: + :show-inheritance: Making own filters (Custom filters) From ee0ceee70420caab5ce1345b925685a918e7c9d5 Mon Sep 17 00:00:00 2001 From: Oleg A Date: Sat, 20 Mar 2021 20:57:07 +0300 Subject: [PATCH 07/10] feat: delete_message shortcut for Chat (#526) --- aiogram/types/chat.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/aiogram/types/chat.py b/aiogram/types/chat.py index 0a444fd8..3b0a7b9d 100644 --- a/aiogram/types/chat.py +++ b/aiogram/types/chat.py @@ -608,6 +608,15 @@ class Chat(base.TelegramObject): invite_link=invite_link, ) + async def delete_message(self, + message_id: base.Integer, + ) -> base.Boolean: + """ Shortcut for deleteMessage method. """ + return await self.bot.delete_message( + chat_id=self.id, + message_id=message_id, + ) + def __int__(self): return self.id From b0f2fe3ed496fba6645a0e9c2931282e9c72b937 Mon Sep 17 00:00:00 2001 From: Andrew <11490628+andrew000@users.noreply.github.com> Date: Sun, 21 Mar 2021 09:37:00 +0200 Subject: [PATCH 08/10] FIX TelegramObject.__setitem__ (#532) * FIX TelegramObject.__setitem__ Removed 'raise KeyError(key)' * Add warning and log in TelegramObject.__setitem__ When Telegram adds a new field -> Aiogram will warn about this. * Removed warnings.warn * Set logger to 'aiogram' * Removed 'f' before string --- aiogram/types/base.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/aiogram/types/base.py b/aiogram/types/base.py index 373f47be..0ed8579c 100644 --- a/aiogram/types/base.py +++ b/aiogram/types/base.py @@ -1,6 +1,7 @@ from __future__ import annotations import io +import logging import typing from typing import TypeVar @@ -26,6 +27,9 @@ Float = TypeVar('Float', bound=float) Boolean = TypeVar('Boolean', bound=bool) T = TypeVar('T') +# Main aiogram logger +log = logging.getLogger('aiogram') + class MetaTelegramObject(type): """ @@ -225,7 +229,9 @@ class TelegramObject(ContextInstanceMixin, metaclass=MetaTelegramObject): if key in self.props: return self.props[key].set_value(self, value, self.conf.get('parent', None)) self.values[key] = value - raise KeyError(key) + + # Log warning when Telegram silently adds new Fields + log.warning("Field '%s' doesn't exist in %s", key, self.__class__) def __contains__(self, item: str) -> bool: """ From e2273e6c31aaf4eb70554239493547a13e486398 Mon Sep 17 00:00:00 2001 From: Ramzan Bekbulatov Date: Sun, 21 Mar 2021 10:41:03 +0300 Subject: [PATCH 09/10] new: add mime types parsing (#431) --- aiogram/types/document.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/aiogram/types/document.py b/aiogram/types/document.py index e15b745d..c3d19fa9 100644 --- a/aiogram/types/document.py +++ b/aiogram/types/document.py @@ -2,6 +2,7 @@ from . import base from . import fields from . import mixins from .photo_size import PhotoSize +from ..utils import helper class Document(base.TelegramObject, mixins.Downloadable): @@ -16,3 +17,34 @@ class Document(base.TelegramObject, mixins.Downloadable): file_name: base.String = fields.Field() mime_type: base.String = fields.Field() file_size: base.Integer = fields.Field() + + @property + def mime_base(self) -> str: + base_type, _, _ = self.mime_type.partition('/') + return base_type + + @property + def mime_subtype(self) -> str: + _, _, subtype = self.mime_type.partition('/') + return subtype + + +class MimeBase(helper.Helper): + """ + List of mime base types registered in IANA + + https://www.iana.org/assignments/media-types/media-types.xhtml + """ + + mode = helper.HelperMode.lowercase + + APPLICATION = helper.Item() # application + AUDIO = helper.Item() # audio + EXAMPLE = helper.Item() # example + FONT = helper.Item() # font + IMAGE = helper.Item() # image + MESSAGE = helper.Item() # message + MODEL = helper.Item() # model + MULTIPART = helper.Item() # multipart + TEXT = helper.Item() # text + VIDEO = helper.Item() # video From 15a6e94135f86777af1ff96a7e40c1e5923558e3 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Mon, 22 Mar 2021 22:01:44 +0200 Subject: [PATCH 10/10] Bump version --- aiogram/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiogram/__init__.py b/aiogram/__init__.py index ef832be9..590afc50 100644 --- a/aiogram/__init__.py +++ b/aiogram/__init__.py @@ -43,5 +43,5 @@ __all__ = ( 'utils', ) -__version__ = '2.12' +__version__ = '2.12.1' __api_version__ = '5.1'