mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-01-19 01:18:19 +08:00
Merge branch 'master' of https://github.com/nonebot/nonebot2 into fix_command_type
This commit is contained in:
commit
60916434d6
@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
const path = require("path");
|
||||
|
||||
module.exports = context => ({
|
||||
title: "NoneBot",
|
||||
description: "基于 酷Q 的 Python 异步 QQ 机器人框架",
|
||||
markdown: {
|
||||
@ -20,54 +22,79 @@ module.exports = {
|
||||
{ name: "apple-mobile-web-app-status-bar-style", content: "black" }
|
||||
]
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
repo: "nonebot/nonebot",
|
||||
docsDir: "docs",
|
||||
docsBranch: "dev2",
|
||||
editLinks: true,
|
||||
editLinkText: "在 GitHub 上编辑此页",
|
||||
lastUpdated: "上次更新",
|
||||
smoothScroll: true,
|
||||
nav: [{ text: "API", link: "/api/" }],
|
||||
sidebar: {
|
||||
"/api/": [
|
||||
{
|
||||
title: "NoneBot Api Reference",
|
||||
path: "",
|
||||
collapsable: false,
|
||||
sidebarDepth: 3,
|
||||
children: [
|
||||
{
|
||||
title: "nonebot 模块",
|
||||
path: "nonebot",
|
||||
sidebar: "auto"
|
||||
},
|
||||
{
|
||||
title: "nonebot.typing 模块",
|
||||
path: "typing",
|
||||
sidebar: "auto"
|
||||
},
|
||||
{
|
||||
title: "nonebot.log 模块",
|
||||
path: "log",
|
||||
sidebar: "auto"
|
||||
},
|
||||
{
|
||||
title: "nonebot.exception 模块",
|
||||
path: "exception",
|
||||
sidebar: "auto"
|
||||
},
|
||||
{
|
||||
title: "nonebot.config 模块",
|
||||
path: "config",
|
||||
sidebar: "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
locales: {
|
||||
"/": {
|
||||
lang: "zh-CN",
|
||||
title: "NoneBot",
|
||||
description: "基于 酷Q 的 Python 异步 QQ 机器人框架"
|
||||
}
|
||||
},
|
||||
|
||||
plugins: ["@vuepress/plugin-back-to-top", "@vuepress/plugin-medium-zoom"]
|
||||
};
|
||||
theme: "titanium",
|
||||
themeConfig: {
|
||||
logo: "/logo.png",
|
||||
repo: "nonebot/nonebot",
|
||||
docsDir: "docs",
|
||||
docsBranch: "dev2",
|
||||
docsDirVersioned: "archive",
|
||||
docsDirPages: "pages",
|
||||
editLinks: true,
|
||||
smoothScroll: true,
|
||||
|
||||
locales: {
|
||||
"/": {
|
||||
label: "简体中文",
|
||||
selectText: "Languages",
|
||||
editLinkText: "在 GitHub 上编辑此页",
|
||||
lastUpdated: "上次更新",
|
||||
nav: [{ text: "API", link: "/api/" }],
|
||||
sidebar: {
|
||||
"/api/": [
|
||||
{
|
||||
title: "NoneBot Api Reference",
|
||||
path: "",
|
||||
collapsable: false,
|
||||
children: [
|
||||
{
|
||||
title: "nonebot 模块",
|
||||
path: "nonebot"
|
||||
},
|
||||
{
|
||||
title: "nonebot.typing 模块",
|
||||
path: "typing"
|
||||
},
|
||||
{
|
||||
title: "nonebot.log 模块",
|
||||
path: "log"
|
||||
},
|
||||
{
|
||||
title: "nonebot.exception 模块",
|
||||
path: "exception"
|
||||
},
|
||||
{
|
||||
title: "nonebot.config 模块",
|
||||
path: "config"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
plugins: [
|
||||
"@vuepress/plugin-back-to-top",
|
||||
"@vuepress/plugin-medium-zoom",
|
||||
[
|
||||
"versioning",
|
||||
{
|
||||
versionedSourceDir: path.resolve(context.sourceDir, "..", "archive"),
|
||||
pagesSourceDir: path.resolve(context.sourceDir, "..", "pages"),
|
||||
onNewVersion(version, versionDestPath) {
|
||||
console.log(`Created version ${version} in ${versionDestPath}`);
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.config 模块
|
||||
|
||||
## 配置
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.exception 模块
|
||||
|
||||
## 异常
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.log 模块
|
||||
|
||||
## 日志
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot 模块
|
||||
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.typing 模块
|
||||
|
||||
## 类型
|
||||
|
@ -10,9 +10,9 @@
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.config 模块
|
||||
===================
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.exception 模块
|
||||
======================
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.log 模块
|
||||
=================
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot 模块
|
||||
===============
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.typing 模块
|
||||
===================
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import typing
|
||||
import inspect
|
||||
from functools import wraps
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
@ -38,6 +39,13 @@ class Matcher:
|
||||
self.handlers = self.handlers.copy()
|
||||
self.state = self._default_state.copy()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (f"<Matcher {self.type}, priority={self.priority},"
|
||||
f" temp={self.temp}, expire={self.expire_time}>")
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
|
||||
@classmethod
|
||||
def new(cls,
|
||||
type_: str = "",
|
||||
@ -117,7 +125,7 @@ class Matcher:
|
||||
cls.handlers.append(_handler)
|
||||
|
||||
def _decorator(func: Handler) -> Handler:
|
||||
if cls.handlers[-1] is not func:
|
||||
if not cls.handlers or cls.handlers[-1] is not func:
|
||||
cls.handlers.append(func)
|
||||
|
||||
return func
|
||||
@ -141,6 +149,8 @@ class Matcher:
|
||||
raise PausedException
|
||||
|
||||
async def _key_parser(bot: Bot, event: Event, state: dict):
|
||||
if key in state:
|
||||
return
|
||||
parser = args_parser or cls._default_parser
|
||||
if parser:
|
||||
await parser(bot, event, state)
|
||||
@ -151,8 +161,15 @@ class Matcher:
|
||||
cls.handlers.append(_key_parser)
|
||||
|
||||
def _decorator(func: Handler) -> Handler:
|
||||
if cls.handlers[-1] is not func:
|
||||
cls.handlers.append(func)
|
||||
if not hasattr(cls.handlers[-1], "__wrapped__"):
|
||||
parser = cls.handlers.pop()
|
||||
|
||||
@wraps(func)
|
||||
async def wrapper(bot: Bot, event: Event, state: dict):
|
||||
await parser(bot, event, state)
|
||||
await func(bot, event, state)
|
||||
|
||||
cls.handlers.append(wrapper)
|
||||
|
||||
return func
|
||||
|
||||
@ -180,34 +197,35 @@ class Matcher:
|
||||
handler = self.handlers.pop(0)
|
||||
annotation = typing.get_type_hints(handler)
|
||||
BotType = annotation.get("bot")
|
||||
if BotType and not isinstance(bot, BotType):
|
||||
if BotType and inspect.isclass(BotType) and not isinstance(
|
||||
bot, BotType):
|
||||
continue
|
||||
await handler(bot, event, self.state)
|
||||
|
||||
except RejectedException:
|
||||
self.handlers.insert(0, handler) # type: ignore
|
||||
matcher = Matcher.new(
|
||||
Matcher.new(
|
||||
self.type,
|
||||
self.rule,
|
||||
Rule(),
|
||||
USER(event.user_id, perm=self.permission), # type:ignore
|
||||
self.handlers,
|
||||
temp=True,
|
||||
priority=0,
|
||||
block=True,
|
||||
default_state=self.state,
|
||||
expire_time=datetime.now() + bot.config.session_expire_timeout)
|
||||
matchers[0].append(matcher)
|
||||
return
|
||||
except PausedException:
|
||||
matcher = Matcher.new(
|
||||
Matcher.new(
|
||||
self.type,
|
||||
self.rule,
|
||||
Rule(),
|
||||
USER(event.user_id, perm=self.permission), # type:ignore
|
||||
self.handlers,
|
||||
temp=True,
|
||||
priority=0,
|
||||
block=True,
|
||||
default_state=self.state,
|
||||
expire_time=datetime.now() + bot.config.session_expire_timeout)
|
||||
matchers[0].append(matcher)
|
||||
return
|
||||
except FinishedException:
|
||||
return
|
||||
|
@ -22,7 +22,7 @@ def event_preprocessor(func: PreProcessor) -> PreProcessor:
|
||||
|
||||
async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
|
||||
state: dict) -> Union[None, NoReturn]:
|
||||
if datetime.now() > Matcher.expire_time:
|
||||
if Matcher.expire_time and datetime.now() > Matcher.expire_time:
|
||||
raise _ExceptionContainer([ExpiredException])
|
||||
|
||||
try:
|
||||
@ -65,8 +65,7 @@ async def handle_event(bot: Bot, event: Event):
|
||||
return
|
||||
|
||||
# Trie Match
|
||||
if event.type == "message":
|
||||
_, _ = TrieRule.get_value(bot, event, state)
|
||||
_, _ = TrieRule.get_value(bot, event, state)
|
||||
|
||||
break_flag = False
|
||||
for priority in sorted(matchers.keys()):
|
||||
|
@ -2,9 +2,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
import sys
|
||||
import pkgutil
|
||||
import importlib
|
||||
from importlib.util import module_from_spec
|
||||
from importlib._bootstrap import _load
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot.matcher import Matcher
|
||||
@ -185,9 +186,12 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]:
|
||||
if name.startswith("_"):
|
||||
continue
|
||||
|
||||
spec = module_info.module_finder.find_spec(name)
|
||||
if spec.name in sys.modules:
|
||||
continue
|
||||
|
||||
try:
|
||||
spec = module_info.module_finder.find_spec(name)
|
||||
module = module_from_spec(spec)
|
||||
module = _load(spec)
|
||||
|
||||
plugin = Plugin(name, module, _tmp_matchers.copy())
|
||||
plugins[name] = plugin
|
||||
|
@ -59,6 +59,11 @@ class TrieRule:
|
||||
@classmethod
|
||||
def get_value(cls, bot: Bot, event: Event,
|
||||
state: dict) -> Tuple[Dict[str, Any], Dict[str, Any]]:
|
||||
if event.type != "message":
|
||||
state["_prefix"] = {}
|
||||
state["_suffix"] = {}
|
||||
return {}, {}
|
||||
|
||||
prefix = None
|
||||
suffix = None
|
||||
message = event.message[0]
|
||||
@ -109,8 +114,12 @@ def command(command: Tuple[str, ...]) -> Rule:
|
||||
config = get_driver().config
|
||||
command_start = config.command_start
|
||||
command_sep = config.command_sep
|
||||
for start, sep in product(command_start, command_sep):
|
||||
TrieRule.add_prefix(f"{start}{sep.join(command)}", command)
|
||||
if len(command) == 1:
|
||||
for start in command_start:
|
||||
TrieRule.add_prefix(f"{start}{command[0]}", command)
|
||||
else:
|
||||
for start, sep in product(command_start, command_sep):
|
||||
TrieRule.add_prefix(f"{start}{sep.join(command)}", command)
|
||||
|
||||
async def _command(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return command in state["_prefix"].values()
|
||||
|
50
package-lock.json
generated
50
package-lock.json
generated
@ -10157,6 +10157,56 @@
|
||||
"smoothscroll-polyfill": "^0.4.3"
|
||||
}
|
||||
},
|
||||
"vuepress-plugin-versioning": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/vuepress-plugin-versioning/-/vuepress-plugin-versioning-4.5.0.tgz",
|
||||
"integrity": "sha512-tnth/oXq5yqTHvfbSfl1GaPIQcr8ckSDX+wyecnm3tS/FSaZH55Fb8wPwhdM2jEEXWPe6DpQCh9O7fvsthIvRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@vuepress/shared-utils": "^1.5.2",
|
||||
"fs-extra": "^8.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vuepress-theme-titanium": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/vuepress-theme-titanium/-/vuepress-theme-titanium-4.5.1.tgz",
|
||||
"integrity": "sha512-yWDbv4Omwk611ftN0WEAf30n4dE0TbyH7ROPYTt3u185hhE8qRiba9HJBwm8CU2CKfp+Yjv5y24V/OHGfSqJzQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@vuepress/plugin-nprogress": "^1.5.2",
|
||||
"@vuepress/plugin-search": "^1.5.2",
|
||||
"docsearch.js": "^2.6.3",
|
||||
"lodash": "^4.17.15",
|
||||
"stylus": "^0.54.5",
|
||||
"stylus-loader": "^3.0.2",
|
||||
"vuepress-plugin-container": "^2.0.2",
|
||||
"vuepress-plugin-smooth-scroll": "^0.0.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"vuepress-plugin-smooth-scroll": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.9.tgz",
|
||||
"integrity": "sha512-UXX+HLZO1NKVwyiOJlj0smh8F9dKnwybjEi7w/Mj9EYLhKrNYr5uXs+N+OTt8VwKCn3f0vZ1XAwFIjsPlD7GJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"smoothscroll-polyfill": "^0.4.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",
|
||||
|
@ -4,8 +4,7 @@
|
||||
"description": "An asynchronous QQ bot framework.",
|
||||
"homepage": "https://nonebot.cqp.moe/",
|
||||
"main": "index.js",
|
||||
"contributors": [
|
||||
{
|
||||
"contributors": [{
|
||||
"name": "Richard Chien",
|
||||
"email": "richardchienthebest@gmail.com"
|
||||
},
|
||||
@ -24,8 +23,10 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"vuepress": "^1.3.1",
|
||||
"@vuepress/plugin-back-to-top": "^1.3.1",
|
||||
"@vuepress/plugin-medium-zoom": "^1.3.1"
|
||||
"@vuepress/plugin-medium-zoom": "^1.3.1",
|
||||
"vuepress": "^1.3.1",
|
||||
"vuepress-plugin-versioning": "^4.5.0",
|
||||
"vuepress-theme-titanium": "^4.5.1"
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from nonebot.plugin import on_metaevent
|
||||
from nonebot.typing import Bot, Event
|
||||
from nonebot.plugin import on_metaevent
|
||||
|
||||
|
||||
async def heartbeat(bot: Bot, event: Event, state: dict) -> bool:
|
||||
|
@ -11,8 +11,8 @@ test_command = on_command("帮助", to_me())
|
||||
|
||||
@test_command.handle()
|
||||
async def test_handler(bot: Bot, event: Event, state: dict):
|
||||
print("[!] Command:", state["_prefix"])
|
||||
args = str(event.message)[len(state["_prefix"]):].strip()
|
||||
args = str(event.message)[len(list(state["_prefix"].keys())[0]):].strip()
|
||||
print("[!] Command:", state["_prefix"], "Args:", args)
|
||||
if args:
|
||||
state["help"] = args
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user