Merge branch 'master' of https://github.com/nonebot/nonebot2 into fix_command_type

This commit is contained in:
AsakuraMizu 2020-08-24 23:11:53 +08:00
commit 60916434d6
20 changed files with 235 additions and 77 deletions

View File

@ -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}`);
}
}
]
]
});

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
# NoneBot.config 模块
## 配置

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
# NoneBot.exception 模块
## 异常

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
# NoneBot.log 模块
## 日志

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
# NoneBot 模块

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
# NoneBot.typing 模块
## 类型

View File

@ -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 -----------------------------------------------------

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
NoneBot.config 模块
===================

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
NoneBot.exception 模块
======================

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
NoneBot.log 模块
=================

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
NoneBot 模块
===============

View File

@ -1,3 +1,8 @@
---
contentSidebar: true
sidebarDepth: 0
---
NoneBot.typing 模块
===================

View File

@ -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

View File

@ -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()):

View File

@ -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

View File

@ -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
View File

@ -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",

View File

@ -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"
}
}

View File

@ -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:

View File

@ -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: