mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-10-06 18:56:45 +00:00
Compare commits
110 Commits
v2.0.0-rc.
...
v2.0.0rc2
Author | SHA1 | Date | |
---|---|---|---|
|
d83866f03b | ||
|
cb83e76e16 | ||
|
1644615462 | ||
|
89d8abf863 | ||
|
f8cf7c94ae | ||
|
bef494615f | ||
|
6e110e725e | ||
|
85390a14b6 | ||
|
276041e314 | ||
|
2922da7b2f | ||
|
c783ab5e9b | ||
|
139190bff7 | ||
|
1524434444 | ||
|
b6857d59b8 | ||
|
a7b0eb10a0 | ||
|
0eadb44e20 | ||
|
6b43209d37 | ||
|
a50990bef2 | ||
|
f1525c1ecd | ||
|
7df9756205 | ||
|
376a720881 | ||
|
c7377647fa | ||
|
cfbd6f1e4d | ||
|
cecc853f25 | ||
|
fe5f85517e | ||
|
66040a7e44 | ||
|
81d2f017f6 | ||
|
4355025f87 | ||
|
0bc8a39578 | ||
|
7308f57776 | ||
|
7de8912edb | ||
|
42a4edc3ee | ||
|
4a12429a38 | ||
|
092f6d05f5 | ||
|
2c0c05dca1 | ||
|
31bafc832f | ||
|
e1720d8ea0 | ||
|
08be5724b9 | ||
|
828714a4e3 | ||
|
a79eeb73a6 | ||
|
c1aec637d5 | ||
|
12cc08efbd | ||
|
f410af72dc | ||
|
113021cdf4 | ||
|
fcc23f98f8 | ||
|
0b693c419e | ||
|
36e5b81510 | ||
|
71f17bebaa | ||
|
2f45f25d13 | ||
|
17d52446c3 | ||
|
2304aaf22b | ||
|
a70c37de69 | ||
|
1cabc18277 | ||
|
ed1235ed11 | ||
|
9952b4e838 | ||
|
e81390a104 | ||
|
7bc22289b4 | ||
|
bfa4a079bf | ||
|
403850262b | ||
|
ed25e7aa39 | ||
|
7ab480f044 | ||
|
d7d6152094 | ||
|
2954e58c77 | ||
|
f684b96433 | ||
|
4388d1c9e6 | ||
|
876acf3e88 | ||
|
963e73f517 | ||
|
bdc9e44142 | ||
|
4f2efb7304 | ||
|
6ae891124f | ||
|
145bd4d4e1 | ||
|
ab54049909 | ||
|
7aa554f5a2 | ||
|
5566777374 | ||
|
b2594f61de | ||
|
1ad1e0606c | ||
|
583d5060db | ||
|
eaa3dbdfa8 | ||
|
03f378690a | ||
|
512c66ccc0 | ||
|
9d20c7510a | ||
|
29ad8a6686 | ||
|
db534b8824 | ||
|
67b96528af | ||
|
a5929f80f7 | ||
|
9619477a27 | ||
|
8377680fd7 | ||
|
3e3d6f91a5 | ||
|
1d3d886004 | ||
|
ebc5a3cc9e | ||
|
1092767a51 | ||
|
ab227ee64b | ||
|
00b37fb3d2 | ||
|
e6494dc98e | ||
|
c80869f952 | ||
|
2be72eac5e | ||
|
830c4f8c6a | ||
|
138fb458b7 | ||
|
2c93f82ef3 | ||
|
77aa16c2fc | ||
|
945da7151e | ||
|
41ea0df0a5 | ||
|
cec45cf89c | ||
|
2de8c66c70 | ||
|
0bcc4277e5 | ||
|
d3dd93b36c | ||
|
e9bd81d9bb | ||
|
997d4f5042 | ||
|
3bb321c519 | ||
|
fe92d29322 |
@@ -1,15 +0,0 @@
|
||||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.238.1/containers/codespaces-linux/.devcontainer/base.Dockerfile
|
||||
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/universal:2-focal
|
||||
|
||||
# ** [Optional] Uncomment this section to install additional packages. **
|
||||
# USER root
|
||||
#
|
||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
||||
|
||||
USER codespace
|
||||
|
||||
# [Required] Poetry
|
||||
RUN curl -sSL https://install.python-poetry.org | python - -y
|
||||
RUN poetry config virtualenvs.in-project true
|
@@ -1,32 +1,13 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.238.1/containers/codespaces-linux
|
||||
{
|
||||
"name": "GitHub Codespaces (Default)",
|
||||
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile"
|
||||
"name": "Default Linux Universal",
|
||||
"image": "mcr.microsoft.com/devcontainers/universal:2-linux",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers-contrib/features/poetry:1": {}
|
||||
},
|
||||
|
||||
// Configure tool-specific properties.
|
||||
"postCreateCommand": "poetry config virtualenvs.in-project true && poetry install -E all && poetry run pre-commit install && yarn install",
|
||||
"customizations": {
|
||||
// Configure properties specific to VS Code.
|
||||
"vscode": {
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"go.toolsManagement.checkForUpdates": "local",
|
||||
"go.useLanguageServer": true,
|
||||
"go.gopath": "/go",
|
||||
"python.defaultInterpreterPath": "/opt/python/latest/bin/python",
|
||||
"python.linting.enabled": true,
|
||||
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
|
||||
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
|
||||
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
|
||||
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
|
||||
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
|
||||
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
|
||||
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
|
||||
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
|
||||
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
|
||||
"python.analysis.diagnosticMode": "workspace",
|
||||
"python.analysis.typeCheckingMode": "basic",
|
||||
"[python]": {
|
||||
@@ -50,7 +31,6 @@
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"lldb.executable": "/usr/bin/lldb",
|
||||
"files.exclude": {
|
||||
"**/__pycache__": true
|
||||
},
|
||||
@@ -59,10 +39,7 @@
|
||||
"**/__pycache__": true
|
||||
}
|
||||
},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"GitHub.vscode-pull-request-github",
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"ms-python.isort",
|
||||
@@ -72,27 +49,5 @@
|
||||
"bradlc.vscode-tailwindcss"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"remoteUser": "codespace",
|
||||
|
||||
"overrideCommand": false,
|
||||
|
||||
"mounts": [
|
||||
"source=codespaces-linux-var-lib-docker,target=/var/lib/docker,type=volume"
|
||||
],
|
||||
|
||||
"runArgs": [
|
||||
"--cap-add=SYS_PTRACE",
|
||||
"--security-opt",
|
||||
"seccomp=unconfined",
|
||||
"--privileged",
|
||||
"--init"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// "oryx build" will automatically install your dependencies and attempt to build your project
|
||||
"postCreateCommand": "poetry install && poetry run pre-commit install && yarn install"
|
||||
}
|
||||
}
|
||||
|
4
.github/actions/setup-node/action.yml
vendored
4
.github/actions/setup-node/action.yml
vendored
@@ -9,10 +9,10 @@ runs:
|
||||
node-version: "16"
|
||||
|
||||
- id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
|
19
.github/actions/setup-python/action.yml
vendored
19
.github/actions/setup-python/action.yml
vendored
@@ -10,22 +10,15 @@ inputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- id: python
|
||||
uses: actions/setup-python@v2
|
||||
- name: Install poetry
|
||||
run: pipx install poetry
|
||||
shell: bash
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
architecture: "x64"
|
||||
|
||||
- uses: Gr1N/setup-poetry@v7
|
||||
|
||||
- id: poetry-cache
|
||||
run: echo "::set-output name=dir::$(poetry config virtualenvs.path)"
|
||||
shell: bash
|
||||
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.poetry-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-poetry-${{ steps.python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
|
||||
cache: "poetry"
|
||||
|
||||
- run: poetry install -E all
|
||||
shell: bash
|
||||
|
2
.github/workflows/codecov.yml
vendored
2
.github/workflows/codecov.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
cancel-in-progress: true
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.8", "3.9", "3.10"]
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11"]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
fail-fast: false
|
||||
env:
|
||||
|
@@ -13,16 +13,16 @@ repos:
|
||||
stages: [commit]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.8.0
|
||||
rev: 22.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
stages: [commit]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v3.0.0-alpha.0
|
||||
rev: v3.0.0-alpha.4
|
||||
hooks:
|
||||
- id: prettier
|
||||
types_or: [javascript, jsx, ts, tsx, markdown, yaml]
|
||||
types_or: [javascript, jsx, ts, tsx, markdown, yaml, json]
|
||||
stages: [commit]
|
||||
|
||||
- repo: https://github.com/nonebot/nonemoji
|
||||
|
@@ -33,7 +33,7 @@ pre-commit install
|
||||
|
||||
### 使用 GitHub Codespaces(Dev Container)
|
||||
|
||||
使用 GitHub Codespaces 选择 `NoneBot2` 项目,然后选择 `.devcontainer/devcontainer.json` 配置即可。
|
||||
[](https://github.com/codespaces/new?hide_repo_select=true&ref=master&repo=289605524)
|
||||
|
||||
### Commit 规范
|
||||
|
||||
|
23
README.md
23
README.md
@@ -96,17 +96,18 @@ NoneBot2 是一个现代、跨平台、可扩展的 Python 聊天机器人框架
|
||||
- 社区丰富:社区用户众多,直接和间接用户超过十万人,每天都有大量的活跃用户 ([社区资源](#社区资源))
|
||||
- 海纳百川:一个框架,支持多个聊天软件平台,可自定义通信协议
|
||||
|
||||
| 协议名称 | 状态 | 注释 |
|
||||
| :---------------------------------------------------: | :--: | :----------------------------------------------------------------: |
|
||||
| [OneBot 协议](https://onebot.dev/) | ✅ | 支持 QQ、TG、微信公众号等[平台](https://onebot.dev/ecosystem.html) |
|
||||
| [Telegram](https://core.telegram.org/bots/api) | ✅ | |
|
||||
| [飞书](https://open.feishu.cn/document/home/index) | ✅ | |
|
||||
| [GitHub](https://docs.github.com/en/developers/apps) | ✅ | GitHub APP & OAuth APP |
|
||||
| [QQ 频道](https://bot.q.qq.com/wiki/) | ✅ | 官方接口调整较多 |
|
||||
| [钉钉](https://open.dingtalk.com/document/) | 🤗 | 寻找 Maintainer |
|
||||
| Console | ✅ | 控制台交互 |
|
||||
| [开黑啦](https://developer.kookapp.cn/) | ↗️ | 由社区贡献 |
|
||||
| [Mirai](https://docs.mirai.mamoe.net/mirai-api-http/) | ↗️ | 由社区贡献 |
|
||||
| 协议名称 | 状态 | 注释 |
|
||||
| :--------------------------------------------------------: | :--: | :----------------------------------------------------------------: |
|
||||
| [OneBot 协议](https://onebot.dev/) | ✅ | 支持 QQ、TG、微信公众号等[平台](https://onebot.dev/ecosystem.html) |
|
||||
| [Telegram](https://core.telegram.org/bots/api) | ✅ | |
|
||||
| [飞书](https://open.feishu.cn/document/home/index) | ✅ | |
|
||||
| [GitHub](https://docs.github.com/en/developers/apps) | ✅ | GitHub APP & OAuth APP |
|
||||
| [QQ 频道](https://bot.q.qq.com/wiki/) | ✅ | 官方接口调整较多 |
|
||||
| [钉钉](https://open.dingtalk.com/document/) | 🤗 | 寻找 Maintainer |
|
||||
| Console | ✅ | 控制台交互 |
|
||||
| [开黑啦](https://developer.kookapp.cn/) | ↗️ | 由社区贡献 |
|
||||
| [Mirai](https://docs.mirai.mamoe.net/mirai-api-http/) | ↗️ | 由社区贡献 |
|
||||
| [Ntchat](https://github.com/JustUndertaker/adapter-ntchat) | ↗️ | 由社区贡献 |
|
||||
|
||||
- 坚实后盾:支持多种 web 框架,可自定义替换、组合
|
||||
|
||||
|
@@ -37,10 +37,13 @@ FrontMatter:
|
||||
description: nonebot 模块
|
||||
"""
|
||||
|
||||
import os
|
||||
import importlib
|
||||
from importlib.metadata import version
|
||||
from typing import Any, Dict, Type, Optional
|
||||
|
||||
import loguru
|
||||
from pydantic.env_settings import DotenvType
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot.adapters import Bot
|
||||
@@ -49,14 +52,9 @@ from nonebot.config import Env, Config
|
||||
from nonebot.drivers import Driver, ReverseDriver, combine_driver
|
||||
|
||||
try:
|
||||
import pkg_resources
|
||||
|
||||
_dist: pkg_resources.Distribution = pkg_resources.get_distribution("nonebot2")
|
||||
__version__ = _dist.version
|
||||
VERSION = _dist.parsed_version
|
||||
__version__ = version("nonebot2")
|
||||
except Exception: # pragma: no cover
|
||||
__version__ = None
|
||||
VERSION = None
|
||||
|
||||
_driver: Optional[Driver] = None
|
||||
|
||||
@@ -217,7 +215,7 @@ def _log_patcher(record: "loguru.Record"):
|
||||
)
|
||||
|
||||
|
||||
def init(*, _env_file: Optional[str] = None, **kwargs: Any) -> None:
|
||||
def init(*, _env_file: Optional[DotenvType] = None, **kwargs: Any) -> None:
|
||||
"""初始化 NoneBot 以及 全局 {ref}`nonebot.drivers.Driver` 对象。
|
||||
|
||||
NoneBot 将会从 .env 文件中读取环境信息,并使用相应的 env 文件配置。
|
||||
@@ -237,10 +235,12 @@ def init(*, _env_file: Optional[str] = None, **kwargs: Any) -> None:
|
||||
if not _driver:
|
||||
logger.success("NoneBot is initializing...")
|
||||
env = Env()
|
||||
_env_file = _env_file or f".env.{env.environment}"
|
||||
config = Config(
|
||||
**kwargs,
|
||||
_common_config=env.dict(),
|
||||
_env_file=_env_file or f".env.{env.environment}",
|
||||
_env_file=(".env", _env_file)
|
||||
if isinstance(_env_file, (str, os.PathLike))
|
||||
else _env_file,
|
||||
)
|
||||
|
||||
logger.configure(
|
||||
|
@@ -7,21 +7,6 @@ FrontMatter:
|
||||
description: nonebot.adapters 模块
|
||||
"""
|
||||
|
||||
from typing import Iterable
|
||||
|
||||
try:
|
||||
import pkg_resources
|
||||
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
del pkg_resources
|
||||
except ImportError:
|
||||
import pkgutil
|
||||
|
||||
__path__: Iterable[str] = pkgutil.extend_path(__path__, __name__) # type: ignore
|
||||
del pkgutil
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
from nonebot.internal.adapter import Bot as Bot
|
||||
from nonebot.internal.adapter import Event as Event
|
||||
from nonebot.internal.adapter import Adapter as Adapter
|
||||
|
@@ -14,14 +14,14 @@ from datetime import timedelta
|
||||
from ipaddress import IPv4Address
|
||||
from typing import TYPE_CHECKING, Any, Set, Dict, Tuple, Union, Mapping, Optional
|
||||
|
||||
from pydantic import BaseSettings, IPvAnyAddress
|
||||
from pydantic.utils import deep_update
|
||||
from pydantic import Extra, BaseSettings, IPvAnyAddress
|
||||
from pydantic.env_settings import (
|
||||
DotenvType,
|
||||
SettingsError,
|
||||
EnvSettingsSource,
|
||||
InitSettingsSource,
|
||||
SettingsSourceCallable,
|
||||
read_env_file,
|
||||
env_file_sentinel,
|
||||
)
|
||||
|
||||
from nonebot.log import logger
|
||||
@@ -32,33 +32,15 @@ class CustomEnvSettings(EnvSettingsSource):
|
||||
"""
|
||||
Build environment variables suitable for passing to the Model.
|
||||
"""
|
||||
d: Dict[str, Optional[str]] = {}
|
||||
d: Dict[str, Any] = {}
|
||||
|
||||
if settings.__config__.case_sensitive:
|
||||
env_vars: Mapping[str, Optional[str]] = os.environ # pragma: no cover
|
||||
else:
|
||||
env_vars = {k.lower(): v for k, v in os.environ.items()}
|
||||
|
||||
env_file_vars: Dict[str, Optional[str]] = {}
|
||||
env_file = (
|
||||
self.env_file
|
||||
if self.env_file != env_file_sentinel
|
||||
else settings.__config__.env_file
|
||||
)
|
||||
env_file_encoding = (
|
||||
self.env_file_encoding
|
||||
if self.env_file_encoding is not None
|
||||
else settings.__config__.env_file_encoding
|
||||
)
|
||||
if env_file is not None:
|
||||
env_path = Path(env_file)
|
||||
if env_path.is_file():
|
||||
env_file_vars = read_env_file(
|
||||
env_path,
|
||||
encoding=env_file_encoding, # type: ignore
|
||||
case_sensitive=settings.__config__.case_sensitive,
|
||||
)
|
||||
env_vars = {**env_file_vars, **env_vars}
|
||||
env_file_vars = self._read_env_files(settings.__config__.case_sensitive)
|
||||
env_vars = {**env_file_vars, **env_vars}
|
||||
|
||||
for field in settings.__fields__.values():
|
||||
env_val: Optional[str] = None
|
||||
@@ -69,31 +51,56 @@ class CustomEnvSettings(EnvSettingsSource):
|
||||
if env_val is not None:
|
||||
break
|
||||
|
||||
if env_val is None:
|
||||
continue
|
||||
|
||||
if field.is_complex():
|
||||
try:
|
||||
env_val = settings.__config__.json_loads(env_val)
|
||||
except ValueError as e: # pragma: no cover
|
||||
raise SettingsError(
|
||||
f'error parsing JSON for "{env_name}"' # type: ignore
|
||||
) from e
|
||||
d[field.alias] = env_val
|
||||
|
||||
if env_file_vars:
|
||||
for env_name in env_file_vars.keys():
|
||||
env_val = env_vars[env_name]
|
||||
if env_val and (val_striped := env_val.strip()):
|
||||
is_complex, allow_parse_failure = self.field_is_complex(field)
|
||||
if is_complex:
|
||||
if env_val is None:
|
||||
if env_val_built := self.explode_env_vars(field, env_vars):
|
||||
d[field.alias] = env_val_built
|
||||
else:
|
||||
# field is complex and there's a value, decode that as JSON, then add explode_env_vars
|
||||
try:
|
||||
env_val = settings.__config__.json_loads(val_striped)
|
||||
env_val = settings.__config__.parse_env_var(field.name, env_val)
|
||||
except ValueError as e:
|
||||
logger.trace(
|
||||
"Error while parsing JSON for "
|
||||
f"{env_name!r}={val_striped!r}. "
|
||||
"Assumed as string."
|
||||
)
|
||||
if not allow_parse_failure:
|
||||
raise SettingsError(
|
||||
f'error parsing env var "{env_name}"' # type: ignore
|
||||
) from e
|
||||
|
||||
if isinstance(env_val, dict):
|
||||
d[field.alias] = deep_update(
|
||||
env_val, self.explode_env_vars(field, env_vars)
|
||||
)
|
||||
else:
|
||||
d[field.alias] = env_val
|
||||
elif env_val is not None:
|
||||
# simplest case, field is not complex, we only need to add the value if it was found
|
||||
d[field.alias] = env_val
|
||||
|
||||
# remain user custom config
|
||||
for env_name in env_file_vars:
|
||||
env_val = env_vars[env_name]
|
||||
if env_val and (val_striped := env_val.strip()):
|
||||
# there's a value, decode that as JSON
|
||||
try:
|
||||
env_val = settings.__config__.parse_env_var(env_name, val_striped)
|
||||
except ValueError as e:
|
||||
logger.trace(
|
||||
"Error while parsing JSON for "
|
||||
f"{env_name!r}={val_striped!r}. "
|
||||
"Assumed as string."
|
||||
)
|
||||
|
||||
# explode value when it's a nested dict
|
||||
env_name, *nested_keys = env_name.split(self.env_nested_delimiter)
|
||||
if nested_keys and (env_name not in d or isinstance(d[env_name], dict)):
|
||||
result = {}
|
||||
*keys, last_key = nested_keys
|
||||
_tmp = result
|
||||
for key in keys:
|
||||
_tmp = _tmp.setdefault(key, {})
|
||||
_tmp[last_key] = env_val
|
||||
d[env_name] = deep_update(d.get(env_name, {}), result)
|
||||
elif not nested_keys:
|
||||
d[env_name] = env_val
|
||||
|
||||
return d
|
||||
@@ -106,6 +113,9 @@ class BaseConfig(BaseSettings):
|
||||
return self.__dict__.get(name)
|
||||
|
||||
class Config:
|
||||
extra = Extra.allow
|
||||
env_nested_delimiter = "__"
|
||||
|
||||
@classmethod
|
||||
def customise_sources(
|
||||
cls,
|
||||
@@ -117,7 +127,10 @@ class BaseConfig(BaseSettings):
|
||||
return (
|
||||
init_settings,
|
||||
CustomEnvSettings(
|
||||
env_settings.env_file, env_settings.env_file_encoding
|
||||
env_settings.env_file,
|
||||
env_settings.env_file_encoding,
|
||||
env_settings.env_nested_delimiter,
|
||||
env_settings.env_prefix_len,
|
||||
),
|
||||
InitSettingsSource(common_config),
|
||||
file_secret_settings,
|
||||
@@ -137,7 +150,6 @@ class Env(BaseConfig):
|
||||
"""
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
env_file = ".env"
|
||||
|
||||
|
||||
@@ -150,8 +162,7 @@ class Config(BaseConfig):
|
||||
配置方法参考: [配置](https://v2.nonebot.dev/docs/tutorial/configuration)
|
||||
"""
|
||||
|
||||
_env_file: str = ".env"
|
||||
_common_config: Dict[str, Any] = {}
|
||||
_env_file: DotenvType = ".env", ".env.prod"
|
||||
|
||||
# nonebot configs
|
||||
driver: str = "~fastapi"
|
||||
@@ -231,8 +242,7 @@ class Config(BaseConfig):
|
||||
# or from env file using json loads
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
env_file = ".env.prod"
|
||||
env_file = ".env", ".env.prod"
|
||||
|
||||
|
||||
__autodoc__ = {
|
||||
|
@@ -42,3 +42,11 @@ REGEX_GROUP: Literal["_matched_groups"] = "_matched_groups"
|
||||
"""正则匹配 group 元组存储 key"""
|
||||
REGEX_DICT: Literal["_matched_dict"] = "_matched_dict"
|
||||
"""正则匹配 group 字典存储 key"""
|
||||
STARTSWITH_KEY: Literal["_startswith"] = "_startswith"
|
||||
"""响应触发前缀 key"""
|
||||
ENDSWITH_KEY: Literal["_endswith"] = "_endswith"
|
||||
"""响应触发后缀 key"""
|
||||
FULLMATCH_KEY: Literal["_fullmatch"] = "_fullmatch"
|
||||
"""响应触发完整消息 key"""
|
||||
KEYWORD_KEY: Literal["_keyword"] = "_keyword"
|
||||
"""响应触发关键字 key"""
|
||||
|
@@ -4,11 +4,11 @@ FrontMatter:
|
||||
description: nonebot.dependencies.utils 模块
|
||||
"""
|
||||
import inspect
|
||||
from typing import Any, Dict, TypeVar, Callable
|
||||
from typing import Any, Dict, TypeVar, Callable, ForwardRef
|
||||
|
||||
from loguru import logger
|
||||
from pydantic.fields import ModelField
|
||||
from pydantic.typing import ForwardRef, evaluate_forwardref
|
||||
from pydantic.typing import evaluate_forwardref
|
||||
|
||||
from nonebot.exception import TypeMisMatch
|
||||
|
||||
|
@@ -262,7 +262,7 @@ class FastAPIWebSocket(BaseWebSocket):
|
||||
async def close(
|
||||
self, code: int = status.WS_1000_NORMAL_CLOSURE, reason: str = ""
|
||||
) -> None:
|
||||
await self.websocket.close(code)
|
||||
await self.websocket.close(code, reason)
|
||||
|
||||
@overrides(BaseWebSocket)
|
||||
async def receive(self) -> Union[str, bytes]:
|
||||
|
@@ -43,6 +43,10 @@ class Bot(abc.ABC):
|
||||
return f"Bot(type={self.type!r}, self_id={self.self_id!r})"
|
||||
|
||||
def __getattr__(self, name: str) -> "_ApiCall":
|
||||
if name.startswith("__") and name.endswith("__"):
|
||||
raise AttributeError(
|
||||
f"'{self.__class__.__name__}' object has no attribute '{name}'"
|
||||
)
|
||||
return partial(self.call_api, name)
|
||||
|
||||
@property
|
||||
|
11
nonebot/internal/matcher/__init__.py
Normal file
11
nonebot/internal/matcher/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from .manager import MatcherManager as MatcherManager
|
||||
from .provider import MatcherProvider as MatcherProvider
|
||||
from .provider import DEFAULT_PROVIDER_CLASS as DEFAULT_PROVIDER_CLASS
|
||||
|
||||
matchers = MatcherManager()
|
||||
|
||||
from .matcher import Matcher as Matcher
|
||||
from .matcher import current_bot as current_bot
|
||||
from .matcher import current_event as current_event
|
||||
from .matcher import current_handler as current_handler
|
||||
from .matcher import current_matcher as current_matcher
|
104
nonebot/internal/matcher/manager.py
Normal file
104
nonebot/internal/matcher/manager.py
Normal file
@@ -0,0 +1,104 @@
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
List,
|
||||
Type,
|
||||
Tuple,
|
||||
Union,
|
||||
TypeVar,
|
||||
Iterator,
|
||||
KeysView,
|
||||
Optional,
|
||||
ItemsView,
|
||||
ValuesView,
|
||||
MutableMapping,
|
||||
overload,
|
||||
)
|
||||
|
||||
from .provider import DEFAULT_PROVIDER_CLASS, MatcherProvider
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .matcher import Matcher
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class MatcherManager(MutableMapping[int, List[Type["Matcher"]]]):
|
||||
"""事件响应器管理器
|
||||
|
||||
实现了常用字典操作,用于管理事件响应器。
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.provider: MatcherProvider = DEFAULT_PROVIDER_CLASS({})
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"MatcherManager(provider={self.provider!r})"
|
||||
|
||||
def __contains__(self, o: object) -> bool:
|
||||
return o in self.provider
|
||||
|
||||
def __iter__(self) -> Iterator[int]:
|
||||
return iter(self.provider)
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.provider)
|
||||
|
||||
def __getitem__(self, key: int) -> List[Type["Matcher"]]:
|
||||
return self.provider[key]
|
||||
|
||||
def __setitem__(self, key: int, value: List[Type["Matcher"]]) -> None:
|
||||
self.provider[key] = value
|
||||
|
||||
def __delitem__(self, key: int) -> None:
|
||||
del self.provider[key]
|
||||
|
||||
def __eq__(self, other: Any) -> bool:
|
||||
return isinstance(other, MatcherManager) and self.provider == other.provider
|
||||
|
||||
def keys(self) -> KeysView[int]:
|
||||
return self.provider.keys()
|
||||
|
||||
def values(self) -> ValuesView[List[Type["Matcher"]]]:
|
||||
return self.provider.values()
|
||||
|
||||
def items(self) -> ItemsView[int, List[Type["Matcher"]]]:
|
||||
return self.provider.items()
|
||||
|
||||
@overload
|
||||
def get(self, key: int) -> Optional[List[Type["Matcher"]]]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def get(self, key: int, default: T) -> Union[List[Type["Matcher"]], T]:
|
||||
...
|
||||
|
||||
def get(
|
||||
self, key: int, default: Optional[T] = None
|
||||
) -> Optional[Union[List[Type["Matcher"]], T]]:
|
||||
return self.provider.get(key, default)
|
||||
|
||||
def pop(self, key: int) -> List[Type["Matcher"]]:
|
||||
return self.provider.pop(key)
|
||||
|
||||
def popitem(self) -> Tuple[int, List[Type["Matcher"]]]:
|
||||
return self.provider.popitem()
|
||||
|
||||
def clear(self) -> None:
|
||||
self.provider.clear()
|
||||
|
||||
def update(self, __m: MutableMapping[int, List[Type["Matcher"]]]) -> None:
|
||||
self.provider.update(__m)
|
||||
|
||||
def setdefault(
|
||||
self, key: int, default: List[Type["Matcher"]]
|
||||
) -> List[Type["Matcher"]]:
|
||||
return self.provider.setdefault(key, default)
|
||||
|
||||
def set_provider(self, provider_class: Type[MatcherProvider]) -> None:
|
||||
"""设置事件响应器存储器
|
||||
|
||||
参数:
|
||||
provider_class: 事件响应器存储器类
|
||||
"""
|
||||
self.provider = provider_class(self.provider)
|
@@ -1,12 +1,10 @@
|
||||
from types import ModuleType
|
||||
from contextvars import ContextVar
|
||||
from collections import defaultdict
|
||||
from contextlib import AsyncExitStack
|
||||
from datetime import datetime, timedelta
|
||||
from contextlib import AsyncExitStack, contextmanager
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Type,
|
||||
Union,
|
||||
@@ -19,7 +17,16 @@ from typing import (
|
||||
)
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot.internal.rule import Rule
|
||||
from nonebot.dependencies import Dependent
|
||||
from nonebot.internal.permission import USER, User, Permission
|
||||
from nonebot.internal.adapter import (
|
||||
Bot,
|
||||
Event,
|
||||
Message,
|
||||
MessageSegment,
|
||||
MessageTemplate,
|
||||
)
|
||||
from nonebot.consts import (
|
||||
ARG_KEY,
|
||||
RECEIVE_KEY,
|
||||
@@ -42,11 +49,7 @@ from nonebot.exception import (
|
||||
FinishedException,
|
||||
RejectedException,
|
||||
)
|
||||
|
||||
from .rule import Rule
|
||||
from .permission import USER, User, Permission
|
||||
from .adapter import Bot, Event, Message, MessageSegment, MessageTemplate
|
||||
from .params import (
|
||||
from nonebot.internal.params import (
|
||||
Depends,
|
||||
ArgParam,
|
||||
BotParam,
|
||||
@@ -57,13 +60,13 @@ from .params import (
|
||||
MatcherParam,
|
||||
)
|
||||
|
||||
from . import matchers
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from nonebot.plugin import Plugin
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
matchers: Dict[int, List[Type["Matcher"]]] = defaultdict(list)
|
||||
"""用于存储当前所有的事件响应器"""
|
||||
current_bot: ContextVar[Bot] = ContextVar("current_bot")
|
||||
current_event: ContextVar[Event] = ContextVar("current_event")
|
||||
current_matcher: ContextVar["Matcher"] = ContextVar("current_matcher")
|
||||
@@ -661,6 +664,18 @@ class Matcher(metaclass=MatcherMeta):
|
||||
if REJECT_CACHE_TARGET in self.state:
|
||||
self.state[REJECT_TARGET] = self.state[REJECT_CACHE_TARGET]
|
||||
|
||||
@contextmanager
|
||||
def ensure_context(self, bot: Bot, event: Event):
|
||||
b_t = current_bot.set(bot)
|
||||
e_t = current_event.set(event)
|
||||
m_t = current_matcher.set(self)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
current_bot.reset(b_t)
|
||||
current_event.reset(e_t)
|
||||
current_matcher.reset(m_t)
|
||||
|
||||
async def simple_run(
|
||||
self,
|
||||
bot: Bot,
|
||||
@@ -673,35 +688,31 @@ class Matcher(metaclass=MatcherMeta):
|
||||
f"{self} run with incoming args: "
|
||||
f"bot={bot}, event={event!r}, state={state!r}"
|
||||
)
|
||||
b_t = current_bot.set(bot)
|
||||
e_t = current_event.set(event)
|
||||
m_t = current_matcher.set(self)
|
||||
try:
|
||||
# Refresh preprocess state
|
||||
self.state.update(state)
|
||||
|
||||
while self.handlers:
|
||||
handler = self.handlers.pop(0)
|
||||
current_handler.set(handler)
|
||||
logger.debug(f"Running handler {handler}")
|
||||
try:
|
||||
await handler(
|
||||
matcher=self,
|
||||
bot=bot,
|
||||
event=event,
|
||||
state=self.state,
|
||||
stack=stack,
|
||||
dependency_cache=dependency_cache,
|
||||
)
|
||||
except SkippedException:
|
||||
logger.debug(f"Handler {handler} skipped")
|
||||
except StopPropagation:
|
||||
self.block = True
|
||||
finally:
|
||||
logger.info(f"{self} running complete")
|
||||
current_bot.reset(b_t)
|
||||
current_event.reset(e_t)
|
||||
current_matcher.reset(m_t)
|
||||
with self.ensure_context(bot, event):
|
||||
try:
|
||||
# Refresh preprocess state
|
||||
self.state.update(state)
|
||||
|
||||
while self.handlers:
|
||||
handler = self.handlers.pop(0)
|
||||
current_handler.set(handler)
|
||||
logger.debug(f"Running handler {handler}")
|
||||
try:
|
||||
await handler(
|
||||
matcher=self,
|
||||
bot=bot,
|
||||
event=event,
|
||||
state=self.state,
|
||||
stack=stack,
|
||||
dependency_cache=dependency_cache,
|
||||
)
|
||||
except SkippedException:
|
||||
logger.debug(f"Handler {handler} skipped")
|
||||
except StopPropagation:
|
||||
self.block = True
|
||||
finally:
|
||||
logger.info(f"{self} running complete")
|
||||
|
||||
# 运行handlers
|
||||
async def run(
|
||||
@@ -756,14 +767,3 @@ class Matcher(metaclass=MatcherMeta):
|
||||
)
|
||||
except FinishedException:
|
||||
pass
|
||||
|
||||
|
||||
__autodoc__ = {
|
||||
"MatcherMeta": False,
|
||||
"Matcher.get_target": False,
|
||||
"Matcher.set_target": False,
|
||||
"Matcher.update_type": False,
|
||||
"Matcher.update_permission": False,
|
||||
"Matcher.resolve_reject": False,
|
||||
"Matcher.simple_run": False,
|
||||
}
|
27
nonebot/internal/matcher/provider.py
Normal file
27
nonebot/internal/matcher/provider.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import abc
|
||||
from collections import defaultdict
|
||||
from typing import TYPE_CHECKING, List, Type, Mapping, MutableMapping
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .matcher import Matcher
|
||||
|
||||
|
||||
class MatcherProvider(abc.ABC, MutableMapping[int, List[Type["Matcher"]]]):
|
||||
"""事件响应器存储器基类
|
||||
|
||||
参数:
|
||||
matchers: 当前存储器中已有的事件响应器
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __init__(self, matchers: Mapping[int, List[Type["Matcher"]]]):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class _DictProvider(defaultdict, MatcherProvider):
|
||||
def __init__(self, matchers: Mapping[int, List[Type["Matcher"]]]):
|
||||
super().__init__(list, matchers)
|
||||
|
||||
|
||||
DEFAULT_PROVIDER_CLASS = _DictProvider
|
||||
"""默认存储器类型"""
|
@@ -9,10 +9,16 @@ from nonebot.internal.matcher import Matcher as Matcher
|
||||
from nonebot.internal.matcher import matchers as matchers
|
||||
from nonebot.internal.matcher import current_bot as current_bot
|
||||
from nonebot.internal.matcher import current_event as current_event
|
||||
from nonebot.internal.matcher import MatcherManager as MatcherManager
|
||||
from nonebot.internal.matcher import MatcherProvider as MatcherProvider
|
||||
from nonebot.internal.matcher import current_handler as current_handler
|
||||
from nonebot.internal.matcher import current_matcher as current_matcher
|
||||
from nonebot.internal.matcher import DEFAULT_PROVIDER_CLASS as DEFAULT_PROVIDER_CLASS
|
||||
|
||||
__autodoc__ = {
|
||||
"Matcher": True,
|
||||
"matchers": True,
|
||||
"MatcherManager": True,
|
||||
"MatcherProvider": True,
|
||||
"DEFAULT_PROVIDER_CLASS": True,
|
||||
}
|
||||
|
@@ -167,17 +167,19 @@ async def _run_matcher(
|
||||
)
|
||||
for proc in _run_preprocessors
|
||||
]:
|
||||
try:
|
||||
await asyncio.gather(*coros)
|
||||
except IgnoredException:
|
||||
logger.opt(colors=True).info(f"{matcher} running is <b>cancelled</b>")
|
||||
return
|
||||
except Exception as e:
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
"<r><bg #f8bbd0>Error when running RunPreProcessors. Running cancelled!</bg #f8bbd0></r>"
|
||||
)
|
||||
# ensure matcher function can be correctly called
|
||||
with matcher.ensure_context(bot, event):
|
||||
try:
|
||||
await asyncio.gather(*coros)
|
||||
except IgnoredException:
|
||||
logger.opt(colors=True).info(f"{matcher} running is <b>cancelled</b>")
|
||||
return
|
||||
except Exception as e:
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
"<r><bg #f8bbd0>Error when running RunPreProcessors. Running cancelled!</bg #f8bbd0></r>"
|
||||
)
|
||||
|
||||
return
|
||||
return
|
||||
|
||||
exception = None
|
||||
|
||||
@@ -205,12 +207,14 @@ async def _run_matcher(
|
||||
)
|
||||
for proc in _run_postprocessors
|
||||
]:
|
||||
try:
|
||||
await asyncio.gather(*coros)
|
||||
except Exception as e:
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
"<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>"
|
||||
)
|
||||
# ensure matcher function can be correctly called
|
||||
with matcher.ensure_context(bot, event):
|
||||
try:
|
||||
await asyncio.gather(*coros)
|
||||
except Exception as e:
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
"<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>"
|
||||
)
|
||||
|
||||
if matcher.block:
|
||||
raise StopPropagation
|
||||
|
@@ -29,10 +29,14 @@ from nonebot.consts import (
|
||||
SHELL_ARGS,
|
||||
SHELL_ARGV,
|
||||
CMD_ARG_KEY,
|
||||
KEYWORD_KEY,
|
||||
RAW_CMD_KEY,
|
||||
REGEX_GROUP,
|
||||
ENDSWITH_KEY,
|
||||
CMD_START_KEY,
|
||||
FULLMATCH_KEY,
|
||||
REGEX_MATCHED,
|
||||
STARTSWITH_KEY,
|
||||
)
|
||||
|
||||
|
||||
@@ -153,6 +157,42 @@ def RegexDict() -> Dict[str, Any]:
|
||||
return Depends(_regex_dict, use_cache=False)
|
||||
|
||||
|
||||
def _startswith(state: T_State) -> str:
|
||||
return state[STARTSWITH_KEY]
|
||||
|
||||
|
||||
def Startswith() -> str:
|
||||
"""响应触发前缀"""
|
||||
return Depends(_startswith, use_cache=False)
|
||||
|
||||
|
||||
def _endswith(state: T_State) -> str:
|
||||
return state[ENDSWITH_KEY]
|
||||
|
||||
|
||||
def Endswith() -> str:
|
||||
"""响应触发后缀"""
|
||||
return Depends(_endswith, use_cache=False)
|
||||
|
||||
|
||||
def _fullmatch(state: T_State) -> str:
|
||||
return state[FULLMATCH_KEY]
|
||||
|
||||
|
||||
def Fullmatch() -> str:
|
||||
"""响应触发完整消息"""
|
||||
return Depends(_fullmatch, use_cache=False)
|
||||
|
||||
|
||||
def _keyword(state: T_State) -> str:
|
||||
return state[KEYWORD_KEY]
|
||||
|
||||
|
||||
def Keyword() -> str:
|
||||
"""响应触发关键字"""
|
||||
return Depends(_keyword, use_cache=False)
|
||||
|
||||
|
||||
def Received(id: Optional[str] = None, default: Any = None) -> Any:
|
||||
"""`receive` 事件参数"""
|
||||
|
||||
|
@@ -18,7 +18,6 @@ from argparse import ArgumentParser as ArgParser
|
||||
from typing import (
|
||||
IO,
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
List,
|
||||
Type,
|
||||
Tuple,
|
||||
@@ -48,10 +47,14 @@ from nonebot.consts import (
|
||||
SHELL_ARGS,
|
||||
SHELL_ARGV,
|
||||
CMD_ARG_KEY,
|
||||
KEYWORD_KEY,
|
||||
RAW_CMD_KEY,
|
||||
REGEX_GROUP,
|
||||
ENDSWITH_KEY,
|
||||
CMD_START_KEY,
|
||||
FULLMATCH_KEY,
|
||||
REGEX_MATCHED,
|
||||
STARTSWITH_KEY,
|
||||
)
|
||||
|
||||
T = TypeVar("T")
|
||||
@@ -136,20 +139,21 @@ class StartswithRule:
|
||||
def __hash__(self) -> int:
|
||||
return hash((frozenset(self.msg), self.ignorecase))
|
||||
|
||||
async def __call__(self, event: Event) -> bool:
|
||||
async def __call__(self, event: Event, state: T_State) -> bool:
|
||||
if event.get_type() != "message":
|
||||
return False
|
||||
try:
|
||||
text = event.get_plaintext()
|
||||
except Exception:
|
||||
return False
|
||||
return bool(
|
||||
re.match(
|
||||
f"^(?:{'|'.join(re.escape(prefix) for prefix in self.msg)})",
|
||||
text,
|
||||
re.IGNORECASE if self.ignorecase else 0,
|
||||
)
|
||||
)
|
||||
if match := re.match(
|
||||
f"^(?:{'|'.join(re.escape(prefix) for prefix in self.msg)})",
|
||||
text,
|
||||
re.IGNORECASE if self.ignorecase else 0,
|
||||
):
|
||||
state[STARTSWITH_KEY] = match.group()
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def startswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule:
|
||||
@@ -192,20 +196,21 @@ class EndswithRule:
|
||||
def __hash__(self) -> int:
|
||||
return hash((frozenset(self.msg), self.ignorecase))
|
||||
|
||||
async def __call__(self, event: Event) -> bool:
|
||||
async def __call__(self, event: Event, state: T_State) -> bool:
|
||||
if event.get_type() != "message":
|
||||
return False
|
||||
try:
|
||||
text = event.get_plaintext()
|
||||
except Exception:
|
||||
return False
|
||||
return bool(
|
||||
re.search(
|
||||
f"(?:{'|'.join(re.escape(prefix) for prefix in self.msg)})$",
|
||||
text,
|
||||
re.IGNORECASE if self.ignorecase else 0,
|
||||
)
|
||||
)
|
||||
if match := re.search(
|
||||
f"(?:{'|'.join(re.escape(suffix) for suffix in self.msg)})$",
|
||||
text,
|
||||
re.IGNORECASE if self.ignorecase else 0,
|
||||
):
|
||||
state[ENDSWITH_KEY] = match.group()
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def endswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule:
|
||||
@@ -248,14 +253,20 @@ class FullmatchRule:
|
||||
def __hash__(self) -> int:
|
||||
return hash((frozenset(self.msg), self.ignorecase))
|
||||
|
||||
async def __call__(self, event: Event) -> bool:
|
||||
async def __call__(self, event: Event, state: T_State) -> bool:
|
||||
if event.get_type() != "message":
|
||||
return False
|
||||
try:
|
||||
text = event.get_plaintext()
|
||||
except Exception:
|
||||
return False
|
||||
return (text.casefold() if self.ignorecase else text) in self.msg
|
||||
if not text:
|
||||
return False
|
||||
text = text.casefold() if self.ignorecase else text
|
||||
if text in self.msg:
|
||||
state[FULLMATCH_KEY] = text
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def fullmatch(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule:
|
||||
@@ -294,14 +305,19 @@ class KeywordsRule:
|
||||
def __hash__(self) -> int:
|
||||
return hash(frozenset(self.keywords))
|
||||
|
||||
async def __call__(self, event: Event) -> bool:
|
||||
async def __call__(self, event: Event, state: T_State) -> bool:
|
||||
if event.get_type() != "message":
|
||||
return False
|
||||
try:
|
||||
text = event.get_plaintext()
|
||||
except Exception:
|
||||
return False
|
||||
return bool(text and any(keyword in text for keyword in self.keywords))
|
||||
if not text:
|
||||
return False
|
||||
if key := next((k for k in self.keywords if k in text), None):
|
||||
state[KEYWORD_KEY] = key
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def keyword(*keywords: str) -> Rule:
|
||||
|
1104
poetry.lock
generated
1104
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "nonebot2"
|
||||
version = "2.0.0-rc.1"
|
||||
version = "2.0.0rc2"
|
||||
description = "An asynchronous python bot framework."
|
||||
authors = ["yanyongyu <yyy@nonebot.dev>"]
|
||||
license = "MIT"
|
||||
@@ -26,25 +26,30 @@ python = "^3.8"
|
||||
yarl = "^1.7.2"
|
||||
loguru = "^0.6.0"
|
||||
pygtrie = "^2.4.1"
|
||||
fastapi = "^0.79.0"
|
||||
fastapi = ">=0.87.0,<1.0.0"
|
||||
tomlkit = ">=0.10.0,<1.0.0"
|
||||
typing-extensions = ">=3.10.0,<5.0.0"
|
||||
Quart = { version = "^0.17.0", optional = true }
|
||||
websockets = { version="^10.0", optional = true }
|
||||
pydantic = { version = "~1.9.0", extras = ["dotenv"] }
|
||||
uvicorn = { version = "^0.18.0", extras = ["standard"] }
|
||||
aiohttp = { version = "^3.7.4", extras = ["speedups"], optional = true }
|
||||
httpx = { version = ">=0.20.0, <1.0.0", extras = ["http2"], optional = true }
|
||||
pydantic = { version = "^1.10.0", extras = ["dotenv"] }
|
||||
uvicorn = { version = ">=0.20.0,<1.0.0", extras = ["standard"] }
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
websockets = { version="^10.0", optional = true }
|
||||
Quart = { version = ">=0.18.0,<1.0.0", optional = true }
|
||||
aiohttp = { version = "^3.7.4", extras = ["speedups"], optional = true }
|
||||
httpx = { version = ">=0.20.0,<1.0.0", extras = ["http2"], optional = true }
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
isort = "^5.10.1"
|
||||
black = "^22.1.0"
|
||||
nonemoji = "^0.1.2"
|
||||
pytest-cov = "^3.0.0"
|
||||
pre-commit = "^2.16.0"
|
||||
pytest-xdist = "^2.5.0"
|
||||
pytest-asyncio = "^0.19.0"
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
pytest-cov = "^4.0.0"
|
||||
pytest-xdist = "^3.0.2"
|
||||
pytest-asyncio = "^0.20.0"
|
||||
nonebug = { git = "https://github.com/nonebot/nonebug.git" }
|
||||
|
||||
[tool.poetry.group.docs.dependencies]
|
||||
nb-autodoc = { git = "https://github.com/nonebot/nb-autodoc.git" }
|
||||
|
||||
[tool.poetry.extras]
|
||||
@@ -64,7 +69,7 @@ filterwarnings = [
|
||||
|
||||
[tool.black]
|
||||
line-length = 88
|
||||
target-version = ["py37", "py38", "py39", "py310"]
|
||||
target-version = ["py38", "py39", "py310", "py311"]
|
||||
include = '\.pyi?$'
|
||||
extend-exclude = '''
|
||||
'''
|
||||
|
@@ -1,2 +1,3 @@
|
||||
ENVIRONMENT=test
|
||||
COMMON_CONFIG=common
|
||||
COMMON_OVERRIDE=old
|
||||
|
@@ -1,5 +1,13 @@
|
||||
LOG_LEVEL=TRACE
|
||||
NICKNAME=["test"]
|
||||
SUPERUSERS=["test", "fake:faketest"]
|
||||
COMMON_OVERRIDE=new
|
||||
CONFIG_FROM_ENV=
|
||||
CONFIG_OVERRIDE=old
|
||||
NESTED_DICT={"a": 1}
|
||||
NESTED_DICT__B=2
|
||||
NESTED_DICT__C__D=3
|
||||
NESTED_MISSING_DICT__A=1
|
||||
NESTED_MISSING_DICT__B__C=2
|
||||
NOT_NESTED=some string
|
||||
NOT_NESTED__A=1
|
||||
|
@@ -4,10 +4,14 @@ from nonebot.typing import T_State
|
||||
from nonebot.adapters import Message
|
||||
from nonebot.params import (
|
||||
Command,
|
||||
Keyword,
|
||||
Endswith,
|
||||
Fullmatch,
|
||||
RegexDict,
|
||||
CommandArg,
|
||||
RawCommand,
|
||||
RegexGroup,
|
||||
Startswith,
|
||||
CommandStart,
|
||||
RegexMatched,
|
||||
ShellCommandArgs,
|
||||
@@ -65,3 +69,19 @@ async def regex_group(regex_group: Tuple = RegexGroup()) -> Tuple:
|
||||
|
||||
async def regex_matched(regex_matched: str = RegexMatched()) -> str:
|
||||
return regex_matched
|
||||
|
||||
|
||||
async def startswith(startswith: str = Startswith()) -> str:
|
||||
return startswith
|
||||
|
||||
|
||||
async def endswith(endswith: str = Endswith()) -> str:
|
||||
return endswith
|
||||
|
||||
|
||||
async def fullmatch(fullmatch: str = Fullmatch()) -> str:
|
||||
return fullmatch
|
||||
|
||||
|
||||
async def keyword(keyword: str = Keyword()) -> str:
|
||||
return keyword
|
||||
|
@@ -29,6 +29,10 @@ async def test_init(nonebug_init):
|
||||
assert config.config_override == "new"
|
||||
assert config.config_from_init == "init"
|
||||
assert config.common_config == "common"
|
||||
assert config.common_override == "new"
|
||||
assert config.nested_dict == {"a": 1, "b": 2, "c": {"d": 3}}
|
||||
assert config.nested_missing_dict == {"a": 1, "b": {"c": 2}}
|
||||
assert config.not_nested == "some string"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
11
tests/test_matcher/test_provider.py
Normal file
11
tests/test_matcher/test_provider.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import pytest
|
||||
from nonebug import App
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_manager(app: App, load_plugin):
|
||||
from nonebot.matcher import DEFAULT_PROVIDER_CLASS, matchers
|
||||
|
||||
default_provider = matchers.provider
|
||||
matchers.set_provider(DEFAULT_PROVIDER_CLASS)
|
||||
assert matchers.provider == default_provider
|
@@ -168,15 +168,23 @@ async def test_state(app: App, load_plugin):
|
||||
SHELL_ARGS,
|
||||
SHELL_ARGV,
|
||||
CMD_ARG_KEY,
|
||||
KEYWORD_KEY,
|
||||
RAW_CMD_KEY,
|
||||
REGEX_GROUP,
|
||||
ENDSWITH_KEY,
|
||||
CMD_START_KEY,
|
||||
FULLMATCH_KEY,
|
||||
REGEX_MATCHED,
|
||||
STARTSWITH_KEY,
|
||||
)
|
||||
from plugins.param.param_state import (
|
||||
state,
|
||||
command,
|
||||
keyword,
|
||||
endswith,
|
||||
fullmatch,
|
||||
regex_dict,
|
||||
startswith,
|
||||
command_arg,
|
||||
raw_command,
|
||||
regex_group,
|
||||
@@ -201,6 +209,10 @@ async def test_state(app: App, load_plugin):
|
||||
REGEX_MATCHED: "[cq:test,arg=value]",
|
||||
REGEX_GROUP: ("test", "arg=value"),
|
||||
REGEX_DICT: {"type": "test", "arg": "value"},
|
||||
STARTSWITH_KEY: "startswith",
|
||||
ENDSWITH_KEY: "endswith",
|
||||
FULLMATCH_KEY: "fullmatch",
|
||||
KEYWORD_KEY: "keyword",
|
||||
}
|
||||
|
||||
async with app.test_dependent(state, allow_types=[StateParam]) as ctx:
|
||||
@@ -271,6 +283,30 @@ async def test_state(app: App, load_plugin):
|
||||
ctx.pass_params(state=fake_state)
|
||||
ctx.should_return(fake_state[REGEX_DICT])
|
||||
|
||||
async with app.test_dependent(
|
||||
startswith, allow_types=[StateParam, DependParam]
|
||||
) as ctx:
|
||||
ctx.pass_params(state=fake_state)
|
||||
ctx.should_return(fake_state[STARTSWITH_KEY])
|
||||
|
||||
async with app.test_dependent(
|
||||
endswith, allow_types=[StateParam, DependParam]
|
||||
) as ctx:
|
||||
ctx.pass_params(state=fake_state)
|
||||
ctx.should_return(fake_state[ENDSWITH_KEY])
|
||||
|
||||
async with app.test_dependent(
|
||||
fullmatch, allow_types=[StateParam, DependParam]
|
||||
) as ctx:
|
||||
ctx.pass_params(state=fake_state)
|
||||
ctx.should_return(fake_state[FULLMATCH_KEY])
|
||||
|
||||
async with app.test_dependent(
|
||||
keyword, allow_types=[StateParam, DependParam]
|
||||
) as ctx:
|
||||
ctx.pass_params(state=fake_state)
|
||||
ctx.should_return(fake_state[KEYWORD_KEY])
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_matcher(app: App, load_plugin):
|
||||
|
@@ -65,19 +65,24 @@ async def test_startswith(
|
||||
text: Optional[str],
|
||||
expected: bool,
|
||||
):
|
||||
from nonebot.consts import STARTSWITH_KEY
|
||||
from nonebot.rule import StartswithRule, startswith
|
||||
|
||||
test_startswith = startswith(msg, ignorecase)
|
||||
dependent = list(test_startswith.checkers)[0]
|
||||
checker = dependent.call
|
||||
|
||||
msg = (msg,) if isinstance(msg, str) else msg
|
||||
|
||||
assert isinstance(checker, StartswithRule)
|
||||
assert checker.msg == (msg,) if isinstance(msg, str) else msg
|
||||
assert checker.msg == msg
|
||||
assert checker.ignorecase == ignorecase
|
||||
|
||||
message = text if text is None else make_fake_message()(text)
|
||||
event = make_fake_event(_type=type, _message=message)()
|
||||
assert await dependent(event=event) == expected
|
||||
for prefix in msg:
|
||||
state = {STARTSWITH_KEY: prefix}
|
||||
assert await dependent(event=event, state=state) == expected
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -103,19 +108,24 @@ async def test_endswith(
|
||||
text: Optional[str],
|
||||
expected: bool,
|
||||
):
|
||||
from nonebot.consts import ENDSWITH_KEY
|
||||
from nonebot.rule import EndswithRule, endswith
|
||||
|
||||
test_endswith = endswith(msg, ignorecase)
|
||||
dependent = list(test_endswith.checkers)[0]
|
||||
checker = dependent.call
|
||||
|
||||
msg = (msg,) if isinstance(msg, str) else msg
|
||||
|
||||
assert isinstance(checker, EndswithRule)
|
||||
assert checker.msg == (msg,) if isinstance(msg, str) else msg
|
||||
assert checker.msg == msg
|
||||
assert checker.ignorecase == ignorecase
|
||||
|
||||
message = text if text is None else make_fake_message()(text)
|
||||
event = make_fake_event(_type=type, _message=message)()
|
||||
assert await dependent(event=event) == expected
|
||||
for suffix in msg:
|
||||
state = {ENDSWITH_KEY: suffix}
|
||||
assert await dependent(event=event, state=state) == expected
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -141,19 +151,24 @@ async def test_fullmatch(
|
||||
text: Optional[str],
|
||||
expected: bool,
|
||||
):
|
||||
from nonebot.consts import FULLMATCH_KEY
|
||||
from nonebot.rule import FullmatchRule, fullmatch
|
||||
|
||||
test_fullmatch = fullmatch(msg, ignorecase)
|
||||
dependent = list(test_fullmatch.checkers)[0]
|
||||
checker = dependent.call
|
||||
|
||||
msg = (msg,) if isinstance(msg, str) else msg
|
||||
|
||||
assert isinstance(checker, FullmatchRule)
|
||||
assert checker.msg == ((msg,) if isinstance(msg, str) else msg)
|
||||
assert checker.msg == msg
|
||||
assert checker.ignorecase == ignorecase
|
||||
|
||||
message = text if text is None else make_fake_message()(text)
|
||||
event = make_fake_event(_type=type, _message=message)()
|
||||
assert await dependent(event=event) == expected
|
||||
for full in msg:
|
||||
state = {FULLMATCH_KEY: full}
|
||||
assert await dependent(event=event, state=state) == expected
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -164,6 +179,7 @@ async def test_fullmatch(
|
||||
(("key", "foo"), "message", "_foo_", True),
|
||||
(("key",), "message", None, False),
|
||||
(("key",), "notice", "foo", False),
|
||||
(("key",), "message", "foo", False),
|
||||
],
|
||||
)
|
||||
async def test_keyword(
|
||||
@@ -173,6 +189,7 @@ async def test_keyword(
|
||||
text: Optional[str],
|
||||
expected: bool,
|
||||
):
|
||||
from nonebot.consts import KEYWORD_KEY
|
||||
from nonebot.rule import KeywordsRule, keyword
|
||||
|
||||
test_keyword = keyword(*kws)
|
||||
@@ -184,7 +201,9 @@ async def test_keyword(
|
||||
|
||||
message = text if text is None else make_fake_message()(text)
|
||||
event = make_fake_event(_type=type, _message=message)()
|
||||
assert await dependent(event=event) == expected
|
||||
for kw in kws:
|
||||
state = {KEYWORD_KEY: kw}
|
||||
assert await dependent(event=event, state=state) == expected
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
@@ -363,6 +363,62 @@ matcher = on_regex("regex")
|
||||
async def _(foo: Dict[str, Any] = RegexDict()): ...
|
||||
```
|
||||
|
||||
### Startswith
|
||||
|
||||
获取触发响应器的消息前缀字符串。
|
||||
|
||||
```python {7}
|
||||
from nonebot import on_startswith
|
||||
from nonebot.params import Startswith
|
||||
|
||||
matcher = on_startswith("prefix")
|
||||
|
||||
@matcher.handle()
|
||||
async def _(foo: str = Startswith()): ...
|
||||
```
|
||||
|
||||
### Endswith
|
||||
|
||||
获取触发响应器的消息后缀字符串。
|
||||
|
||||
```python {7}
|
||||
from nonebot import on_endswith
|
||||
from nonebot.params import Endswith
|
||||
|
||||
matcher = on_endswith("suffix")
|
||||
|
||||
@matcher.handle()
|
||||
async def _(foo: str = Endswith()): ...
|
||||
```
|
||||
|
||||
### Fullmatch
|
||||
|
||||
获取触发响应器的消息字符串。
|
||||
|
||||
```python {7}
|
||||
from nonebot import on_fullmatch
|
||||
from nonebot.params import Fullmatch
|
||||
|
||||
matcher = on_fullmatch("fullmatch")
|
||||
|
||||
@matcher.handle()
|
||||
async def _(foo: str = Fullmatch()): ...
|
||||
```
|
||||
|
||||
### Keyword
|
||||
|
||||
获取触发响应器的关键字字符串。
|
||||
|
||||
```python {7}
|
||||
from nonebot import on_keyword
|
||||
from nonebot.params import Keyword
|
||||
|
||||
matcher = on_keyword({"keyword"})
|
||||
|
||||
@matcher.handle()
|
||||
async def _(foo: str = Keyword()): ...
|
||||
```
|
||||
|
||||
### Matcher
|
||||
|
||||
获取当前事件响应器实例。
|
||||
|
@@ -5,6 +5,85 @@ toc_max_heading_level: 2
|
||||
|
||||
# 更新日志
|
||||
|
||||
## v2.0.0rc2
|
||||
|
||||
### 💥 破坏性变更
|
||||
|
||||
- Feature: 使用 `importlib.metadata` 替换 `pkg_resources` [@A-kirami](https://github.com/A-kirami) ([#1388](https://github.com/nonebot/nonebot2/pull/1388))
|
||||
|
||||
### 🚀 新功能
|
||||
|
||||
- Feature: 支持自定义 matchers 存储管理 [@yanyongyu](https://github.com/yanyongyu) ([#1395](https://github.com/nonebot/nonebot2/pull/1395))
|
||||
- Feature: 升级 devcontainer 配置 [@yanyongyu](https://github.com/yanyongyu) ([#1392](https://github.com/nonebot/nonebot2/pull/1392))
|
||||
- Feature: 使用 `importlib.metadata` 替换 `pkg_resources` [@A-kirami](https://github.com/A-kirami) ([#1388](https://github.com/nonebot/nonebot2/pull/1388))
|
||||
- CI: 测试环境添加 Python 3.11 [@StarHeartHunt](https://github.com/StarHeartHunt) ([#1366](https://github.com/nonebot/nonebot2/pull/1366))
|
||||
- Feature: 新增 dotenv 嵌套配置项支持 [@yanyongyu](https://github.com/yanyongyu) ([#1324](https://github.com/nonebot/nonebot2/pull/1324))
|
||||
- Feature: 添加 State 响应器触发消息注入 [@A-kirami](https://github.com/A-kirami) ([#1315](https://github.com/nonebot/nonebot2/pull/1315))
|
||||
- Remove: 移除无用的 namespace 声明 [@yanyongyu](https://github.com/yanyongyu) ([#1306](https://github.com/nonebot/nonebot2/pull/1306))
|
||||
|
||||
### 🐛 Bug 修复
|
||||
|
||||
- Fix: Bot `__getattr__` 不再对 `__xxx__` 方法返回 [@synodriver](https://github.com/synodriver) ([#1398](https://github.com/nonebot/nonebot2/pull/1398))
|
||||
- Fix: 修复 run pre/post hook 没有在正确的上下文中运行 [@yanyongyu](https://github.com/yanyongyu) ([#1391](https://github.com/nonebot/nonebot2/pull/1391))
|
||||
|
||||
### 📝 文档
|
||||
|
||||
- Docs: 添加 ntchat 社区适配器 [@JustUndertaker](https://github.com/JustUndertaker) ([#1414](https://github.com/nonebot/nonebot2/pull/1414))
|
||||
|
||||
### 💫 杂项
|
||||
|
||||
- Plugin: b 站用户信息查询 [@Ikaros-521](https://github.com/Ikaros-521) ([#1410](https://github.com/nonebot/nonebot2/pull/1410))
|
||||
- Plugin: 由于 Sena-nana 项目拆分,之前的插件地址更改 [@sena-nana](https://github.com/sena-nana) ([#1378](https://github.com/nonebot/nonebot2/pull/1378))
|
||||
- Plugin: 更新 ayaka 插件的主页链接 [@bridgeL](https://github.com/bridgeL) ([#1346](https://github.com/nonebot/nonebot2/pull/1346))
|
||||
- Plugin: 补充 novelai 插件信息 [@sena-nana](https://github.com/sena-nana) ([#1333](https://github.com/nonebot/nonebot2/pull/1333))
|
||||
- Bot: 修改 Inkar Suki 描述 [@HornCopper](https://github.com/HornCopper) ([#1312](https://github.com/nonebot/nonebot2/pull/1312))
|
||||
- Plugin: 修改插件 MCQQ MCRcon 主页地址 [@17TheWord](https://github.com/17TheWord) ([#1303](https://github.com/nonebot/nonebot2/pull/1303))
|
||||
|
||||
### 🍻 插件发布
|
||||
|
||||
- Plugin: 谁在窥屏 [@yanyongyu](https://github.com/yanyongyu) ([#1416](https://github.com/nonebot/nonebot2/pull/1416))
|
||||
- Plugin: 免费版 NovelAI 生图插件 [@yanyongyu](https://github.com/yanyongyu) ([#1408](https://github.com/nonebot/nonebot2/pull/1408))
|
||||
- Plugin: sky 光遇 [@yanyongyu](https://github.com/yanyongyu) ([#1394](https://github.com/nonebot/nonebot2/pull/1394))
|
||||
- Plugin: Colab-NovelAI [@yanyongyu](https://github.com/yanyongyu) ([#1390](https://github.com/nonebot/nonebot2/pull/1390))
|
||||
- Plugin: b 站用户直播号、粉丝、舰团数查询 [@yanyongyu](https://github.com/yanyongyu) ([#1385](https://github.com/nonebot/nonebot2/pull/1385))
|
||||
- Plugin: 投胎模拟器 [@yanyongyu](https://github.com/yanyongyu) ([#1382](https://github.com/nonebot/nonebot2/pull/1382))
|
||||
- Plugin: Apex API Query [@yanyongyu](https://github.com/yanyongyu) ([#1375](https://github.com/nonebot/nonebot2/pull/1375))
|
||||
- Plugin: 随个人 [@yanyongyu](https://github.com/yanyongyu) ([#1373](https://github.com/nonebot/nonebot2/pull/1373))
|
||||
- Plugin: 动漫资源获取 [@yanyongyu](https://github.com/yanyongyu) ([#1371](https://github.com/nonebot/nonebot2/pull/1371))
|
||||
- Plugin: 日麻小工具 [@yanyongyu](https://github.com/yanyongyu) ([#1365](https://github.com/nonebot/nonebot2/pull/1365))
|
||||
- Plugin: 图像超分辨率增强 [@yanyongyu](https://github.com/yanyongyu) ([#1362](https://github.com/nonebot/nonebot2/pull/1362))
|
||||
- Plugin: 二次元化图像 [@yanyongyu](https://github.com/yanyongyu) ([#1360](https://github.com/nonebot/nonebot2/pull/1360))
|
||||
- Plugin: 日麻寄分器 [@yanyongyu](https://github.com/yanyongyu) ([#1357](https://github.com/nonebot/nonebot2/pull/1357))
|
||||
- Plugin: 文本生成器 [@yanyongyu](https://github.com/yanyongyu) ([#1355](https://github.com/nonebot/nonebot2/pull/1355))
|
||||
- Plugin: 反嘴臭插件 [@yanyongyu](https://github.com/yanyongyu) ([#1350](https://github.com/nonebot/nonebot2/pull/1350))
|
||||
- Plugin: 用户\&群聊黑名单 [@yanyongyu](https://github.com/yanyongyu) ([#1348](https://github.com/nonebot/nonebot2/pull/1348))
|
||||
- Plugin: NoneBot SQLAlchemy 封装 [@yanyongyu](https://github.com/yanyongyu) ([#1345](https://github.com/nonebot/nonebot2/pull/1345))
|
||||
- Plugin: 通用抽图/语音 [@yanyongyu](https://github.com/yanyongyu) ([#1341](https://github.com/nonebot/nonebot2/pull/1341))
|
||||
- Plugin: kfcrazy [@yanyongyu](https://github.com/yanyongyu) ([#1339](https://github.com/nonebot/nonebot2/pull/1339))
|
||||
- Plugin: 二次元图像鉴赏 [@yanyongyu](https://github.com/yanyongyu) ([#1337](https://github.com/nonebot/nonebot2/pull/1337))
|
||||
- Plugin: ayaka 衍生插件 - 坏词撤回 [@yanyongyu](https://github.com/yanyongyu) ([#1335](https://github.com/nonebot/nonebot2/pull/1335))
|
||||
- Plugin: ayaka 衍生插件 - 时区助手 [@yanyongyu](https://github.com/yanyongyu) ([#1332](https://github.com/nonebot/nonebot2/pull/1332))
|
||||
- Plugin: ayaka 衍生插件 - 谁是卧底 [@yanyongyu](https://github.com/yanyongyu) ([#1330](https://github.com/nonebot/nonebot2/pull/1330))
|
||||
- Plugin: ayaka 衍生插件 - 小游戏合集 [@yanyongyu](https://github.com/yanyongyu) ([#1328](https://github.com/nonebot/nonebot2/pull/1328))
|
||||
- Plugin: bnhhsh -「不能好好说话!」 [@yanyongyu](https://github.com/yanyongyu) ([#1326](https://github.com/nonebot/nonebot2/pull/1326))
|
||||
- Plugin: AI 绘图 [@yanyongyu](https://github.com/yanyongyu) ([#1323](https://github.com/nonebot/nonebot2/pull/1323))
|
||||
- Plugin: novelai [@yanyongyu](https://github.com/yanyongyu) ([#1319](https://github.com/nonebot/nonebot2/pull/1319))
|
||||
- Plugin: 游戏王小程序查价 [@yanyongyu](https://github.com/yanyongyu) ([#1317](https://github.com/nonebot/nonebot2/pull/1317))
|
||||
- Plugin: 监测群事件 [@yanyongyu](https://github.com/yanyongyu) ([#1320](https://github.com/nonebot/nonebot2/pull/1320))
|
||||
- Plugin: 轮盘禁言小游戏 [@yanyongyu](https://github.com/yanyongyu) ([#1311](https://github.com/nonebot/nonebot2/pull/1311))
|
||||
- Plugin: 真白萌自动签到 [@yanyongyu](https://github.com/yanyongyu) ([#1308](https://github.com/nonebot/nonebot2/pull/1308))
|
||||
- Plugin: BiliRequestAll [@yanyongyu](https://github.com/yanyongyu) ([#1302](https://github.com/nonebot/nonebot2/pull/1302))
|
||||
- Plugin: 监听者 [@yanyongyu](https://github.com/yanyongyu) ([#1299](https://github.com/nonebot/nonebot2/pull/1299))
|
||||
|
||||
### 🍻 机器人发布
|
||||
|
||||
- Bot: Bread Dog Bot [@yanyongyu](https://github.com/yanyongyu) ([#1380](https://github.com/nonebot/nonebot2/pull/1380))
|
||||
- Bot: hsbot [@yanyongyu](https://github.com/yanyongyu) ([#1369](https://github.com/nonebot/nonebot2/pull/1369))
|
||||
|
||||
### 🍻 适配器发布
|
||||
|
||||
- Adapter: Ntchat [@yanyongyu](https://github.com/yanyongyu) ([#1314](https://github.com/nonebot/nonebot2/pull/1314))
|
||||
|
||||
## v2.0.0-rc.1
|
||||
|
||||
### 💥 破坏性变更
|
||||
|
@@ -98,5 +98,20 @@
|
||||
"homepage": "https://github.com/nonebot/adapter-github",
|
||||
"tags": [],
|
||||
"is_official": true
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot.adapters.ntchat",
|
||||
"project_link": "nonebot-adapter-ntchat",
|
||||
"name": "Ntchat",
|
||||
"desc": "pc hook的微信客户端适配",
|
||||
"author": "JustUndertaker",
|
||||
"homepage": "https://github.com/JustUndertaker/adapter-ntchat",
|
||||
"tags": [
|
||||
{
|
||||
"label": "微信",
|
||||
"color": "#ea5252"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@@ -123,7 +123,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Inkar Suki",
|
||||
"desc": "一个十分方便的Bot,支持包括Webhook、群管、互动等一系列功能",
|
||||
"desc": "一个十分方便的Bot,支持包括Webhook、群管、剑网3等一系列功能,持续更新中……",
|
||||
"author": "HornCopper",
|
||||
"homepage": "https://github.com/HornCopper/Inkar-Suki",
|
||||
"tags": [
|
||||
@@ -136,8 +136,8 @@
|
||||
"color": "#374fd0"
|
||||
},
|
||||
{
|
||||
"label": "群管",
|
||||
"color": "#4ede39"
|
||||
"label": "剑网3",
|
||||
"color": "#ff0033"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
@@ -276,5 +276,39 @@
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"name": "hsbot",
|
||||
"desc": "服务于《炉石传说》玩家的机器人,上线至今已有加入十余个个炉石相关群聊,上千名用户使用,响应请求数万次。 数据使用:HSreplay, Fbigame, Hearthstone API",
|
||||
"author": "gzy02",
|
||||
"homepage": "https://github.com/gzy02/hsbot",
|
||||
"tags": [
|
||||
{
|
||||
"label": "炉石传说",
|
||||
"color": "#526fea"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"name": "Bread Dog Bot",
|
||||
"desc": "Terraria TShock QQ 机器人",
|
||||
"author": "Qianyiovo",
|
||||
"homepage": "https://github.com/Qianyiovo/bread_dog_bot",
|
||||
"tags": [
|
||||
{
|
||||
"label": "TShock",
|
||||
"color": "#ea5252"
|
||||
},
|
||||
{
|
||||
"label": "泰拉瑞亚",
|
||||
"color": "#5dea52"
|
||||
},
|
||||
{
|
||||
"label": "Terraria",
|
||||
"color": "#5dea52"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@@ -2426,10 +2426,10 @@
|
||||
"name": "MagiaDice骰娘及TRPGLOG",
|
||||
"desc": "能够实时在网页围观的TRPG记录插件,同时具有骰娘的功能",
|
||||
"author": "sena-nana",
|
||||
"homepage": "https://github.com/sena-nana/MutsukiBot/tree/main/nonebot-plugin-magiadice",
|
||||
"homepage": "https://github.com/sena-nana/nonebot-plugin-magiadice",
|
||||
"tags": [
|
||||
{
|
||||
"label": "TRPG",
|
||||
"label": "t:TRPG",
|
||||
"color": "#ea5252"
|
||||
}
|
||||
],
|
||||
@@ -2439,20 +2439,20 @@
|
||||
"module_name": "nonebot-plugin-send",
|
||||
"project_link": "nonebot-plugin-send",
|
||||
"name": "反馈及通知",
|
||||
"desc": "用户通过bot向superuser发送反馈,以及bot向全群发送通知",
|
||||
"desc": "用户通过bot向superuser发送反馈,以及bot向所有群发送通知",
|
||||
"author": "sena-nana",
|
||||
"homepage": "https://github.com/sena-nana/MutsukiBot/tree/main/nonebot-plugin-send",
|
||||
"homepage": "https://github.com/sena-nana/nonebot-plugin-send",
|
||||
"tags": [
|
||||
{
|
||||
"label": "send",
|
||||
"label": "t:send",
|
||||
"color": "#ea5252"
|
||||
},
|
||||
{
|
||||
"label": "notice",
|
||||
"label": "t:notice",
|
||||
"color": "#ea5252"
|
||||
},
|
||||
{
|
||||
"label": "公告",
|
||||
"label": "t:公告",
|
||||
"color": "#ea5252"
|
||||
}
|
||||
],
|
||||
@@ -2464,10 +2464,10 @@
|
||||
"name": "雨课堂自动签到",
|
||||
"desc": "使用playwright模拟浏览器签到雨课堂,并将腾讯会议号发送给superuser",
|
||||
"author": "sena-nana",
|
||||
"homepage": "https://github.com/sena-nana/MutsukiBot/tree/main/nonebot-plugin-ykt",
|
||||
"homepage": "https://github.com/sena-nana/nonebot-plugin-ykt",
|
||||
"tags": [
|
||||
{
|
||||
"label": "playwright",
|
||||
"label": "t:playwright",
|
||||
"color": "#ea5252"
|
||||
}
|
||||
],
|
||||
@@ -2553,7 +2553,7 @@
|
||||
"name": "MC_QQ_MCRcon",
|
||||
"desc": "基于NoneBot的QQ群聊与Minecraft Server消息互通插件",
|
||||
"author": "17TheWord",
|
||||
"homepage": "https://github.com/17TheWord/nonebot-plugin-mcqq/tree/mcqq_mcrcon",
|
||||
"homepage": "https://github.com/17TheWord/nonebot-plugin-mcqq",
|
||||
"tags": [
|
||||
{
|
||||
"label": "Minecraft",
|
||||
@@ -2697,7 +2697,7 @@
|
||||
"name": "ayaka - 文字游戏开发辅助插件",
|
||||
"desc": "提供了状态机、命令隔离、缓存、固存、帮助指令等功能,可以管理多个文字游戏避免命令冲突,帮助开发者在nonebot2框架基础上快速开发qq文字游戏",
|
||||
"author": "bridgeL",
|
||||
"homepage": "https://github.com/bridgeL/nonebot-plugin-ayaka",
|
||||
"homepage": "https://bridgel.github.io/ayaka_doc/",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:cqhttp",
|
||||
@@ -2877,5 +2877,532 @@
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_listener",
|
||||
"project_link": "nonebot-plugin-listener",
|
||||
"name": "监听者",
|
||||
"desc": "监听指定消息并转发到指定群",
|
||||
"author": "AbCooly",
|
||||
"homepage": "https://github.com/AbCooly/nonebot_plugin_listener",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_BiliRequestAll",
|
||||
"project_link": "nonebot-plugin-BiliRequestAll",
|
||||
"name": "BiliRequestAll",
|
||||
"desc": "通过B站UID审核入群",
|
||||
"author": "Shadow403",
|
||||
"homepage": "https://github.com/Shadow403/nonebot_plugin_BiliRequestAll",
|
||||
"tags": [
|
||||
{
|
||||
"label": "bilibili",
|
||||
"color": "#ea52e9"
|
||||
},
|
||||
{
|
||||
"label": "request",
|
||||
"color": "#5eea52"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot-plugin-masiro",
|
||||
"project_link": "nonebot-plugin-masiro",
|
||||
"name": "真白萌自动签到",
|
||||
"desc": "帮你每天在真白萌签到,助力成为二次元婆罗门!",
|
||||
"author": "Ankhyty",
|
||||
"homepage": "https://github.com/Ankhyty/nonebot-plugin-masiro",
|
||||
"tags": [
|
||||
{
|
||||
"label": "t:漫研",
|
||||
"color": "#1435e4"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_russian_ban",
|
||||
"project_link": "nonebot-plugin-russian-ban",
|
||||
"name": "轮盘禁言小游戏",
|
||||
"desc": "轮盘禁言小游戏,附送快捷禁言/解禁",
|
||||
"author": "KarisAya",
|
||||
"homepage": "https://github.com/KarisAya/nonebot_plugin_russian_ban",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_monitor",
|
||||
"project_link": "nonebot-plugin-monitor",
|
||||
"name": "监测群事件",
|
||||
"desc": "监测群成员变动、文件上传、红包运气王、管理员变动等等...",
|
||||
"author": "cjladmin",
|
||||
"homepage": "https://github.com/cjladmin/nonebot_plugin_monitor",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_ygo_trade",
|
||||
"project_link": "nonebot-plugin-ygo-trade",
|
||||
"name": "游戏王小程序查价",
|
||||
"desc": "集换社游戏王的卡价查询",
|
||||
"author": "Kaguyaya",
|
||||
"homepage": "https://github.com/Kaguyaya/nonebot_plugin_ygo_trade",
|
||||
"tags": [
|
||||
{
|
||||
"label": "游戏王",
|
||||
"color": "#ea5252"
|
||||
},
|
||||
{
|
||||
"label": "YGO",
|
||||
"color": "#ea5252"
|
||||
},
|
||||
{
|
||||
"label": "集换社",
|
||||
"color": "#eada52"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot-plugin-novelai",
|
||||
"project_link": "nonebot-plugin-novelai",
|
||||
"name": "novelai",
|
||||
"desc": "一个支持novelai、naifu、webui,支持中文功能丰富的ai绘图插件",
|
||||
"author": "sena-nana",
|
||||
"homepage": "https://github.com/sena-nana/nonebot-plugin-novelai",
|
||||
"tags": [
|
||||
{
|
||||
"label": "t:aidraw",
|
||||
"color": "#ffc646"
|
||||
},
|
||||
{
|
||||
"label": "t:naifu",
|
||||
"color": "#ffc646"
|
||||
},
|
||||
{
|
||||
"label": "t:webui",
|
||||
"color": "#ffc646"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_aidraw",
|
||||
"project_link": "nonebot-plugin-aidraw",
|
||||
"name": "AI绘图",
|
||||
"desc": "使用第三方 API 的 NovelAI 绘图插件",
|
||||
"author": "A-kirami",
|
||||
"homepage": "https://github.com/A-kirami/nonebot-plugin-aidraw",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_bnhhsh",
|
||||
"project_link": "nonebot-plugin-bnhhsh",
|
||||
"name": "bnhhsh -「不能好好说话!」",
|
||||
"desc": "不对劲的拼音首字母缩写翻译工具 | 基于 RimoChan/bnhhsh",
|
||||
"author": "lgc2333",
|
||||
"homepage": "https://github.com/lgc2333/nonebot-plugin-bnhhsh",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:OB V11",
|
||||
"color": "#000000"
|
||||
},
|
||||
{
|
||||
"label": "t:涩涩!",
|
||||
"color": "#ffc646"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "ayaka_games",
|
||||
"project_link": "nonebot-plugin-ayaka-games",
|
||||
"name": "ayaka衍生插件 - 小游戏合集",
|
||||
"desc": "多功能聚合,基于ayaka插件实现:背包、 签到 、印加宝藏、生成糊文字截图、bingo、b站视频链接分析、原神接龙、成语接龙、缩写翻译",
|
||||
"author": "bridgeL",
|
||||
"homepage": "https://github.com/bridgeL/nonebot-plugin-ayaka-games",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:cqhttp",
|
||||
"color": "#0c0c0c"
|
||||
},
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#0c0c0c"
|
||||
},
|
||||
{
|
||||
"label": "t:文字游戏",
|
||||
"color": "#e36306"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "ayaka_who_is_suspect",
|
||||
"project_link": "nonebot-plugin-ayaka-who-is-suspect",
|
||||
"name": "ayaka衍生插件 - 谁是卧底",
|
||||
"desc": "至少4人游玩,游玩前需要加bot好友,否则无法通过私聊告知关键词",
|
||||
"author": "bridgeL",
|
||||
"homepage": "https://github.com/bridgeL/nonebot-plugin-ayaka-who-is-suspect",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:cqhttp",
|
||||
"color": "#000000"
|
||||
},
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#000000"
|
||||
},
|
||||
{
|
||||
"label": "t:文字游戏",
|
||||
"color": "#e36306"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "ayaka_timezone",
|
||||
"project_link": "nonebot-plugin-ayaka-timezone",
|
||||
"name": "ayaka衍生插件 - 时区助手",
|
||||
"desc": "提供不同时区时间询问服务",
|
||||
"author": "bridgeL",
|
||||
"homepage": "https://github.com/bridgeL/nonebot-plugin-ayaka-timezone",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:cqhttp",
|
||||
"color": "#000000"
|
||||
},
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#000000"
|
||||
},
|
||||
{
|
||||
"label": "t:timezone",
|
||||
"color": "#e36306"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "ayaka_prevent_bad_words",
|
||||
"project_link": "nonebot-plugin-ayaka-prevent-bad-words",
|
||||
"name": "ayaka衍生插件 - 坏词撤回",
|
||||
"desc": "撤回有问题的发言",
|
||||
"author": "bridgeL",
|
||||
"homepage": "https://github.com/bridgeL/nonebot-plugin-ayaka-prevent-bad-words",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:cqhttp",
|
||||
"color": "#000000"
|
||||
},
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#000000"
|
||||
},
|
||||
{
|
||||
"label": "t:撤回",
|
||||
"color": "#e36306"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_savor",
|
||||
"project_link": "nonebot-plugin-savor",
|
||||
"name": "二次元图像鉴赏",
|
||||
"desc": "二次元图像分析",
|
||||
"author": "A-kirami",
|
||||
"homepage": "https://github.com/A-kirami/nonebot-plugin-savor",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_kfcrazy",
|
||||
"project_link": "nonebot-plugin-kfcrazy",
|
||||
"name": "kfcrazy",
|
||||
"desc": "肯德基查询插件,输入地区即可查询全国店铺的数据,支持疯狂星期四",
|
||||
"author": "Kaguya233qwq",
|
||||
"homepage": "https://github.com/Kaguya233qwq/nonebot_plugin_kfcrazy",
|
||||
"tags": [
|
||||
{
|
||||
"label": "肯德基",
|
||||
"color": "#d93b3b"
|
||||
},
|
||||
{
|
||||
"label": "疯狂星期四",
|
||||
"color": "#e52124"
|
||||
},
|
||||
{
|
||||
"label": "KFC",
|
||||
"color": "#cb5c5e"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot-plugin-random",
|
||||
"project_link": "nonebot-plugin-random",
|
||||
"name": "通用抽图/语音",
|
||||
"desc": "Nonebot2 通用抽图/语音插件",
|
||||
"author": "jcjrobert",
|
||||
"homepage": "https://github.com/jcjrobert/nonebot-plugin-random",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_sqlalchemy",
|
||||
"project_link": "nonebot-plugin-sqlalchemy",
|
||||
"name": "NoneBot SQLAlchemy封装",
|
||||
"desc": "提供简单的sqlalchemy封装",
|
||||
"author": "ssttkkl",
|
||||
"homepage": "https://github.com/ssttkkl/nonebot-plugin-sqlalchemy",
|
||||
"tags": [
|
||||
{
|
||||
"label": "t:sql",
|
||||
"color": "#ad1717"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_blacklist",
|
||||
"project_link": "nonebot-plugin-blacklist",
|
||||
"name": "用户&群聊黑名单",
|
||||
"desc": "另一个黑名单插件, 可批量屏蔽用户和群聊",
|
||||
"author": "tkgs0",
|
||||
"homepage": "https://github.com/tkgs0/nonebot-plugin-blacklist",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_antiinsult",
|
||||
"project_link": "nonebot-plugin-antiinsult",
|
||||
"name": "反嘴臭插件",
|
||||
"desc": "检测到有用户 @机器人 并嘴臭时将其临时屏蔽(bot重启后失效), 当bot为群管理时会请对方喝昏睡红茶(禁言), 可批量增删敏感词",
|
||||
"author": "tkgs0",
|
||||
"homepage": "https://github.com/tkgs0/nonebot-plugin-antiinsult",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#000000"
|
||||
},
|
||||
{
|
||||
"label": "t:被动",
|
||||
"color": "#ea5252"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_oddtext",
|
||||
"project_link": "nonebot-plugin-oddtext",
|
||||
"name": "文本生成器",
|
||||
"desc": "抽象话、火星文等多种文本生成",
|
||||
"author": "MeetWq",
|
||||
"homepage": "https://github.com/noneplugin/nonebot-plugin-oddtext",
|
||||
"tags": [
|
||||
{
|
||||
"label": "t:RCNB!",
|
||||
"color": "#ea5252"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_mahjong_scoreboard",
|
||||
"project_link": "nonebot-plugin-mahjong-scoreboard",
|
||||
"name": "日麻寄分器",
|
||||
"desc": "为群友提供日麻对局分数记录。根据马点进行PT精算,统计PT增减,支持对局与榜单查询与导出。",
|
||||
"author": "ssttkkl",
|
||||
"homepage": "https://github.com/ssttkkl/nonebot-plugin-mahjong-scoreboard",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#4684d3"
|
||||
},
|
||||
{
|
||||
"label": "t:日麻",
|
||||
"color": "#4684d3"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_cartoon",
|
||||
"project_link": "nonebot-plugin-cartoon",
|
||||
"name": "二次元化图像",
|
||||
"desc": "对三次元图像动漫化, 打开二次元的大门",
|
||||
"author": "A-kirami",
|
||||
"homepage": "https://github.com/A-kirami/nonebot-plugin-cartoon",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_super_resolution",
|
||||
"project_link": "nonebot-plugin-super-resolution",
|
||||
"name": "图像超分辨率增强",
|
||||
"desc": "动漫图像超分辨率增强",
|
||||
"author": "A-kirami",
|
||||
"homepage": "https://github.com/A-kirami/nonebot-plugin-super-resolution",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_mahjong_utils",
|
||||
"project_link": "nonebot-plugin-mahjong-utils",
|
||||
"name": "日麻小工具",
|
||||
"desc": "日麻小工具插件,支持手牌分析、番符点数查询",
|
||||
"author": "ssttkkl",
|
||||
"homepage": "https://github.com/ssttkkl/nonebot-plugin-mahjong-utils",
|
||||
"tags": [
|
||||
{
|
||||
"label": "t:日麻",
|
||||
"color": "#edad34"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_animeres",
|
||||
"project_link": "nonebot-plugin-animeres",
|
||||
"name": "动漫资源获取",
|
||||
"desc": "动漫资源获取",
|
||||
"author": "Melodyknit",
|
||||
"homepage": "https://github.com/Melodyknit/nonebot_plugin_animeres",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#ec5252"
|
||||
},
|
||||
{
|
||||
"label": "anime",
|
||||
"color": "#ec5252"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot-plugin-person",
|
||||
"project_link": "nonebot-plugin-person",
|
||||
"name": "随个人",
|
||||
"desc": "随个群友当幸运观众🤪",
|
||||
"author": "jcjrobert",
|
||||
"homepage": "https://github.com/jcjrobert/nonebot-plugin-person",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_apex_api_query",
|
||||
"project_link": "nonebot-plugin-apex-api-query",
|
||||
"name": "Apex API Query",
|
||||
"desc": "Apex Legends API 查询插件",
|
||||
"author": "H-xiaoH",
|
||||
"homepage": "https://github.com/H-xiaoH/nonebot-plugin-apex-api-query",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_reborn",
|
||||
"project_link": "nonebot-plugin-reborn",
|
||||
"name": "投胎模拟器",
|
||||
"desc": "重生后你会到哪里?",
|
||||
"author": "Aziteee",
|
||||
"homepage": "https://github.com/Aziteee/nonebot_plugin_reborn",
|
||||
"tags": [],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_searchBiliInfo",
|
||||
"project_link": "nonebot-plugin-searchBiliInfo",
|
||||
"name": "b站用户信息查询",
|
||||
"desc": "查询b站用户粉丝数、舰团信息;主播直播收益数据(总收益、礼物、SC、上舰);用户观看直播信息(观看、弹幕记录);通过关键词搜昵称、UID等",
|
||||
"author": "Ikaros-521",
|
||||
"homepage": "https://github.com/Ikaros-521/nonebot_plugin_searchBiliInfo",
|
||||
"tags": [
|
||||
{
|
||||
"label": "bilibili",
|
||||
"color": "#e55d80"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_colab_novelai",
|
||||
"project_link": "nonebot-plugin-colab-novelai",
|
||||
"name": "Colab-NovelAI",
|
||||
"desc": "解放你的双手,让Colab持续给你提供算力生产色图!",
|
||||
"author": "EtherLeaF",
|
||||
"homepage": "https://github.com/EtherLeaF/nonebot-plugin-colab-novelai",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#ea5252"
|
||||
},
|
||||
{
|
||||
"label": "t:NovelAI",
|
||||
"color": "#eacd52"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_sky",
|
||||
"project_link": "nonebot-plugin-sky",
|
||||
"name": "sky光遇",
|
||||
"desc": "基于NoneBot2的光遇每日攻略插件",
|
||||
"author": "Kaguya233qwq",
|
||||
"homepage": "https://github.com/Kaguya233qwq/nonebot_plugin_sky",
|
||||
"tags": [
|
||||
{
|
||||
"label": "光遇",
|
||||
"color": "#7ebdf0"
|
||||
},
|
||||
{
|
||||
"label": "攻略",
|
||||
"color": "#2079c1"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_zyk_novelai",
|
||||
"project_link": "nonebot-plugin-zyk-novelai",
|
||||
"name": "免费版NovelAI生图插件",
|
||||
"desc": "一个用于nonebot2的简约AI绘图插件。没有繁琐的使用指令,配置过程简单迅捷,代码简洁易懂,还有更多功能将会陆续加入。",
|
||||
"author": "ZYKsslm",
|
||||
"homepage": "https://github.com/ZYKsslm/nonebot_plugin_zyk_novelai",
|
||||
"tags": [
|
||||
{
|
||||
"label": "Free",
|
||||
"color": "#42e22f"
|
||||
},
|
||||
{
|
||||
"label": "Simple",
|
||||
"color": "#e2d92f"
|
||||
},
|
||||
{
|
||||
"label": "Novelai",
|
||||
"color": "#3e10e9"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_repeep",
|
||||
"project_link": "nonebot-plugin-repeep",
|
||||
"name": "谁在窥屏",
|
||||
"desc": "用于获取QQ中当前窥屏用户信息",
|
||||
"author": "p0ise",
|
||||
"homepage": "https://github.com/p0ise/nonebot-plugin-repeep",
|
||||
"tags": [
|
||||
{
|
||||
"label": "a:onebot",
|
||||
"color": "#ea5252"
|
||||
}
|
||||
],
|
||||
"is_official": false
|
||||
}
|
||||
]
|
||||
]
|
||||
|
Before Width: | Height: | Size: 376 KiB After Width: | Height: | Size: 376 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
@@ -21,7 +21,7 @@ NoneBot 使用 [`pydantic`](https://pydantic-docs.helpmanual.io/) 以及 [`pytho
|
||||
|
||||
- **参数**
|
||||
|
||||
- `_env_file` (str | os.PathLike | NoneType)
|
||||
- `_env_file` (str | os.PathLike | list[str | os.PathLike] | tuple[str | os.PathLike, ...] | NoneType)
|
||||
|
||||
- `_env_file_encoding` (str | None)
|
||||
|
||||
@@ -56,7 +56,7 @@ NoneBot 使用 [`pydantic`](https://pydantic-docs.helpmanual.io/) 以及 [`pytho
|
||||
|
||||
- **参数**
|
||||
|
||||
- `_env_file` (str | os.PathLike | NoneType)
|
||||
- `_env_file` (str | os.PathLike | list[str | os.PathLike] | tuple[str | os.PathLike, ...] | NoneType)
|
||||
|
||||
- `_env_file_encoding` (str | None)
|
||||
|
||||
@@ -72,7 +72,7 @@ NoneBot 使用 [`pydantic`](https://pydantic-docs.helpmanual.io/) 以及 [`pytho
|
||||
|
||||
- `log_level` (int | str)
|
||||
|
||||
- `api_timeout` (float)
|
||||
- `api_timeout` (float | None)
|
||||
|
||||
- `superusers` (set[str])
|
||||
|
@@ -96,3 +96,27 @@ description: nonebot.consts 模块
|
||||
- **类型:** Literal['_matched_dict']
|
||||
|
||||
- **说明:** 正则匹配 group 字典存储 key
|
||||
|
||||
## _var_ `STARTSWITH_KEY` {#STARTSWITH_KEY}
|
||||
|
||||
- **类型:** Literal['_startswith']
|
||||
|
||||
- **说明:** 响应触发前缀 key
|
||||
|
||||
## _var_ `ENDSWITH_KEY` {#ENDSWITH_KEY}
|
||||
|
||||
- **类型:** Literal['_endswith']
|
||||
|
||||
- **说明:** 响应触发后缀 key
|
||||
|
||||
## _var_ `FULLMATCH_KEY` {#FULLMATCH_KEY}
|
||||
|
||||
- **类型:** Literal['_fullmatch']
|
||||
|
||||
- **说明:** 响应触发完整消息 key
|
||||
|
||||
## _var_ `KEYWORD_KEY` {#KEYWORD_KEY}
|
||||
|
||||
- **类型:** Literal['_keyword']
|
||||
|
||||
- **说明:** 响应触发关键字 key
|
@@ -19,7 +19,7 @@ description: nonebot.drivers.fastapi 模块
|
||||
|
||||
- **参数**
|
||||
|
||||
- `_env_file` (str | os.PathLike | NoneType)
|
||||
- `_env_file` (str | os.PathLike | list[str | os.PathLike] | tuple[str | os.PathLike, ...] | NoneType)
|
||||
|
||||
- `_env_file_encoding` (str | None)
|
||||
|
||||
@@ -27,23 +27,23 @@ description: nonebot.drivers.fastapi 模块
|
||||
|
||||
- `_secrets_dir` (str | os.PathLike | NoneType)
|
||||
|
||||
- `fastapi_openapi_url` (str)
|
||||
- `fastapi_openapi_url` (str | None)
|
||||
|
||||
- `fastapi_docs_url` (str)
|
||||
- `fastapi_docs_url` (str | None)
|
||||
|
||||
- `fastapi_redoc_url` (str)
|
||||
- `fastapi_redoc_url` (str | None)
|
||||
|
||||
- `fastapi_include_adapter_schema` (bool)
|
||||
|
||||
- `fastapi_reload` (bool)
|
||||
|
||||
- `fastapi_reload_dirs` (list[str])
|
||||
- `fastapi_reload_dirs` (list[str] | None)
|
||||
|
||||
- `fastapi_reload_delay` (float)
|
||||
|
||||
- `fastapi_reload_includes` (list[str])
|
||||
- `fastapi_reload_includes` (list[str] | None)
|
||||
|
||||
- `fastapi_reload_excludes` (list[str])
|
||||
- `fastapi_reload_excludes` (list[str] | None)
|
||||
|
||||
### _class-var_ `fastapi_openapi_url` {#Config-fastapi_openapi_url}
|
||||
|
@@ -25,7 +25,7 @@ pip install nonebot2[quart]
|
||||
|
||||
- **参数**
|
||||
|
||||
- `_env_file` (str | os.PathLike | NoneType)
|
||||
- `_env_file` (str | os.PathLike | list[str | os.PathLike] | tuple[str | os.PathLike, ...] | NoneType)
|
||||
|
||||
- `_env_file_encoding` (str | None)
|
||||
|
||||
@@ -35,13 +35,13 @@ pip install nonebot2[quart]
|
||||
|
||||
- `quart_reload` (bool)
|
||||
|
||||
- `quart_reload_dirs` (list[str])
|
||||
- `quart_reload_dirs` (list[str] | None)
|
||||
|
||||
- `quart_reload_delay` (float)
|
||||
|
||||
- `quart_reload_includes` (list[str])
|
||||
- `quart_reload_includes` (list[str] | None)
|
||||
|
||||
- `quart_reload_excludes` (list[str])
|
||||
- `quart_reload_excludes` (list[str] | None)
|
||||
|
||||
### _class-var_ `quart_reload` {#Config-quart_reload}
|
||||
|
@@ -170,7 +170,7 @@ description: nonebot 模块
|
||||
|
||||
- **参数**
|
||||
|
||||
- `_env_file` (str | None): 配置文件名,默认从 `.env.{env_name}` 中读取配置
|
||||
- `_env_file` (str | os.PathLike | list[str | os.PathLike] | tuple[str | os.PathLike, ...] | NoneType): 配置文件名,默认从 `.env.{env_name}` 中读取配置
|
||||
|
||||
- `**kwargs` (Any): 任意变量,将会存储到 {ref}`nonebot.drivers.Driver.config` 对象里
|
||||
|
@@ -67,6 +67,18 @@ description: nonebot.matcher 模块
|
||||
|
||||
- bool: 是否满足匹配规则
|
||||
|
||||
### _method_ `ensure_context(self, bot, event)` {#Matcher-ensure_context}
|
||||
|
||||
- **参数**
|
||||
|
||||
- `bot` (nonebot.internal.adapter.bot.Bot)
|
||||
|
||||
- `event` (nonebot.internal.adapter.event.Event)
|
||||
|
||||
- **返回**
|
||||
|
||||
- Unknown
|
||||
|
||||
### _async classmethod_ `finish(cls, message=None, **kwargs)` {#Matcher-finish}
|
||||
|
||||
- **说明**
|
||||
@@ -479,3 +491,115 @@ description: nonebot.matcher 模块
|
||||
- **返回**
|
||||
|
||||
- str
|
||||
|
||||
## _class_ `MatcherManager()` {#MatcherManager}
|
||||
|
||||
- **说明**
|
||||
|
||||
事件响应器管理器
|
||||
|
||||
实现了常用字典操作,用于管理事件响应器。
|
||||
|
||||
### _method_ `clear(self)` {#MatcherManager-clear}
|
||||
|
||||
- **返回**
|
||||
|
||||
- None
|
||||
|
||||
### _method_ `get(self, key, default=None)` {#MatcherManager-get}
|
||||
|
||||
- **参数**
|
||||
|
||||
- `key` (int)
|
||||
|
||||
- `default` ((~ T) | None)
|
||||
|
||||
- **返回**
|
||||
|
||||
- list[Type[Matcher]] | (~ T) | NoneType
|
||||
|
||||
### _method_ `items(self)` {#MatcherManager-items}
|
||||
|
||||
- **返回**
|
||||
|
||||
- ItemsView[int, list[Type[Matcher]]]
|
||||
|
||||
### _method_ `keys(self)` {#MatcherManager-keys}
|
||||
|
||||
- **返回**
|
||||
|
||||
- KeysView[int]
|
||||
|
||||
### _method_ `pop(self, key)` {#MatcherManager-pop}
|
||||
|
||||
- **参数**
|
||||
|
||||
- `key` (int)
|
||||
|
||||
- **返回**
|
||||
|
||||
- list[Type[Matcher]]
|
||||
|
||||
### _method_ `popitem(self)` {#MatcherManager-popitem}
|
||||
|
||||
- **返回**
|
||||
|
||||
- tuple[int, list[Type[Matcher]]]
|
||||
|
||||
### _method_ `set_provider(self, provider_class)` {#MatcherManager-set_provider}
|
||||
|
||||
- **说明**
|
||||
|
||||
设置事件响应器存储器
|
||||
|
||||
- **参数**
|
||||
|
||||
- `provider_class` (Type[nonebot.internal.matcher.provider.MatcherProvider]): 事件响应器存储器类
|
||||
|
||||
- **返回**
|
||||
|
||||
- None
|
||||
|
||||
### _method_ `setdefault(self, key, default)` {#MatcherManager-setdefault}
|
||||
|
||||
- **参数**
|
||||
|
||||
- `key` (int)
|
||||
|
||||
- `default` (list[Type[Matcher]])
|
||||
|
||||
- **返回**
|
||||
|
||||
- list[Type[Matcher]]
|
||||
|
||||
### _method_ `update(self, _MatcherManager__m)` {#MatcherManager-update}
|
||||
|
||||
- **参数**
|
||||
|
||||
- `_MatcherManager__m` (MutableMapping[int, list[Type[Matcher]]])
|
||||
|
||||
- **返回**
|
||||
|
||||
- None
|
||||
|
||||
### _method_ `values(self)` {#MatcherManager-values}
|
||||
|
||||
- **返回**
|
||||
|
||||
- ValuesView[list[Type[Matcher]]]
|
||||
|
||||
## _abstract class_ `MatcherProvider(matchers)` {#MatcherProvider}
|
||||
|
||||
- **说明**
|
||||
|
||||
事件响应器存储器基类
|
||||
|
||||
- **参数**
|
||||
|
||||
- `matchers` (Mapping[int, list[Type[Matcher]]]): 当前存储器中已有的事件响应器
|
||||
|
||||
## _class_ `DEFAULT_PROVIDER_CLASS(matchers)` {#DEFAULT_PROVIDER_CLASS}
|
||||
|
||||
- **参数**
|
||||
|
||||
- `matchers` (Mapping[int, list[Type[Matcher]]])
|
@@ -307,6 +307,46 @@ description: nonebot.params 模块
|
||||
|
||||
- dict[str, Any]
|
||||
|
||||
## _def_ `Startswith()` {#Startswith}
|
||||
|
||||
- **说明**
|
||||
|
||||
响应触发前缀
|
||||
|
||||
- **返回**
|
||||
|
||||
- str
|
||||
|
||||
## _def_ `Endswith()` {#Endswith}
|
||||
|
||||
- **说明**
|
||||
|
||||
响应触发后缀
|
||||
|
||||
- **返回**
|
||||
|
||||
- str
|
||||
|
||||
## _def_ `Fullmatch()` {#Fullmatch}
|
||||
|
||||
- **说明**
|
||||
|
||||
响应触发完整消息
|
||||
|
||||
- **返回**
|
||||
|
||||
- str
|
||||
|
||||
## _def_ `Keyword()` {#Keyword}
|
||||
|
||||
- **说明**
|
||||
|
||||
响应触发关键字
|
||||
|
||||
- **返回**
|
||||
|
||||
- str
|
||||
|
||||
## _def_ `Received(id=None, default=None)` {#Received}
|
||||
|
||||
- **说明**
|
@@ -35,7 +35,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_metaevent(rule=..., *, handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_metaevent}
|
||||
|
||||
@@ -61,7 +61,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_message(rule=..., permission=..., *, handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_message}
|
||||
|
||||
@@ -89,7 +89,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_notice(rule=..., *, handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_notice}
|
||||
|
||||
@@ -115,7 +115,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_request(rule=..., *, handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_request}
|
||||
|
||||
@@ -141,7 +141,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_startswith(msg, rule=..., ignorecase=..., *, permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_startswith}
|
||||
|
||||
@@ -173,7 +173,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_endswith(msg, rule=..., ignorecase=..., *, permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_endswith}
|
||||
|
||||
@@ -205,7 +205,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_fullmatch(msg, rule=..., ignorecase=..., *, permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_fullmatch}
|
||||
|
||||
@@ -237,7 +237,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_keyword(keywords, rule=..., *, permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_keyword}
|
||||
|
||||
@@ -267,7 +267,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_command(cmd, rule=..., aliases=..., *, permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_command}
|
||||
|
||||
@@ -301,7 +301,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_shell_command(cmd, rule=..., aliases=..., parser=..., *, permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_shell_command}
|
||||
|
||||
@@ -339,7 +339,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_regex(pattern, flags=..., rule=..., *, permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_regex}
|
||||
|
||||
@@ -373,7 +373,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _def_ `on_type(types, rule=..., *, permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#on_type}
|
||||
|
||||
@@ -403,7 +403,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _class_ `CommandGroup(cmd, *, rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#CommandGroup}
|
||||
|
||||
@@ -457,7 +457,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `shell_command(self, cmd, *, rule=..., aliases=..., parser=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#CommandGroup-shell_command}
|
||||
|
||||
@@ -491,7 +491,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
## _class_ `MatcherGroup(*, type=..., rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup}
|
||||
|
||||
@@ -543,7 +543,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_command(self, cmd, aliases=..., *, rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_command}
|
||||
|
||||
@@ -577,7 +577,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_endswith(self, msg, *, ignorecase=..., rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_endswith}
|
||||
|
||||
@@ -609,7 +609,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_fullmatch(self, msg, *, ignorecase=..., rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_fullmatch}
|
||||
|
||||
@@ -641,7 +641,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_keyword(self, keywords, *, rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_keyword}
|
||||
|
||||
@@ -671,7 +671,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_message(self, *, rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_message}
|
||||
|
||||
@@ -699,7 +699,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_metaevent(self, *, rule=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_metaevent}
|
||||
|
||||
@@ -725,7 +725,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_notice(self, *, rule=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_notice}
|
||||
|
||||
@@ -751,7 +751,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_regex(self, pattern, flags=..., *, rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_regex}
|
||||
|
||||
@@ -785,7 +785,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_request(self, *, rule=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_request}
|
||||
|
||||
@@ -811,7 +811,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_shell_command(self, cmd, aliases=..., parser=..., *, rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_shell_command}
|
||||
|
||||
@@ -849,7 +849,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_startswith(self, msg, *, ignorecase=..., rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_startswith}
|
||||
|
||||
@@ -881,7 +881,7 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
||||
|
||||
### _method_ `on_type(self, types, *, rule=..., permission=..., handlers=..., temp=..., expire_time=..., priority=..., block=..., state=...)` {#MatcherGroup-on_type}
|
||||
|
||||
@@ -911,4 +911,4 @@ description: nonebot.plugin.on 模块
|
||||
|
||||
- **返回**
|
||||
|
||||
- Type[nonebot.internal.matcher.Matcher]
|
||||
- Type[nonebot.internal.matcher.matcher.Matcher]
|
@@ -65,7 +65,7 @@ description: nonebot.plugin.plugin 模块
|
||||
|
||||
- `manager` (PluginManager)
|
||||
|
||||
- `matcher` (set[Type[nonebot.internal.matcher.Matcher]])
|
||||
- `matcher` (set[Type[nonebot.internal.matcher.matcher.Matcher]])
|
||||
|
||||
- `parent_plugin` (Plugin | None)
|
||||
|
||||
@@ -105,7 +105,7 @@ description: nonebot.plugin.plugin 模块
|
||||
|
||||
### _instance-var_ `matcher` {#Plugin-matcher}
|
||||
|
||||
- **类型:** set[Type[nonebot.internal.matcher.Matcher]]
|
||||
- **类型:** set[Type[nonebot.internal.matcher.matcher.Matcher]]
|
||||
|
||||
- **说明:** 插件内定义的 `Matcher`
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user