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,11 +63,7 @@ class Bot(BaseBot):
if "message" in event.keys(): if "message" in event.keys():
event["message"] = Message(event["message"]) event["message"] = Message(event["message"])
# TODO: Handle Meta Event await handle_event(self, event)
if event.type == "meta_event":
pass
else:
await handle_event(self, event)
async def call_api(self, api: str, data: dict): async def call_api(self, api: str, data: dict):
# TODO: Call API # TODO: Call API

View File

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

View File

@ -2,6 +2,19 @@
# -*- coding: utf-8 -*- # -*- 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): class PausedException(Exception):
"""Block a message from further handling and try to receive a new message""" """Block a message from further handling and try to receive a new message"""
pass pass

View File

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

View File

@ -1,19 +1,39 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import asyncio
from typing import Set, Callable
from nonebot.log import logger from nonebot.log import logger
from nonebot.event import Event from nonebot.event import Event
from nonebot.matcher import matchers 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): async def handle_event(bot, event: Event):
# TODO: PreProcess # 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 priority in sorted(matchers.keys()):
for index in range(len(matchers[priority])): for index in range(len(matchers[priority])):
Matcher = matchers[priority][index] Matcher = matchers[priority][index]
try: try:
if not Matcher.check_rule(event): if not Matcher.check_rule(bot, event):
continue continue
except Exception as e: except Exception as e:
logger.error( logger.error(

View File

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

View File

@ -9,52 +9,74 @@ from nonebot.event import Event
class Rule: class Rule:
def __init__(self, checker: Optional[Callable[[Event], bool]] = None): def __init__(
self.checker = checker or (lambda event: True) self,
checker: Optional[Callable[["BaseBot", Event], # type: ignore
bool]] = None):
self.checker = checker or (lambda bot, event: True)
def __call__(self, event: Event) -> bool: def __call__(self, bot, event: Event) -> bool:
return self.checker(event) return self.checker(bot, event)
def __and__(self, other: "Rule") -> "Rule": 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": 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": 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: 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: 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: def group(*group: int) -> Rule:
return Rule( return Rule(lambda bot, event: event.detail_type == "group" and event.
lambda event: event.detail_type == "group" and event.group_id in group) group_id in group)
def discuss(*discuss: int) -> Rule: 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) discuss_id in discuss)
def startswith(msg, start: int = None, end: int = None) -> Rule: 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: 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: 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: def regex(regex, flags: Union[int, re.RegexFlag] = 0) -> Rule:
pattern = re.compile(regex, flags) 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")