mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-16 20:23:32 +00:00
Add base of messages handler.
This commit is contained in:
parent
4bd8544531
commit
b7bba77d29
3 changed files with 134 additions and 22 deletions
|
|
@ -1,15 +1,21 @@
|
|||
import asyncio
|
||||
import logging
|
||||
|
||||
from .filters import CommandsFilter, RegexpFilter, ContentTypeFilter
|
||||
from .handler import Handler
|
||||
from ..bot import AIOGramBot
|
||||
from ..types.message import ContentType
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Dispatcher:
|
||||
def __init__(self, bot):
|
||||
def __init__(self, bot, loop=None):
|
||||
self.bot: AIOGramBot = bot
|
||||
if loop is None:
|
||||
loop = self.bot.loop
|
||||
|
||||
self.loop = loop
|
||||
|
||||
self.last_update_id = 0
|
||||
self.updates = Handler(self)
|
||||
|
|
@ -33,7 +39,7 @@ class Dispatcher:
|
|||
|
||||
async def process_updates(self, updates):
|
||||
for update in updates:
|
||||
self.bot.loop.create_task(self.updates.notify(update))
|
||||
self.loop.create_task(self.updates.notify(update))
|
||||
|
||||
async def process_update(self, update):
|
||||
if update.message:
|
||||
|
|
@ -42,6 +48,8 @@ class Dispatcher:
|
|||
async def start_pooling(self, timeout=20, relax=0.1):
|
||||
if self._pooling:
|
||||
raise RuntimeError('Pooling already started')
|
||||
log.info('Start pooling.')
|
||||
|
||||
self._pooling = True
|
||||
offset = None
|
||||
while self._pooling:
|
||||
|
|
@ -53,10 +61,49 @@ class Dispatcher:
|
|||
continue
|
||||
|
||||
if updates:
|
||||
log.info(f"Received {len(updates)} updates.")
|
||||
offset = updates[-1].update_id + 1
|
||||
await self.process_updates(updates)
|
||||
|
||||
await asyncio.sleep(relax)
|
||||
|
||||
log.warning('Pooling is stopped.')
|
||||
|
||||
def stop_pooling(self):
|
||||
self._pooling = False
|
||||
|
||||
def message_handler(self, commands=None, regexp=None, content_type=None, func=None,
|
||||
custom_filters=None):
|
||||
if commands is None:
|
||||
commands = []
|
||||
if content_type is None:
|
||||
content_type = [ContentType.TEXT]
|
||||
if custom_filters is None:
|
||||
custom_filters = []
|
||||
|
||||
filters_preset = []
|
||||
if commands:
|
||||
if isinstance(commands, str):
|
||||
commands = [commands]
|
||||
filters_preset.append(CommandsFilter(commands))
|
||||
|
||||
if regexp:
|
||||
filters_preset.append(RegexpFilter(regexp))
|
||||
|
||||
if content_type:
|
||||
filters_preset.append(ContentTypeFilter(content_type))
|
||||
|
||||
if func:
|
||||
filters_preset.append(func)
|
||||
|
||||
if custom_filters:
|
||||
filters_preset += custom_filters
|
||||
|
||||
def decorator(func):
|
||||
self.messages.register(func, filters_preset)
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
def __del__(self):
|
||||
self._pooling = False
|
||||
|
|
|
|||
80
aiogram/dispatcher/filters.py
Normal file
80
aiogram/dispatcher/filters.py
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import inspect
|
||||
import re
|
||||
|
||||
|
||||
async def check_filter(filter_, args, kwargs):
|
||||
if any((inspect.isasyncgen(filter_),
|
||||
inspect.iscoroutine(filter_),
|
||||
inspect.isawaitable(filter_),
|
||||
inspect.isasyncgenfunction(filter_),
|
||||
inspect.iscoroutinefunction(filter_))):
|
||||
return await filter_(*args, **kwargs)
|
||||
elif callable(filter_):
|
||||
return filter_(*args, **kwargs)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
async def check_filters(filters, args, kwargs):
|
||||
if filters is not None:
|
||||
for filter_ in filters:
|
||||
f = await check_filter(filter_, args, kwargs)
|
||||
if not f:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class Filter:
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self.check(*args, **kwargs)
|
||||
|
||||
def check(self, *args, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AsyncFilter(Filter):
|
||||
def __aiter__(self):
|
||||
return None
|
||||
|
||||
def __await__(self):
|
||||
return self.check
|
||||
|
||||
async def check(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class CommandsFilter(AsyncFilter):
|
||||
def __init__(self, commands):
|
||||
self.commands = commands
|
||||
|
||||
async def check(self, message):
|
||||
if not message.is_command():
|
||||
return False
|
||||
|
||||
command = message.text.split()[0][1:]
|
||||
command, _, mention = command.partition('@')
|
||||
|
||||
if mention and mention != (await message.bot.me).username:
|
||||
return False
|
||||
|
||||
if command not in self.commands:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class RegexpFilter(Filter):
|
||||
def __init__(self, regexp):
|
||||
self.regexp = re.compile(regexp)
|
||||
|
||||
def check(self, message):
|
||||
if message.text:
|
||||
return bool(self.regexp.match(message.text))
|
||||
|
||||
|
||||
class ContentTypeFilter(Filter):
|
||||
def __init__(self, content_types):
|
||||
self.content_types = content_types
|
||||
|
||||
def check(self, message):
|
||||
return message.content_type in self.content_types
|
||||
|
|
@ -1,27 +1,10 @@
|
|||
import inspect
|
||||
|
||||
|
||||
async def check_filter(filter_, args, kwargs):
|
||||
if inspect.iscoroutinefunction(filter_):
|
||||
return await filter_(*args, **kwargs)
|
||||
elif callable(filter_):
|
||||
return filter_(*args, **kwargs)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
async def check_filters(filters, args, kwargs):
|
||||
if filters is not None:
|
||||
for filter_ in filters:
|
||||
f = await check_filter(filter_, args, kwargs)
|
||||
if not f:
|
||||
return False
|
||||
return True
|
||||
from .filters import check_filters
|
||||
|
||||
|
||||
class Handler:
|
||||
def __init__(self, dispatcher):
|
||||
def __init__(self, dispatcher, once=True):
|
||||
self.dispatcher = dispatcher
|
||||
self.once = once
|
||||
|
||||
self.handlers = []
|
||||
|
||||
|
|
@ -42,3 +25,5 @@ class Handler:
|
|||
for filters, handler in self.handlers:
|
||||
if await check_filters(filters, args, kwargs):
|
||||
await handler(*args, **kwargs)
|
||||
if self.once:
|
||||
break
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue