Fix issues and rework AdminFilter

This commit is contained in:
Arslan 'Ars2014' Sakhapov 2019-08-08 20:53:52 +05:00
parent 9f6b577f08
commit c0e60f8706
5 changed files with 58 additions and 29 deletions

View file

@ -9,7 +9,7 @@ import aiohttp
from aiohttp.helpers import sentinel from aiohttp.helpers import sentinel
from .filters import Command, ContentTypeFilter, ExceptionsFilter, FiltersFactory, HashTag, Regexp, \ from .filters import Command, ContentTypeFilter, ExceptionsFilter, FiltersFactory, HashTag, Regexp, \
RegexpCommandsFilter, StateFilter, Text, IdFilter, AdminFilter RegexpCommandsFilter, StateFilter, Text, IDFilter, AdminFilter
from .handler import Handler from .handler import Handler
from .middlewares import MiddlewareManager from .middlewares import MiddlewareManager
from .storage import BaseStorage, DELTA, DisabledStorage, EXCEEDED_COUNT, FSMContext, \ from .storage import BaseStorage, DELTA, DisabledStorage, EXCEEDED_COUNT, FSMContext, \
@ -114,7 +114,7 @@ class Dispatcher(DataMixin, ContextInstanceMixin):
filters_factory.bind(ExceptionsFilter, event_handlers=[ filters_factory.bind(ExceptionsFilter, event_handlers=[
self.errors_handlers self.errors_handlers
]) ])
filters_factory.bind(IdFilter, event_handlers=[ filters_factory.bind(IDFilter, event_handlers=[
self.message_handlers, self.edited_message_handlers, self.message_handlers, self.edited_message_handlers,
self.channel_post_handlers, self.edited_channel_post_handlers, self.channel_post_handlers, self.edited_channel_post_handlers,
self.callback_query_handlers, self.inline_query_handlers self.callback_query_handlers, self.inline_query_handlers

View file

@ -1,5 +1,5 @@
from .builtin import Command, CommandHelp, CommandPrivacy, CommandSettings, CommandStart, ContentTypeFilter, \ from .builtin import Command, CommandHelp, CommandPrivacy, CommandSettings, CommandStart, ContentTypeFilter, \
ExceptionsFilter, HashTag, Regexp, RegexpCommandsFilter, StateFilter, Text, IdFilter, AdminFilter ExceptionsFilter, HashTag, Regexp, RegexpCommandsFilter, StateFilter, Text, IDFilter, AdminFilter
from .factory import FiltersFactory from .factory import FiltersFactory
from .filters import AbstractFilter, BoundFilter, Filter, FilterNotPassed, FilterRecord, execute_filter, \ from .filters import AbstractFilter, BoundFilter, Filter, FilterNotPassed, FilterRecord, execute_filter, \
check_filters, get_filter_spec, get_filters_spec check_filters, get_filter_spec, get_filters_spec
@ -23,7 +23,7 @@ __all__ = [
'Regexp', 'Regexp',
'StateFilter', 'StateFilter',
'Text', 'Text',
'IdFilter', 'IDFilter',
'AdminFilter', 'AdminFilter',
'get_filter_spec', 'get_filter_spec',
'get_filters_spec', 'get_filters_spec',

View file

@ -9,7 +9,7 @@ from babel.support import LazyProxy
from aiogram import types from aiogram import types
from aiogram.dispatcher.filters.filters import BoundFilter, Filter from aiogram.dispatcher.filters.filters import BoundFilter, Filter
from aiogram.types import CallbackQuery, Message, InlineQuery, Poll from aiogram.types import CallbackQuery, Message, InlineQuery, Poll, ChatType
class Command(Filter): class Command(Filter):
@ -571,34 +571,50 @@ class AdminFilter(Filter):
chat_id is required for InlineQuery. chat_id is required for InlineQuery.
""" """
def __init__(self, admin_chat_id: typing.Optional[int] = None, admin_current_chat: typing.Optional[bool] = False): def __init__(self, is_chat_admin: Optional[Union[Iterable[Union[int, str]], str, int, bool]] = None):
self.chat_id = admin_chat_id self._all_chats = False
self.check_current_chat = admin_current_chat self.chat_ids = None
if is_chat_admin is False:
raise ValueError("is_chat_admin cannot be False")
if is_chat_admin:
if isinstance(is_chat_admin, bool):
self._all_chats = is_chat_admin
if isinstance(is_chat_admin, Iterable):
self.chat_ids = list(map(int, is_chat_admin))
else:
self.chat_ids = [int(is_chat_admin)]
else:
self._all_chats = True
@classmethod @classmethod
def validate(cls, full_config: typing.Dict[str, typing.Any]) -> typing.Optional[typing.Dict[str, typing.Any]]: def validate(cls, full_config: typing.Dict[str, typing.Any]) -> typing.Optional[typing.Dict[str, typing.Any]]:
result = {} result = {}
if "admin_chat_id" in full_config: # use prefix 'admin' to not conflict with IdFilter if "is_chat_admin" in full_config:
result["admin_chat_id"] = full_config.pop("admin_chat_id") result["is_chat_admin"] = full_config.pop("is_chat_admin")
if "admin_current_chat" in full_config: # set True if need to check current chat
result["admin_current_chat"] = full_config.pop("admin_current_chat")
return result return result
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery]) -> bool: async def check(self, obj: Union[Message, CallbackQuery, InlineQuery]) -> bool:
user_id = obj.from_user.id user_id = obj.from_user.id
chat_id = self.chat_id chat_ids = None
if self._all_chats:
if ChatType.is_private(obj): # there is no admin in private chats
return False
if not chat_id or self.check_current_chat:
if isinstance(obj, Message): if isinstance(obj, Message):
chat_id = obj.chat.id chat_ids = [obj.chat.id]
elif isinstance(obj, CallbackQuery): elif isinstance(obj, CallbackQuery):
if obj.message: if obj.message:
chat_id = obj.message.chat.id chat_ids = [obj.message.chat.id]
else: else:
raise ValueError("Cannot get current chat in a InlineQuery") return False
else:
chat_ids = self.chat_ids
admins = [member.user.id for member in await obj.bot.get_chat_administrators(chat_id)] admins = [member.user.id for chat_id in chat_ids for member in await obj.bot.get_chat_administrators(chat_id)]
return user_id in admins return user_id in admins

View file

@ -111,10 +111,18 @@ ExceptionsFilter
:show-inheritance: :show-inheritance:
IdFilter IDFilter
---------------- ----------------
.. autoclass:: aiogram.dispatcher.filters.builtin.IdFilter .. autoclass:: aiogram.dispatcher.filters.builtin.IDFilter
:members:
:show-inheritance:
AdminFilter
----------------
.. autoclass:: aiogram.dispatcher.filters.builtin.AdminFilter
:members: :members:
:show-inheritance: :show-inheritance:

View file

@ -2,26 +2,31 @@ import logging
from aiogram import Bot, Dispatcher, types, executor from aiogram import Bot, Dispatcher, types, executor
API_TOKEN = 'API TOKEN HERE' API_TOKEN = 'API_TOKEN_HERE'
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
bot = Bot(token=API_TOKEN) bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot=bot) dp = Dispatcher(bot=bot)
chat_id = -1001241113577
# checks specified chat # checks specified chat
@dp.message_handler(admin_chat_id=chat_id) @dp.message_handler(is_chat_admin=-1001241113577)
async def handler(msg: types.Message): async def handle_specified(msg: types.Message):
await msg.reply(f"You are an admin of the chat '{chat_id}'", reply=False) await msg.answer("You are an admin of the specified chat!")
# checks multiple chats
@dp.message_handler(is_chat_admin=[-1001241113577, -320463906])
async def handle_multiple(msg: types.Message):
await msg.answer("You are an admin of multiple chats!")
# checks current chat # checks current chat
@dp.message_handler(admin_current_chat=True) @dp.message_handler(is_chat_admin=True)
async def handler(msg: types.Message): async def handler3(msg: types.Message):
await msg.reply("You are an admin of the current chat!", reply=False) await msg.answer("You are an admin of the current chat!")
if __name__ == '__main__': if __name__ == '__main__':