mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-12-01 01:25:07 +08:00
🔀 Merge pull request #73
This commit is contained in:
commit
de07a6594d
@ -1,6 +1,7 @@
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
module.exports = context => ({
|
module.exports = context => ({
|
||||||
|
base: process.env.VUEPRESS_BASE || "/",
|
||||||
title: "NoneBot",
|
title: "NoneBot",
|
||||||
description: "基于 酷Q 的 Python 异步 QQ 机器人框架",
|
description: "基于 酷Q 的 Python 异步 QQ 机器人框架",
|
||||||
markdown: {
|
markdown: {
|
||||||
@ -117,12 +118,7 @@ module.exports = context => ({
|
|||||||
title: "进阶",
|
title: "进阶",
|
||||||
collapsable: false,
|
collapsable: false,
|
||||||
sidebar: "auto",
|
sidebar: "auto",
|
||||||
children: [
|
children: ["", "scheduler", "permission", "runtime-hook"]
|
||||||
"",
|
|
||||||
"scheduler",
|
|
||||||
"permission",
|
|
||||||
"runtime-hook"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"/api/": [
|
"/api/": [
|
||||||
|
@ -49,9 +49,18 @@ sidebarDepth: 0
|
|||||||
* `load_builtin_plugins` => `nonebot.plugin.load_builtin_plugins`
|
* `load_builtin_plugins` => `nonebot.plugin.load_builtin_plugins`
|
||||||
|
|
||||||
|
|
||||||
|
* `get_plugin` => `nonebot.plugin.get_plugin`
|
||||||
|
|
||||||
|
|
||||||
* `get_loaded_plugins` => `nonebot.plugin.get_loaded_plugins`
|
* `get_loaded_plugins` => `nonebot.plugin.get_loaded_plugins`
|
||||||
|
|
||||||
|
|
||||||
|
* `export` => `nonebot.plugin.export`
|
||||||
|
|
||||||
|
|
||||||
|
* `require` => `nonebot.plugin.require`
|
||||||
|
|
||||||
|
|
||||||
## `get_driver()`
|
## `get_driver()`
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,37 @@ sidebarDepth: 0
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## _class_ `Export`
|
||||||
|
|
||||||
|
基类:`dict`
|
||||||
|
|
||||||
|
|
||||||
|
* **说明**
|
||||||
|
|
||||||
|
插件导出内容以使得其他插件可以获得。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* **示例**
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
nonebot.export().default = "bar"
|
||||||
|
|
||||||
|
@nonebot.export()
|
||||||
|
def some_function():
|
||||||
|
pass
|
||||||
|
|
||||||
|
# this don't work under python 3.9
|
||||||
|
# use
|
||||||
|
# export = nonebot.export(); @export.sub
|
||||||
|
# instead
|
||||||
|
@nonebot.export().sub
|
||||||
|
def something_else():
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## _class_ `Plugin`
|
## _class_ `Plugin`
|
||||||
|
|
||||||
基类:`object`
|
基类:`object`
|
||||||
@ -59,6 +90,15 @@ sidebarDepth: 0
|
|||||||
* **说明**: 插件内定义的 `Matcher`
|
* **说明**: 插件内定义的 `Matcher`
|
||||||
|
|
||||||
|
|
||||||
|
### `export`
|
||||||
|
|
||||||
|
|
||||||
|
* **类型**: `Export`
|
||||||
|
|
||||||
|
|
||||||
|
* **说明**: 插件内定义的导出内容
|
||||||
|
|
||||||
|
|
||||||
## `on(type='', rule=None, permission=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
## `on(type='', rule=None, permission=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||||
|
|
||||||
|
|
||||||
@ -614,12 +654,35 @@ sidebarDepth: 0
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## `get_plugin(name)`
|
||||||
|
|
||||||
|
|
||||||
|
* **说明**
|
||||||
|
|
||||||
|
获取当前导入的某个插件。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* **参数**
|
||||||
|
|
||||||
|
|
||||||
|
* `name: str`: 插件名,与 `load_plugin` 参数一致。如果为 `load_plugins` 导入的插件,则为文件(夹)名。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* **返回**
|
||||||
|
|
||||||
|
|
||||||
|
* `Optional[Plugin]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## `get_loaded_plugins()`
|
## `get_loaded_plugins()`
|
||||||
|
|
||||||
|
|
||||||
* **说明**
|
* **说明**
|
||||||
|
|
||||||
获取当前已导入的插件。
|
获取当前已导入的所有插件。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -627,3 +690,42 @@ sidebarDepth: 0
|
|||||||
|
|
||||||
|
|
||||||
* `Set[Plugin]`
|
* `Set[Plugin]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## `export()`
|
||||||
|
|
||||||
|
|
||||||
|
* **说明**
|
||||||
|
|
||||||
|
获取插件的导出内容对象
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* **返回**
|
||||||
|
|
||||||
|
|
||||||
|
* `Export`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## `require(name)`
|
||||||
|
|
||||||
|
|
||||||
|
* **说明**
|
||||||
|
|
||||||
|
获取一个插件的导出内容
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* **参数**
|
||||||
|
|
||||||
|
|
||||||
|
* `name: str`: 插件名,与 `load_plugin` 参数一致。如果为 `load_plugins` 导入的插件,则为文件(夹)名。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* **返回**
|
||||||
|
|
||||||
|
|
||||||
|
* `Optional[Export]`
|
||||||
|
@ -17,7 +17,10 @@
|
|||||||
- ``load_plugin`` => ``nonebot.plugin.load_plugin``
|
- ``load_plugin`` => ``nonebot.plugin.load_plugin``
|
||||||
- ``load_plugins`` => ``nonebot.plugin.load_plugins``
|
- ``load_plugins`` => ``nonebot.plugin.load_plugins``
|
||||||
- ``load_builtin_plugins`` => ``nonebot.plugin.load_builtin_plugins``
|
- ``load_builtin_plugins`` => ``nonebot.plugin.load_builtin_plugins``
|
||||||
|
- ``get_plugin`` => ``nonebot.plugin.get_plugin``
|
||||||
- ``get_loaded_plugins`` => ``nonebot.plugin.get_loaded_plugins``
|
- ``get_loaded_plugins`` => ``nonebot.plugin.get_loaded_plugins``
|
||||||
|
- ``export`` => ``nonebot.plugin.export``
|
||||||
|
- ``require`` => ``nonebot.plugin.require``
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
@ -239,4 +242,5 @@ async def _start_scheduler():
|
|||||||
|
|
||||||
from nonebot.plugin import on_message, on_notice, on_request, on_metaevent, CommandGroup
|
from nonebot.plugin import on_message, on_notice, on_request, on_metaevent, CommandGroup
|
||||||
from nonebot.plugin import on_startswith, on_endswith, on_keyword, on_command, on_regex
|
from nonebot.plugin import on_startswith, on_endswith, on_keyword, on_command, on_regex
|
||||||
from nonebot.plugin import load_plugin, load_plugins, load_builtin_plugins, get_loaded_plugins
|
from nonebot.plugin import load_plugin, load_plugins, load_builtin_plugins
|
||||||
|
from nonebot.plugin import export, require, get_plugin, get_loaded_plugins
|
||||||
|
@ -112,9 +112,17 @@ async def _check_reply(bot: "Bot", event: "Event"):
|
|||||||
return
|
return
|
||||||
msg_seg = event.message[index]
|
msg_seg = event.message[index]
|
||||||
event.reply = await bot.get_msg(message_id=msg_seg.data["id"])
|
event.reply = await bot.get_msg(message_id=msg_seg.data["id"])
|
||||||
if event.reply["sender"]["user_id"] == event.self_id:
|
# ensure string comparation
|
||||||
|
if str(event.reply["sender"]["user_id"]) == str(event.self_id):
|
||||||
event.to_me = True
|
event.to_me = True
|
||||||
del event.message[index]
|
del event.message[index]
|
||||||
|
if len(event.message) > index and event.message[index].type == "at":
|
||||||
|
del event.message[index]
|
||||||
|
if len(event.message) > index and event.message[index].type == "text":
|
||||||
|
event.message[index].data["text"] = event.message[index].data[
|
||||||
|
"text"].lstrip()
|
||||||
|
if not event.message[index].data["text"]:
|
||||||
|
del event.message[index]
|
||||||
if not event.message:
|
if not event.message:
|
||||||
event.message.append(MessageSegment.text(""))
|
event.message.append(MessageSegment.text(""))
|
||||||
|
|
||||||
@ -142,14 +150,14 @@ def _check_at_me(bot: "Bot", event: "Event"):
|
|||||||
if event.message[0] == at_me_seg:
|
if event.message[0] == at_me_seg:
|
||||||
event.to_me = True
|
event.to_me = True
|
||||||
del event.message[0]
|
del event.message[0]
|
||||||
if event.message[0].type == "text":
|
if event.message and event.message[0].type == "text":
|
||||||
event.message[0].data["text"] = event.message[0].data[
|
event.message[0].data["text"] = event.message[0].data[
|
||||||
"text"].lstrip()
|
"text"].lstrip()
|
||||||
if not event.message[0].data["text"]:
|
if not event.message[0].data["text"]:
|
||||||
del event.message[0]
|
del event.message[0]
|
||||||
if event.message[0] == at_me_seg:
|
if event.message and event.message[0] == at_me_seg:
|
||||||
del event.message[0]
|
del event.message[0]
|
||||||
if event.message[0].type == "text":
|
if event.message and event.message[0].type == "text":
|
||||||
event.message[0].data["text"] = event.message[0].data[
|
event.message[0].data["text"] = event.message[0].data[
|
||||||
"text"].lstrip()
|
"text"].lstrip()
|
||||||
if not event.message[0].data["text"]:
|
if not event.message[0].data["text"]:
|
||||||
|
@ -92,8 +92,9 @@ async def _check_matcher(priority: int, bot: Bot, event: Event,
|
|||||||
async def _check(Matcher: Type[Matcher], bot: Bot, event: Event,
|
async def _check(Matcher: Type[Matcher], bot: Bot, event: Event,
|
||||||
state: dict) -> Optional[Type[Matcher]]:
|
state: dict) -> Optional[Type[Matcher]]:
|
||||||
try:
|
try:
|
||||||
if await Matcher.check_perm(
|
if (not Matcher.expire_time or datetime.now() <= Matcher.expire_time
|
||||||
bot, event) and await Matcher.check_rule(bot, event, state):
|
) and await Matcher.check_perm(
|
||||||
|
bot, event) and await Matcher.check_rule(bot, event, state):
|
||||||
return Matcher
|
return Matcher
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.opt(colors=True, exception=e).error(
|
logger.opt(colors=True, exception=e).error(
|
||||||
@ -149,6 +150,8 @@ async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
|
|||||||
try:
|
try:
|
||||||
logger.debug(f"Running matcher {matcher}")
|
logger.debug(f"Running matcher {matcher}")
|
||||||
await matcher.run(bot, event, state)
|
await matcher.run(bot, event, state)
|
||||||
|
except StopPropagation as e:
|
||||||
|
exception = e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.opt(colors=True, exception=e).error(
|
logger.opt(colors=True, exception=e).error(
|
||||||
f"<r><bg #f8bbd0>Running matcher {matcher} failed.</bg #f8bbd0></r>"
|
f"<r><bg #f8bbd0>Running matcher {matcher} failed.</bg #f8bbd0></r>"
|
||||||
@ -166,7 +169,7 @@ async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
|
|||||||
"<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>"
|
"<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>"
|
||||||
)
|
)
|
||||||
|
|
||||||
if matcher.block:
|
if matcher.block or isinstance(exception, StopPropagation):
|
||||||
raise StopPropagation
|
raise StopPropagation
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import pkgutil
|
|||||||
import importlib
|
import importlib
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from importlib._bootstrap import _load
|
from importlib._bootstrap import _load
|
||||||
|
from contextvars import Context, ContextVar, copy_context
|
||||||
|
|
||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot.matcher import Matcher
|
from nonebot.matcher import Matcher
|
||||||
@ -25,7 +26,49 @@ plugins: Dict[str, "Plugin"] = {}
|
|||||||
:说明: 已加载的插件
|
:说明: 已加载的插件
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_tmp_matchers: Set[Type[Matcher]] = set()
|
_tmp_matchers: ContextVar[Set[Type[Matcher]]] = ContextVar("_tmp_matchers")
|
||||||
|
_export: ContextVar["Export"] = ContextVar("_export")
|
||||||
|
|
||||||
|
|
||||||
|
class Export(dict):
|
||||||
|
"""
|
||||||
|
:说明:
|
||||||
|
插件导出内容以使得其他插件可以获得。
|
||||||
|
:示例:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
nonebot.export().default = "bar"
|
||||||
|
|
||||||
|
@nonebot.export()
|
||||||
|
def some_function():
|
||||||
|
pass
|
||||||
|
|
||||||
|
# this don't work under python 3.9
|
||||||
|
# use
|
||||||
|
# export = nonebot.export(); @export.sub
|
||||||
|
# instead
|
||||||
|
@nonebot.export().sub
|
||||||
|
def something_else():
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __call__(self, func, **kwargs):
|
||||||
|
self[func.__name__] = func
|
||||||
|
self.update(kwargs)
|
||||||
|
return func
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
super().__setitem__(key,
|
||||||
|
Export(value) if isinstance(value, dict) else value)
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
self[name] = Export(value) if isinstance(value, dict) else value
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if name not in self:
|
||||||
|
self[name] = Export()
|
||||||
|
return self[name]
|
||||||
|
|
||||||
|
|
||||||
@dataclass(eq=False)
|
@dataclass(eq=False)
|
||||||
@ -46,6 +89,11 @@ class Plugin(object):
|
|||||||
- **类型**: ``Set[Type[Matcher]]``
|
- **类型**: ``Set[Type[Matcher]]``
|
||||||
- **说明**: 插件内定义的 ``Matcher``
|
- **说明**: 插件内定义的 ``Matcher``
|
||||||
"""
|
"""
|
||||||
|
export: Export
|
||||||
|
"""
|
||||||
|
- **类型**: ``Export``
|
||||||
|
- **说明**: 插件内定义的导出内容
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def on(type: str = "",
|
def on(type: str = "",
|
||||||
@ -80,7 +128,7 @@ def on(type: str = "",
|
|||||||
block=block,
|
block=block,
|
||||||
handlers=handlers,
|
handlers=handlers,
|
||||||
default_state=state)
|
default_state=state)
|
||||||
_tmp_matchers.add(matcher)
|
_tmp_matchers.get().add(matcher)
|
||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
@ -112,7 +160,7 @@ def on_metaevent(rule: Optional[Union[Rule, RuleChecker]] = None,
|
|||||||
block=block,
|
block=block,
|
||||||
handlers=handlers,
|
handlers=handlers,
|
||||||
default_state=state)
|
default_state=state)
|
||||||
_tmp_matchers.add(matcher)
|
_tmp_matchers.get().add(matcher)
|
||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
@ -146,7 +194,7 @@ def on_message(rule: Optional[Union[Rule, RuleChecker]] = None,
|
|||||||
block=block,
|
block=block,
|
||||||
handlers=handlers,
|
handlers=handlers,
|
||||||
default_state=state)
|
default_state=state)
|
||||||
_tmp_matchers.add(matcher)
|
_tmp_matchers.get().add(matcher)
|
||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
@ -178,7 +226,7 @@ def on_notice(rule: Optional[Union[Rule, RuleChecker]] = None,
|
|||||||
block=block,
|
block=block,
|
||||||
handlers=handlers,
|
handlers=handlers,
|
||||||
default_state=state)
|
default_state=state)
|
||||||
_tmp_matchers.add(matcher)
|
_tmp_matchers.get().add(matcher)
|
||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
@ -210,7 +258,7 @@ def on_request(rule: Optional[Union[Rule, RuleChecker]] = None,
|
|||||||
block=block,
|
block=block,
|
||||||
handlers=handlers,
|
handlers=handlers,
|
||||||
default_state=state)
|
default_state=state)
|
||||||
_tmp_matchers.add(matcher)
|
_tmp_matchers.get().add(matcher)
|
||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
@ -387,27 +435,35 @@ def load_plugin(module_path: str) -> Optional[Plugin]:
|
|||||||
:返回:
|
:返回:
|
||||||
- ``Optional[Plugin]``
|
- ``Optional[Plugin]``
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
_tmp_matchers.clear()
|
def _load_plugin(module_path: str) -> Optional[Plugin]:
|
||||||
if module_path in plugins:
|
try:
|
||||||
return plugins[module_path]
|
_tmp_matchers.set(set())
|
||||||
elif module_path in sys.modules:
|
_export.set(Export())
|
||||||
logger.warning(
|
if module_path in plugins:
|
||||||
f"Module {module_path} has been loaded by other plugins! Ignored"
|
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)
|
||||||
|
for m in _tmp_matchers.get():
|
||||||
|
m.module = module_path
|
||||||
|
plugin = Plugin(module_path, module, _tmp_matchers.get(),
|
||||||
|
_export.get())
|
||||||
|
plugins[module_path] = plugin
|
||||||
|
logger.opt(
|
||||||
|
colors=True).info(f'Succeeded to import "<y>{module_path}</y>"')
|
||||||
|
return plugin
|
||||||
|
except Exception as e:
|
||||||
|
logger.opt(colors=True, exception=e).error(
|
||||||
|
f'<r><bg #f8bbd0>Failed to import "{module_path}"</bg #f8bbd0></r>'
|
||||||
)
|
)
|
||||||
return
|
return None
|
||||||
module = importlib.import_module(module_path)
|
|
||||||
for m in _tmp_matchers:
|
context: Context = copy_context()
|
||||||
m.module = module_path
|
return context.run(_load_plugin, module_path)
|
||||||
plugin = Plugin(module_path, module, _tmp_matchers.copy())
|
|
||||||
plugins[module_path] = plugin
|
|
||||||
logger.opt(
|
|
||||||
colors=True).info(f'Succeeded to import "<y>{module_path}</y>"')
|
|
||||||
return plugin
|
|
||||||
except Exception as e:
|
|
||||||
logger.opt(colors=True, exception=e).error(
|
|
||||||
f'<r><bg #f8bbd0>Failed to import "{module_path}"</bg #f8bbd0></r>')
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def load_plugins(*plugin_dir: str) -> Set[Plugin]:
|
def load_plugins(*plugin_dir: str) -> Set[Plugin]:
|
||||||
@ -419,33 +475,42 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]:
|
|||||||
:返回:
|
:返回:
|
||||||
- ``Set[Plugin]``
|
- ``Set[Plugin]``
|
||||||
"""
|
"""
|
||||||
loaded_plugins = set()
|
|
||||||
for module_info in pkgutil.iter_modules(plugin_dir):
|
def _load_plugin(module_info) -> Optional[Plugin]:
|
||||||
_tmp_matchers.clear()
|
_tmp_matchers.set(set())
|
||||||
|
_export.set(Export())
|
||||||
name = module_info.name
|
name = module_info.name
|
||||||
if name.startswith("_"):
|
if name.startswith("_"):
|
||||||
continue
|
return
|
||||||
|
|
||||||
spec = module_info.module_finder.find_spec(name, None)
|
spec = module_info.module_finder.find_spec(name, None)
|
||||||
if spec.name in plugins:
|
if spec.name in plugins:
|
||||||
continue
|
return
|
||||||
elif spec.name in sys.modules:
|
elif spec.name in sys.modules:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"Module {spec.name} has been loaded by other plugin! Ignored")
|
f"Module {spec.name} has been loaded by other plugin! Ignored")
|
||||||
continue
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
module = _load(spec)
|
module = _load(spec)
|
||||||
|
|
||||||
for m in _tmp_matchers:
|
for m in _tmp_matchers.get():
|
||||||
m.module = name
|
m.module = name
|
||||||
plugin = Plugin(name, module, _tmp_matchers.copy())
|
plugin = Plugin(name, module, _tmp_matchers.get(), _export.get())
|
||||||
plugins[name] = plugin
|
plugins[name] = plugin
|
||||||
loaded_plugins.add(plugin)
|
|
||||||
logger.opt(colors=True).info(f'Succeeded to import "<y>{name}</y>"')
|
logger.opt(colors=True).info(f'Succeeded to import "<y>{name}</y>"')
|
||||||
|
return plugin
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.opt(colors=True, exception=e).error(
|
logger.opt(colors=True, exception=e).error(
|
||||||
f'<r><bg #f8bbd0>Failed to import "{name}"</bg #f8bbd0></r>')
|
f'<r><bg #f8bbd0>Failed to import "{name}"</bg #f8bbd0></r>')
|
||||||
|
return None
|
||||||
|
|
||||||
|
loaded_plugins = set()
|
||||||
|
for module_info in pkgutil.iter_modules(plugin_dir):
|
||||||
|
context: Context = copy_context()
|
||||||
|
result = context.run(_load_plugin, module_info)
|
||||||
|
if result:
|
||||||
|
loaded_plugins.add(result)
|
||||||
return loaded_plugins
|
return loaded_plugins
|
||||||
|
|
||||||
|
|
||||||
@ -459,11 +524,46 @@ def load_builtin_plugins() -> Optional[Plugin]:
|
|||||||
return load_plugin("nonebot.plugins.base")
|
return load_plugin("nonebot.plugins.base")
|
||||||
|
|
||||||
|
|
||||||
|
def get_plugin(name: str) -> Optional[Plugin]:
|
||||||
|
"""
|
||||||
|
:说明:
|
||||||
|
获取当前导入的某个插件。
|
||||||
|
:参数:
|
||||||
|
* ``name: str``: 插件名,与 ``load_plugin`` 参数一致。如果为 ``load_plugins`` 导入的插件,则为文件(夹)名。
|
||||||
|
:返回:
|
||||||
|
- ``Optional[Plugin]``
|
||||||
|
"""
|
||||||
|
return plugins.get(name)
|
||||||
|
|
||||||
|
|
||||||
def get_loaded_plugins() -> Set[Plugin]:
|
def get_loaded_plugins() -> Set[Plugin]:
|
||||||
"""
|
"""
|
||||||
:说明:
|
:说明:
|
||||||
获取当前已导入的插件。
|
获取当前已导入的所有插件。
|
||||||
:返回:
|
:返回:
|
||||||
- ``Set[Plugin]``
|
- ``Set[Plugin]``
|
||||||
"""
|
"""
|
||||||
return set(plugins.values())
|
return set(plugins.values())
|
||||||
|
|
||||||
|
|
||||||
|
def export() -> Export:
|
||||||
|
"""
|
||||||
|
:说明:
|
||||||
|
获取插件的导出内容对象
|
||||||
|
:返回:
|
||||||
|
- ``Export``
|
||||||
|
"""
|
||||||
|
return _export.get()
|
||||||
|
|
||||||
|
|
||||||
|
def require(name: str) -> Optional[Export]:
|
||||||
|
"""
|
||||||
|
:说明:
|
||||||
|
获取一个插件的导出内容
|
||||||
|
:参数:
|
||||||
|
* ``name: str``: 插件名,与 ``load_plugin`` 参数一致。如果为 ``load_plugins`` 导入的插件,则为文件(夹)名。
|
||||||
|
:返回:
|
||||||
|
- ``Optional[Export]``
|
||||||
|
"""
|
||||||
|
plugin = get_plugin(name)
|
||||||
|
return plugin.export if plugin else None
|
||||||
|
@ -1,17 +1,32 @@
|
|||||||
import re
|
import re
|
||||||
|
from contextvars import ContextVar
|
||||||
|
|
||||||
from nonebot.typing import Rule, Matcher, Handler, Permission, RuleChecker
|
from nonebot.typing import Rule, Matcher, Handler, Permission, RuleChecker
|
||||||
from nonebot.typing import Set, List, Dict, Type, Tuple, Union, Optional, ModuleType
|
from nonebot.typing import Set, List, Dict, Type, Tuple, Union, Optional, ModuleType
|
||||||
|
|
||||||
plugins: Dict[str, "Plugin"] = ...
|
plugins: Dict[str, "Plugin"] = ...
|
||||||
|
|
||||||
_tmp_matchers: Set[Type[Matcher]] = ...
|
_tmp_matchers: ContextVar[Set[Type[Matcher]]] = ...
|
||||||
|
_export: ContextVar["Export"] = ...
|
||||||
|
|
||||||
|
|
||||||
|
class Export(dict):
|
||||||
|
|
||||||
|
def __call__(self, func, **kwargs):
|
||||||
|
...
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
...
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
name: str
|
name: str
|
||||||
module: ModuleType
|
module: ModuleType
|
||||||
matcher: Set[Type[Matcher]]
|
matcher: Set[Type[Matcher]]
|
||||||
|
export: Export
|
||||||
|
|
||||||
|
|
||||||
def on(type: str = ...,
|
def on(type: str = ...,
|
||||||
@ -141,10 +156,22 @@ def load_builtin_plugins():
|
|||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def get_plugin(name: str) -> Optional[Plugin]:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
def get_loaded_plugins() -> Set[Plugin]:
|
def get_loaded_plugins() -> Set[Plugin]:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def export() -> Export:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def require(name: str) -> Export:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
class CommandGroup:
|
class CommandGroup:
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
|
@ -4,6 +4,14 @@ sidebar: auto
|
|||||||
|
|
||||||
# 更新日志
|
# 更新日志
|
||||||
|
|
||||||
|
## v2.0.0a7
|
||||||
|
|
||||||
|
- 修复 cqhttp 检查 to me 时出现 IndexError
|
||||||
|
- 修复已失效的事件响应器仍会运行一次的 bug
|
||||||
|
- 修改 cqhttp 检查 reply 时未去除后续 at 以及空格
|
||||||
|
- 添加 get_plugin 获取插件函数
|
||||||
|
- 添加插件 export, require 方法
|
||||||
|
|
||||||
## v2.0.0a6
|
## v2.0.0a6
|
||||||
|
|
||||||
- 修复 block 失效问题 (hotfix)
|
- 修复 block 失效问题 (hotfix)
|
||||||
|
@ -22,6 +22,8 @@ nonebot.load_builtin_plugins()
|
|||||||
# load local plugins
|
# load local plugins
|
||||||
nonebot.load_plugins("test_plugins")
|
nonebot.load_plugins("test_plugins")
|
||||||
|
|
||||||
|
print(nonebot.require("test_export"))
|
||||||
|
|
||||||
# modify some config / config depends on loaded configs
|
# modify some config / config depends on loaded configs
|
||||||
config = nonebot.get_driver().config
|
config = nonebot.get_driver().config
|
||||||
config.custom_config3 = config.custom_config1
|
config.custom_config3 = config.custom_config1
|
||||||
|
15
tests/test_plugins/test_export.py
Normal file
15
tests/test_plugins/test_export.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import nonebot
|
||||||
|
|
||||||
|
export = nonebot.export()
|
||||||
|
export.foo = "bar"
|
||||||
|
export["bar"] = "foo"
|
||||||
|
|
||||||
|
|
||||||
|
@export
|
||||||
|
def a():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@export.sub
|
||||||
|
def b():
|
||||||
|
pass
|
Loading…
Reference in New Issue
Block a user