feat: add ChatType builtin filter (#356)

* feat: ChatTypesFilter

* feat: add example of usage

* feat: docs

* fix: add import in filters/__init__

* fix: remove some of event_handlers

* fix

* fix imports

* fix: rename to ChatTypeFilter

* fix: rename argument to chat_type

fix: rename example file name

fix: str is container also lol. example fixed also

* fix: respect type hints

* fix: add warning with respect to type hint

* fix: use warnings instead of logging
This commit is contained in:
Egor 2020-07-02 14:17:48 +03:00 committed by GitHub
parent d179789ea7
commit 81b36bd192
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 90 additions and 5 deletions

View file

@ -11,8 +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, \
AbstractFilter
from .filters.builtin import IsSenderContact
IsSenderContact, ChatTypeFilter, AbstractFilter
from .handler import Handler
from .middlewares import MiddlewareManager
from .storage import BaseStorage, DELTA, DisabledStorage, EXCEEDED_COUNT, FSMContext, \
@ -167,6 +166,13 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
self.channel_post_handlers,
self.edited_channel_post_handlers
])
filters_factory.bind(ChatTypeFilter, event_handlers=[
self.message_handlers,
self.edited_message_handlers,
self.channel_post_handlers,
self.edited_channel_post_handlers,
self.callback_query_handlers,
])
def __del__(self):
self.stop_polling()

View file

@ -1,6 +1,7 @@
from .builtin import Command, CommandHelp, CommandPrivacy, CommandSettings, CommandStart, ContentTypeFilter, \
ExceptionsFilter, HashTag, Regexp, RegexpCommandsFilter, StateFilter, \
Text, IDFilter, AdminFilter, IsReplyFilter, IsSenderContact, ForwardedMessageFilter
Text, IDFilter, AdminFilter, IsReplyFilter, IsSenderContact, ForwardedMessageFilter, \
ChatTypeFilter
from .factory import FiltersFactory
from .filters import AbstractFilter, BoundFilter, Filter, FilterNotPassed, FilterRecord, execute_filter, \
check_filters, get_filter_spec, get_filters_spec
@ -33,4 +34,5 @@ __all__ = [
'execute_filter',
'check_filters',
'ForwardedMessageFilter',
'ChatTypeFilter',
]

View file

@ -1,6 +1,7 @@
import inspect
import re
import typing
import warnings
from contextvars import ContextVar
from dataclasses import dataclass, field
from typing import Any, Dict, Iterable, Optional, Union
@ -9,8 +10,7 @@ from babel.support import LazyProxy
from aiogram import types
from aiogram.dispatcher.filters.filters import BoundFilter, Filter
from aiogram.types import CallbackQuery, Message, InlineQuery, Poll, ChatType
from aiogram.types import CallbackQuery, ChatType, InlineQuery, Message, Poll
ChatIDArgumentType = typing.Union[typing.Iterable[typing.Union[int, str]], str, int]
@ -691,3 +691,24 @@ class ForwardedMessageFilter(BoundFilter):
async def check(self, message: Message):
return bool(getattr(message, "forward_date")) is self.is_forwarded
class ChatTypeFilter(BoundFilter):
key = 'chat_type'
def __init__(self, chat_type: typing.Container[ChatType]):
if isinstance(chat_type, str):
chat_type = {chat_type}
self.chat_type: typing.Set[str] = set(chat_type)
async def check(self, obj: Union[Message, CallbackQuery]):
if isinstance(obj, Message):
obj = obj.chat
elif isinstance(obj, CallbackQuery):
obj = obj.message.chat
else:
warnings.warn("ChatTypeFilter doesn't support %s as input", type(obj))
return False
return obj.type in self.chat_type

View file

@ -10,6 +10,7 @@ from .chat_member import ChatMember
from .chat_permissions import ChatPermissions
from .chat_photo import ChatPhoto
from .input_file import InputFile
from ..utils.deprecated import deprecated
class Chat(base.TelegramObject):
@ -512,6 +513,7 @@ class ChatType(helper.Helper):
return obj.type in chat_types
@classmethod
@deprecated("This filter was moved to ChatTypeFilter, and will be removed in aiogram v3.0")
def is_private(cls, obj) -> bool:
"""
Check chat is private
@ -522,6 +524,7 @@ class ChatType(helper.Helper):
return cls._check(obj, [cls.PRIVATE])
@classmethod
@deprecated("This filter was moved to ChatTypeFilter, and will be removed in aiogram v3.0")
def is_group(cls, obj) -> bool:
"""
Check chat is group
@ -532,6 +535,7 @@ class ChatType(helper.Helper):
return cls._check(obj, [cls.GROUP])
@classmethod
@deprecated("This filter was moved to ChatTypeFilter, and will be removed in aiogram v3.0")
def is_super_group(cls, obj) -> bool:
"""
Check chat is super-group
@ -542,6 +546,7 @@ class ChatType(helper.Helper):
return cls._check(obj, [cls.SUPER_GROUP])
@classmethod
@deprecated("This filter was moved to ChatTypeFilter, and will be removed in aiogram v3.0")
def is_group_or_super_group(cls, obj) -> bool:
"""
Check chat is group or super-group
@ -552,6 +557,7 @@ class ChatType(helper.Helper):
return cls._check(obj, [cls.GROUP, cls.SUPER_GROUP])
@classmethod
@deprecated("This filter was moved to ChatTypeFilter, and will be removed in aiogram v3.0")
def is_channel(cls, obj) -> bool:
"""
Check chat is channel

View file

@ -149,6 +149,14 @@ ForwardedMessageFilter
:show-inheritance:
ChatTypeFilter
-------------
.. autoclass:: aiogram.dispatcher.filters.filters.ChatTypeFilter
:members:
:show-inheritance:
Making own filters (Custom filters)
===================================

View file

@ -0,0 +1,42 @@
"""
This is an example with usage of ChatTypeFilter
It filters incoming object based on type of its chat type
"""
import logging
from aiogram import Bot, Dispatcher, executor, types
from aiogram.dispatcher.handler import SkipHandler
from aiogram.types import ChatType
API_TOKEN = 'BOT TOKEN HERE'
# Configure logging
logging.basicConfig(level=logging.INFO)
# Initialize bot and dispatcher
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)
@dp.message_handler(chat_type=[ChatType.PRIVATE, ChatType.CHANNEL])
async def send_welcome(message: types.Message):
"""
This handler will be called when user sends `/start` or `/help` command
"""
await message.reply("Hi!\nI'm hearing your messages in private chats and channels")
# propagate message to the next handler
raise SkipHandler
@dp.message_handler(chat_type=ChatType.PRIVATE)
async def send_welcome(message: types.Message):
"""
This handler will be called when user sends `/start` or `/help` command
"""
await message.reply("Hi!\nI'm hearing your messages only in private chats")
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)