🔧 change command and add builtin plugin

This commit is contained in:
yanyongyu 2020-08-29 21:59:36 +08:00
parent def5caedbc
commit f5b655ef71
6 changed files with 79 additions and 21 deletions

View File

@ -201,4 +201,6 @@ def run(host: Optional[str] = None,
get_driver().run(host, port, *args, **kwargs) get_driver().run(host, port, *args, **kwargs)
from nonebot.plugin import load_plugin, load_plugins, get_loaded_plugins from nonebot.plugin import on_message, on_notice, on_request, on_metaevent
from nonebot.plugin import on_startswith, on_endswith, on_command, on_regex
from nonebot.plugin import load_plugin, load_plugins, load_builtin_plugins, get_loaded_plugins

View File

@ -10,8 +10,9 @@ from importlib._bootstrap import _load
from nonebot.log import logger from nonebot.log import logger
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.permission import Permission from nonebot.permission import Permission
from nonebot.typing import Handler, RuleChecker
from nonebot.rule import Rule, startswith, endswith, command, regex from nonebot.rule import Rule, startswith, endswith, command, regex
from nonebot.typing import Set, Dict, Type, Tuple, Union, Optional, ModuleType, RuleChecker from nonebot.typing import Set, List, Dict, Type, Tuple, Union, Optional, ModuleType
plugins: Dict[str, "Plugin"] = {} plugins: Dict[str, "Plugin"] = {}
@ -20,10 +21,9 @@ _tmp_matchers: Set[Type[Matcher]] = set()
class Plugin(object): class Plugin(object):
# TODO: store plugin informations def __init__(self, name: str, module: ModuleType,
def __init__(self, module_path: str, module: ModuleType,
matchers: Set[Type[Matcher]]): matchers: Set[Type[Matcher]]):
self.module_path = module_path self.name = name
self.module = module self.module = module
self.matchers = matchers self.matchers = matchers
@ -31,7 +31,7 @@ class Plugin(object):
def on(rule: Union[Rule, RuleChecker] = Rule(), def on(rule: Union[Rule, RuleChecker] = Rule(),
permission: Permission = Permission(), permission: Permission = Permission(),
*, *,
handlers: Optional[list] = None, handlers: Optional[List[Handler]] = None,
temp: bool = False, temp: bool = False,
priority: int = 1, priority: int = 1,
block: bool = False, block: bool = False,
@ -50,7 +50,7 @@ def on(rule: Union[Rule, RuleChecker] = Rule(),
def on_metaevent(rule: Union[Rule, RuleChecker] = Rule(), def on_metaevent(rule: Union[Rule, RuleChecker] = Rule(),
*, *,
handlers: Optional[list] = None, handlers: Optional[List[Handler]] = None,
temp: bool = False, temp: bool = False,
priority: int = 1, priority: int = 1,
block: bool = False, block: bool = False,
@ -70,7 +70,7 @@ def on_metaevent(rule: Union[Rule, RuleChecker] = Rule(),
def on_message(rule: Union[Rule, RuleChecker] = Rule(), def on_message(rule: Union[Rule, RuleChecker] = Rule(),
permission: Permission = Permission(), permission: Permission = Permission(),
*, *,
handlers: Optional[list] = None, handlers: Optional[List[Handler]] = None,
temp: bool = False, temp: bool = False,
priority: int = 1, priority: int = 1,
block: bool = True, block: bool = True,
@ -89,7 +89,7 @@ def on_message(rule: Union[Rule, RuleChecker] = Rule(),
def on_notice(rule: Union[Rule, RuleChecker] = Rule(), def on_notice(rule: Union[Rule, RuleChecker] = Rule(),
*, *,
handlers: Optional[list] = None, handlers: Optional[List[Handler]] = None,
temp: bool = False, temp: bool = False,
priority: int = 1, priority: int = 1,
block: bool = False, block: bool = False,
@ -108,7 +108,7 @@ def on_notice(rule: Union[Rule, RuleChecker] = Rule(),
def on_request(rule: Union[Rule, RuleChecker] = Rule(), def on_request(rule: Union[Rule, RuleChecker] = Rule(),
*, *,
handlers: Optional[list] = None, handlers: Optional[List[Handler]] = None,
temp: bool = False, temp: bool = False,
priority: int = 1, priority: int = 1,
block: bool = False, block: bool = False,
@ -149,9 +149,19 @@ def on_command(cmd: Union[str, Tuple[str, ...]],
**kwargs) -> Type[Matcher]: **kwargs) -> Type[Matcher]:
if isinstance(cmd, str): if isinstance(cmd, str):
cmd = (cmd,) cmd = (cmd,)
return on_message(command(cmd) &
rule, permission, **kwargs) if rule else on_message( async def _strip_cmd(bot, event, state: dict):
command(cmd), permission, **kwargs) message = event.message
event.message = message.__class__(
str(message)[len(state["_prefix"]["raw_command"]):].strip())
handlers = kwargs.pop("handlers", [])
handlers.insert(0, _strip_cmd)
return on_message(
command(cmd) &
rule, permission, handlers=handlers, **kwargs) if rule else on_message(
command(cmd), permission, handlers=handlers, **kwargs)
def on_regex(pattern: str, def on_regex(pattern: str,
@ -167,12 +177,20 @@ def on_regex(pattern: str,
def load_plugin(module_path: str) -> Optional[Plugin]: def load_plugin(module_path: str) -> Optional[Plugin]:
try: try:
_tmp_matchers.clear() _tmp_matchers.clear()
if module_path in plugins:
return plugins[module_path]
elif module_path in sys.modules:
logger.warning(
f"Module {module_path} has been loaded by other plugins! Ignored"
)
return
module = importlib.import_module(module_path) module = importlib.import_module(module_path)
for m in _tmp_matchers: for m in _tmp_matchers:
m.module = module_path m.module = module_path
plugin = Plugin(module_path, module, _tmp_matchers.copy()) plugin = Plugin(module_path, module, _tmp_matchers.copy())
plugins[module_path] = plugin plugins[module_path] = plugin
logger.opt(colors=True).info(f'Succeeded to import "{module_path}"') logger.opt(
colors=True).info(f'Succeeded to import "<y>{module_path}</y>"')
return plugin return plugin
except Exception as e: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
@ -189,7 +207,11 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]:
continue continue
spec = module_info.module_finder.find_spec(name) spec = module_info.module_finder.find_spec(name)
if spec.name in sys.modules: if spec.name in plugins:
continue
elif spec.name in sys.modules:
logger.warning(
f"Module {spec.name} has been loaded by other plugin! Ignored")
continue continue
try: try:
@ -207,5 +229,9 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]:
return loaded_plugins return loaded_plugins
def load_builtin_plugins():
return load_plugin("nonebot.plugins.base")
def get_loaded_plugins() -> Set[Plugin]: def get_loaded_plugins() -> Set[Plugin]:
return set(plugins.values()) return set(plugins.values())

10
nonebot/plugins/base.py Normal file
View File

@ -0,0 +1,10 @@
from nonebot.rule import to_me
from nonebot.plugin import on_command
from nonebot.typing import Bot, Event
say = on_command("say", to_me())
@say.handle()
async def repeat(bot: Bot, event: Event, state: dict):
await bot.send(message=event.message, event=event)

View File

@ -74,13 +74,21 @@ class TrieRule:
suffix = cls.suffix.longest_prefix( suffix = cls.suffix.longest_prefix(
message_r.data["text"].rstrip()[::-1]) message_r.data["text"].rstrip()[::-1])
state["_prefix"] = {prefix.key: prefix.value} if prefix else {} state["_prefix"] = {
state["_suffix"] = {suffix.key: suffix.value} if suffix else {} "raw_command": prefix.key,
"command": prefix.value
} if prefix else {}
state["_suffix"] = {
"raw_command": suffix.key,
"command": suffix.value
} if suffix else {}
return ({ return ({
prefix.key: prefix.value "raw_command": prefix.key,
"command": prefix.value
} if prefix else {}, { } if prefix else {}, {
suffix.key: suffix.value "raw_command": suffix.key,
"command": suffix.value
} if suffix else {}) } if suffix else {})
@ -122,7 +130,7 @@ def command(command: Tuple[str, ...]) -> Rule:
TrieRule.add_prefix(f"{start}{sep.join(command)}", command) TrieRule.add_prefix(f"{start}{sep.join(command)}", command)
async def _command(bot: Bot, event: Event, state: dict) -> bool: async def _command(bot: Bot, event: Event, state: dict) -> bool:
return command in state["_prefix"].values() return command == state["_prefix"]["command"]
return Rule(_command) return Rule(_command)

View File

@ -7,10 +7,22 @@ import sys
sys.path.insert(0, os.path.abspath("..")) sys.path.insert(0, os.path.abspath(".."))
import nonebot import nonebot
from nonebot.log import logger, default_format
# test custom log
logger.add("error.log",
rotation="00:00",
diagnose=False,
level="ERROR",
format=default_format)
nonebot.init() nonebot.init()
app = nonebot.get_asgi() app = nonebot.get_asgi()
# load builtin plugin
nonebot.load_plugin("nonebot.plugins.base")
# load local plugins
nonebot.load_plugins("test_plugins") nonebot.load_plugins("test_plugins")
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -11,7 +11,7 @@ test_command = on_command("帮助", to_me())
@test_command.handle() @test_command.handle()
async def test_handler(bot: Bot, event: Event, state: dict): async def test_handler(bot: Bot, event: Event, state: dict):
args = str(event.message)[len(list(state["_prefix"].keys())[0]):].strip() args = str(event.message).strip()
print("[!] Command:", state["_prefix"], "Args:", args) print("[!] Command:", state["_prefix"], "Args:", args)
if args: if args:
state["help"] = args state["help"] = args