change rule and event handle

This commit is contained in:
yanyongyu 2020-07-25 12:28:30 +08:00
parent 10f1ab70b4
commit a39c2e223a
8 changed files with 140 additions and 33 deletions

View File

@ -63,10 +63,6 @@ class Bot(BaseBot):
if "message" in event.keys():
event["message"] = Message(event["message"])
# TODO: Handle Meta Event
if event.type == "meta_event":
pass
else:
await handle_event(self, event)
async def call_api(self, api: str, data: dict):

View File

@ -45,10 +45,6 @@ class BaseDriver(abc.ABC):
async def _handle_ws_reverse(self):
raise NotImplementedError
@abc.abstractmethod
async def _handle_http_api(self):
raise NotImplementedError
class BaseWebSocket(object):

View File

@ -2,6 +2,19 @@
# -*- coding: utf-8 -*-
class IgnoredException(Exception):
"""
Raised by event_preprocessor indicating that
the bot should ignore the event
"""
def __init__(self, reason):
"""
:param reason: reason to ignore the event
"""
self.reason = reason
class PausedException(Exception):
"""Block a message from further handling and try to receive a new message"""
pass

View File

@ -62,7 +62,7 @@ class Matcher:
return NewMatcher
@classmethod
def check_rule(cls, event: Event) -> bool:
def check_rule(cls, bot, event: Event) -> bool:
"""检查 Matcher 的 Rule 是否成立
Args:
@ -71,7 +71,7 @@ class Matcher:
Returns:
bool: 条件成立与否
"""
return cls.rule(event)
return cls.rule(bot, event)
# @classmethod
# def args_parser(cls, func: Callable[[Event, dict], None]):
@ -141,9 +141,6 @@ class Matcher:
# 运行handlers
async def run(self, bot, event):
if not self.rule(event):
return
try:
# if self.parser:
# await self.parser(event, state) # type: ignore

View File

@ -1,19 +1,39 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
from typing import Set, Callable
from nonebot.log import logger
from nonebot.event import Event
from nonebot.matcher import matchers
from nonebot.exception import IgnoredException
_event_preprocessors: Set[Callable] = set()
def event_preprocessor(func: Callable) -> Callable:
_event_preprocessors.add(func)
return func
async def handle_event(bot, event: Event):
# TODO: PreProcess
coros = []
for preprocessor in _event_preprocessors:
coros.append(preprocessor(bot, event))
if coros:
try:
await asyncio.gather(*coros)
except IgnoredException:
logger.info(f"Event {event} is ignored")
return
for priority in sorted(matchers.keys()):
for index in range(len(matchers[priority])):
Matcher = matchers[priority][index]
try:
if not Matcher.check_rule(event):
if not Matcher.check_rule(bot, event):
continue
except Exception as e:
logger.error(

View File

@ -7,9 +7,9 @@ import importlib
from types import ModuleType
from typing import Set, Dict, Type, Optional
from nonebot.rule import Rule
from nonebot.log import logger
from nonebot.matcher import Matcher
from nonebot.rule import Rule, metaevent, message, notice, request
plugins: Dict[str, "Plugin"] = {}
@ -26,13 +26,58 @@ class Plugin(object):
self.matchers = matchers
def on_metaevent(rule: Rule,
*,
handlers=[],
temp=False,
priority: int = 1,
state={}) -> Type[Matcher]:
matcher = Matcher.new(metaevent() & rule,
temp=temp,
priority=priority,
handlers=handlers,
default_state=state)
_tmp_matchers.add(matcher)
return matcher
def on_message(rule: Rule,
*,
handlers=[],
temp=False,
priority: int = 1,
state={}) -> Type[Matcher]:
matcher = Matcher.new(rule,
matcher = Matcher.new(message() & rule,
temp=temp,
priority=priority,
handlers=handlers,
default_state=state)
_tmp_matchers.add(matcher)
return matcher
def on_notice(rule: Rule,
*,
handlers=[],
temp=False,
priority: int = 1,
state={}) -> Type[Matcher]:
matcher = Matcher.new(notice() & rule,
temp=temp,
priority=priority,
handlers=handlers,
default_state=state)
_tmp_matchers.add(matcher)
return matcher
def on_request(rule: Rule,
*,
handlers=[],
temp=False,
priority: int = 1,
state={}) -> Type[Matcher]:
matcher = Matcher.new(request() & rule,
temp=temp,
priority=priority,
handlers=handlers,

View File

@ -9,52 +9,74 @@ from nonebot.event import Event
class Rule:
def __init__(self, checker: Optional[Callable[[Event], bool]] = None):
self.checker = checker or (lambda event: True)
def __init__(
self,
checker: Optional[Callable[["BaseBot", Event], # type: ignore
bool]] = None):
self.checker = checker or (lambda bot, event: True)
def __call__(self, event: Event) -> bool:
return self.checker(event)
def __call__(self, bot, event: Event) -> bool:
return self.checker(bot, event)
def __and__(self, other: "Rule") -> "Rule":
return Rule(lambda event: self.checker(event) and other.checker(event))
return Rule(lambda bot, event: self.checker(bot, event) and other.
checker(bot, event))
def __or__(self, other: "Rule") -> "Rule":
return Rule(lambda event: self.checker(event) or other.checker(event))
return Rule(lambda bot, event: self.checker(bot, event) or other.
checker(bot, event))
def __neg__(self) -> "Rule":
return Rule(lambda event: not self.checker(event))
return Rule(lambda bot, event: not self.checker(bot, event))
def message() -> Rule:
return Rule(lambda bot, event: event.type == "message")
def notice() -> Rule:
return Rule(lambda bot, event: event.type == "notice")
def request() -> Rule:
return Rule(lambda bot, event: event.type == "request")
def metaevent() -> Rule:
return Rule(lambda bot, event: event.type == "meta_event")
def user(*qq: int) -> Rule:
return Rule(lambda event: event.user_id in qq)
return Rule(lambda bot, event: event.user_id in qq)
def private() -> Rule:
return Rule(lambda event: event.detail_type == "private")
return Rule(lambda bot, event: event.detail_type == "private")
def group(*group: int) -> Rule:
return Rule(
lambda event: event.detail_type == "group" and event.group_id in group)
return Rule(lambda bot, event: event.detail_type == "group" and event.
group_id in group)
def discuss(*discuss: int) -> Rule:
return Rule(lambda event: event.detail_type == "discuss" and event.
return Rule(lambda bot, event: event.detail_type == "discuss" and event.
discuss_id in discuss)
def startswith(msg, start: int = None, end: int = None) -> Rule:
return Rule(lambda event: event.message.startswith(msg, start, end))
return Rule(lambda bot, event: event.message.startswith(msg, start, end))
def endswith(msg, start: int = None, end: int = None) -> Rule:
return Rule(lambda event: event.message.endswith(msg, start=None, end=None))
return Rule(
lambda bot, event: event.message.endswith(msg, start=None, end=None))
def has(msg: str) -> Rule:
return Rule(lambda event: msg in event.message)
return Rule(lambda bot, event: msg in event.message)
def regex(regex, flags: Union[int, re.RegexFlag] = 0) -> Rule:
pattern = re.compile(regex, flags)
return Rule(lambda event: bool(pattern.search(event.message)))
return Rule(lambda bot, event: bool(pattern.search(str(event.message))))

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from nonebot.rule import Rule
from nonebot.event import Event
from nonebot.plugin import on_metaevent
def heartbeat(bot, event: Event) -> bool:
return event.detail_type == "heartbeat"
test_matcher = on_metaevent(Rule(heartbeat))
@test_matcher.handle()
async def handle_heartbeat(bot, event: Event, state: dict):
print("[i] Heartbeat")