33
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report to help us improve
|
||||
title: 'Bug: Something went wrong'
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**描述问题:**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**如何复现?**
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**期望的结果**
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**环境信息:**
|
||||
|
||||
- OS: [e.g. Linux]
|
||||
- Python Version: [e.g. 3.8]
|
||||
- Nonebot Version [e.g. 2.0.0]
|
||||
|
||||
**截图**
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: 'Feature: Something you want'
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**是否在使用中遇到某些问题而需要新的特性?请描述:**
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**描述你所需要的特性:**
|
||||
|
||||
A clear and concise description of what you want to happen.
|
36
.github/ISSUE_TEMPLATE/plugin-publish.md
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
name: Plugin Publish
|
||||
about: Publish your plugin to nonebot homepage and nb-cli
|
||||
title: "Plugin: blabla 的插件"
|
||||
labels: Plugin
|
||||
assignees: ""
|
||||
|
||||
---
|
||||
|
||||
**你的插件名称:**
|
||||
|
||||
例:复读机
|
||||
|
||||
**简短描述插件功能:**
|
||||
|
||||
例:复读群友的消息
|
||||
|
||||
**插件 import 使用的名称**
|
||||
|
||||
例:nonebot-plugin-example
|
||||
|
||||
**插件 install 使用的名称**
|
||||
|
||||
例 1:nonebot-plugin-example
|
||||
|
||||
通过 pypi 安装
|
||||
|
||||
> 请事先发布插件到[pypi](https://pypi.org/)
|
||||
|
||||
例 2:git+https://github.com/nonebot/nonebot-plugin-example
|
||||
|
||||
从 github 仓库安装
|
||||
|
||||
**插件项目仓库/主页链接**
|
||||
|
||||
例:nonebot/nonebot2(默认 github )或其他链接
|
31
.github/release-drafter.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
name-template: 'v$RESOLVED_VERSION 🌈'
|
||||
tag-template: 'v$RESOLVED_VERSION'
|
||||
categories:
|
||||
- title: '🚀 Features'
|
||||
labels:
|
||||
- 'feature'
|
||||
- 'enhancement'
|
||||
- title: '🐛 Bug Fixes'
|
||||
labels:
|
||||
- 'fix'
|
||||
- 'bugfix'
|
||||
- 'bug'
|
||||
- title: '🧰 Maintenance'
|
||||
label: 'chore'
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
||||
version-resolver:
|
||||
major:
|
||||
labels:
|
||||
- 'major'
|
||||
minor:
|
||||
labels:
|
||||
- 'minor'
|
||||
patch:
|
||||
labels:
|
||||
- 'patch'
|
||||
default: patch
|
||||
template: |
|
||||
## Changes
|
||||
|
||||
$CHANGES
|
3
.github/workflows/api_docs.yml
vendored
@ -1,7 +1,7 @@
|
||||
name: Build API Doc
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
types: [ opened, synchronize, reopened ]
|
||||
|
||||
jobs:
|
||||
@ -12,6 +12,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
|
14
.github/workflows/release-draft.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
name: Release Drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
52
README.md
@ -1,19 +1,46 @@
|
||||
<div align=center>
|
||||
<img src="./docs/.vuepress/public/logo.png" width="200" height="200">
|
||||
<p align="center">
|
||||
<a href="https://v2.nonebot.dev/"><img src="https://raw.githubusercontent.com/nonebot/nonebot2/master/docs/.vuepress/public/logo.png" width="200" height="200" alt="nonebot"></a>
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
|
||||
# NoneBot
|
||||
|
||||
[![License](https://img.shields.io/github/license/nonebot/nonebot2.svg)](LICENSE)
|
||||
[![PyPI](https://img.shields.io/pypi/v/nonebot2.svg)](https://pypi.python.org/pypi/nonebot2)
|
||||
![Python Version](https://img.shields.io/badge/python-3.7+-blue.svg)
|
||||
![CQHTTP Version](https://img.shields.io/badge/cqhttp-11+-black.svg)
|
||||
[![QQ 群](https://img.shields.io/badge/qq%E7%BE%A4-768887710-orange.svg)](https://jq.qq.com/?_wv=1027&k=5OFifDh)
|
||||
[![Telegram](https://img.shields.io/badge/telegram-chat-blue.svg)](https://t.me/cqhttp)
|
||||
[![QQ 版本发布群](https://img.shields.io/badge/%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E7%BE%A4-218529254-green.svg)](https://jq.qq.com/?_wv=1027&k=5Nl0zhE)
|
||||
[![Telegram 版本发布频道](https://img.shields.io/badge/%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E9%A2%91%E9%81%93-join-green.svg)](https://t.me/cqhttp_release)
|
||||
_✨ Python 异步机器人框架 ✨_
|
||||
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://raw.githubusercontent.com/nonebot/nonebot2/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/nonebot/nonebot2.svg" alt="license">
|
||||
</a>
|
||||
<a href="https://pypi.python.org/pypi/nonebot2">
|
||||
<img src="https://img.shields.io/pypi/v/nonebot2.svg" alt="pypi">
|
||||
</a>
|
||||
<img src="https://img.shields.io/badge/python-3.7+-blue.svg" alt="python">
|
||||
<img src="https://img.shields.io/badge/cqhttp-11+-black.svg" alt="cqhttp"><br />
|
||||
<a href="https://jq.qq.com/?_wv=1027&k=5OFifDh">
|
||||
<img src="https://img.shields.io/badge/qq%E7%BE%A4-768887710-orange.svg" alt="QQ Chat">
|
||||
</a>
|
||||
<a href="https://t.me/cqhttp">
|
||||
<img src="https://img.shields.io/badge/telegram-chat-blue.svg" alt="Telegram Chat">
|
||||
</a>
|
||||
<a href="https://jq.qq.com/?_wv=1027&k=5Nl0zhE">
|
||||
<img src="https://img.shields.io/badge/%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E7%BE%A4-218529254-green.svg" alt="QQ Release">
|
||||
</a>
|
||||
<a href="https://t.me/cqhttp_release">
|
||||
<img src="https://img.shields.io/badge/版本发布频道-join-green.svg" alt="Telegram Release">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://v2.nonebot.dev/">文档</a>
|
||||
·
|
||||
<a href="https://v2.nonebot.dev/guide/installation.html">安装</a>
|
||||
·
|
||||
<a href="https://v2.nonebot.dev/guide/getting-started.html">开始使用</a>
|
||||
</p>
|
||||
|
||||
## 简介
|
||||
|
||||
NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人收到的消息进行解析和处理,并以插件化的形式,分发给消息所对应的命令处理器和自然语言处理器,来完成具体的功能。
|
||||
@ -26,6 +53,11 @@ NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人
|
||||
|
||||
需要注意的是,NoneBot 仅支持 Python 3.7+ 及 CQHTTP(OneBot) 插件 v11+。
|
||||
|
||||
此外,NoneBot2 还有可配套使用的额外脚手架/框架:
|
||||
|
||||
- [NB-CLI](https://github.com/nonebot/nb-cli)
|
||||
- [NoneBot-Test](https://github.com/nonebot/nonebot-test)
|
||||
|
||||
## 文档
|
||||
|
||||
文档目前尚未完成,「API」部分由 sphinx 自动生成,你可以在 [这里](https://v2.nonebot.dev/) 查看。
|
||||
|
@ -1,41 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.adapters 模块
|
||||
|
||||
|
||||
## _class_ `BaseBot`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
|
||||
## _class_ `BaseEvent`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
|
||||
### `_raw_event`
|
||||
|
||||
原始 event
|
||||
|
||||
|
||||
## _class_ `BaseMessageSegment`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
|
||||
## _class_ `BaseMessage`
|
||||
|
||||
基类:`list`, `abc.ABC`
|
||||
|
||||
|
||||
### `append(obj)`
|
||||
|
||||
Append object to the end of the list.
|
||||
|
||||
|
||||
### `extend(obj)`
|
||||
|
||||
Extend list by appending elements from the iterable.
|
@ -1,122 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.rule 模块
|
||||
|
||||
## 规则
|
||||
|
||||
每个 `Matcher` 拥有一个 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。
|
||||
|
||||
:::tip 提示
|
||||
`RuleChecker` 既可以是 async function 也可以是 sync function
|
||||
:::
|
||||
|
||||
|
||||
## _class_ `Rule`
|
||||
|
||||
基类:`object`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
`Matcher` 规则类,当事件传递时,在 `Matcher` 运行前进行检查。
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
|
||||
```python
|
||||
Rule(async_function) & sync_function
|
||||
# 等价于
|
||||
from nonebot.utils import run_sync
|
||||
Rule(async_function, run_sync(sync_function))
|
||||
```
|
||||
|
||||
|
||||
### `__init__(*checkers)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*checkers: Callable[[Bot, Event, dict], Awaitable[bool]]`: **异步** RuleChecker
|
||||
|
||||
|
||||
|
||||
### `checkers`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
存储 `RuleChecker`
|
||||
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
|
||||
* `Set[Callable[[Bot, Event, dict], Awaitable[bool]]]`
|
||||
|
||||
|
||||
|
||||
### _async_ `__call__(bot, event, state)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否符合所有规则
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
* `state: dict`: 当前 State
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`
|
||||
|
||||
|
||||
|
||||
## `startswith(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息开头
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 消息开头字符串
|
||||
|
||||
|
||||
|
||||
## `endswith(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息结尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 消息结尾字符串
|
@ -7,16 +7,13 @@
|
||||
* [nonebot](nonebot.html)
|
||||
|
||||
|
||||
* [nonebot.typing](typing.html)
|
||||
|
||||
|
||||
* [nonebot.config](config.html)
|
||||
|
||||
|
||||
* [nonebot.sched](sched.html)
|
||||
* [nonebot.plugin](plugin.html)
|
||||
|
||||
|
||||
* [nonebot.log](log.html)
|
||||
* [nonebot.matcher](matcher.html)
|
||||
|
||||
|
||||
* [nonebot.rule](rule.html)
|
||||
@ -25,10 +22,28 @@
|
||||
* [nonebot.permission](permission.html)
|
||||
|
||||
|
||||
* [nonebot.sched](sched.html)
|
||||
|
||||
|
||||
* [nonebot.log](log.html)
|
||||
|
||||
|
||||
* [nonebot.utils](utils.html)
|
||||
|
||||
|
||||
* [nonebot.typing](typing.html)
|
||||
|
||||
|
||||
* [nonebot.exception](exception.html)
|
||||
|
||||
|
||||
* [nonebot.drivers](drivers/)
|
||||
|
||||
|
||||
* [nonebot.drivers.fastapi](drivers/fastapi.html)
|
||||
|
||||
|
||||
* [nonebot.adapters](adapters/)
|
||||
|
||||
|
||||
* [nonebot.adapters.cqhttp](adapters/cqhttp.html)
|
323
archive/2.0.0a4/api/adapters/README.md
Normal file
@ -0,0 +1,323 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.adapters 模块
|
||||
|
||||
## 协议适配基类
|
||||
|
||||
各协议请继承以下基类,并使用 `driver.register_adapter` 注册适配器
|
||||
|
||||
|
||||
## _class_ `BaseBot`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Bot 基类。用于处理上报消息,并提供 API 调用接口。
|
||||
|
||||
|
||||
### _abstract_ `__init__(driver, connection_type, config, self_id, *, websocket=None)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `driver: Driver`: Driver 对象
|
||||
|
||||
|
||||
* `connection_type: str`: http 或者 websocket
|
||||
|
||||
|
||||
* `config: Config`: Config 对象
|
||||
|
||||
|
||||
* `self_id: str`: 机器人 ID
|
||||
|
||||
|
||||
* `websocket: Optional[WebSocket]`: Websocket 连接对象
|
||||
|
||||
|
||||
|
||||
### `driver`
|
||||
|
||||
Driver 对象
|
||||
|
||||
|
||||
### `connection_type`
|
||||
|
||||
连接类型
|
||||
|
||||
|
||||
### `config`
|
||||
|
||||
Config 配置对象
|
||||
|
||||
|
||||
### `self_id`
|
||||
|
||||
机器人 ID
|
||||
|
||||
|
||||
### `websocket`
|
||||
|
||||
Websocket 连接对象
|
||||
|
||||
|
||||
### _abstract property_ `type`
|
||||
|
||||
Adapter 类型
|
||||
|
||||
|
||||
### _abstract async_ `handle_message(message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
处理上报消息的函数,转换为 `Event` 事件后调用 `nonebot.message.handle_event` 进一步处理事件。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: dict`: 收到的上报消息
|
||||
|
||||
|
||||
|
||||
### _abstract async_ `call_api(api, **data)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `api: str`: API 名称
|
||||
|
||||
|
||||
* `**data`: API 数据
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
|
||||
```python
|
||||
await bot.call_api("send_msg", data={"message": "hello world"})
|
||||
await bot.send_msg(message="hello world")
|
||||
```
|
||||
|
||||
|
||||
### _abstract async_ `send(event, message, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用机器人基础发送消息接口
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 要发送的消息
|
||||
|
||||
|
||||
* `**kwargs`
|
||||
|
||||
|
||||
|
||||
## _class_ `BaseEvent`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Event 基类。提供上报信息的关键信息,其余信息可从原始上报消息获取。
|
||||
|
||||
|
||||
### `__init__(raw_event)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `raw_event: dict`: 原始上报消息
|
||||
|
||||
|
||||
|
||||
### _property_ `raw_event`
|
||||
|
||||
原始上报消息
|
||||
|
||||
|
||||
### _abstract property_ `id`
|
||||
|
||||
事件 ID
|
||||
|
||||
|
||||
### _abstract property_ `name`
|
||||
|
||||
事件名称
|
||||
|
||||
|
||||
### _abstract property_ `self_id`
|
||||
|
||||
机器人 ID
|
||||
|
||||
|
||||
### _abstract property_ `time`
|
||||
|
||||
事件发生时间
|
||||
|
||||
|
||||
### _abstract property_ `type`
|
||||
|
||||
事件主类型
|
||||
|
||||
|
||||
### _abstract property_ `detail_type`
|
||||
|
||||
事件详细类型
|
||||
|
||||
|
||||
### _abstract property_ `sub_type`
|
||||
|
||||
事件子类型
|
||||
|
||||
|
||||
### _abstract property_ `user_id`
|
||||
|
||||
触发事件的主体 ID
|
||||
|
||||
|
||||
### _abstract property_ `group_id`
|
||||
|
||||
触发事件的主体群 ID
|
||||
|
||||
|
||||
### _abstract property_ `to_me`
|
||||
|
||||
事件是否为发送给机器人的消息
|
||||
|
||||
|
||||
### _abstract property_ `message`
|
||||
|
||||
消息内容
|
||||
|
||||
|
||||
### _abstract property_ `reply`
|
||||
|
||||
回复的消息
|
||||
|
||||
|
||||
### _abstract property_ `raw_message`
|
||||
|
||||
原始消息
|
||||
|
||||
|
||||
### _abstract property_ `plain_text`
|
||||
|
||||
纯文本消息
|
||||
|
||||
|
||||
### _abstract property_ `sender`
|
||||
|
||||
消息发送者信息
|
||||
|
||||
|
||||
## _class_ `BaseMessageSegment`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
消息段基类
|
||||
|
||||
|
||||
### `type`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 消息段类型
|
||||
|
||||
|
||||
### `data`
|
||||
|
||||
|
||||
* 类型: `Dict[str, Union[str, list]]`
|
||||
|
||||
|
||||
* 说明: 消息段数据
|
||||
|
||||
|
||||
## _class_ `BaseMessage`
|
||||
|
||||
基类:`list`, `abc.ABC`
|
||||
|
||||
消息数组
|
||||
|
||||
|
||||
### `__init__(message=None, *args, **kwargs)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, dict, list, MessageSegment, Message]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### `append(obj)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
添加一个消息段到消息数组末尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `obj: Union[str, MessageSegment]`: 要添加的消息段
|
||||
|
||||
|
||||
|
||||
### `extend(obj)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
拼接一个消息数组或多个消息段到消息数组末尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `obj: Union[Message, Iterable[MessageSegment]]`: 要添加的消息数组
|
||||
|
||||
|
||||
|
||||
### `reduce()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
缩减消息数组,即拼接相邻纯文本消息段
|
||||
|
||||
|
||||
|
||||
### `extract_plain_text()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
提取消息内纯文本消息
|
@ -323,10 +323,10 @@ CQHTTP 协议 Event 适配。继承属性参考 [BaseEvent](./#class-baseevent)
|
||||
### _property_ `sub_type`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 说明: 事件类型
|
||||
* 说明: 事件子类型
|
||||
|
||||
|
||||
### _property_ `user_id`
|
||||
@ -405,7 +405,11 @@ CQHTTP 协议 Event 适配。继承属性参考 [BaseEvent](./#class-baseevent)
|
||||
|
||||
基类:[`nonebot.adapters.BaseMessageSegment`](#None)
|
||||
|
||||
CQHTTP 协议 MessageSegment 适配。具体方法参考协议消息段类型或源码。
|
||||
|
||||
|
||||
## _class_ `Message`
|
||||
|
||||
基类:[`nonebot.adapters.BaseMessage`](#None)
|
||||
|
||||
CQHTTP 协议 Message 适配。
|
@ -194,10 +194,10 @@ SUPER_USERS=[12345789]
|
||||
### `nickname`
|
||||
|
||||
|
||||
* 类型: `Union[str, Set[str]]`
|
||||
* 类型: `Set[str]`
|
||||
|
||||
|
||||
* 默认值: `""`
|
||||
* 默认值: `set()`
|
||||
|
||||
|
||||
* 说明:
|
246
archive/2.0.0a4/api/drivers/README.md
Normal file
@ -0,0 +1,246 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.drivers 模块
|
||||
|
||||
## 后端驱动适配基类
|
||||
|
||||
各驱动请继承以下基类
|
||||
|
||||
|
||||
## _class_ `BaseDriver`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Driver 基类。将后端框架封装,以满足适配器使用。
|
||||
|
||||
|
||||
### `_adapters`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Type[Bot]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
已注册的适配器列表
|
||||
|
||||
|
||||
|
||||
### _abstract_ `__init__(env, config)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `env: Env`: 包含环境信息的 Env 对象
|
||||
|
||||
|
||||
* `config: Config`: 包含配置信息的 Config 对象
|
||||
|
||||
|
||||
|
||||
### `env`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`str`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
环境名称
|
||||
|
||||
|
||||
|
||||
### `config`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Config`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
配置对象
|
||||
|
||||
|
||||
|
||||
### `_clients`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Bot]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
已连接的 Bot
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `register_adapter(name, adapter)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个协议适配器
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `name: str`: 适配器名称,用于在连接时进行识别
|
||||
|
||||
|
||||
* `adapter: Type[Bot]`: 适配器 Class
|
||||
|
||||
|
||||
|
||||
### _abstract property_ `type`
|
||||
|
||||
驱动类型名称
|
||||
|
||||
|
||||
### _abstract property_ `server_app`
|
||||
|
||||
驱动 APP 对象
|
||||
|
||||
|
||||
### _abstract property_ `asgi`
|
||||
|
||||
驱动 ASGI 对象
|
||||
|
||||
|
||||
### _abstract property_ `logger`
|
||||
|
||||
驱动专属 logger 日志记录器
|
||||
|
||||
|
||||
### _property_ `bots`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Bot]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取当前所有已连接的 Bot
|
||||
|
||||
|
||||
|
||||
### _abstract_ `on_startup(func)`
|
||||
|
||||
注册一个在驱动启动时运行的函数
|
||||
|
||||
|
||||
### _abstract_ `on_shutdown(func)`
|
||||
|
||||
注册一个在驱动停止时运行的函数
|
||||
|
||||
|
||||
### _abstract_ `run(host=None, port=None, *args, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
启动驱动框架
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `host: Optional[str]`: 驱动绑定 IP
|
||||
|
||||
|
||||
* `post: Optional[int]`: 驱动绑定端口
|
||||
|
||||
|
||||
* `*args`
|
||||
|
||||
|
||||
* `**kwargs`
|
||||
|
||||
|
||||
|
||||
### _abstract async_ `_handle_http()`
|
||||
|
||||
用于处理 HTTP 类型请求的函数
|
||||
|
||||
|
||||
### _abstract async_ `_handle_ws_reverse()`
|
||||
|
||||
用于处理 WebSocket 类型请求的函数
|
||||
|
||||
|
||||
## _class_ `BaseWebSocket`
|
||||
|
||||
基类:`object`
|
||||
|
||||
WebSocket 连接封装,统一接口方便外部调用。
|
||||
|
||||
|
||||
### _abstract_ `__init__(websocket)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `websocket: Any`: WebSocket 连接对象
|
||||
|
||||
|
||||
|
||||
### _property_ `websocket`
|
||||
|
||||
WebSocket 连接对象
|
||||
|
||||
|
||||
### _abstract property_ `closed`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
连接是否已经关闭
|
||||
|
||||
|
||||
|
||||
### _abstract async_ `accept()`
|
||||
|
||||
接受 WebSocket 连接请求
|
||||
|
||||
|
||||
### _abstract async_ `close(code)`
|
||||
|
||||
关闭 WebSocket 连接请求
|
||||
|
||||
|
||||
### _abstract async_ `receive()`
|
||||
|
||||
接收一条 WebSocket 信息
|
||||
|
||||
|
||||
### _abstract async_ `send(data)`
|
||||
|
||||
发送一条 WebSocket 信息
|
125
archive/2.0.0a4/api/drivers/fastapi.md
Normal file
@ -0,0 +1,125 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.drivers.fastapi 模块
|
||||
|
||||
## FastAPI 驱动适配
|
||||
|
||||
后端使用方法请参考: [FastAPI 文档](https://fastapi.tiangolo.com/)
|
||||
|
||||
|
||||
## _class_ `Driver`
|
||||
|
||||
基类:[`nonebot.drivers.BaseDriver`](#None)
|
||||
|
||||
FastAPI 驱动框架
|
||||
|
||||
|
||||
### `__init__(env, config)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
|
||||
* `env: Env`: 包含环境信息的 Env 对象
|
||||
|
||||
|
||||
* `config: Config`: 包含配置信息的 Config 对象
|
||||
|
||||
|
||||
### _property_ `type`
|
||||
|
||||
驱动名称: `fastapi`
|
||||
|
||||
|
||||
### _property_ `server_app`
|
||||
|
||||
`FastAPI APP` 对象
|
||||
|
||||
|
||||
### _property_ `asgi`
|
||||
|
||||
`FastAPI APP` 对象
|
||||
|
||||
|
||||
### _property_ `logger`
|
||||
|
||||
fastapi 使用的 logger
|
||||
|
||||
|
||||
### `on_startup(func)`
|
||||
|
||||
参考文档: [Events](https://fastapi.tiangolo.com/advanced/events/#startup-event)
|
||||
|
||||
|
||||
### `on_shutdown(func)`
|
||||
|
||||
参考文档: [Events](https://fastapi.tiangolo.com/advanced/events/#startup-event)
|
||||
|
||||
|
||||
### `run(host=None, port=None, *, app=None, **kwargs)`
|
||||
|
||||
使用 `uvicorn` 启动 FastAPI
|
||||
|
||||
|
||||
### _async_ `_handle_http(adapter, data=Body(Ellipsis), x_self_id=Header(None), x_signature=Header(None), auth=Depends(get_auth_bearer))`
|
||||
|
||||
用于处理 HTTP 类型请求的函数
|
||||
|
||||
|
||||
### _async_ `_handle_ws_reverse(adapter, websocket, x_self_id=Header(None), auth=Depends(get_auth_bearer))`
|
||||
|
||||
用于处理 WebSocket 类型请求的函数
|
||||
|
||||
|
||||
## _class_ `WebSocket`
|
||||
|
||||
基类:[`nonebot.drivers.BaseWebSocket`](#None)
|
||||
|
||||
|
||||
### `__init__(websocket)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
|
||||
* `websocket: Any`: WebSocket 连接对象
|
||||
|
||||
|
||||
### _property_ `closed`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
连接是否已经关闭
|
||||
|
||||
|
||||
|
||||
### _async_ `accept()`
|
||||
|
||||
接受 WebSocket 连接请求
|
||||
|
||||
|
||||
### _async_ `close(code=1000)`
|
||||
|
||||
关闭 WebSocket 连接请求
|
||||
|
||||
|
||||
### _async_ `receive()`
|
||||
|
||||
接收一条 WebSocket 信息
|
||||
|
||||
|
||||
### _async_ `send(data)`
|
||||
|
||||
发送一条 WebSocket 信息
|
497
archive/2.0.0a4/api/matcher.md
Normal file
@ -0,0 +1,497 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.matcher 模块
|
||||
|
||||
## 事件响应器
|
||||
|
||||
该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行 对话 。
|
||||
|
||||
|
||||
## `matchers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[int, List[Type[Matcher]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
用于存储当前所有的事件响应器
|
||||
|
||||
|
||||
|
||||
## _class_ `Matcher`
|
||||
|
||||
基类:`object`
|
||||
|
||||
事件响应器类
|
||||
|
||||
|
||||
### `module`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[str]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器所在模块名称
|
||||
|
||||
|
||||
|
||||
### `type`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`str`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器类型
|
||||
|
||||
|
||||
|
||||
### `rule`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Rule`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器匹配规则
|
||||
|
||||
|
||||
|
||||
### `permission`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Permission`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器触发权限
|
||||
|
||||
|
||||
|
||||
### `priority`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`int`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器优先级
|
||||
|
||||
|
||||
|
||||
### `block`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器是否阻止事件传播
|
||||
|
||||
|
||||
|
||||
### `temp`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器是否为临时
|
||||
|
||||
|
||||
|
||||
### `expire_time`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[datetime]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器过期时间点
|
||||
|
||||
|
||||
|
||||
### `_default_state`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`dict`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器默认状态
|
||||
|
||||
|
||||
|
||||
### `_default_parser`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[ArgsParser]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器默认参数解析函数
|
||||
|
||||
|
||||
|
||||
### `__init__()`
|
||||
|
||||
实例化 Matcher 以便运行
|
||||
|
||||
|
||||
### `handlers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`List[Handler]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器拥有的事件处理函数列表
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
创建一个新的事件响应器,并存储至 [matchers](#matchers)
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `type_: str`: 事件响应器类型,与 `event.type` 一致时触发,空字符串表示任意
|
||||
|
||||
|
||||
* `rule: Optional[Rule]`: 匹配规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器,即触发一次后删除
|
||||
|
||||
|
||||
* `priority: int`: 响应优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级的响应器传播
|
||||
|
||||
|
||||
* `module: Optional[str]`: 事件响应器所在模块名称
|
||||
|
||||
|
||||
* `default_state: Optional[dict]`: 默认状态 `state`
|
||||
|
||||
|
||||
* `expire_time: Optional[datetime]`: 事件响应器最终有效时间点,过时即被删除
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`: 新的事件响应器类
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `check_perm(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否满足触发权限
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`: 是否满足权限
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `check_rule(bot, event, state)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否满足匹配规则
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
* `state: dict`: 当前状态
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`: 是否满足匹配规则
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `args_parser(func)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来更改当前事件响应器的默认参数解析函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `func: ArgsParser`: 参数解析函数
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `handle()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来向事件响应器直接添加一个处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `receive()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来指示 NoneBot 在接收用户新的一条消息后继续运行该函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `got(key, prompt=None, args_parser=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来指示 NoneBot 当要获取的 `key` 不存在时接收用户新的一条消息并经过 `ArgsParser` 处理后再运行该函数,如果 `key` 已存在则直接继续运行
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `key: str`: 参数名
|
||||
|
||||
|
||||
* `prompt: Optional[Union[str, Message, MessageSegment]]`: 在参数不存在时向用户发送的消息
|
||||
|
||||
|
||||
* `args_parser: Optional[ArgsParser]`: 可选参数解析函数,空则使用默认解析函数
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `send(message, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `bot.send` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `finish(message=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并结束当前事件响应器
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `bot.send` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `pause(prompt=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后继续下一个处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `prompt: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `bot.send` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `reject(prompt=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后重新运行当前处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `prompt: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `bot.send` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
|
||||
|
||||
|
||||
## _class_ `MatcherGroup`
|
||||
|
||||
基类:`object`
|
||||
|
||||
事件响应器组合,统一管理。用法同 `Matcher`
|
||||
|
||||
|
||||
### `__init__(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
创建一个事件响应器组合,参数为默认值,与 `Matcher.new` 一致
|
||||
|
||||
|
||||
|
||||
### `matchers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`List[Type[Matcher]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
组内事件响应器列表
|
||||
|
||||
|
||||
|
||||
### `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在组中创建一个新的事件响应器,参数留空则使用组合默认值
|
||||
|
||||
|
||||
:::danger 警告
|
||||
如果使用 handlers 参数覆盖组合默认值则该事件响应器不会随组合一起添加新的事件处理函数
|
||||
:::
|
@ -5,6 +5,55 @@ sidebarDepth: 0
|
||||
|
||||
# NoneBot 模块
|
||||
|
||||
## 快捷导入
|
||||
|
||||
为方便使用,`nonebot` 模块从子模块导入了部分内容
|
||||
|
||||
|
||||
* `on_message` => `nonebot.plugin.on_message`
|
||||
|
||||
|
||||
* `on_notice` => `nonebot.plugin.on_notice`
|
||||
|
||||
|
||||
* `on_request` => `nonebot.plugin.on_request`
|
||||
|
||||
|
||||
* `on_metaevent` => `nonebot.plugin.on_metaevent`
|
||||
|
||||
|
||||
* `on_startswith` => `nonebot.plugin.on_startswith`
|
||||
|
||||
|
||||
* `on_endswith` => `nonebot.plugin.on_endswith`
|
||||
|
||||
|
||||
* `on_command` => `nonebot.plugin.on_command`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `CommandGroup` => `nonebot.plugin.CommandGroup`
|
||||
|
||||
|
||||
* `load_plugin` => `nonebot.plugin.load_plugin`
|
||||
|
||||
|
||||
* `load_plugins` => `nonebot.plugin.load_plugins`
|
||||
|
||||
|
||||
* `load_builtin_plugins` => `nonebot.plugin.load_builtin_plugins`
|
||||
|
||||
|
||||
* `get_loaded_plugins` => `nonebot.plugin.get_loaded_plugins`
|
||||
|
||||
|
||||
## `get_driver()`
|
||||
|
629
archive/2.0.0a4/api/plugin.md
Normal file
@ -0,0 +1,629 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.plugin 模块
|
||||
|
||||
## 插件
|
||||
|
||||
为 NoneBot 插件开发提供便携的定义函数。
|
||||
|
||||
|
||||
## `plugins`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Plugin]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
已加载的插件
|
||||
|
||||
|
||||
|
||||
## _class_ `Plugin`
|
||||
|
||||
基类:`object`
|
||||
|
||||
存储插件信息
|
||||
|
||||
|
||||
### `name`
|
||||
|
||||
|
||||
* **类型**: `str`
|
||||
|
||||
|
||||
* **说明**: 插件名称,使用 文件/文件夹 名称作为插件名
|
||||
|
||||
|
||||
### `module`
|
||||
|
||||
|
||||
* **类型**: `ModuleType`
|
||||
|
||||
|
||||
* **说明**: 插件模块对象
|
||||
|
||||
|
||||
### `matcher`
|
||||
|
||||
|
||||
* **类型**: `Set[Type[Matcher]]`
|
||||
|
||||
|
||||
* **说明**: 插件内定义的 `Matcher`
|
||||
|
||||
|
||||
## `on(type='', rule=None, permission=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个基础事件响应器,可自定义类型。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `type: str`: 事件响应器类型
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_metaevent(rule=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个元事件响应器。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_message(rule=None, permission=None, *, handlers=None, temp=False, priority=1, block=True, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_notice(rule=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个通知事件响应器。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_request(rule=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个请求事件响应器。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_startswith(msg, rule=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息的\*\*文本部分\*\*以指定内容开头时响应。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 指定消息开头内容
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_endswith(msg, rule=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息的\*\*文本部分\*\*以指定内容结尾时响应。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 指定消息结尾内容
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_keyword(keywords, rule=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息纯文本部分包含关键词时响应。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `keywords: Set[str]`: 关键词列表
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_command(cmd, rule=None, aliases=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息以指定命令开头时响应。
|
||||
|
||||
命令匹配规则参考: [命令形式匹配](rule.html#command-command)
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `cmd: Union[str, Tuple[str, ...]]`: 指定命令内容
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `aliases: Optional[Set[Union[str, Tuple[str, ...]]]]`: 命令别名
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_regex(pattern, flags=0, rule=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息匹配正则表达式时响应。
|
||||
|
||||
命令匹配规则参考: [正则匹配](rule.html#regex-regex-flags-0)
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `pattern: str`: 正则表达式
|
||||
|
||||
|
||||
* `flags: Union[int, re.RegexFlag]`: 正则匹配标志
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## _class_ `CommandGroup`
|
||||
|
||||
基类:`object`
|
||||
|
||||
命令组,用于声明一组有相同名称前缀的命令。
|
||||
|
||||
|
||||
### `__init__(cmd, **kwargs)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `cmd: Union[str, Tuple[str, ...]]`: 命令前缀
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `on_command` 的参数默认值,参考 [on_command](#on-command-cmd-rule-none-aliases-none-kwargs)
|
||||
|
||||
|
||||
|
||||
### `basecmd`
|
||||
|
||||
|
||||
* **类型**: `Tuple[str, ...]`
|
||||
|
||||
|
||||
* **说明**: 命令前缀
|
||||
|
||||
|
||||
### `base_kwargs`
|
||||
|
||||
|
||||
* **类型**: `Dict[str, Any]`
|
||||
|
||||
|
||||
* **说明**: 其他传递给 `on_command` 的参数默认值
|
||||
|
||||
|
||||
### `command(cmd, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个新的命令。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `cmd: Union[str, Tuple[str, ...]]`: 命令前缀
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `on_command` 的参数,将会覆盖命令组默认值
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `load_plugin(module_path)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
使用 `importlib` 加载单个插件,可以是本地插件或是通过 `pip` 安装的插件。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `module_path: str`: 插件名称 `path.to.your.plugin`
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Optional[Plugin]`
|
||||
|
||||
|
||||
|
||||
## `load_plugins(*plugin_dir)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
导入目录下多个插件,以 `_` 开头的插件不会被导入!
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*plugin_dir: str`: 插件路径
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Set[Plugin]`
|
||||
|
||||
|
||||
|
||||
## `load_builtin_plugins()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
导入 NoneBot 内置插件
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Plugin`
|
||||
|
||||
|
||||
|
||||
## `get_loaded_plugins()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取当前已导入的插件。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Set[Plugin]`
|
210
archive/2.0.0a4/api/rule.md
Normal file
@ -0,0 +1,210 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.rule 模块
|
||||
|
||||
## 规则
|
||||
|
||||
每个事件响应器 `Matcher` 拥有一个匹配规则 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。
|
||||
|
||||
:::tip 提示
|
||||
`RuleChecker` 既可以是 async function 也可以是 sync function,但在最终会被 `nonebot.utils.run_sync` 转换为 async function
|
||||
:::
|
||||
|
||||
|
||||
## _class_ `Rule`
|
||||
|
||||
基类:`object`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
`Matcher` 规则类,当事件传递时,在 `Matcher` 运行前进行检查。
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
|
||||
```python
|
||||
Rule(async_function) & sync_function
|
||||
# 等价于
|
||||
from nonebot.utils import run_sync
|
||||
Rule(async_function, run_sync(sync_function))
|
||||
```
|
||||
|
||||
|
||||
### `__init__(*checkers)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*checkers: Callable[[Bot, Event, dict], Awaitable[bool]]`: **异步** RuleChecker
|
||||
|
||||
|
||||
|
||||
### `checkers`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
存储 `RuleChecker`
|
||||
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
|
||||
* `Set[Callable[[Bot, Event, dict], Awaitable[bool]]]`
|
||||
|
||||
|
||||
|
||||
### _async_ `__call__(bot, event, state)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否符合所有规则
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
* `state: dict`: 当前 State
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`
|
||||
|
||||
|
||||
|
||||
## `startswith(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息开头
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 消息开头字符串
|
||||
|
||||
|
||||
|
||||
## `endswith(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息结尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 消息结尾字符串
|
||||
|
||||
|
||||
|
||||
## `keyword(*keywords)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息关键词
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*keywords: str`: 关键词
|
||||
|
||||
|
||||
|
||||
## `command(*cmds)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。
|
||||
|
||||
可以通过 `state["_prefix"]["command"]` 获取匹配成功的命令(例:`("test",)`),通过 `state["_prefix"]["raw_command"]` 获取匹配成功的原始命令文本(例:`"/test"`)。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*cmds: Union[str, Tuple[str, ...]]`: 命令内容
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
使用默认 `command_start`, `command_sep` 配置
|
||||
|
||||
命令 `("test",)` 可以匹配:`/test` 开头的消息
|
||||
命令 `("test", "sub")` 可以匹配”`/test.sub` 开头的消息
|
||||
|
||||
|
||||
:::tip 提示
|
||||
命令内容与后续消息间无需空格!
|
||||
:::
|
||||
|
||||
|
||||
## `regex(regex, flags=0)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
根据正则表达式进行匹配。
|
||||
|
||||
可以通过 `state["_matched"]` 获取正则表达式匹配成功的文本。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `regex: str`: 正则表达式
|
||||
|
||||
|
||||
* `flags: Union[int, re.RegexFlag]`: 正则标志
|
||||
|
||||
|
||||
:::tip 提示
|
||||
正则表达式匹配使用 search 而非 match,如需从头匹配请使用 `r"^xxx"` 来确保匹配开头
|
||||
:::
|
||||
|
||||
|
||||
## `to_me()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
通过 `event.to_me` 判断消息是否是发送给机器人
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
@ -20,11 +20,9 @@ NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人
|
||||
|
||||
## 它如何工作?
|
||||
|
||||
NoneBot 的运行离不开 酷 Q 和 CQHTTP 插件。酷 Q 扮演着「无头 QQ 客户端」的角色,它进行实际的消息、通知、请求的接收和发送,当 酷 Q 收到消息时,它将这个消息包装为一个事件(通知和请求同理),并通过它自己的插件机制将事件传送给 CQHTTP 插件,后者再根据其配置中的 `post_url` 或 `ws_reverse_url` 等项来将事件发送至 NoneBot。
|
||||
<!-- TODO: how to work -->
|
||||
|
||||
在 NoneBot 收到事件前,它底层的 aiocqhttp 实际已经先看到了事件,aiocqhttp 根据事件的类型信息,通知到 NoneBot 的相应函数。特别地,对于消息类型的事件,还将消息内容转换成了 `aiocqhttp.message.Message` 类型,以便处理。
|
||||
|
||||
NoneBot 的事件处理函数收到通知后,对于不同类型的事件,再做相应的预处理和解析,然后调用对应的插件,并向其提供适合此类事件的会话(Session)对象。NoneBot 插件的编写者要做的,就是利用 Session 对象中提供的数据,在插件的处理函数中实现所需的功能。
|
||||
~~未填坑~~
|
||||
|
||||
## 特色
|
||||
|
@ -136,11 +136,11 @@ QQ 协议端举例:
|
||||
现在,尝试向你的 QQ 机器人账号发送如下内容:
|
||||
|
||||
```default
|
||||
/say 你好,世界
|
||||
/echo 你好,世界
|
||||
```
|
||||
|
||||
到这里如果一切 OK,你应该会收到机器人给你回复了 `你好,世界`。这一历史性的对话标志着你已经成功地运行了一个 NoneBot 的最小实例,开始了编写更强大的 QQ 机器人的创意之旅!
|
||||
|
||||
<ClientOnly>
|
||||
<Messenger :messages="[{ position: 'right', msg: '/say 你好,世界' }, { position: 'left', msg: '你好,世界' }]"/>
|
||||
<Messenger :messages="[{ position: 'right', msg: '/echo 你好,世界' }, { position: 'left', msg: '你好,世界' }]"/>
|
||||
</ClientOnly>
|
@ -6,7 +6,10 @@
|
||||
请确保你的 Python 版本 >= 3.7。
|
||||
:::
|
||||
|
||||
请在安装 nonebot2 之前卸载 nonebot 1.x
|
||||
|
||||
```bash
|
||||
pip uninstall nonebot
|
||||
pip install nonebot2
|
||||
```
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"sidebar": {},
|
||||
"locales": {
|
||||
"/": {
|
||||
"label": "简体中文",
|
||||
@ -17,6 +18,10 @@
|
||||
{
|
||||
"text": "API",
|
||||
"link": "/api/"
|
||||
},
|
||||
{
|
||||
"text": "插件广场",
|
||||
"link": "/plugin-store"
|
||||
}
|
||||
],
|
||||
"sidebarDepth": 2,
|
||||
@ -47,21 +52,17 @@
|
||||
"title": "nonebot 模块",
|
||||
"path": "nonebot"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.typing 模块",
|
||||
"path": "typing"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.config 模块",
|
||||
"path": "config"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.sched 模块",
|
||||
"path": "sched"
|
||||
"title": "nonebot.plugin 模块",
|
||||
"path": "plugin"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.log 模块",
|
||||
"path": "log"
|
||||
"title": "nonebot.matcher 模块",
|
||||
"path": "matcher"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.rule 模块",
|
||||
@ -71,14 +72,34 @@
|
||||
"title": "nonebot.permission 模块",
|
||||
"path": "permission"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.sched 模块",
|
||||
"path": "sched"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.log 模块",
|
||||
"path": "log"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.utils 模块",
|
||||
"path": "utils"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.typing 模块",
|
||||
"path": "typing"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.exception 模块",
|
||||
"path": "exception"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.drivers 模块",
|
||||
"path": "drivers/"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.drivers.fastapi 模块",
|
||||
"path": "drivers/fastapi"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.adapters 模块",
|
||||
"path": "adapters/"
|
162
docs/.vuepress/components/Plugins.vue
Normal file
@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<div class="plugins">
|
||||
<v-app>
|
||||
<v-main>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field
|
||||
v-model="filterText"
|
||||
dense
|
||||
rounded
|
||||
outlined
|
||||
clearable
|
||||
hide-details
|
||||
label="Filter Plugin"
|
||||
>
|
||||
<template v-slot:prepend-inner>
|
||||
<div class="v-input__icon v-input__icon--prepend-inner">
|
||||
<v-icon small>fa-filter</v-icon>
|
||||
</div>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-btn
|
||||
block
|
||||
color="primary"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://github.com/nonebot/nonebot2/issues/new?template=plugin-publish.md"
|
||||
>Publish Your Plugin
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-pagination
|
||||
v-model="page"
|
||||
:length="pageNum"
|
||||
prev-icon="fa-caret-left"
|
||||
next-icon="fa-caret-right"
|
||||
></v-pagination>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<hr />
|
||||
<v-row>
|
||||
<v-col
|
||||
cols="12"
|
||||
sm="6"
|
||||
v-for="(plugin, index) in filteredPlugins"
|
||||
:key="index"
|
||||
>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
{{ plugin.name }}
|
||||
<v-spacer></v-spacer>
|
||||
<a
|
||||
class="repo-link"
|
||||
v-if="repoLink(plugin.repo)"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
:title="plugin.repo"
|
||||
:href="repoLink(plugin.repo)"
|
||||
>
|
||||
<v-icon>fab fa-github</v-icon>
|
||||
</a>
|
||||
</v-card-title>
|
||||
<v-card-text>{{ plugin.desc }}</v-card-text>
|
||||
<v-card-text>
|
||||
<v-icon x-small>fa-fingerprint</v-icon>
|
||||
{{ plugin.id }}
|
||||
<v-icon x-small class="ml-2">fa-user</v-icon>
|
||||
{{ plugin.author }}
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn
|
||||
block
|
||||
depressed
|
||||
class="btn-copy"
|
||||
@click="copyCommand(plugin)"
|
||||
>
|
||||
copy nb-cli command
|
||||
<v-icon right small>fa-copy</v-icon>
|
||||
</v-btn>
|
||||
<v-snackbar v-model="snackbar">Copied!</v-snackbar>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-pagination
|
||||
v-model="page"
|
||||
:length="pageNum"
|
||||
prev-icon="fa-caret-left"
|
||||
next-icon="fa-caret-right"
|
||||
></v-pagination>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-main>
|
||||
</v-app>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import copy from "copy-to-clipboard";
|
||||
import plugins from "../public/plugins.json";
|
||||
|
||||
export default {
|
||||
name: "Plugins",
|
||||
data() {
|
||||
return {
|
||||
plugins: plugins,
|
||||
snackbar: false,
|
||||
filterText: "",
|
||||
page: 1
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
pageNum() {
|
||||
return Math.ceil(this.filteredPlugins.length / 10);
|
||||
},
|
||||
filteredPlugins() {
|
||||
return this.plugins.filter(plugin => {
|
||||
return (
|
||||
plugin.id.indexOf(this.filterText) != -1 ||
|
||||
plugin.name.indexOf(this.filterText) != -1 ||
|
||||
plugin.desc.indexOf(this.filterText) != -1 ||
|
||||
plugin.author.indexOf(this.filterText) != -1
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
repoLink(repo) {
|
||||
if (repo) {
|
||||
return /^https?:/.test(repo) ? repo : `https://github.com/${repo}`;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
copyCommand(plugin) {
|
||||
copy(`nb plugin install ${plugin.id}`, {
|
||||
format: "text/plain"
|
||||
});
|
||||
this.snackbar = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.v-application--wrap {
|
||||
min-height: 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.repo-link {
|
||||
text-decoration: none !important;
|
||||
display: inline-block;
|
||||
}
|
||||
.repo-link:hover i {
|
||||
color: #ea5252;
|
||||
}
|
||||
</style>
|
@ -13,7 +13,8 @@ module.exports = context => ({
|
||||
*/
|
||||
head: [
|
||||
["link", { rel: "icon", href: "/logo.png" }],
|
||||
["meta", { name: "theme-color", content: "#d32f2f" }],
|
||||
["link", { rel: "manifest", href: "/manifest.json" }],
|
||||
["meta", { name: "theme-color", content: "#ea5252" }],
|
||||
["meta", { name: "application-name", content: "NoneBot" }],
|
||||
["meta", { name: "apple-mobile-web-app-title", content: "NoneBot" }],
|
||||
["meta", { name: "apple-mobile-web-app-capable", content: "yes" }],
|
||||
@ -21,6 +22,26 @@ module.exports = context => ({
|
||||
"meta",
|
||||
{ name: "apple-mobile-web-app-status-bar-style", content: "black" }
|
||||
],
|
||||
[
|
||||
"link",
|
||||
{ rel: "apple-touch-icon", href: "/icons/apple-touch-icon-180x180.png" }
|
||||
],
|
||||
[
|
||||
"link",
|
||||
{
|
||||
rel: "mask-icon",
|
||||
href: "/icons/safari-pinned-tab.svg",
|
||||
color: "#ea5252"
|
||||
}
|
||||
],
|
||||
[
|
||||
"meta",
|
||||
{
|
||||
name: "msapplication-TileImage",
|
||||
content: "/icons/mstile-150x150.png"
|
||||
}
|
||||
],
|
||||
["meta", { name: "msapplication-TileColor", content: "#ea5252" }],
|
||||
[
|
||||
"link",
|
||||
{
|
||||
@ -38,12 +59,12 @@ module.exports = context => ({
|
||||
}
|
||||
},
|
||||
|
||||
theme: "titanium",
|
||||
theme: "nonebot",
|
||||
themeConfig: {
|
||||
logo: "/logo.png",
|
||||
repo: "nonebot/nonebot",
|
||||
repo: "nonebot/nonebot2",
|
||||
docsDir: "docs",
|
||||
docsBranch: "dev2",
|
||||
docsBranch: "dev",
|
||||
docsDirVersioned: "archive",
|
||||
docsDirPages: "pages",
|
||||
editLinks: true,
|
||||
@ -58,14 +79,14 @@ module.exports = context => ({
|
||||
nav: [
|
||||
{ text: "主页", link: "/" },
|
||||
{ text: "指南", link: "/guide/" },
|
||||
{ text: "API", link: "/api/" }
|
||||
{ text: "API", link: "/api/" },
|
||||
{ text: "插件广场", link: "/plugin-store" }
|
||||
],
|
||||
sidebarDepth: 2,
|
||||
sidebar: {
|
||||
"/guide/": [
|
||||
{
|
||||
title: "指南",
|
||||
path: "",
|
||||
title: "开始",
|
||||
collapsable: false,
|
||||
sidebar: "auto",
|
||||
children: [
|
||||
@ -73,8 +94,17 @@ module.exports = context => ({
|
||||
"installation",
|
||||
"getting-started",
|
||||
"creating-a-project",
|
||||
"basic-configuration",
|
||||
"writing-a-plugin"
|
||||
"basic-configuration"
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "编写插件",
|
||||
collapsable: false,
|
||||
sidebar: "auto",
|
||||
children: [
|
||||
"loading-a-plugin",
|
||||
"creating-a-plugin",
|
||||
"creating-a-matcher"
|
||||
]
|
||||
}
|
||||
],
|
||||
@ -92,6 +122,10 @@ module.exports = context => ({
|
||||
title: "nonebot.config 模块",
|
||||
path: "config"
|
||||
},
|
||||
{
|
||||
title: "nonebot.plugin 模块",
|
||||
path: "plugin"
|
||||
},
|
||||
{
|
||||
title: "nonebot.matcher 模块",
|
||||
path: "matcher"
|
||||
@ -124,6 +158,14 @@ module.exports = context => ({
|
||||
title: "nonebot.exception 模块",
|
||||
path: "exception"
|
||||
},
|
||||
{
|
||||
title: "nonebot.drivers 模块",
|
||||
path: "drivers/"
|
||||
},
|
||||
{
|
||||
title: "nonebot.drivers.fastapi 模块",
|
||||
path: "drivers/fastapi"
|
||||
},
|
||||
{
|
||||
title: "nonebot.adapters 模块",
|
||||
path: "adapters/"
|
||||
@ -143,6 +185,16 @@ module.exports = context => ({
|
||||
plugins: [
|
||||
"@vuepress/plugin-back-to-top",
|
||||
"@vuepress/plugin-medium-zoom",
|
||||
[
|
||||
"@vuepress/pwa",
|
||||
{
|
||||
serviceWorker: true,
|
||||
updatePopup: {
|
||||
message: "发现新内容",
|
||||
buttonText: "刷新"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
"versioning",
|
||||
{
|
||||
|
BIN
docs/.vuepress/public/icons/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
docs/.vuepress/public/icons/android-chrome-384x384.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
docs/.vuepress/public/icons/apple-touch-icon-180x180.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
docs/.vuepress/public/icons/favicon-16x16.png
Normal file
After Width: | Height: | Size: 626 B |
BIN
docs/.vuepress/public/icons/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1008 B |
BIN
docs/.vuepress/public/icons/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/.vuepress/public/icons/mstile-150x150.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
29
docs/.vuepress/public/icons/safari-pinned-tab.svg
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="500.000000pt" height="500.000000pt" viewBox="0 0 500.000000 500.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M2478 4525 c-2 -1 -57 -5 -122 -9 -65 -4 -122 -8 -125 -10 -3 -2 -30
|
||||
-7 -60 -11 -141 -18 -404 -102 -561 -180 -68 -34 -238 -132 -250 -145 -3 -3
|
||||
-32 -25 -65 -49 -246 -182 -465 -442 -604 -719 -212 -422 -271 -933 -159
|
||||
-1377 11 -44 21 -88 23 -97 8 -38 86 -238 120 -308 206 -415 542 -749 952
|
||||
-945 90 -43 265 -111 309 -119 11 -2 48 -12 84 -21 82 -21 94 -24 155 -31 28
|
||||
-4 53 -8 56 -10 11 -6 172 -17 264 -17 88 -1 239 9 282 17 11 3 43 8 70 12
|
||||
280 40 611 181 855 363 118 87 221 181 311 284 173 195 309 424 392 657 14 41
|
||||
28 82 30 90 2 8 13 51 25 95 25 93 27 103 34 159 3 22 8 52 11 65 9 46 16 166
|
||||
17 276 1 704 -363 1359 -960 1728 -201 125 -484 234 -677 263 -16 3 -52 9 -79
|
||||
15 -27 5 -92 12 -145 15 -53 3 -115 7 -138 8 -23 2 -43 2 -45 1z m162 -89
|
||||
c691 -39 1330 -482 1622 -1121 74 -163 137 -364 152 -490 4 -27 9 -63 11 -80
|
||||
17 -106 21 -305 10 -430 -8 -84 -49 -307 -60 -325 -2 -4 -6 -20 -9 -36 -3 -17
|
||||
-23 -77 -44 -135 -194 -521 -605 -937 -1124 -1135 -562 -214 -1202 -155 -1713
|
||||
160 -317 195 -564 466 -735 806 -60 120 -141 358 -156 465 -3 17 -9 55 -15 85
|
||||
-11 61 -23 217 -22 295 3 525 201 1002 571 1373 340 340 782 542 1247 568 55
|
||||
3 101 7 102 8 2 1 20 1 40 0 21 -2 76 -5 123 -8z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
20
docs/.vuepress/public/manifest.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "NoneBot",
|
||||
"short_name": "NoneBot",
|
||||
"background-color": "#ffffff",
|
||||
"theme-color": "#ea5252",
|
||||
"description": "An asynchronous python bot framework.",
|
||||
"display": "standalone",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icons/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/android-chrome-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
10
docs/.vuepress/public/plugins.json
Normal file
@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"id": "nonebot-plugin-status",
|
||||
"link": "nonebot-plugin-status",
|
||||
"name": "状态监控",
|
||||
"desc": "通过戳一戳获取服务器状态",
|
||||
"author": "nonebot",
|
||||
"repo": "nonebot/nonebot2"
|
||||
}
|
||||
]
|
@ -1,3 +1,3 @@
|
||||
[
|
||||
"2.0.0a2"
|
||||
"2.0.0a4"
|
||||
]
|
@ -3,7 +3,7 @@ home: true
|
||||
heroImage: /logo.png
|
||||
tagline: An asynchronous QQ bot framework.
|
||||
actionText: 开始使用
|
||||
actionLink: /guide/
|
||||
actionLink: guide/
|
||||
features:
|
||||
- title: 简洁
|
||||
details: 提供极其简洁易懂的 API,使你可以毫无压力地开始验证你的绝佳创意,只需编写最少量的代码,即可实现丰富的功能。
|
||||
|
@ -10,6 +10,9 @@
|
||||
* [nonebot.config](config.html)
|
||||
|
||||
|
||||
* [nonebot.plugin](plugin.html)
|
||||
|
||||
|
||||
* [nonebot.matcher](matcher.html)
|
||||
|
||||
|
||||
@ -34,6 +37,12 @@
|
||||
* [nonebot.exception](exception.html)
|
||||
|
||||
|
||||
* [nonebot.drivers](drivers/)
|
||||
|
||||
|
||||
* [nonebot.drivers.fastapi](drivers/fastapi.html)
|
||||
|
||||
|
||||
* [nonebot.adapters](adapters/)
|
||||
|
||||
|
||||
|
@ -405,7 +405,11 @@ CQHTTP 协议 Event 适配。继承属性参考 [BaseEvent](./#class-baseevent)
|
||||
|
||||
基类:[`nonebot.adapters.BaseMessageSegment`](#None)
|
||||
|
||||
CQHTTP 协议 MessageSegment 适配。具体方法参考协议消息段类型或源码。
|
||||
|
||||
|
||||
## _class_ `Message`
|
||||
|
||||
基类:[`nonebot.adapters.BaseMessage`](#None)
|
||||
|
||||
CQHTTP 协议 Message 适配。
|
||||
|
246
docs/api/drivers/README.md
Normal file
@ -0,0 +1,246 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.drivers 模块
|
||||
|
||||
## 后端驱动适配基类
|
||||
|
||||
各驱动请继承以下基类
|
||||
|
||||
|
||||
## _class_ `BaseDriver`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Driver 基类。将后端框架封装,以满足适配器使用。
|
||||
|
||||
|
||||
### `_adapters`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Type[Bot]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
已注册的适配器列表
|
||||
|
||||
|
||||
|
||||
### _abstract_ `__init__(env, config)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `env: Env`: 包含环境信息的 Env 对象
|
||||
|
||||
|
||||
* `config: Config`: 包含配置信息的 Config 对象
|
||||
|
||||
|
||||
|
||||
### `env`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`str`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
环境名称
|
||||
|
||||
|
||||
|
||||
### `config`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Config`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
配置对象
|
||||
|
||||
|
||||
|
||||
### `_clients`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Bot]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
已连接的 Bot
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `register_adapter(name, adapter)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个协议适配器
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `name: str`: 适配器名称,用于在连接时进行识别
|
||||
|
||||
|
||||
* `adapter: Type[Bot]`: 适配器 Class
|
||||
|
||||
|
||||
|
||||
### _abstract property_ `type`
|
||||
|
||||
驱动类型名称
|
||||
|
||||
|
||||
### _abstract property_ `server_app`
|
||||
|
||||
驱动 APP 对象
|
||||
|
||||
|
||||
### _abstract property_ `asgi`
|
||||
|
||||
驱动 ASGI 对象
|
||||
|
||||
|
||||
### _abstract property_ `logger`
|
||||
|
||||
驱动专属 logger 日志记录器
|
||||
|
||||
|
||||
### _property_ `bots`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Bot]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取当前所有已连接的 Bot
|
||||
|
||||
|
||||
|
||||
### _abstract_ `on_startup(func)`
|
||||
|
||||
注册一个在驱动启动时运行的函数
|
||||
|
||||
|
||||
### _abstract_ `on_shutdown(func)`
|
||||
|
||||
注册一个在驱动停止时运行的函数
|
||||
|
||||
|
||||
### _abstract_ `run(host=None, port=None, *args, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
启动驱动框架
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `host: Optional[str]`: 驱动绑定 IP
|
||||
|
||||
|
||||
* `post: Optional[int]`: 驱动绑定端口
|
||||
|
||||
|
||||
* `*args`
|
||||
|
||||
|
||||
* `**kwargs`
|
||||
|
||||
|
||||
|
||||
### _abstract async_ `_handle_http()`
|
||||
|
||||
用于处理 HTTP 类型请求的函数
|
||||
|
||||
|
||||
### _abstract async_ `_handle_ws_reverse()`
|
||||
|
||||
用于处理 WebSocket 类型请求的函数
|
||||
|
||||
|
||||
## _class_ `BaseWebSocket`
|
||||
|
||||
基类:`object`
|
||||
|
||||
WebSocket 连接封装,统一接口方便外部调用。
|
||||
|
||||
|
||||
### _abstract_ `__init__(websocket)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `websocket: Any`: WebSocket 连接对象
|
||||
|
||||
|
||||
|
||||
### _property_ `websocket`
|
||||
|
||||
WebSocket 连接对象
|
||||
|
||||
|
||||
### _abstract property_ `closed`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
连接是否已经关闭
|
||||
|
||||
|
||||
|
||||
### _abstract async_ `accept()`
|
||||
|
||||
接受 WebSocket 连接请求
|
||||
|
||||
|
||||
### _abstract async_ `close(code)`
|
||||
|
||||
关闭 WebSocket 连接请求
|
||||
|
||||
|
||||
### _abstract async_ `receive()`
|
||||
|
||||
接收一条 WebSocket 信息
|
||||
|
||||
|
||||
### _abstract async_ `send(data)`
|
||||
|
||||
发送一条 WebSocket 信息
|
125
docs/api/drivers/fastapi.md
Normal file
@ -0,0 +1,125 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.drivers.fastapi 模块
|
||||
|
||||
## FastAPI 驱动适配
|
||||
|
||||
后端使用方法请参考: [FastAPI 文档](https://fastapi.tiangolo.com/)
|
||||
|
||||
|
||||
## _class_ `Driver`
|
||||
|
||||
基类:[`nonebot.drivers.BaseDriver`](#None)
|
||||
|
||||
FastAPI 驱动框架
|
||||
|
||||
|
||||
### `__init__(env, config)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
|
||||
* `env: Env`: 包含环境信息的 Env 对象
|
||||
|
||||
|
||||
* `config: Config`: 包含配置信息的 Config 对象
|
||||
|
||||
|
||||
### _property_ `type`
|
||||
|
||||
驱动名称: `fastapi`
|
||||
|
||||
|
||||
### _property_ `server_app`
|
||||
|
||||
`FastAPI APP` 对象
|
||||
|
||||
|
||||
### _property_ `asgi`
|
||||
|
||||
`FastAPI APP` 对象
|
||||
|
||||
|
||||
### _property_ `logger`
|
||||
|
||||
fastapi 使用的 logger
|
||||
|
||||
|
||||
### `on_startup(func)`
|
||||
|
||||
参考文档: [Events](https://fastapi.tiangolo.com/advanced/events/#startup-event)
|
||||
|
||||
|
||||
### `on_shutdown(func)`
|
||||
|
||||
参考文档: [Events](https://fastapi.tiangolo.com/advanced/events/#startup-event)
|
||||
|
||||
|
||||
### `run(host=None, port=None, *, app=None, **kwargs)`
|
||||
|
||||
使用 `uvicorn` 启动 FastAPI
|
||||
|
||||
|
||||
### _async_ `_handle_http(adapter, data=Body(Ellipsis), x_self_id=Header(None), x_signature=Header(None), auth=Depends(get_auth_bearer))`
|
||||
|
||||
用于处理 HTTP 类型请求的函数
|
||||
|
||||
|
||||
### _async_ `_handle_ws_reverse(adapter, websocket, x_self_id=Header(None), auth=Depends(get_auth_bearer))`
|
||||
|
||||
用于处理 WebSocket 类型请求的函数
|
||||
|
||||
|
||||
## _class_ `WebSocket`
|
||||
|
||||
基类:[`nonebot.drivers.BaseWebSocket`](#None)
|
||||
|
||||
|
||||
### `__init__(websocket)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
|
||||
* `websocket: Any`: WebSocket 连接对象
|
||||
|
||||
|
||||
### _property_ `closed`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
连接是否已经关闭
|
||||
|
||||
|
||||
|
||||
### _async_ `accept()`
|
||||
|
||||
接受 WebSocket 连接请求
|
||||
|
||||
|
||||
### _async_ `close(code=1000)`
|
||||
|
||||
关闭 WebSocket 连接请求
|
||||
|
||||
|
||||
### _async_ `receive()`
|
||||
|
||||
接收一条 WebSocket 信息
|
||||
|
||||
|
||||
### _async_ `send(data)`
|
||||
|
||||
发送一条 WebSocket 信息
|
@ -377,7 +377,7 @@ sidebarDepth: 0
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `send(message)`
|
||||
### _async classmethod_ `send(message, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
@ -392,8 +392,11 @@ sidebarDepth: 0
|
||||
* `message: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `bot.send` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
|
||||
### _async classmethod_ `finish(message=None)`
|
||||
|
||||
|
||||
### _async classmethod_ `finish(message=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
@ -408,8 +411,11 @@ sidebarDepth: 0
|
||||
* `message: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `bot.send` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
|
||||
### _async classmethod_ `pause(prompt=None)`
|
||||
|
||||
|
||||
### _async classmethod_ `pause(prompt=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
@ -424,8 +430,11 @@ sidebarDepth: 0
|
||||
* `prompt: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `bot.send` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
|
||||
### _async classmethod_ `reject(prompt=None)`
|
||||
|
||||
|
||||
### _async classmethod_ `reject(prompt=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
@ -440,6 +449,9 @@ sidebarDepth: 0
|
||||
* `prompt: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `bot.send` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
|
||||
|
||||
|
||||
## _class_ `MatcherGroup`
|
||||
|
||||
|
629
docs/api/plugin.md
Normal file
@ -0,0 +1,629 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.plugin 模块
|
||||
|
||||
## 插件
|
||||
|
||||
为 NoneBot 插件开发提供便携的定义函数。
|
||||
|
||||
|
||||
## `plugins`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Plugin]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
已加载的插件
|
||||
|
||||
|
||||
|
||||
## _class_ `Plugin`
|
||||
|
||||
基类:`object`
|
||||
|
||||
存储插件信息
|
||||
|
||||
|
||||
### `name`
|
||||
|
||||
|
||||
* **类型**: `str`
|
||||
|
||||
|
||||
* **说明**: 插件名称,使用 文件/文件夹 名称作为插件名
|
||||
|
||||
|
||||
### `module`
|
||||
|
||||
|
||||
* **类型**: `ModuleType`
|
||||
|
||||
|
||||
* **说明**: 插件模块对象
|
||||
|
||||
|
||||
### `matcher`
|
||||
|
||||
|
||||
* **类型**: `Set[Type[Matcher]]`
|
||||
|
||||
|
||||
* **说明**: 插件内定义的 `Matcher`
|
||||
|
||||
|
||||
## `on(type='', rule=None, permission=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个基础事件响应器,可自定义类型。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `type: str`: 事件响应器类型
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_metaevent(rule=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个元事件响应器。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_message(rule=None, permission=None, *, handlers=None, temp=False, priority=1, block=True, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_notice(rule=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个通知事件响应器。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_request(rule=None, *, handlers=None, temp=False, priority=1, block=False, state=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个请求事件响应器。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_startswith(msg, rule=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息的\*\*文本部分\*\*以指定内容开头时响应。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 指定消息开头内容
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_endswith(msg, rule=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息的\*\*文本部分\*\*以指定内容结尾时响应。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 指定消息结尾内容
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_keyword(keywords, rule=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息纯文本部分包含关键词时响应。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `keywords: Set[str]`: 关键词列表
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_command(cmd, rule=None, aliases=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息以指定命令开头时响应。
|
||||
|
||||
命令匹配规则参考: [命令形式匹配](rule.html#command-command)
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `cmd: Union[str, Tuple[str, ...]]`: 指定命令内容
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `aliases: Optional[Set[Union[str, Tuple[str, ...]]]]`: 命令别名
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `on_regex(pattern, flags=0, rule=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个消息事件响应器,并且当消息匹配正则表达式时响应。
|
||||
|
||||
命令匹配规则参考: [正则匹配](rule.html#regex-regex-flags-0)
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `pattern: str`: 正则表达式
|
||||
|
||||
|
||||
* `flags: Union[int, re.RegexFlag]`: 正则匹配标志
|
||||
|
||||
|
||||
* `rule: Optional[Union[Rule, RuleChecker]]`: 事件响应规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 事件响应权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器(仅执行一次)
|
||||
|
||||
|
||||
* `priority: int`: 事件响应器优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级传递
|
||||
|
||||
|
||||
* `state: Optional[dict]`: 默认的 state
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## _class_ `CommandGroup`
|
||||
|
||||
基类:`object`
|
||||
|
||||
命令组,用于声明一组有相同名称前缀的命令。
|
||||
|
||||
|
||||
### `__init__(cmd, **kwargs)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `cmd: Union[str, Tuple[str, ...]]`: 命令前缀
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `on_command` 的参数默认值,参考 [on_command](#on-command-cmd-rule-none-aliases-none-kwargs)
|
||||
|
||||
|
||||
|
||||
### `basecmd`
|
||||
|
||||
|
||||
* **类型**: `Tuple[str, ...]`
|
||||
|
||||
|
||||
* **说明**: 命令前缀
|
||||
|
||||
|
||||
### `base_kwargs`
|
||||
|
||||
|
||||
* **类型**: `Dict[str, Any]`
|
||||
|
||||
|
||||
* **说明**: 其他传递给 `on_command` 的参数默认值
|
||||
|
||||
|
||||
### `command(cmd, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
注册一个新的命令。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `cmd: Union[str, Tuple[str, ...]]`: 命令前缀
|
||||
|
||||
|
||||
* `**kwargs`: 其他传递给 `on_command` 的参数,将会覆盖命令组默认值
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`
|
||||
|
||||
|
||||
|
||||
## `load_plugin(module_path)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
使用 `importlib` 加载单个插件,可以是本地插件或是通过 `pip` 安装的插件。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `module_path: str`: 插件名称 `path.to.your.plugin`
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Optional[Plugin]`
|
||||
|
||||
|
||||
|
||||
## `load_plugins(*plugin_dir)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
导入目录下多个插件,以 `_` 开头的插件不会被导入!
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*plugin_dir: str`: 插件路径
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Set[Plugin]`
|
||||
|
||||
|
||||
|
||||
## `load_builtin_plugins()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
导入 NoneBot 内置插件
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Plugin`
|
||||
|
||||
|
||||
|
||||
## `get_loaded_plugins()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取当前已导入的插件。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Set[Plugin]`
|
@ -123,7 +123,7 @@ Rule(async_function, run_sync(sync_function))
|
||||
|
||||
|
||||
|
||||
## `keyword(msg)`
|
||||
## `keyword(*keywords)`
|
||||
|
||||
|
||||
* **说明**
|
||||
@ -135,23 +135,25 @@ Rule(async_function, run_sync(sync_function))
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 关键词
|
||||
* `*keywords: str`: 关键词
|
||||
|
||||
|
||||
|
||||
## `command(command)`
|
||||
## `command(*cmds)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。
|
||||
|
||||
可以通过 `state["_prefix"]["command"]` 获取匹配成功的命令(例:`("test",)`),通过 `state["_prefix"]["raw_command"]` 获取匹配成功的原始命令文本(例:`"/test"`)。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `command: Tuples[str, ...]`: 命令内容
|
||||
* `*cmds: Union[str, Tuple[str, ...]]`: 命令内容
|
||||
|
||||
|
||||
|
||||
@ -173,7 +175,9 @@ Rule(async_function, run_sync(sync_function))
|
||||
|
||||
* **说明**
|
||||
|
||||
根据正则表达式进行匹配
|
||||
根据正则表达式进行匹配。
|
||||
|
||||
可以通过 `state["_matched"]` 获取正则表达式匹配成功的文本。
|
||||
|
||||
|
||||
|
||||
@ -186,6 +190,10 @@ Rule(async_function, run_sync(sync_function))
|
||||
* `flags: Union[int, re.RegexFlag]`: 正则标志
|
||||
|
||||
|
||||
:::tip 提示
|
||||
正则表达式匹配使用 search 而非 match,如需从头匹配请使用 `r"^xxx"` 来确保匹配开头
|
||||
:::
|
||||
|
||||
|
||||
## `to_me()`
|
||||
|
||||
|
@ -110,7 +110,7 @@ sidebarDepth: 0
|
||||
|
||||
|
||||
|
||||
## `PreProcessor`
|
||||
## `EventPreProcessor`
|
||||
|
||||
|
||||
* **类型**
|
||||
@ -121,7 +121,55 @@ sidebarDepth: 0
|
||||
|
||||
* **说明**
|
||||
|
||||
消息预处理函数 PreProcessor 类型
|
||||
事件预处理函数 EventPreProcessor 类型
|
||||
|
||||
|
||||
|
||||
|
||||
## `EventPostProcessor`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件预处理函数 EventPostProcessor 类型
|
||||
|
||||
|
||||
|
||||
|
||||
## `RunPreProcessor`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Matcher, Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器运行前预处理函数 RunPreProcessor 类型
|
||||
|
||||
|
||||
|
||||
|
||||
## `RunPostProcessor`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Matcher, List[Any], Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器运行前预处理函数 RunPostProcessor 类型,第二个参数包含运行时产生的错误以及 `ExpiredException`, `StopPropagation` (如果存在)
|
||||
|
||||
|
||||
|
||||
|
@ -20,11 +20,9 @@ NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人
|
||||
|
||||
## 它如何工作?
|
||||
|
||||
NoneBot 的运行离不开 酷 Q 和 CQHTTP 插件。酷 Q 扮演着「无头 QQ 客户端」的角色,它进行实际的消息、通知、请求的接收和发送,当 酷 Q 收到消息时,它将这个消息包装为一个事件(通知和请求同理),并通过它自己的插件机制将事件传送给 CQHTTP 插件,后者再根据其配置中的 `post_url` 或 `ws_reverse_url` 等项来将事件发送至 NoneBot。
|
||||
<!-- TODO: how to work -->
|
||||
|
||||
在 NoneBot 收到事件前,它底层的 aiocqhttp 实际已经先看到了事件,aiocqhttp 根据事件的类型信息,通知到 NoneBot 的相应函数。特别地,对于消息类型的事件,还将消息内容转换成了 `aiocqhttp.message.Message` 类型,以便处理。
|
||||
|
||||
NoneBot 的事件处理函数收到通知后,对于不同类型的事件,再做相应的预处理和解析,然后调用对应的插件,并向其提供适合此类事件的会话(Session)对象。NoneBot 插件的编写者要做的,就是利用 Session 对象中提供的数据,在插件的处理函数中实现所需的功能。
|
||||
~~未填坑~~
|
||||
|
||||
## 特色
|
||||
|
||||
|
@ -1,95 +1,8 @@
|
||||
# 编写插件
|
||||
# 注册事件响应器
|
||||
|
||||
本章将以一个天气查询插件为例,教学如何编写自己的命令。
|
||||
好了,现在插件已经创建完毕,我们可以开始编写实际代码了,下面将以一个简易单文件天气查询插件为例。
|
||||
|
||||
## 加载插件
|
||||
|
||||
在 [创建一个完整的项目](creating-a-project) 一章节中,我们已经创建了插件目录 `awesome_bot/plugins`,现在我们在机器人入口文件中加载它。当然,你也可以单独加载一个插件。
|
||||
|
||||
:::tip 提示
|
||||
加载插件目录时,目录下以 `_` 下划线开头的插件将不会被加载!
|
||||
:::
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5,7}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载单独的一个插件,参数为合法的python包名
|
||||
nonebot.load_plugin("nonebot.plugins.base")
|
||||
# 加载插件目录,该目录下为各插件,以下划线开头的插件将不会被加载
|
||||
nonebot.load_plugins("awesome_bot/plugins")
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
尝试运行 `nb run` 或者 `python bot.py`,可以看到日志输出了类似如下内容:
|
||||
|
||||
```plain
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "nonebot.plugins.base"
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "plugin_in_folder"
|
||||
```
|
||||
|
||||
## 创建插件
|
||||
|
||||
现在我们已经有了一个空的插件目录,我们可以开始创建插件了!插件有两种形式
|
||||
|
||||
### 单文件形式
|
||||
|
||||
在插件目录下创建名为 `weather.py` 的 Python 文件,暂时留空,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `weather.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候它已经可以被称为一个插件了,尽管它还什么都没做。
|
||||
|
||||
### 包形式
|
||||
|
||||
在插件目录下创建文件夹 `weather`,并在该文件夹下创建文件 `__init__.py`,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `weather`
|
||||
│ └── `__init__.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候 `weather` 就是一个合法的 Python 包了,同时也是合法的 NoneBot 插件,插件内容可以在 `__init__.py` 中编写。
|
||||
|
||||
## 编写真正的内容
|
||||
|
||||
好了,现在插件已经可以正确加载,我们可以开始编写命令的实际代码了。在 `weather.py` 中添加如下代码:
|
||||
在插件目录下 `weather.py` 中添加如下代码:
|
||||
|
||||
```python
|
||||
from nonebot import on_command
|
||||
@ -121,13 +34,13 @@ async def get_weather(city: str):
|
||||
|
||||
为了简单起见,我们在这里的例子中没有接入真实的天气数据,但要接入也非常简单,你可以使用中国天气网、和风天气等网站提供的 API。
|
||||
|
||||
下面我们来说明这段代码是如何工作的。
|
||||
接下来我们来说明这段代码是如何工作的。
|
||||
|
||||
:::tip 提示
|
||||
从这里开始,你需要对 Python 的 asyncio 编程有所了解,因为 NoneBot 是完全基于 asyncio 的,具体可以参考 [廖雪峰的 Python 教程](https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152)
|
||||
:::
|
||||
|
||||
### 注册一个 [事件响应器](../api/matcher.md)
|
||||
## [事件响应器](../api/matcher.md)
|
||||
|
||||
```python{4}
|
||||
from nonebot import on_command
|
||||
@ -147,47 +60,30 @@ weather = on_command("天气", rule=to_me(), permission=Permission(), priority=5
|
||||
|
||||
其他详细配置可以参考 API 文档,下面我们详细说明各个部分:
|
||||
|
||||
#### 事件响应器类型 type
|
||||
### 事件响应器类型 type
|
||||
|
||||
事件响应器类型其实就是对应 `Event.type` ,NoneBot 提供了一个基础类型事件响应器 `on()` 以及一些内置的事件响应器。
|
||||
事件响应器类型其实就是对应事件的类型 `Event.type` ,NoneBot 提供了一个基础类型事件响应器 `on()` 以及一些其他内置的事件响应器。
|
||||
|
||||
以下所有类型的事件响应器都是由 `on(type, rule)` 的形式进行了简化封装。
|
||||
|
||||
- `on("事件类型")`: 基础事件响应器,第一个参数为事件类型,空字符串表示不限
|
||||
- `on_metaevent()` ~ `on("meta_event")`: 元事件响应器
|
||||
- `on_message()` ~ `on("message")`: 消息事件响应器
|
||||
- `on_request()` ~ `on("request")`: 请求事件响应器
|
||||
- `on_notice()` ~ `on("notice")`: 通知事件响应器
|
||||
- `on_startswith(str)` ~ `on("message", startswith(str))`: 消息开头匹配处理器
|
||||
- `on_endswith(str)` ~ `on("message", endswith(str))`: 消息结尾匹配处理器
|
||||
- `on_command(str|tuple)` ~ `on("message", command(str|tuple))`: 命令处理器
|
||||
- `on_regex(pattern_str)` ~ `on("message", regex(pattern_str))`: 正则匹配处理器
|
||||
- `on_startswith(str)` ~ `on("message", startswith(str))`: 消息开头匹配响应器,参考 [startswith](../api/rule.md#startswith-msg)
|
||||
- `on_endswith(str)` ~ `on("message", endswith(str))`: 消息结尾匹配响应器,参考 [endswith](../api/rule.md#endswith-msg)
|
||||
- `on_keyword(set)` ~ `on("message", keyword(str))`: 消息关键词匹配响应器,参考 [keyword](../api/rule.md#keyword-keywords)
|
||||
- `on_command(str|tuple)` ~ `on("message", command(str|tuple))`: 命令响应器,参考 [command](../api/rule.md#command-cmds)
|
||||
- `on_regex(pattern_str)` ~ `on("message", regex(pattern_str))`: 正则匹配处理器,参考 [regex](../api/rule.md#regex-regex-flags-0)
|
||||
|
||||
#### 匹配规则 rule
|
||||
### 匹配规则 rule
|
||||
|
||||
事件响应器的匹配规则即 `Rule`,由非负个 `RuleChecker` 组成,当所有 `RuleChecker` 返回 `True` 时匹配成功。这些 `RuleChecker` 的形式如下:
|
||||
事件响应器的匹配规则即 `Rule`,详细内容在下方介绍。[直达](#自定义-rule)
|
||||
|
||||
```python
|
||||
async def check(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return True
|
||||
### 优先级 priority
|
||||
|
||||
def check(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return True
|
||||
```
|
||||
|
||||
`Rule` 和 `RuleChecker` 之间可以使用 `与 &` 互相组合:
|
||||
|
||||
```python
|
||||
from nonebot.rule import Rule
|
||||
|
||||
Rule(async_checker1) & sync_checker & async_checker2
|
||||
```
|
||||
|
||||
:::danger 警告
|
||||
`Rule(*checkers)` 只接受 async function,或使用 `nonebot.utils.run_sync` 自行包裹 sync function。在使用 `与 &` 时,NoneBot 会自动包裹 sync function
|
||||
:::
|
||||
|
||||
#### 优先级 priority
|
||||
|
||||
事件响应器的优先级代表事件响应器的执行顺序,同一优先级的事件响应器会 **同时执行!**
|
||||
事件响应器的优先级代表事件响应器的执行顺序,同一优先级的事件响应器会 **同时执行!**,优先级数字**越小**越先响应!优先级请从 `1` 开始排序!
|
||||
|
||||
:::tip 提示
|
||||
使用 `nonebot-test` 可以看到当前所有事件响应器的执行流程,有助理解事件响应流程!
|
||||
@ -198,12 +94,55 @@ pip install nonebot2[test]
|
||||
|
||||
:::
|
||||
|
||||
#### 阻断 block
|
||||
### 阻断 block
|
||||
|
||||
当有任意事件响应器发出了阻止事件传递信号时,该事件将不再会传递给下一优先级,直接结束处理。
|
||||
|
||||
NoneBot 内置的事件响应器中,所有 `message` 类的事件响应器默认会阻断事件传递,其他则不会。
|
||||
|
||||
## 自定义 rule
|
||||
|
||||
rule 的出现使得 nonebot 对事件的响应可以非常自由,nonebot 内置了一些规则:
|
||||
|
||||
- [startswith(msg)](../api/rule.md#startswith-msg)
|
||||
- [endswith(msg)](../api/rule.md#endswith-msg)
|
||||
- [keyword(*keywords)](../api/rule.md#keyword-keywords)
|
||||
- [command(*cmds)](../api/rule.md#command-cmds)
|
||||
- [regex(regex, flag)](../api/rule.md#regex-regex-flags-0)
|
||||
|
||||
以上规则都是返回类型为 `Rule` 的函数,`Rule` 由非负个 `RuleChecker` 组成,当所有 `RuleChecker` 返回 `True` 时匹配成功。这些 `Rule`, `RuleChecker` 的形式如下:
|
||||
|
||||
```python
|
||||
from nonebot.rule import Rule
|
||||
|
||||
async def async_checker(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return True
|
||||
|
||||
def sync_checker(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return True
|
||||
|
||||
def check(arg1, args2):
|
||||
|
||||
async def _checker(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return bool(arg1 + arg2)
|
||||
|
||||
return Rule(_check)
|
||||
```
|
||||
|
||||
`Rule` 和 `RuleChecker` 之间可以使用 `与 &` 互相组合:
|
||||
|
||||
```python
|
||||
from nonebot.rule import Rule
|
||||
|
||||
Rule(async_checker1) & sync_checker & async_checker2
|
||||
```
|
||||
|
||||
***请勿将事件处理的逻辑写入 `rule` 中,这会使得事件处理返回奇怪的响应。***
|
||||
|
||||
:::danger 警告
|
||||
`Rule(*checkers)` 只接受 async function,或使用 `nonebot.utils.run_sync` 自行包裹 sync function。在使用 `与 &` 时,NoneBot 会自动包裹 sync function
|
||||
:::
|
||||
|
||||
### 编写事件处理函数 [Handler](../api/typing.md#handler)
|
||||
|
||||
```python{1,2,8,9}
|
113
docs/guide/creating-a-plugin.md
Normal file
@ -0,0 +1,113 @@
|
||||
# 创建插件
|
||||
|
||||
如果之前使用 `nb-cli` 生成了项目结构,那我们已经有了一个空的插件目录 `Awesome-Bot/awesome_bot/plugins`,并且它已在 `bot.py` 中被加载,我们现在可以开始创建插件了!
|
||||
|
||||
插件通常有两种形式,下面分别介绍
|
||||
|
||||
## 单文件形式
|
||||
|
||||
在插件目录下创建名为 `foo.py` 的 Python 文件,暂时留空,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `foo.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候它已经可以被称为一个插件了,尽管它还什么都没做。
|
||||
|
||||
## 包形式(推荐)
|
||||
|
||||
在插件目录下创建文件夹 `foo`,并在该文件夹下创建文件 `__init__.py`,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `foo`
|
||||
│ └── `__init__.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候 `foo` 就是一个合法的 Python 包了,同时也是合法的 NoneBot 插件,插件内容可以在 `__init__.py` 中编写。
|
||||
|
||||
### 推荐结构(仅供参考)
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
foo
|
||||
├── `__init__.py`
|
||||
├── `config.py`
|
||||
├── `data_source.py`
|
||||
└── `model.py`
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### \_\_init\_\_.py
|
||||
|
||||
在该文件中编写各类事件响应及处理逻辑。
|
||||
|
||||
#### config.py
|
||||
|
||||
在该文件中使用 `pydantic` 定义插件所需要的配置项以及类型。
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
from pydantic import BaseSetting
|
||||
|
||||
|
||||
class Config(BaseSetting):
|
||||
|
||||
# plugin custom config
|
||||
plugin_setting: str = "default"
|
||||
|
||||
class Config:
|
||||
extra = "ignore"
|
||||
```
|
||||
|
||||
并在 `__init__.py` 文件中添加以下行
|
||||
|
||||
```python
|
||||
import nonebot
|
||||
from .config import Config
|
||||
|
||||
global_config = nonebot.get_bot().config
|
||||
plugin_config = Config(**global_config.dict())
|
||||
```
|
||||
|
||||
此时就可以通过 `plugin_config.plugin_setting` 获取到插件所需要的配置项了。
|
||||
|
||||
#### data_source.py
|
||||
|
||||
在该文件中编写数据获取函数。
|
||||
|
||||
:::warning 警告
|
||||
数据获取应尽量使用**异步**处理!例如使用 [httpx](https://www.python-httpx.org/) 而非 [requests](https://requests.readthedocs.io/en/master/)
|
||||
:::
|
||||
|
||||
#### model.py
|
||||
|
||||
在该文件中编写数据库模型。
|
@ -136,11 +136,11 @@ QQ 协议端举例:
|
||||
现在,尝试向你的 QQ 机器人账号发送如下内容:
|
||||
|
||||
```default
|
||||
/say 你好,世界
|
||||
/echo 你好,世界
|
||||
```
|
||||
|
||||
到这里如果一切 OK,你应该会收到机器人给你回复了 `你好,世界`。这一历史性的对话标志着你已经成功地运行了一个 NoneBot 的最小实例,开始了编写更强大的 QQ 机器人的创意之旅!
|
||||
|
||||
<ClientOnly>
|
||||
<Messenger :messages="[{ position: 'right', msg: '/say 你好,世界' }, { position: 'left', msg: '你好,世界' }]"/>
|
||||
<Messenger :messages="[{ position: 'right', msg: '/echo 你好,世界' }, { position: 'left', msg: '你好,世界' }]"/>
|
||||
</ClientOnly>
|
||||
|
@ -6,7 +6,10 @@
|
||||
请确保你的 Python 版本 >= 3.7。
|
||||
:::
|
||||
|
||||
请在安装 nonebot2 之前卸载 nonebot 1.x
|
||||
|
||||
```bash
|
||||
pip uninstall nonebot
|
||||
pip install nonebot2
|
||||
```
|
||||
|
||||
|
95
docs/guide/loading-a-plugin.md
Normal file
@ -0,0 +1,95 @@
|
||||
# 加载插件
|
||||
|
||||
在 [创建一个完整的项目](creating-a-project) 一章节中,我们已经创建了插件目录 `awesome_bot/plugins`,现在我们在机器人入口文件中加载它。当然,你也可以单独加载一个插件。
|
||||
|
||||
## 加载内置插件
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载 nonebot 内置插件
|
||||
nonebot.load_bulitin_plugins()
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
这将会加载 nonebot 内置的插件,它包含:
|
||||
|
||||
- 命令 `say`:可由**superuser**使用,可以将消息内容由特殊纯文本转为富文本
|
||||
- 命令 `echo`:可由任何人使用,将消息原样返回
|
||||
|
||||
以上命令均需要指定机器人,即私聊、群聊内@机器人、群聊内称呼机器人昵称。参考 [Rule: to_me](../api/rule.md#to-me)
|
||||
|
||||
## 加载插件目录
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载插件目录,该目录下为各插件,以下划线开头的插件将不会被加载
|
||||
nonebot.load_plugins("awesome_bot/plugins")
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
加载插件目录时,目录下以 `_` 下划线开头的插件将不会被加载!
|
||||
:::
|
||||
|
||||
:::warning 提示
|
||||
**插件不能存在相同名称!**
|
||||
:::
|
||||
|
||||
:::danger 警告
|
||||
插件间不应该存在过多的耦合,如果确实需要导入某个插件内的数据,可以使用如下两种方法:
|
||||
|
||||
1. (推荐) `from plugin_name import xxx` 而非 `from awesome_bot.plugins.plugin_name import xxx`
|
||||
2. 在需要导入其他插件的文件中添加 `__package__ = "plugins"; from .plugin_name import xxx` (将共同的上层目录设定为父包后使用相对导入)
|
||||
|
||||
具体可以参考:[nonebot/nonebot2#32](https://github.com/nonebot/nonebot2/issues/32)
|
||||
:::
|
||||
|
||||
## 加载单个插件
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5,7}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载一个 pip 安装的插件
|
||||
nonebot.load_plugin("nonebot_plugin_status")
|
||||
# 加载本地的单独插件
|
||||
nonebot.load_plugin("awesome_bot.plugins.xxx")
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
## 子插件(嵌套插件)
|
||||
|
||||
<!-- TODO: 子插件 -->
|
||||
|
||||
~~待填坑~~
|
||||
|
||||
## 运行结果
|
||||
|
||||
尝试运行 `nb run` 或者 `python bot.py`,可以看到日志输出了类似如下内容:
|
||||
|
||||
```plain
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "nonebot.plugins.base"
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "plugin_in_folder"
|
||||
```
|
@ -4,6 +4,7 @@ NoneBot Api Reference
|
||||
:模块索引:
|
||||
- `nonebot <nonebot.html>`_
|
||||
- `nonebot.config <config.html>`_
|
||||
- `nonebot.plugin <plugin.html>`_
|
||||
- `nonebot.matcher <matcher.html>`_
|
||||
- `nonebot.rule <rule.html>`_
|
||||
- `nonebot.permission <permission.html>`_
|
||||
@ -12,5 +13,7 @@ NoneBot Api Reference
|
||||
- `nonebot.utils <utils.html>`_
|
||||
- `nonebot.typing <typing.html>`_
|
||||
- `nonebot.exception <exception.html>`_
|
||||
- `nonebot.drivers <drivers/>`_
|
||||
- `nonebot.drivers.fastapi <drivers/fastapi.html>`_
|
||||
- `nonebot.adapters <adapters/>`_
|
||||
- `nonebot.adapters.cqhttp <adapters/cqhttp.html>`_
|
||||
|
13
docs_build/drivers/README.rst
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.drivers 模块
|
||||
=====================
|
||||
|
||||
.. automodule:: nonebot.drivers
|
||||
:members:
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
13
docs_build/drivers/fastapi.rst
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.drivers.fastapi 模块
|
||||
=====================
|
||||
|
||||
.. automodule:: nonebot.drivers.fastapi
|
||||
:members:
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
12
docs_build/plugin.rst
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.plugin 模块
|
||||
====================
|
||||
|
||||
.. automodule:: nonebot.plugin
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __init__
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
快捷导入
|
||||
========
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
协议适配基类
|
||||
============
|
||||
@ -288,6 +286,9 @@ class BaseMessageSegment(abc.ABC):
|
||||
def __setitem__(self, key, value):
|
||||
return setattr(self, key, value)
|
||||
|
||||
def get(self, key, default=None):
|
||||
return getattr(self, key, default)
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def text(cls, text: str) -> "BaseMessageSegment":
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
CQHTTP (OneBot) v11 协议适配
|
||||
============================
|
||||
@ -635,6 +633,9 @@ class Event(BaseEvent):
|
||||
|
||||
|
||||
class MessageSegment(BaseMessageSegment):
|
||||
"""
|
||||
CQHTTP 协议 MessageSegment 适配。具体方法参考协议消息段类型或源码。
|
||||
"""
|
||||
|
||||
@overrides(BaseMessageSegment)
|
||||
def __init__(self, type: str, data: Dict[str, Any]) -> None:
|
||||
@ -813,6 +814,9 @@ class MessageSegment(BaseMessageSegment):
|
||||
|
||||
|
||||
class Message(BaseMessage):
|
||||
"""
|
||||
CQHTTP 协议 Message 适配。
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
@overrides(BaseMessage)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import asyncio
|
||||
|
||||
from nonebot.config import Config
|
||||
from nonebot.adapters import BaseBot
|
||||
from nonebot.adapters import BaseBot, BaseEvent, BaseMessage, BaseMessageSegment
|
||||
from nonebot.typing import Any, Dict, List, Union, Driver, Optional, NoReturn, WebSocket, Iterable
|
||||
|
||||
|
||||
@ -750,7 +750,7 @@ class Bot(BaseBot):
|
||||
...
|
||||
|
||||
|
||||
class Event:
|
||||
class Event(BaseEvent):
|
||||
|
||||
def __init__(self, raw_event: dict):
|
||||
...
|
||||
@ -856,7 +856,7 @@ class Event:
|
||||
...
|
||||
|
||||
|
||||
class MessageSegment:
|
||||
class MessageSegment(BaseMessageSegment):
|
||||
|
||||
def __init__(self, type: str, data: Dict[str, Any]) -> None:
|
||||
...
|
||||
@ -982,7 +982,7 @@ class MessageSegment:
|
||||
...
|
||||
|
||||
|
||||
class Message:
|
||||
class Message(BaseMessage):
|
||||
|
||||
@staticmethod
|
||||
def _construct(msg: Union[str, dict, list]) -> Iterable[MessageSegment]:
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
配置
|
||||
====
|
||||
|
@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
后端驱动适配基类
|
||||
===============
|
||||
|
||||
各驱动请继承以下基类
|
||||
"""
|
||||
|
||||
import abc
|
||||
|
||||
@ -9,16 +13,48 @@ from nonebot.typing import Bot, Dict, Type, Union, Optional, Callable
|
||||
|
||||
|
||||
class BaseDriver(abc.ABC):
|
||||
"""
|
||||
Driver 基类。将后端框架封装,以满足适配器使用。
|
||||
"""
|
||||
|
||||
_adapters: Dict[str, Type[Bot]] = {}
|
||||
"""
|
||||
:类型: ``Dict[str, Type[Bot]]``
|
||||
:说明: 已注册的适配器列表
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __init__(self, env: Env, config: Config):
|
||||
"""
|
||||
:参数:
|
||||
* ``env: Env``: 包含环境信息的 Env 对象
|
||||
* ``config: Config``: 包含配置信息的 Config 对象
|
||||
"""
|
||||
self.env = env.environment
|
||||
"""
|
||||
:类型: ``str``
|
||||
:说明: 环境名称
|
||||
"""
|
||||
self.config = config
|
||||
"""
|
||||
:类型: ``Config``
|
||||
:说明: 配置对象
|
||||
"""
|
||||
self._clients: Dict[str, Bot] = {}
|
||||
"""
|
||||
:类型: ``Dict[str, Bot]``
|
||||
:说明: 已连接的 Bot
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def register_adapter(cls, name: str, adapter: Type[Bot]):
|
||||
"""
|
||||
:说明:
|
||||
注册一个协议适配器
|
||||
:参数:
|
||||
* ``name: str``: 适配器名称,用于在连接时进行识别
|
||||
* ``adapter: Type[Bot]``: 适配器 Class
|
||||
"""
|
||||
cls._adapters[name] = adapter
|
||||
logger.opt(
|
||||
colors=True).debug(f'Succeeded to load adapter "<y>{name}</y>"')
|
||||
@ -26,33 +62,43 @@ class BaseDriver(abc.ABC):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def type(self):
|
||||
"""驱动类型名称"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def server_app(self):
|
||||
"""驱动 APP 对象"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def asgi(self):
|
||||
"""驱动 ASGI 对象"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def logger(self):
|
||||
"""驱动专属 logger 日志记录器"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def bots(self) -> Dict[str, Bot]:
|
||||
"""
|
||||
:类型: ``Dict[str, Bot]``
|
||||
:说明: 获取当前所有已连接的 Bot
|
||||
"""
|
||||
return self._clients
|
||||
|
||||
@abc.abstractmethod
|
||||
def on_startup(self, func: Callable) -> Callable:
|
||||
"""注册一个在驱动启动时运行的函数"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def on_shutdown(self, func: Callable) -> Callable:
|
||||
"""注册一个在驱动停止时运行的函数"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
@ -61,44 +107,69 @@ class BaseDriver(abc.ABC):
|
||||
port: Optional[int] = None,
|
||||
*args,
|
||||
**kwargs):
|
||||
"""
|
||||
:说明:
|
||||
启动驱动框架
|
||||
:参数:
|
||||
* ``host: Optional[str]``: 驱动绑定 IP
|
||||
* ``post: Optional[int]``: 驱动绑定端口
|
||||
* ``*args``
|
||||
* ``**kwargs``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def _handle_http(self):
|
||||
"""用于处理 HTTP 类型请求的函数"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def _handle_ws_reverse(self):
|
||||
"""用于处理 WebSocket 类型请求的函数"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class BaseWebSocket(object):
|
||||
"""WebSocket 连接封装,统一接口方便外部调用。"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __init__(self, websocket):
|
||||
"""
|
||||
:参数:
|
||||
* ``websocket: Any``: WebSocket 连接对象
|
||||
"""
|
||||
self._websocket = websocket
|
||||
|
||||
@property
|
||||
def websocket(self):
|
||||
"""WebSocket 连接对象"""
|
||||
return self._websocket
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def closed(self):
|
||||
"""
|
||||
:类型: ``bool``
|
||||
:说明: 连接是否已经关闭
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def accept(self):
|
||||
"""接受 WebSocket 连接请求"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def close(self, code: int):
|
||||
"""关闭 WebSocket 连接请求"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def receive(self) -> dict:
|
||||
"""接收一条 WebSocket 信息"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def send(self, data: dict):
|
||||
"""发送一条 WebSocket 信息"""
|
||||
raise NotImplementedError
|
||||
|
@ -1,5 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
FastAPI 驱动适配
|
||||
================
|
||||
|
||||
后端使用方法请参考: `FastAPI 文档`_
|
||||
|
||||
.. _FastAPI 文档:
|
||||
https://fastapi.tiangolo.com/
|
||||
"""
|
||||
|
||||
import hmac
|
||||
import json
|
||||
@ -23,7 +30,7 @@ def get_auth_bearer(access_token: Optional[str] = Header(
|
||||
if not access_token:
|
||||
return None
|
||||
scheme, _, param = access_token.partition(" ")
|
||||
if scheme.lower() != "bearer":
|
||||
if scheme.lower() not in ["bearer", "token"]:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Not authenticated",
|
||||
headers={"WWW-Authenticate": "Bearer"})
|
||||
@ -31,6 +38,7 @@ def get_auth_bearer(access_token: Optional[str] = Header(
|
||||
|
||||
|
||||
class Driver(BaseDriver):
|
||||
"""FastAPI 驱动框架"""
|
||||
|
||||
def __init__(self, env: Env, config: Config):
|
||||
super().__init__(env, config)
|
||||
@ -50,29 +58,35 @@ class Driver(BaseDriver):
|
||||
@property
|
||||
@overrides(BaseDriver)
|
||||
def type(self) -> str:
|
||||
"""驱动名称: ``fastapi``"""
|
||||
return "fastapi"
|
||||
|
||||
@property
|
||||
@overrides(BaseDriver)
|
||||
def server_app(self) -> FastAPI:
|
||||
"""``FastAPI APP`` 对象"""
|
||||
return self._server_app
|
||||
|
||||
@property
|
||||
@overrides(BaseDriver)
|
||||
def asgi(self):
|
||||
"""``FastAPI APP`` 对象"""
|
||||
return self._server_app
|
||||
|
||||
@property
|
||||
@overrides(BaseDriver)
|
||||
def logger(self) -> logging.Logger:
|
||||
"""fastapi 使用的 logger"""
|
||||
return logging.getLogger("fastapi")
|
||||
|
||||
@overrides(BaseDriver)
|
||||
def on_startup(self, func: Callable) -> Callable:
|
||||
"""参考文档: `Events <https://fastapi.tiangolo.com/advanced/events/#startup-event>`_"""
|
||||
return self.server_app.on_event("startup")(func)
|
||||
|
||||
@overrides(BaseDriver)
|
||||
def on_shutdown(self, func: Callable) -> Callable:
|
||||
"""参考文档: `Events <https://fastapi.tiangolo.com/advanced/events/#startup-event>`_"""
|
||||
return self.server_app.on_event("shutdown")(func)
|
||||
|
||||
@overrides(BaseDriver)
|
||||
@ -82,6 +96,7 @@ class Driver(BaseDriver):
|
||||
*,
|
||||
app: Optional[str] = None,
|
||||
**kwargs):
|
||||
"""使用 ``uvicorn`` 启动 FastAPI"""
|
||||
LOGGING_CONFIG = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
异常
|
||||
====
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
日志
|
||||
====
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
事件响应器
|
||||
==========
|
||||
@ -262,7 +260,8 @@ class Matcher(metaclass=MatcherMeta):
|
||||
state["_current_key"] = key
|
||||
if key not in state:
|
||||
if prompt:
|
||||
await bot.send(event=event, message=prompt)
|
||||
await bot.send(event=event,
|
||||
message=str(prompt).format(**state))
|
||||
raise PausedException
|
||||
else:
|
||||
state["_skip_key"] = True
|
||||
@ -298,66 +297,70 @@ class Matcher(metaclass=MatcherMeta):
|
||||
return _decorator
|
||||
|
||||
@classmethod
|
||||
async def send(cls, message: Union[str, Message, MessageSegment]):
|
||||
async def send(cls, message: Union[str, Message, MessageSegment], **kwargs):
|
||||
"""
|
||||
:说明:
|
||||
发送一条消息给当前交互用户
|
||||
:参数:
|
||||
* ``message: Union[str, Message, MessageSegment]``: 消息内容
|
||||
* ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
"""
|
||||
bot = current_bot.get()
|
||||
event = current_event.get()
|
||||
await bot.send(event=event, message=message)
|
||||
await bot.send(event=event, message=message, **kwargs)
|
||||
|
||||
@classmethod
|
||||
async def finish(
|
||||
cls,
|
||||
async def finish(cls,
|
||||
message: Optional[Union[str, Message,
|
||||
MessageSegment]] = None) -> NoReturn:
|
||||
MessageSegment]] = None,
|
||||
**kwargs) -> NoReturn:
|
||||
"""
|
||||
:说明:
|
||||
发送一条消息给当前交互用户并结束当前事件响应器
|
||||
:参数:
|
||||
* ``message: Union[str, Message, MessageSegment]``: 消息内容
|
||||
* ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
"""
|
||||
bot = current_bot.get()
|
||||
event = current_event.get()
|
||||
if message:
|
||||
await bot.send(event=event, message=message)
|
||||
await bot.send(event=event, message=message, **kwargs)
|
||||
raise FinishedException
|
||||
|
||||
@classmethod
|
||||
async def pause(
|
||||
cls,
|
||||
async def pause(cls,
|
||||
prompt: Optional[Union[str, Message,
|
||||
MessageSegment]] = None) -> NoReturn:
|
||||
MessageSegment]] = None,
|
||||
**kwargs) -> NoReturn:
|
||||
"""
|
||||
:说明:
|
||||
发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后继续下一个处理函数
|
||||
:参数:
|
||||
* ``prompt: Union[str, Message, MessageSegment]``: 消息内容
|
||||
* ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
"""
|
||||
bot = current_bot.get()
|
||||
event = current_event.get()
|
||||
if prompt:
|
||||
await bot.send(event=event, message=prompt)
|
||||
await bot.send(event=event, message=prompt, **kwargs)
|
||||
raise PausedException
|
||||
|
||||
@classmethod
|
||||
async def reject(
|
||||
cls,
|
||||
async def reject(cls,
|
||||
prompt: Optional[Union[str, Message,
|
||||
MessageSegment]] = None) -> NoReturn:
|
||||
MessageSegment]] = None,
|
||||
**kwargs) -> NoReturn:
|
||||
"""
|
||||
:说明:
|
||||
发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后重新运行当前处理函数
|
||||
:参数:
|
||||
* ``prompt: Union[str, Message, MessageSegment]``: 消息内容
|
||||
* ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api
|
||||
"""
|
||||
bot = current_bot.get()
|
||||
event = current_event.get()
|
||||
if prompt:
|
||||
await bot.send(event=event, message=prompt)
|
||||
await bot.send(event=event, message=prompt, **kwargs)
|
||||
raise RejectedException
|
||||
|
||||
# 运行handlers
|
||||
@ -492,6 +495,7 @@ class MatcherGroup:
|
||||
return matcher
|
||||
|
||||
def args_parser(self, func: ArgsParser) -> ArgsParser:
|
||||
self._default_parser = func
|
||||
for matcher in self.matchers:
|
||||
matcher.args_parser(func)
|
||||
return func
|
||||
@ -532,7 +536,8 @@ class MatcherGroup:
|
||||
state["_current_key"] = key
|
||||
if key not in state:
|
||||
if prompt:
|
||||
await bot.send(event=event, message=prompt)
|
||||
await bot.send(event=event,
|
||||
message=str(prompt).format(state))
|
||||
raise PausedException
|
||||
else:
|
||||
state["_skip_key"] = True
|
||||
@ -567,37 +572,38 @@ class MatcherGroup:
|
||||
|
||||
return _decorator
|
||||
|
||||
async def send(self, message: Union[str, Message, MessageSegment]):
|
||||
async def send(self, message: Union[str, Message, MessageSegment],
|
||||
**kwargs):
|
||||
bot = current_bot.get()
|
||||
event = current_event.get()
|
||||
await bot.send(event=event, message=message)
|
||||
await bot.send(event=event, message=message, **kwargs)
|
||||
|
||||
async def finish(
|
||||
self,
|
||||
async def finish(self,
|
||||
message: Optional[Union[str, Message,
|
||||
MessageSegment]] = None) -> NoReturn:
|
||||
MessageSegment]] = None,
|
||||
**kwargs) -> NoReturn:
|
||||
bot = current_bot.get()
|
||||
event = current_event.get()
|
||||
if message:
|
||||
await bot.send(event=event, message=message)
|
||||
await bot.send(event=event, message=message, **kwargs)
|
||||
raise FinishedException
|
||||
|
||||
async def pause(
|
||||
self,
|
||||
async def pause(self,
|
||||
prompt: Optional[Union[str, Message,
|
||||
MessageSegment]] = None) -> NoReturn:
|
||||
MessageSegment]] = None,
|
||||
**kwargs) -> NoReturn:
|
||||
bot = current_bot.get()
|
||||
event = current_event.get()
|
||||
if prompt:
|
||||
await bot.send(event=event, message=prompt)
|
||||
await bot.send(event=event, message=prompt, **kwargs)
|
||||
raise PausedException
|
||||
|
||||
async def reject(
|
||||
self,
|
||||
async def reject(self,
|
||||
prompt: Optional[Union[str, Message,
|
||||
MessageSegment]] = None) -> NoReturn:
|
||||
MessageSegment]] = None,
|
||||
**kwargs) -> NoReturn:
|
||||
bot = current_bot.get()
|
||||
event = current_event.get()
|
||||
if prompt:
|
||||
await bot.send(event=event, message=prompt)
|
||||
await bot.send(event=event, message=prompt, **kwargs)
|
||||
raise RejectedException
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
@ -8,19 +5,37 @@ from nonebot.log import logger
|
||||
from nonebot.rule import TrieRule
|
||||
from nonebot.utils import escape_tag
|
||||
from nonebot.matcher import matchers
|
||||
from nonebot.typing import Set, Type, Union, NoReturn
|
||||
from nonebot.typing import Bot, Event, Matcher, PreProcessor
|
||||
from nonebot.exception import IgnoredException, ExpiredException
|
||||
from nonebot.exception import StopPropagation, _ExceptionContainer
|
||||
from nonebot.typing import Set, Type, Union, NoReturn, Bot, Event, Matcher
|
||||
from nonebot.typing import EventPreProcessor, RunPreProcessor, EventPostProcessor, RunPostProcessor
|
||||
|
||||
_event_preprocessors: Set[PreProcessor] = set()
|
||||
_event_preprocessors: Set[EventPreProcessor] = set()
|
||||
_event_postprocessors: Set[EventPostProcessor] = set()
|
||||
_run_preprocessors: Set[RunPreProcessor] = set()
|
||||
_run_postprocessors: Set[RunPostProcessor] = set()
|
||||
|
||||
|
||||
def event_preprocessor(func: PreProcessor) -> PreProcessor:
|
||||
def event_preprocessor(func: EventPreProcessor) -> EventPreProcessor:
|
||||
_event_preprocessors.add(func)
|
||||
return func
|
||||
|
||||
|
||||
def event_postprocessor(func: EventPostProcessor) -> EventPostProcessor:
|
||||
_event_postprocessors.add(func)
|
||||
return func
|
||||
|
||||
|
||||
def run_preprocessor(func: RunPreProcessor) -> RunPreProcessor:
|
||||
_run_preprocessors.add(func)
|
||||
return func
|
||||
|
||||
|
||||
def run_postprocessor(func: RunPostProcessor) -> RunPostProcessor:
|
||||
_run_postprocessors.add(func)
|
||||
return func
|
||||
|
||||
|
||||
async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
|
||||
state: dict) -> Union[None, NoReturn]:
|
||||
if Matcher.expire_time and datetime.now() > Matcher.expire_time:
|
||||
@ -38,7 +53,24 @@ async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
|
||||
logger.info(f"Event will be handled by {Matcher}")
|
||||
|
||||
matcher = Matcher()
|
||||
# TODO: BeforeMatcherRun
|
||||
|
||||
coros = list(
|
||||
map(lambda x: x(matcher, bot, event, state), _run_preprocessors))
|
||||
if coros:
|
||||
try:
|
||||
await asyncio.gather(*coros)
|
||||
except IgnoredException:
|
||||
logger.opt(colors=True).info(
|
||||
f"Matcher {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
|
||||
|
||||
exceptions = []
|
||||
|
||||
try:
|
||||
logger.debug(f"Running matcher {matcher}")
|
||||
await matcher.run(bot, event, state)
|
||||
@ -46,17 +78,30 @@ async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
f"<r><bg #f8bbd0>Running matcher {matcher} failed.</bg #f8bbd0></r>"
|
||||
)
|
||||
exceptions.append(e)
|
||||
|
||||
exceptions = []
|
||||
if Matcher.temp:
|
||||
exceptions.append(ExpiredException)
|
||||
if Matcher.block:
|
||||
exceptions.append(StopPropagation)
|
||||
|
||||
coros = list(
|
||||
map(lambda x: x(matcher, exceptions, bot, event, state),
|
||||
_run_postprocessors))
|
||||
if coros:
|
||||
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 exceptions:
|
||||
raise _ExceptionContainer(exceptions)
|
||||
|
||||
|
||||
async def handle_event(bot: Bot, event: Event):
|
||||
show_log = True
|
||||
log_msg = f"<m>{bot.type.upper()} </m>| {event.self_id} [{event.name}]: "
|
||||
if event.type == "message":
|
||||
log_msg += f"Message {event.id} from "
|
||||
@ -74,13 +119,13 @@ async def handle_event(bot: Bot, event: Event):
|
||||
elif event.type == "request":
|
||||
log_msg += f"Request {event.raw_event}"
|
||||
elif event.type == "meta_event":
|
||||
log_msg += f"MetaEvent {event.detail_type}"
|
||||
# log_msg += f"MetaEvent {event.detail_type}"
|
||||
show_log = False
|
||||
if show_log:
|
||||
logger.opt(colors=True).info(log_msg)
|
||||
|
||||
coros = []
|
||||
state = {}
|
||||
for preprocessor in _event_preprocessors:
|
||||
coros.append(preprocessor(bot, event, state))
|
||||
coros = list(map(lambda x: x(bot, event, state), _event_preprocessors))
|
||||
if coros:
|
||||
try:
|
||||
logger.debug("Running PreProcessors...")
|
||||
@ -89,6 +134,11 @@ async def handle_event(bot: Bot, event: Event):
|
||||
logger.opt(
|
||||
colors=True).info(f"Event {event.name} is <b>ignored</b>")
|
||||
return
|
||||
except Exception as e:
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
"<r><bg #f8bbd0>Error when running EventPreProcessors. "
|
||||
"Event ignored!</bg #f8bbd0></r>")
|
||||
return
|
||||
|
||||
# Trie Match
|
||||
_, _ = TrieRule.get_value(bot, event, state)
|
||||
@ -103,6 +153,7 @@ async def handle_event(bot: Bot, event: Event):
|
||||
for matcher in matchers[priority]
|
||||
]
|
||||
|
||||
if show_log:
|
||||
logger.debug(f"Checking for matchers in priority {priority}...")
|
||||
results = await asyncio.gather(*pending_tasks, return_exceptions=True)
|
||||
|
||||
@ -120,3 +171,13 @@ async def handle_event(bot: Bot, event: Event):
|
||||
)
|
||||
del matchers[priority][index - i]
|
||||
i += 1
|
||||
|
||||
coros = list(map(lambda x: x(bot, event, state), _event_postprocessors))
|
||||
if coros:
|
||||
try:
|
||||
logger.debug("Running PostProcessors...")
|
||||
await asyncio.gather(*coros)
|
||||
except Exception as e:
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
"<r><bg #f8bbd0>Error when running EventPostProcessors</bg #f8bbd0></r>"
|
||||
)
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
权限
|
||||
====
|
||||
|
@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
插件
|
||||
====
|
||||
|
||||
为 NoneBot 插件开发提供便携的定义函数。
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
@ -9,25 +13,43 @@ from dataclasses import dataclass
|
||||
from importlib._bootstrap import _load
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.permission import Permission
|
||||
from nonebot.typing import Handler, RuleChecker
|
||||
from nonebot.matcher import Matcher, MatcherGroup
|
||||
from nonebot.rule import Rule, startswith, endswith, command, regex
|
||||
from nonebot.typing import Set, List, Dict, Type, Tuple, Union, Optional, ModuleType
|
||||
from nonebot.rule import Rule, startswith, endswith, keyword, command, regex
|
||||
from nonebot.typing import Any, Set, List, Dict, Type, Tuple, Union, Optional, ModuleType
|
||||
|
||||
plugins: Dict[str, "Plugin"] = {}
|
||||
"""
|
||||
:类型: ``Dict[str, Plugin]``
|
||||
:说明: 已加载的插件
|
||||
"""
|
||||
|
||||
_tmp_matchers: Set[Type[Matcher]] = set()
|
||||
|
||||
|
||||
@dataclass(eq=False)
|
||||
class Plugin(object):
|
||||
"""存储插件信息"""
|
||||
name: str
|
||||
"""
|
||||
- **类型**: ``str``
|
||||
- **说明**: 插件名称,使用 文件/文件夹 名称作为插件名
|
||||
"""
|
||||
module: ModuleType
|
||||
"""
|
||||
- **类型**: ``ModuleType``
|
||||
- **说明**: 插件模块对象
|
||||
"""
|
||||
matcher: Set[Type[Matcher]]
|
||||
"""
|
||||
- **类型**: ``Set[Type[Matcher]]``
|
||||
- **说明**: 插件内定义的 ``Matcher``
|
||||
"""
|
||||
|
||||
|
||||
def on(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
def on(type: str = "",
|
||||
rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
permission: Optional[Permission] = None,
|
||||
*,
|
||||
handlers: Optional[List[Handler]] = None,
|
||||
@ -35,7 +57,22 @@ def on(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
priority: int = 1,
|
||||
block: bool = False,
|
||||
state: Optional[dict] = None) -> Type[Matcher]:
|
||||
matcher = Matcher.new("",
|
||||
"""
|
||||
:说明:
|
||||
注册一个基础事件响应器,可自定义类型。
|
||||
:参数:
|
||||
* ``type: str``: 事件响应器类型
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``permission: Optional[Permission]``: 事件响应权限
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
matcher = Matcher.new(type,
|
||||
Rule() & rule,
|
||||
permission or Permission(),
|
||||
temp=temp,
|
||||
@ -54,6 +91,19 @@ def on_metaevent(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
priority: int = 1,
|
||||
block: bool = False,
|
||||
state: Optional[dict] = None) -> Type[Matcher]:
|
||||
"""
|
||||
:说明:
|
||||
注册一个元事件响应器。
|
||||
:参数:
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
matcher = Matcher.new("meta_event",
|
||||
Rule() & rule,
|
||||
Permission(),
|
||||
@ -74,6 +124,20 @@ def on_message(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
priority: int = 1,
|
||||
block: bool = True,
|
||||
state: Optional[dict] = None) -> Type[Matcher]:
|
||||
"""
|
||||
:说明:
|
||||
注册一个消息事件响应器。
|
||||
:参数:
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``permission: Optional[Permission]``: 事件响应权限
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
matcher = Matcher.new("message",
|
||||
Rule() & rule,
|
||||
permission or Permission(),
|
||||
@ -93,6 +157,19 @@ def on_notice(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
priority: int = 1,
|
||||
block: bool = False,
|
||||
state: Optional[dict] = None) -> Type[Matcher]:
|
||||
"""
|
||||
:说明:
|
||||
注册一个通知事件响应器。
|
||||
:参数:
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
matcher = Matcher.new("notice",
|
||||
Rule() & rule,
|
||||
Permission(),
|
||||
@ -112,6 +189,19 @@ def on_request(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
priority: int = 1,
|
||||
block: bool = False,
|
||||
state: Optional[dict] = None) -> Type[Matcher]:
|
||||
"""
|
||||
:说明:
|
||||
注册一个请求事件响应器。
|
||||
:参数:
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
matcher = Matcher.new("request",
|
||||
Rule() & rule,
|
||||
Permission(),
|
||||
@ -127,23 +217,88 @@ def on_request(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
def on_startswith(msg: str,
|
||||
rule: Optional[Optional[Union[Rule, RuleChecker]]] = None,
|
||||
**kwargs) -> Type[Matcher]:
|
||||
return on_message(startswith(msg) & rule, **kwargs) if rule else on_message(
|
||||
startswith(msg), **kwargs)
|
||||
"""
|
||||
:说明:
|
||||
注册一个消息事件响应器,并且当消息的**文本部分**以指定内容开头时响应。
|
||||
:参数:
|
||||
* ``msg: str``: 指定消息开头内容
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``permission: Optional[Permission]``: 事件响应权限
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
return on_message(startswith(msg) & rule, **kwargs)
|
||||
|
||||
|
||||
def on_endswith(msg: str,
|
||||
rule: Optional[Optional[Union[Rule, RuleChecker]]] = None,
|
||||
**kwargs) -> Type[Matcher]:
|
||||
return on_message(endswith(msg) & rule, **kwargs) if rule else on_message(
|
||||
startswith(msg), **kwargs)
|
||||
"""
|
||||
:说明:
|
||||
注册一个消息事件响应器,并且当消息的**文本部分**以指定内容结尾时响应。
|
||||
:参数:
|
||||
* ``msg: str``: 指定消息结尾内容
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``permission: Optional[Permission]``: 事件响应权限
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
return on_message(endswith(msg) & rule, **kwargs)
|
||||
|
||||
|
||||
def on_keyword(keywords: Set[str],
|
||||
rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
**kwargs) -> Type[Matcher]:
|
||||
"""
|
||||
:说明:
|
||||
注册一个消息事件响应器,并且当消息纯文本部分包含关键词时响应。
|
||||
:参数:
|
||||
* ``keywords: Set[str]``: 关键词列表
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``permission: Optional[Permission]``: 事件响应权限
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
return on_message(keyword(*keywords) & rule, **kwargs)
|
||||
|
||||
|
||||
def on_command(cmd: Union[str, Tuple[str, ...]],
|
||||
rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
|
||||
**kwargs) -> Union[Type[Matcher], MatcherGroup]:
|
||||
if isinstance(cmd, str):
|
||||
cmd = (cmd,)
|
||||
**kwargs) -> Type[Matcher]:
|
||||
"""
|
||||
:说明:
|
||||
注册一个消息事件响应器,并且当消息以指定命令开头时响应。
|
||||
|
||||
命令匹配规则参考: `命令形式匹配 <rule.html#command-command>`_
|
||||
:参数:
|
||||
* ``cmd: Union[str, Tuple[str, ...]]``: 指定命令内容
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``aliases: Optional[Set[Union[str, Tuple[str, ...]]]]``: 命令别名
|
||||
* ``permission: Optional[Permission]``: 事件响应权限
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
|
||||
async def _strip_cmd(bot, event, state: dict):
|
||||
message = event.message
|
||||
@ -153,31 +308,85 @@ def on_command(cmd: Union[str, Tuple[str, ...]],
|
||||
handlers = kwargs.pop("handlers", [])
|
||||
handlers.insert(0, _strip_cmd)
|
||||
|
||||
if aliases:
|
||||
aliases = set(map(lambda x: (x,) if isinstance(x, str) else x, aliases))
|
||||
group = MatcherGroup("message",
|
||||
Rule() & rule,
|
||||
handlers=handlers,
|
||||
**kwargs)
|
||||
for cmd_ in [cmd, *aliases]:
|
||||
_tmp_matchers.add(group.new(rule=command(cmd_)))
|
||||
return group
|
||||
else:
|
||||
return on_message(command(cmd) & rule, handlers=handlers, **
|
||||
kwargs) if rule else on_message(
|
||||
command(cmd), handlers=handlers, **kwargs)
|
||||
commands = set([cmd]) | (aliases or set())
|
||||
return on_message(command(*commands) & rule, handlers=handlers, **kwargs)
|
||||
|
||||
|
||||
def on_regex(pattern: str,
|
||||
flags: Union[int, re.RegexFlag] = 0,
|
||||
rule: Optional[Rule] = None,
|
||||
**kwargs) -> Type[Matcher]:
|
||||
return on_message(regex(pattern, flags) &
|
||||
rule, **kwargs) if rule else on_message(
|
||||
regex(pattern, flags), **kwargs)
|
||||
"""
|
||||
:说明:
|
||||
注册一个消息事件响应器,并且当消息匹配正则表达式时响应。
|
||||
|
||||
命令匹配规则参考: `正则匹配 <rule.html#regex-regex-flags-0>`_
|
||||
:参数:
|
||||
* ``pattern: str``: 正则表达式
|
||||
* ``flags: Union[int, re.RegexFlag]``: 正则匹配标志
|
||||
* ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则
|
||||
* ``permission: Optional[Permission]``: 事件响应权限
|
||||
* ``handlers: Optional[List[Handler]]``: 事件处理函数列表
|
||||
* ``temp: bool``: 是否为临时事件响应器(仅执行一次)
|
||||
* ``priority: int``: 事件响应器优先级
|
||||
* ``block: bool``: 是否阻止事件向更低优先级传递
|
||||
* ``state: Optional[dict]``: 默认的 state
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
return on_message(regex(pattern, flags) & rule, **kwargs)
|
||||
|
||||
|
||||
class CommandGroup:
|
||||
"""命令组,用于声明一组有相同名称前缀的命令。"""
|
||||
|
||||
def __init__(self, cmd: Union[str, Tuple[str, ...]], **kwargs):
|
||||
"""
|
||||
:参数:
|
||||
* ``cmd: Union[str, Tuple[str, ...]]``: 命令前缀
|
||||
* ``**kwargs``: 其他传递给 ``on_command`` 的参数默认值,参考 `on_command <#on-command-cmd-rule-none-aliases-none-kwargs>`_
|
||||
"""
|
||||
self.basecmd: Tuple[str, ...] = (cmd,) if isinstance(cmd, str) else cmd
|
||||
"""
|
||||
- **类型**: ``Tuple[str, ...]``
|
||||
- **说明**: 命令前缀
|
||||
"""
|
||||
if "aliases" in kwargs:
|
||||
del kwargs["aliases"]
|
||||
self.base_kwargs: Dict[str, Any] = kwargs
|
||||
"""
|
||||
- **类型**: ``Dict[str, Any]``
|
||||
- **说明**: 其他传递给 ``on_command`` 的参数默认值
|
||||
"""
|
||||
|
||||
def command(self, cmd: Union[str, Tuple[str, ...]],
|
||||
**kwargs) -> Type[Matcher]:
|
||||
"""
|
||||
:说明:
|
||||
注册一个新的命令。
|
||||
:参数:
|
||||
* ``cmd: Union[str, Tuple[str, ...]]``: 命令前缀
|
||||
* ``**kwargs``: 其他传递给 ``on_command`` 的参数,将会覆盖命令组默认值
|
||||
:返回:
|
||||
- ``Type[Matcher]``
|
||||
"""
|
||||
sub_cmd = (cmd,) if isinstance(cmd, str) else cmd
|
||||
cmd = self.basecmd + sub_cmd
|
||||
|
||||
final_kwargs = self.base_kwargs.copy()
|
||||
final_kwargs.update(kwargs)
|
||||
return on_command(cmd, **final_kwargs)
|
||||
|
||||
|
||||
def load_plugin(module_path: str) -> Optional[Plugin]:
|
||||
"""
|
||||
:说明:
|
||||
使用 ``importlib`` 加载单个插件,可以是本地插件或是通过 ``pip`` 安装的插件。
|
||||
:参数:
|
||||
* ``module_path: str``: 插件名称 ``path.to.your.plugin``
|
||||
:返回:
|
||||
- ``Optional[Plugin]``
|
||||
"""
|
||||
try:
|
||||
_tmp_matchers.clear()
|
||||
if module_path in plugins:
|
||||
@ -202,6 +411,14 @@ def load_plugin(module_path: str) -> Optional[Plugin]:
|
||||
|
||||
|
||||
def load_plugins(*plugin_dir: str) -> Set[Plugin]:
|
||||
"""
|
||||
:说明:
|
||||
导入目录下多个插件,以 ``_`` 开头的插件不会被导入!
|
||||
:参数:
|
||||
- ``*plugin_dir: str``: 插件路径
|
||||
:返回:
|
||||
- ``Set[Plugin]``
|
||||
"""
|
||||
loaded_plugins = set()
|
||||
for module_info in pkgutil.iter_modules(plugin_dir):
|
||||
_tmp_matchers.clear()
|
||||
@ -209,7 +426,7 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]:
|
||||
if name.startswith("_"):
|
||||
continue
|
||||
|
||||
spec = module_info.module_finder.find_spec(name)
|
||||
spec = module_info.module_finder.find_spec(name, None)
|
||||
if spec.name in plugins:
|
||||
continue
|
||||
elif spec.name in sys.modules:
|
||||
@ -232,27 +449,21 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]:
|
||||
return loaded_plugins
|
||||
|
||||
|
||||
def load_builtin_plugins():
|
||||
def load_builtin_plugins() -> Optional[Plugin]:
|
||||
"""
|
||||
:说明:
|
||||
导入 NoneBot 内置插件
|
||||
:返回:
|
||||
- ``Plugin``
|
||||
"""
|
||||
return load_plugin("nonebot.plugins.base")
|
||||
|
||||
|
||||
def get_loaded_plugins() -> Set[Plugin]:
|
||||
"""
|
||||
:说明:
|
||||
获取当前已导入的插件。
|
||||
:返回:
|
||||
- ``Set[Plugin]``
|
||||
"""
|
||||
return set(plugins.values())
|
||||
|
||||
|
||||
class CommandGroup:
|
||||
|
||||
def __init__(self, cmd: Union[str, Tuple[str, ...]], **kwargs):
|
||||
self.basecmd = (cmd,) if isinstance(cmd, str) else cmd
|
||||
if "aliases" in kwargs:
|
||||
del kwargs["aliases"]
|
||||
self.base_kwargs = kwargs
|
||||
|
||||
def command(self, cmd: Union[str, Tuple[str, ...]],
|
||||
**kwargs) -> Union[Type[Matcher], MatcherGroup]:
|
||||
sub_cmd = (cmd,) if isinstance(cmd, str) else cmd
|
||||
cmd = self.basecmd + sub_cmd
|
||||
|
||||
final_kwargs = self.base_kwargs.copy()
|
||||
final_kwargs.update(kwargs)
|
||||
return on_command(cmd, **final_kwargs)
|
||||
|
@ -1,10 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
from typing import overload
|
||||
|
||||
from nonebot.typing import Rule, Matcher, Handler, Permission, RuleChecker, MatcherGroup
|
||||
from nonebot.typing import Rule, Matcher, Handler, Permission, RuleChecker
|
||||
from nonebot.typing import Set, List, Dict, Type, Tuple, Union, Optional, ModuleType
|
||||
|
||||
plugins: Dict[str, "Plugin"] = ...
|
||||
@ -18,7 +14,8 @@ class Plugin(object):
|
||||
matcher: Set[Type[Matcher]]
|
||||
|
||||
|
||||
def on(rule: Optional[Union[Rule, RuleChecker]] = ...,
|
||||
def on(type: str = ...,
|
||||
rule: Optional[Union[Rule, RuleChecker]] = ...,
|
||||
permission: Optional[Permission] = ...,
|
||||
*,
|
||||
handlers: Optional[List[Handler]] = ...,
|
||||
@ -72,8 +69,8 @@ def on_request(rule: Optional[Union[Rule, RuleChecker]] = ...,
|
||||
|
||||
def on_startswith(msg: str,
|
||||
rule: Optional[Optional[Union[Rule, RuleChecker]]] = ...,
|
||||
permission: Optional[Permission] = ...,
|
||||
*,
|
||||
permission: Optional[Permission] = ...,
|
||||
handlers: Optional[List[Handler]] = ...,
|
||||
temp: bool = ...,
|
||||
priority: int = ...,
|
||||
@ -84,8 +81,8 @@ def on_startswith(msg: str,
|
||||
|
||||
def on_endswith(msg: str,
|
||||
rule: Optional[Optional[Union[Rule, RuleChecker]]] = ...,
|
||||
permission: Optional[Permission] = ...,
|
||||
*,
|
||||
permission: Optional[Permission] = ...,
|
||||
handlers: Optional[List[Handler]] = ...,
|
||||
temp: bool = ...,
|
||||
priority: int = ...,
|
||||
@ -94,12 +91,10 @@ def on_endswith(msg: str,
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def on_command(cmd: Union[str, Tuple[str, ...]],
|
||||
rule: Optional[Union[Rule, RuleChecker]] = ...,
|
||||
aliases: None = ...,
|
||||
permission: Optional[Permission] = ...,
|
||||
def on_keyword(keywords: Set[str],
|
||||
rule: Optional[Optional[Union[Rule, RuleChecker]]] = ...,
|
||||
*,
|
||||
permission: Optional[Permission] = ...,
|
||||
handlers: Optional[List[Handler]] = ...,
|
||||
temp: bool = ...,
|
||||
priority: int = ...,
|
||||
@ -108,25 +103,24 @@ def on_command(cmd: Union[str, Tuple[str, ...]],
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def on_command(cmd: Union[str, Tuple[str, ...]],
|
||||
rule: Optional[Union[Rule, RuleChecker]] = ...,
|
||||
aliases: Set[Union[str, Tuple[str, ...]]] = ...,
|
||||
permission: Optional[Permission] = ...,
|
||||
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
|
||||
*,
|
||||
permission: Optional[Permission] = ...,
|
||||
handlers: Optional[List[Handler]] = ...,
|
||||
temp: bool = ...,
|
||||
priority: int = ...,
|
||||
block: bool = ...,
|
||||
state: Optional[dict] = ...) -> MatcherGroup:
|
||||
state: Optional[dict] = ...) -> Type[Matcher]:
|
||||
...
|
||||
|
||||
|
||||
def on_regex(pattern: str,
|
||||
flags: Union[int, re.RegexFlag] = 0,
|
||||
rule: Optional[Rule] = ...,
|
||||
permission: Optional[Permission] = ...,
|
||||
*,
|
||||
permission: Optional[Permission] = ...,
|
||||
handlers: Optional[List[Handler]] = ...,
|
||||
temp: bool = ...,
|
||||
priority: int = ...,
|
||||
@ -165,16 +159,15 @@ class CommandGroup:
|
||||
state: Optional[dict] = ...):
|
||||
...
|
||||
|
||||
def command(
|
||||
self,
|
||||
def command(self,
|
||||
cmd: Union[str, Tuple[str, ...]],
|
||||
rule: Optional[Union[Rule, RuleChecker]] = ...,
|
||||
aliases: Set[Union[str, Tuple[str, ...]]] = ...,
|
||||
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
|
||||
permission: Optional[Permission] = ...,
|
||||
*,
|
||||
handlers: Optional[List[Handler]] = ...,
|
||||
temp: bool = ...,
|
||||
priority: int = ...,
|
||||
block: bool = ...,
|
||||
state: Optional[dict] = ...) -> Union[Type[Matcher], MatcherGroup]:
|
||||
state: Optional[dict] = ...) -> Type[Matcher]:
|
||||
...
|
||||
|
@ -26,9 +26,9 @@ echo = on_command("echo", to_me())
|
||||
|
||||
@echo.handle()
|
||||
async def echo_escape(bot: Bot, event: Event, state: dict):
|
||||
Message = event.message.__class__
|
||||
MessageSegment = event.message[0].__class__
|
||||
# Message = event.message.__class__
|
||||
# MessageSegment = event.message[0].__class__
|
||||
|
||||
message = Message().append( # type: ignore
|
||||
MessageSegment.text(str(event.message)))
|
||||
await bot.send(message=message, event=event)
|
||||
# message = Message().append( # type: ignore
|
||||
# MessageSegment.text(str(event.message)))
|
||||
await bot.send(message=event.message, event=event)
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
规则
|
||||
====
|
||||
@ -184,26 +182,29 @@ def endswith(msg: str) -> Rule:
|
||||
return Rule(_endswith)
|
||||
|
||||
|
||||
def keyword(msg: str) -> Rule:
|
||||
def keyword(*keywords: str) -> Rule:
|
||||
"""
|
||||
:说明:
|
||||
匹配消息关键词
|
||||
:参数:
|
||||
* ``msg: str``: 关键词
|
||||
* ``*keywords: str``: 关键词
|
||||
"""
|
||||
|
||||
async def _keyword(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return bool(event.plain_text and msg in event.plain_text)
|
||||
return bool(event.plain_text and
|
||||
any(keyword in event.plain_text for keyword in keywords))
|
||||
|
||||
return Rule(_keyword)
|
||||
|
||||
|
||||
def command(command: Tuple[str, ...]) -> Rule:
|
||||
def command(*cmds: Union[str, Tuple[str, ...]]) -> Rule:
|
||||
"""
|
||||
:说明:
|
||||
命令形式匹配,根据配置里提供的 ``command_start``, ``command_sep`` 判断消息是否为命令。
|
||||
|
||||
可以通过 ``state["_prefix"]["command"]`` 获取匹配成功的命令(例:``("test",)``),通过 ``state["_prefix"]["raw_command"]`` 获取匹配成功的原始命令文本(例:``"/test"``)。
|
||||
:参数:
|
||||
* ``command: Tuples[str, ...]``: 命令内容
|
||||
* ``*cmds: Union[str, Tuple[str, ...]]``: 命令内容
|
||||
:示例:
|
||||
使用默认 ``command_start``, ``command_sep`` 配置
|
||||
|
||||
@ -218,6 +219,11 @@ def command(command: Tuple[str, ...]) -> Rule:
|
||||
config = get_driver().config
|
||||
command_start = config.command_start
|
||||
command_sep = config.command_sep
|
||||
commands = list(cmds)
|
||||
for index, command in enumerate(commands):
|
||||
if isinstance(command, str):
|
||||
commands[index] = command = (command,)
|
||||
|
||||
if len(command) == 1:
|
||||
for start in command_start:
|
||||
TrieRule.add_prefix(f"{start}{command[0]}", command)
|
||||
@ -226,7 +232,7 @@ def command(command: Tuple[str, ...]) -> Rule:
|
||||
TrieRule.add_prefix(f"{start}{sep.join(command)}", command)
|
||||
|
||||
async def _command(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return command == state["_prefix"]["command"]
|
||||
return state["_prefix"]["command"] in commands
|
||||
|
||||
return Rule(_command)
|
||||
|
||||
@ -234,16 +240,28 @@ def command(command: Tuple[str, ...]) -> Rule:
|
||||
def regex(regex: str, flags: Union[int, re.RegexFlag] = 0) -> Rule:
|
||||
"""
|
||||
:说明:
|
||||
根据正则表达式进行匹配
|
||||
根据正则表达式进行匹配。
|
||||
|
||||
可以通过 ``state["_matched"]`` 获取正则表达式匹配成功的文本。
|
||||
:参数:
|
||||
* ``regex: str``: 正则表达式
|
||||
* ``flags: Union[int, re.RegexFlag]``: 正则标志
|
||||
|
||||
\:\:\:tip 提示
|
||||
正则表达式匹配使用 search 而非 match,如需从头匹配请使用 ``r"^xxx"`` 来确保匹配开头
|
||||
\:\:\:
|
||||
"""
|
||||
|
||||
pattern = re.compile(regex, flags)
|
||||
|
||||
async def _regex(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return bool(pattern.search(str(event.message)))
|
||||
matched = pattern.search(str(event.message))
|
||||
if matched:
|
||||
state["_matched"] = matched.group()
|
||||
return True
|
||||
else:
|
||||
state["_matched"] = None
|
||||
return False
|
||||
|
||||
return Rule(_regex)
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
计划任务
|
||||
========
|
||||
|
@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
类型
|
||||
====
|
||||
@ -94,14 +92,41 @@ MessageSegment = TypeVar("MessageSegment", bound="BaseMessageSegment")
|
||||
所有 MessageSegment 的基类。
|
||||
"""
|
||||
|
||||
PreProcessor = Callable[[Bot, Event, dict], Union[Awaitable[None],
|
||||
EventPreProcessor = Callable[[Bot, Event, dict], Union[Awaitable[None],
|
||||
Awaitable[NoReturn]]]
|
||||
"""
|
||||
:类型: ``Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]``
|
||||
|
||||
:说明:
|
||||
|
||||
消息预处理函数 PreProcessor 类型
|
||||
事件预处理函数 EventPreProcessor 类型
|
||||
"""
|
||||
EventPostProcessor = Callable[[Bot, Event, dict], Union[Awaitable[None],
|
||||
Awaitable[NoReturn]]]
|
||||
"""
|
||||
:类型: ``Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]``
|
||||
|
||||
:说明:
|
||||
|
||||
事件预处理函数 EventPostProcessor 类型
|
||||
"""
|
||||
RunPreProcessor = Callable[["Matcher", Bot, Event, dict],
|
||||
Union[Awaitable[None], Awaitable[NoReturn]]]
|
||||
"""
|
||||
:类型: ``Callable[[Matcher, Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]``
|
||||
|
||||
:说明:
|
||||
|
||||
事件响应器运行前预处理函数 RunPreProcessor 类型
|
||||
"""
|
||||
RunPostProcessor = Callable[["Matcher", List[Any], Bot, Event, dict],
|
||||
Union[Awaitable[None], Awaitable[NoReturn]]]
|
||||
"""
|
||||
:类型: ``Callable[[Matcher, List[Any], Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]``
|
||||
|
||||
:说明:
|
||||
|
||||
事件响应器运行前预处理函数 RunPostProcessor 类型,第二个参数包含运行时产生的错误以及 ``ExpiredException``, ``StopPropagation`` (如果存在)
|
||||
"""
|
||||
|
||||
Matcher = TypeVar("Matcher", bound="MatcherClass")
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
import json
|
||||
import asyncio
|
||||
|
1693
package-lock.json
generated
18
package.json
@ -16,18 +16,22 @@
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vuepress dev docs",
|
||||
"build": "vuepress build docs"
|
||||
"build": "vuepress build docs",
|
||||
"lint": "npx prettier -c docs/**/* !docs/api/**/*",
|
||||
"lint:fix": "npx prettier --write docs/**/* !docs/api/**/*"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@vuepress/plugin-back-to-top": "^1.5.4",
|
||||
"@vuepress/plugin-medium-zoom": "^1.5.4",
|
||||
"vuepress": "^1.5.4",
|
||||
"vuepress-plugin-versioning": "^4.5.0",
|
||||
"vuepress-theme-titanium": "^4.5.1"
|
||||
"@vuepress/plugin-back-to-top": "^1.7.1",
|
||||
"@vuepress/plugin-medium-zoom": "^1.7.1",
|
||||
"@vuepress/plugin-pwa": "^1.7.1",
|
||||
"vuepress": "^1.7.1",
|
||||
"vuepress-plugin-versioning": "git+https://github.com/nonebot/vuepress-plugin-versioning.git",
|
||||
"vuepress-theme-nonebot": "git+https://github.com/nonebot/vuepress-theme-nonebot.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"vuetify": "^2.3.10",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"vuetify": "^2.3.16",
|
||||
"wowjs": "^1.1.3"
|
||||
}
|
||||
}
|
||||
|
6
pages/plugin-store.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
---
|
||||
|
||||
# 插件广场
|
||||
|
||||
<Plugins></Plugins>
|
1207
poetry.lock
generated
@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "nonebot2"
|
||||
version = "2.0.0a2"
|
||||
version = "2.0.0a4"
|
||||
description = "An asynchronous python bot framework."
|
||||
authors = ["yanyongyu <yanyongyu_1@126.com>"]
|
||||
license = "MIT"
|
||||
@ -24,7 +24,7 @@ include = ["nonebot/py.typed"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.7"
|
||||
httpx = "^0.13.3"
|
||||
httpx = "^0.16.1"
|
||||
loguru = "^0.5.1"
|
||||
pygtrie = "^2.3.3"
|
||||
fastapi = "^0.58.1"
|
||||
@ -32,7 +32,7 @@ uvicorn = "^0.11.5"
|
||||
pydantic = { extras = ["dotenv"], version = "^1.6.1" }
|
||||
apscheduler = { version = "^3.6.3", optional = true }
|
||||
nonebot-test = { version = "^0.1.0", optional = true }
|
||||
nb-cli = { version="^0.1.0", optional = true }
|
||||
nb-cli = { version="^0.2.0", optional = true }
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
yapf = "^0.30.0"
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from nonebot.typing import Bot, Event
|
||||
from nonebot.plugin import on_metaevent
|
||||
|
||||
|
@ -1,4 +1 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import test_command
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.typing import Event
|
||||
from nonebot.plugin import on_command
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.typing import Event
|
||||
from nonebot.plugin import on_startswith
|
||||
|
13
tests/test_plugins/test_processor.py
Normal file
@ -0,0 +1,13 @@
|
||||
from nonebot.typing import Bot, Event, Matcher
|
||||
from nonebot.message import event_preprocessor, run_preprocessor
|
||||
|
||||
|
||||
@event_preprocessor
|
||||
async def handle(bot: Bot, event: Event, state: dict):
|
||||
state["preprocessed"] = True
|
||||
print(event)
|
||||
|
||||
|
||||
@run_preprocessor
|
||||
async def run(matcher: Matcher, bot: Bot, event: Event, state: dict):
|
||||
print(matcher)
|