2020-06-30 10:13:58 +08:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2020-05-02 20:03:36 +08:00
|
|
|
import re
|
2020-08-14 17:41:24 +08:00
|
|
|
import abc
|
|
|
|
import asyncio
|
|
|
|
from typing import cast
|
2020-05-05 16:11:05 +08:00
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
from nonebot.utils import run_sync
|
|
|
|
from nonebot.typing import Bot, Event, Union, Optional, Awaitable
|
|
|
|
from nonebot.typing import RuleChecker, SyncRuleChecker, AsyncRuleChecker
|
2020-05-02 20:03:36 +08:00
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
class BaseRule(abc.ABC):
|
2020-05-02 20:03:36 +08:00
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def __init__(self, checker: RuleChecker):
|
|
|
|
self.checker: RuleChecker = checker
|
2020-05-02 20:03:36 +08:00
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
@abc.abstractmethod
|
|
|
|
def __call__(self, bot: Bot, event: Event) -> Awaitable[bool]:
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def __and__(self, other: Union["BaseRule", RuleChecker]) -> "BaseRule":
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def __or__(self, other: Union["BaseRule", RuleChecker]) -> "BaseRule":
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def __neg__(self) -> "BaseRule":
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
|
|
|
|
class AsyncRule(BaseRule):
|
|
|
|
|
|
|
|
def __init__(self, checker: Optional[AsyncRuleChecker] = None):
|
|
|
|
|
|
|
|
async def always_true(bot: Bot, event: Event) -> bool:
|
|
|
|
return True
|
|
|
|
|
|
|
|
self.checker: AsyncRuleChecker = checker or always_true
|
|
|
|
|
|
|
|
def __call__(self, bot: Bot, event: Event) -> Awaitable[bool]:
|
2020-07-25 12:28:30 +08:00
|
|
|
return self.checker(bot, event)
|
2020-05-02 20:03:36 +08:00
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def __and__(self, other: Union[BaseRule, RuleChecker]) -> "AsyncRule":
|
|
|
|
func = other
|
|
|
|
if isinstance(other, BaseRule):
|
|
|
|
func = other.checker
|
|
|
|
|
|
|
|
if not asyncio.iscoroutinefunction(func):
|
|
|
|
func = run_sync(func)
|
|
|
|
|
|
|
|
async def tmp(bot: Bot, event: Event) -> bool:
|
|
|
|
a, b = await asyncio.gather(self.checker(bot, event),
|
|
|
|
func(bot, event))
|
|
|
|
return a and b
|
|
|
|
|
|
|
|
return AsyncRule(tmp)
|
|
|
|
|
|
|
|
def __or__(self, other: Union[BaseRule, RuleChecker]) -> "AsyncRule":
|
|
|
|
func = other
|
|
|
|
if isinstance(other, BaseRule):
|
|
|
|
func = other.checker
|
|
|
|
|
|
|
|
if not asyncio.iscoroutinefunction(func):
|
|
|
|
func = run_sync(func)
|
|
|
|
|
|
|
|
async def tmp(bot: Bot, event: Event) -> bool:
|
|
|
|
a, b = await asyncio.gather(self.checker(bot, event),
|
|
|
|
func(bot, event))
|
|
|
|
return a or b
|
|
|
|
|
|
|
|
return AsyncRule(tmp)
|
|
|
|
|
|
|
|
def __neg__(self) -> "AsyncRule":
|
|
|
|
|
|
|
|
async def neg(bot: Bot, event: Event) -> bool:
|
|
|
|
result = await self.checker(bot, event)
|
|
|
|
return not result
|
|
|
|
|
|
|
|
return AsyncRule(neg)
|
|
|
|
|
|
|
|
|
|
|
|
class SyncRule(BaseRule):
|
2020-05-02 20:03:36 +08:00
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def __init__(self, checker: Optional[SyncRuleChecker] = None):
|
2020-05-02 20:03:36 +08:00
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def always_true(bot: Bot, event: Event) -> bool:
|
|
|
|
return True
|
2020-07-25 12:28:30 +08:00
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
self.checker: SyncRuleChecker = checker or always_true
|
2020-07-25 12:28:30 +08:00
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def __call__(self, bot: Bot, event: Event) -> Awaitable[bool]:
|
|
|
|
return run_sync(self.checker)(bot, event)
|
|
|
|
|
|
|
|
def __and__(self, other: Union[BaseRule, RuleChecker]) -> BaseRule:
|
|
|
|
func = other
|
|
|
|
if isinstance(other, BaseRule):
|
|
|
|
func = other.checker
|
|
|
|
|
|
|
|
if not asyncio.iscoroutinefunction(func):
|
|
|
|
# func: SyncRuleChecker
|
|
|
|
syncfunc = cast(SyncRuleChecker, func)
|
|
|
|
|
|
|
|
def tmp(bot: Bot, event: Event) -> bool:
|
|
|
|
return self.checker(bot, event) and syncfunc(bot, event)
|
|
|
|
|
|
|
|
return SyncRule(tmp)
|
|
|
|
else:
|
|
|
|
# func: AsyncRuleChecker
|
|
|
|
asyncfunc = cast(AsyncRuleChecker, func)
|
|
|
|
|
|
|
|
async def tmp(bot: Bot, event: Event) -> bool:
|
|
|
|
a, b = await asyncio.gather(
|
|
|
|
run_sync(self.checker)(bot, event), asyncfunc(bot, event))
|
|
|
|
return a and b
|
|
|
|
|
|
|
|
return AsyncRule(tmp)
|
|
|
|
|
|
|
|
def __or__(self, other: Union[BaseRule, RuleChecker]) -> BaseRule:
|
|
|
|
func = other
|
|
|
|
if isinstance(other, BaseRule):
|
|
|
|
func = other.checker
|
|
|
|
|
|
|
|
if not asyncio.iscoroutinefunction(func):
|
|
|
|
# func: SyncRuleChecker
|
|
|
|
syncfunc = cast(SyncRuleChecker, func)
|
|
|
|
|
|
|
|
def tmp(bot: Bot, event: Event) -> bool:
|
|
|
|
return self.checker(bot, event) or syncfunc(bot, event)
|
|
|
|
|
|
|
|
return SyncRule(tmp)
|
|
|
|
else:
|
|
|
|
# func: AsyncRuleChecker
|
|
|
|
asyncfunc = cast(AsyncRuleChecker, func)
|
|
|
|
|
|
|
|
async def tmp(bot: Bot, event: Event) -> bool:
|
|
|
|
a, b = await asyncio.gather(
|
|
|
|
run_sync(self.checker)(bot, event), asyncfunc(bot, event))
|
|
|
|
return a or b
|
|
|
|
|
|
|
|
return AsyncRule(tmp)
|
|
|
|
|
|
|
|
def __neg__(self) -> "SyncRule":
|
|
|
|
|
|
|
|
def neg(bot: Bot, event: Event) -> bool:
|
|
|
|
return not self.checker(bot, event)
|
|
|
|
|
|
|
|
return SyncRule(neg)
|
|
|
|
|
|
|
|
|
|
|
|
def Rule(func: Optional[RuleChecker] = None) -> BaseRule:
|
|
|
|
if func and asyncio.iscoroutinefunction(func):
|
|
|
|
asyncfunc = cast(AsyncRuleChecker, func)
|
|
|
|
return AsyncRule(asyncfunc)
|
|
|
|
else:
|
|
|
|
syncfunc = cast(Optional[SyncRuleChecker], func)
|
|
|
|
return SyncRule(syncfunc)
|
|
|
|
|
|
|
|
|
|
|
|
def message() -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: event.type == "message")
|
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def notice() -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: event.type == "notice")
|
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def request() -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: event.type == "request")
|
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def metaevent() -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: event.type == "meta_event")
|
2020-05-02 20:03:36 +08:00
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def user(*qq: int) -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: event.user_id in qq)
|
2020-05-02 20:03:36 +08:00
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def private() -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: event.detail_type == "private")
|
2020-05-02 20:03:36 +08:00
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def group(*group: int) -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: event.detail_type == "group" and event.
|
|
|
|
group_id in group)
|
2020-05-02 20:03:36 +08:00
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def startswith(msg, start: int = None, end: int = None) -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: event.message.startswith(msg, start, end))
|
2020-05-02 20:03:36 +08:00
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def endswith(msg, start: int = None, end: int = None) -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(
|
|
|
|
lambda bot, event: event.message.endswith(msg, start=None, end=None))
|
2020-05-02 20:03:36 +08:00
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def has(msg: str) -> BaseRule:
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: msg in event.message)
|
2020-05-02 20:03:36 +08:00
|
|
|
|
|
|
|
|
2020-08-14 17:41:24 +08:00
|
|
|
def regex(regex, flags: Union[int, re.RegexFlag] = 0) -> BaseRule:
|
2020-05-02 20:03:36 +08:00
|
|
|
pattern = re.compile(regex, flags)
|
2020-07-25 12:28:30 +08:00
|
|
|
return Rule(lambda bot, event: bool(pattern.search(str(event.message))))
|