Merge branch 'dev' into richardchien-patch-1

This commit is contained in:
Ju4tCode
2021-05-29 18:15:32 +08:00
committed by GitHub
63 changed files with 1492 additions and 823 deletions

View File

@ -1,7 +1,7 @@
<template>
<v-card flat class="adapters">
<v-row>
<v-col cols="12" sm="4">
<v-row class="justify-center">
<v-col cols="12" sm="6">
<v-text-field
v-model="filterText"
dense
@ -9,7 +9,7 @@
outlined
clearable
hide-details
label="Filter Adapter"
label="搜索适配器"
>
<template v-slot:prepend-inner>
<div class="v-input__icon v-input__icon--prepend-inner">
@ -18,16 +18,16 @@
</template>
</v-text-field>
</v-col>
<v-col cols="12" sm="4">
<v-col cols="12" sm="6">
<v-dialog v-model="dialog" max-width="600px">
<template v-slot:activator="{ on, attrs }">
<v-btn dark block color="primary" v-bind="attrs" v-on="on"
>Publish Your Adapter
>发布适配器
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">Adapter Information</span>
<span class="headline">适配器信息</span>
</v-card-title>
<v-card-text>
<v-form ref="newAdapterForm" v-model="valid" lazy-validation>
@ -49,14 +49,14 @@
</v-col>
<v-col cols="12">
<v-text-field
v-model="newAdapter.id"
v-model="newAdapter.link"
label="PyPI 项目名"
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
v-model="newAdapter.link"
v-model="newAdapter.id"
label="协议 import 包名"
required
></v-text-field>
@ -75,7 +75,7 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialog = false">
Close
关闭
</v-btn>
<v-btn
:disabled="!valid"
@ -86,22 +86,23 @@
publishAdapter();
"
>
Publish
发布
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-col>
<v-col cols="12" sm="4">
</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-pagination
></v-col>
</v-row>
<hr />
<v-row>
<v-col
cols="12"
@ -138,7 +139,7 @@ import adapters from "../public/adapters.json";
export default {
name: "Adapters",
components: {
PublishCard
PublishCard,
},
data() {
return {
@ -152,8 +153,8 @@ export default {
desc: null,
id: null,
link: null,
repo: null
}
repo: null,
},
};
},
computed: {
@ -161,7 +162,7 @@ export default {
return Math.ceil(this.filteredAdapters.length / 10);
},
filteredAdapters() {
return this.adapters.filter(adapter => {
return this.adapters.filter((adapter) => {
return (
adapter.id.indexOf(this.filterText || "") != -1 ||
adapter.name.indexOf(this.filterText || "") != -1 ||
@ -173,7 +174,7 @@ export default {
displayAdapters() {
return this.filteredAdapters.slice((this.page - 1) * 10, this.page * 10);
},
publishPlugin() {
publishAdapter() {
if (!this.$refs.newAdapterForm.validate()) {
return;
}
@ -215,7 +216,7 @@ ${this.newAdapter.repo}
window.open(
`https://github.com/nonebot/nonebot2/issues/new?title=${title}&body=${body}&labels=Adapter`
);
}
}
},
},
};
</script>

View File

@ -1,7 +1,7 @@
<template>
<v-card flat class="bots">
<v-row>
<v-col cols="12" sm="4">
<v-col cols="12" sm="6">
<v-text-field
v-model="filterText"
dense
@ -9,7 +9,7 @@
outlined
clearable
hide-details
label="Filter Bot"
label="搜索机器人"
>
<template v-slot:prepend-inner>
<div class="v-input__icon v-input__icon--prepend-inner">
@ -18,16 +18,16 @@
</template>
</v-text-field>
</v-col>
<v-col cols="12" sm="4">
<v-col cols="12" sm="6">
<v-dialog v-model="dialog" max-width="600px">
<template v-slot:activator="{ on, attrs }">
<v-btn dark block color="primary" v-bind="attrs" v-on="on"
>Publish Your Bot
>发布机器人
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">Bot Information</span>
<span class="headline">机器人信息</span>
</v-card-title>
<v-card-text>
<v-form ref="newBotForm" v-model="valid" lazy-validation>
@ -61,7 +61,7 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialog = false">
Close
关闭
</v-btn>
<v-btn
:disabled="!valid"
@ -72,13 +72,15 @@
publishBot();
"
>
Publish
发布
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-col>
<v-col cols="12" sm="4">
</v-row>
<v-row>
<v-col cols="12">
<v-pagination
v-model="page"
:length="pageNum"
@ -87,7 +89,6 @@
></v-pagination>
</v-col>
</v-row>
<hr />
<v-row>
<v-col cols="12" sm="6" v-for="(bot, index) in displayBots" :key="index">
<PublishCard
@ -118,7 +119,7 @@ import bots from "../public/bots.json";
export default {
name: "Bots",
components: {
PublishCard
PublishCard,
},
data() {
return {
@ -130,8 +131,8 @@ export default {
newBot: {
name: null,
desc: null,
repo: null
}
repo: null,
},
};
},
computed: {
@ -139,7 +140,7 @@ export default {
return Math.ceil(this.filteredBots.length / 10);
},
filteredBots() {
return this.bots.filter(bot => {
return this.bots.filter((bot) => {
return (
bot.name.indexOf(this.filterText || "") != -1 ||
bot.desc.indexOf(this.filterText || "") != -1 ||
@ -183,7 +184,7 @@ ${this.newBot.repo}
window.open(
`https://github.com/nonebot/nonebot2/issues/new?title=${title}&body=${body}&labels=Bot`
);
}
}
},
},
};
</script>

View File

@ -136,8 +136,8 @@ export default {
props: {
messages: {
type: Array,
default: () => []
}
default: () => [],
},
},
methods: {
initWOW: function() {
@ -146,13 +146,13 @@ export default {
animateClass: "animate__animated",
offset: 0,
mobile: true,
live: true
live: true,
}).init();
}
},
},
mounted() {
this.initWOW();
}
},
};
</script>

View File

@ -1,7 +1,7 @@
<template>
<v-card flat class="plugins">
<v-row>
<v-col cols="12" sm="4">
<v-col cols="12" sm="6">
<v-text-field
v-model="filterText"
dense
@ -9,7 +9,7 @@
outlined
clearable
hide-details
label="Filter Plugin"
label="搜索插件"
>
<template v-slot:prepend-inner>
<div class="v-input__icon v-input__icon--prepend-inner">
@ -18,16 +18,16 @@
</template>
</v-text-field>
</v-col>
<v-col cols="12" sm="4">
<v-col cols="12" sm="6">
<v-dialog v-model="dialog" max-width="600px">
<template v-slot:activator="{ on, attrs }">
<v-btn dark block color="primary" v-bind="attrs" v-on="on"
>Publish Your Plugin
>发布插件
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">Plugin Information</span>
<span class="headline">插件信息</span>
</v-card-title>
<v-card-text>
<v-form ref="newPluginForm" v-model="valid" lazy-validation>
@ -75,7 +75,7 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialog = false">
Close
关闭
</v-btn>
<v-btn
:disabled="!valid"
@ -86,13 +86,15 @@
publishPlugin();
"
>
Publish
发布
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-col>
<v-col cols="12" sm="4">
</v-row>
<v-row>
<v-col cols="12">
<v-pagination
v-model="page"
:length="pageNum"
@ -101,7 +103,6 @@
></v-pagination>
</v-col>
</v-row>
<hr />
<v-row>
<v-col
cols="12"
@ -115,7 +116,7 @@
:id="plugin.id"
:author="plugin.author"
:link="plugin.repo"
text="copy nb install command"
text="点此复制安装命令"
:command="`nb plugin install ${plugin.id}`"
></PublishCard>
</v-col>
@ -140,7 +141,7 @@ import plugins from "../public/plugins.json";
export default {
name: "Plugins",
components: {
PublishCard
PublishCard,
},
data() {
return {
@ -154,8 +155,8 @@ export default {
desc: null,
id: null,
link: null,
repo: null
}
repo: null,
},
};
},
computed: {
@ -163,7 +164,7 @@ export default {
return Math.ceil(this.filteredPlugins.length / 10);
},
filteredPlugins() {
return this.plugins.filter(plugin => {
return this.plugins.filter((plugin) => {
return (
plugin.id.indexOf(this.filterText || "") != -1 ||
plugin.name.indexOf(this.filterText || "") != -1 ||
@ -217,7 +218,7 @@ ${this.newPlugin.repo}
window.open(
`https://github.com/nonebot/nonebot2/issues/new?title=${title}&body=${body}&labels=Plugin`
);
}
}
},
},
};
</script>

View File

@ -28,7 +28,7 @@
{{ text }}
<v-icon right small>fa-copy</v-icon>
</v-btn>
<v-snackbar v-model="snackbar">Copied!</v-snackbar>
<v-snackbar v-model="snackbar">复制成功</v-snackbar>
</v-card-actions>
</v-card>
</template>
@ -44,17 +44,17 @@ export default {
author: String,
link: String,
text: String,
command: String
command: String,
},
data() {
return {
snackbar: false
snackbar: false,
};
},
computed: {
showCommand() {
return this.text && this.command;
}
},
},
methods: {
repoLink(repo) {
@ -65,11 +65,11 @@ export default {
},
copyCommand() {
copy(this.command, {
format: "text/plain"
format: "text/plain",
});
this.snackbar = true;
}
}
},
},
};
</script>

View File

@ -10,7 +10,7 @@
}}</v-tab>
</v-tabs>
</v-toolbar>
<v-tabs-items class="sub-item" v-model="tab">
<v-tabs-items class="sub-item pt-1" v-model="tab">
<v-tab-item>
<Adapter></Adapter>
</v-tab-item>
@ -37,7 +37,7 @@ export default {
components: {
Adapter,
Plugin,
Bot
Bot,
},
data() {
return {
@ -45,12 +45,12 @@ export default {
tabs: {
0: "协议",
1: "插件",
2: "机器人"
}
2: "机器人",
},
};
},
computed: {},
methods: {}
methods: {},
};
</script>

View File

@ -1 +1,64 @@
# 事件处理函数重载
当我们在编写 `nonebot2` 应用时,常常会遇到这样一个问题:该怎么让同一类型的不同事件执行不同的响应逻辑?又或者如何让不同的 `adapter` 针对同一类型的事件作出不同响应?
针对这个问题, `nonebot2` 提供一个便捷而高效的解决方案:事件处理函数重载机制。简单地说,`handler` (事件处理函数) 会根据其参数的 `type hints` ([PEP484 类型标注](https://www.python.org/dev/peps/pep-0484/)) 来对相对应的 `adapter``Event` 进行响应,并且会忽略不符合其参数类型标注的情况。
必须要注意的是,该机制利用了 `inspect` 标准库获取到了事件处理函数的 `singnature` (签名) ,进一步获取到参数名称和类型标注。故而,我们在编写 `handler` 时,参数的名称和类型标注必须要符合 `T_Handler` 规定,详情可以参看 **指南** 中的[事件处理](../guide/creating-a-handler)。
::: tip 提示
如果想了解更多关于 `inspect` 标准库的信息,可以查看[官方文档](https://docs.python.org/zh-cn/3.9/library/inspect.html)。
:::
下面,我们会以 `CQHTTP` 中的 `群聊消息事件``私聊消息事件` 为例,对该机制的应用进行简单的介绍。
## 一个例子
首先,我们需要导入需要的方法、类型。
```python
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, PrivateMessageEvent
```
之后,我们可以注册一个 `Matcher` 来响应 `消息事件`
```python
matcher = on_command("testoverload")
```
最后, 我们编写不同的 `handler` 并编写不同的类型标注来实现事件处理函数重载:
```python
@matcher.handle()
async def _(bot: Bot, event: GroupMessageEvent):
await matcher.send("群聊消息事件响应成功!")
@matcher.handle()
async def _(bot: Bot, event: PrivateMessageEvent):
await matcher.send("私聊消息事件响应成功!")
```
此时,我们可以在群聊或私聊中对我们的机器人发送 `testoverload` ,它会在不同的场景做出不同的应答。
这样一个简单的事件处理函数重载就完成了。
## 进阶
事件处理函数重载机制同样支持被 `matcher.got` 等装饰器装饰的函数。 例如:
```python
@matcher.got("key1", prompt="群事件提问")
async def _(bot: Bot, event: GroupMessageEvent):
await matcher.send("群聊消息事件响应成功!")
@matcher.got("key2", prompt="私聊事件提问")
async def _(bot: Bot, event: PrivateMessageEvent):
await matcher.send("私聊消息事件响应成功!")
```
只有触发事件符合的函数才会触发装饰器。

View File

@ -1,2 +1,90 @@
# 权限控制
**权限控制**是机器人在实际应用中需要解决的重点问题之一,`Nonebot` 提供了十分完善且灵活的权限控制机制—— `Permission` 机制。接下来我们将对这个机制进行简单的说明。
## 应用
如同 `Rule` 一样, `Permission` 可以在[注册事件响应器](../guide/creating-a-matcher)时添加 `permission` 参数来加以应用,这样 `Nonebot` 会在事件响应时检测事件主体的权限。下面我们以 `SUPERUSER` 为例,对该机制的应用做一下介绍。
```python
from nonebot.permission import SUPERUSER
from nonebot.adapters import Bot
from nonebot import on_command
matcher = on_command("测试超管", permission=SUPERUSER)
@matcher.handle()
async def _(bot: Bot):
await matcher.send("超管命令测试成功")
@matcher.got("key1", "超管提问")
async def _(bot: Bot, event: Event):
await matcher.send("超管命令got成功")
```
在这段代码中,我们事件响应器指定了 `SUPERUSER` 这样一个权限,那么机器人只会响应超级管理员的 `测试超管` 命令,并且会响应该超级管理员的连续对话。
::: tip 提示
在这里需要强调的是,`Permission``Rule` 的表现并不相同, `Rule` 只会在初次响应时生效,在余下的对话中并没有限制事件;但是 `Permission` 会持续生效,在连续对话中会一直对事件主体加以限制。
:::
## 进阶
`Permission` 除了可以在注册事件响应器时加以应用,还可以在编写事件处理函数 `handler` 时主动调用,我们可以利用这个特性在一个 `handler` 里对不同权限的事件主体进行区别响应,下面我们以 `CQHTTP` 中的 `GROUP_ADMIN` (普通管理员非群主)和 `GROUP_OWNER` 为例,说明下怎么进行主动调用。
```python
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot
from nonebot.adapters.cqhttp import GroupMessageEvent
from nonebot.adapters.cqhttp import GROUP_ADMIN, GROUP_OWNER
matcher = on_command("测试权限")
@matcher.handle()
async def _(bot: Bot, event: GroupMessageEvent):
if await GROUP_ADMIN(bot, event):
await matcher.send("管理员测试成功")
elif await GROUP_OWNER(bot, event):
await matcher.send("群主测试成功")
else:
await matcher.send("群员测试成功")
```
在这段代码里,我们并没有对命令的权限指定,这个命令会响应所有在群聊中的 `测试权限` 命令,但是在 `handler` 里,我们对两个 `Permission` 进行主动调用,从而可以对不同的角色进行不同的响应。
## 自定义
如同 `Rule` 一样, `Permission` 也是由非负数个 `PermissionChecker` 组成的,但只需其中一个返回 `True` 时就会匹配成功。下面则是 `PermissionChecker``Permission` 示例:
```python
from nonebot.adapters import Bot, Event
from nonebot.permission import Permission
async def async_checker(bot: Bot, event: Event) -> bool:
return True
def sync_checker(bot: Bot, event: Event) -> bool:
return True
def check(arg1, arg2):
async def _checker(bot: Bot, event: Event) -> bool:
return bool(arg1 + arg2)
return Permission(_checker)
```
`Permission``PermissionChecker` 之间可以使用 `或 |` 互相组合:
```python
from nonebot.permission import Permission
Permission(async_checker1) | sync_checker | async_checker2
```
同样地,如果想用 `Permission(*checkers)` 包裹构造 `Permission` ,函数必须是异步的;但是在利用 `或 |` 符号连接构造时, `Nonebot` 会自动包裹同步函数为异步函数。

View File

@ -6,9 +6,9 @@
## 从 NoneBot v1 迁移
`APScheduler` 作为 `nonebot` v1 的可选依赖,为众多 bot 提供了方便的定时任务功能。`nonebot2` 已将 `APScheduler` 独立为 `nonebot_plugin_apscheduler` 插件,你可以在 [插件广场](https://v2.nonebot.dev/plugin-store.html) 中找到它。
`APScheduler` 作为 `nonebot` v1 的可选依赖,为众多 bot 提供了方便的定时任务功能。`nonebot2` 已将 `APScheduler` 独立为 `nonebot_plugin_apscheduler` 插件,你可以在 [商店](https://v2.nonebot.dev/store.html) 中找到它。
相比于 `nonebot` v1`nonebot` v2只需要安装插件并修改 `scheduler` 的导入方式即可完成迁移。
相比于 `nonebot` v1`nonebot` v2 只需要安装插件并修改 `scheduler` 的导入方式即可完成迁移。
## 安装插件

View File

@ -191,9 +191,6 @@ Adapter 类型
* `api: str`: API 名称
* `self_id: Optional[str]`: 指定调用 API 的机器人
* `**data`: API 数据
@ -256,7 +253,7 @@ await bot.send_msg(message="hello world")
## _class_ `Message`
基类:`list`, `abc.ABC`
基类:`List`[`nonebot.adapters._base.T_MessageSegment`], `abc.ABC`
消息数组

View File

@ -312,12 +312,108 @@ CQHTTP 协议 Bot 适配。继承属性参考 [BaseBot](./#class-basebot) 。
CQHTTP 协议 MessageSegment 适配。具体方法参考协议消息段类型或源码。
### `is_text()`
### _static_ `anonymous(ignore_failure=None)`
### _static_ `at(user_id)`
### _static_ `contact(type_, id)`
### _static_ `contact_group(group_id)`
### _static_ `contact_user(user_id)`
### _static_ `dice()`
### _static_ `face(id_)`
### _static_ `forward(id_)`
### _static_ `image(file, type_=None, cache=True, proxy=True, timeout=None)`
### _static_ `json(data)`
### _static_ `location(latitude, longitude, title=None, content=None)`
### _static_ `music(type_, id_)`
### _static_ `music_custom(url, audio, title, content=None, img_url=None)`
### _static_ `node(id_)`
### _static_ `node_custom(user_id, nickname, content)`
### _static_ `poke(type_, id_)`
### _static_ `record(file, magic=None, cache=None, proxy=None, timeout=None)`
### _static_ `reply(id_)`
### _static_ `rps()`
### _static_ `shake()`
### _static_ `share(url='', title='', content=None, image=None)`
### _static_ `text(text)`
### _static_ `video(file, cache=None, proxy=None, timeout=None)`
### _static_ `xml(data)`
### `type`
* 类型: `str`
* 说明: 消息段类型
### `data`
* 类型: `Dict[str, Union[str, list]]`
* 说明: 消息段数据
## _class_ `Message`
基类:[`nonebot.adapters._base.Message`](README.md#nonebot.adapters._base.Message)
基类:[`nonebot.adapters._base.Message`](README.md#nonebot.adapters._base.Message)[`nonebot.adapters.cqhttp.message.MessageSegment`]
CQHTTP 协议 Message 适配。
### `extract_plain_text()`
# NoneBot.adapters.cqhttp.permission 模块

View File

@ -292,7 +292,7 @@ message += MessageSegment.atDingtalkIds(event.senderId)
## _class_ `Message`
基类:[`nonebot.adapters._base.Message`](README.md#nonebot.adapters._base.Message)
基类:[`nonebot.adapters._base.Message`](README.md#nonebot.adapters._base.Message)[`nonebot.adapters.ding.message.MessageSegment`]
钉钉 协议 Message 适配。

View File

@ -963,7 +963,7 @@ Mirai-API-HTTP 协议 MessageSegment 适配。具体方法参考 [mirai-api-http
## _class_ `MessageChain`
基类:[`nonebot.adapters._base.Message`](README.md#nonebot.adapters._base.Message)
基类:[`nonebot.adapters._base.Message`](README.md#nonebot.adapters._base.Message)[`nonebot.adapters.mirai.message.MessageSegment`]
Mirai 协议 Message 适配

View File

@ -106,6 +106,30 @@ NoneBot 主要配置。大小写不敏感。
### `log_level`
* **类型**: `Union[int, str]`
* **默认值**: `None`
* **说明**
配置 NoneBot 日志输出等级,可以为 `int` 类型等级或等级名称,参考 [loguru 日志等级](https://loguru.readthedocs.io/en/stable/api/logger.html#levels)。
* **示例**
```default
LOG_LEVEL=25
LOG_LEVEL=INFO
```
### `api_root`

View File

@ -14,7 +14,7 @@ sidebarDepth: 0
基类:`abc.ABC`
Driver 基类。将后端框架封装,以满足适配器使用。
Driver 基类。
### `_adapters`
@ -32,33 +32,33 @@ Driver 基类。将后端框架封装,以满足适配器使用。
### `_ws_connection_hook`
### `_bot_connection_hook`
* **类型**
`Set[T_WebSocketConnectionHook]`
`Set[T_BotConnectionHook]`
* **说明**
WebSocket 连接建立时执行的函数
Bot 连接建立时执行的函数
### `_ws_disconnection_hook`
### `_bot_disconnection_hook`
* **类型**
`Set[T_WebSocketDisconnectionHook]`
`Set[T_BotDisconnectionHook]`
* **说明**
WebSocket 连接断开时执行的函数
Bot 连接断开时执行的函数
@ -120,6 +120,21 @@ Driver 基类。将后端框架封装,以满足适配器使用。
### _property_ `bots`
* **类型**
`Dict[str, Bot]`
* **说明**
获取当前所有已连接的 Bot
### `register_adapter(name, adapter, **kwargs)`
@ -144,33 +159,33 @@ Driver 基类。将后端框架封装,以满足适配器使用。
驱动类型名称
### _abstract property_ `server_app`
驱动 APP 对象
### _abstract property_ `asgi`
驱动 ASGI 对象
### _abstract property_ `logger`
驱动专属 logger 日志记录器
### _property_ `bots`
* **类型**
`Dict[str, Bot]`
### _abstract_ `run(host=None, port=None, *args, **kwargs)`
* **说明**
获取当前所有已连接的 Bot
启动驱动框架
* **参数**
* `host: Optional[str]`: 驱动绑定 IP
* `post: Optional[int]`: 驱动绑定端口
* `*args`
* `**kwargs`
@ -226,41 +241,47 @@ Driver 基类。将后端框架封装,以满足适配器使用。
在 WebSocket 连接断开后,调用该函数来注销 bot 对象
### _abstract_ `run(host=None, port=None, *args, **kwargs)`
## _class_ `ReverseDriver`
基类:`nonebot.drivers.Driver`
Reverse Driver 基类。将后端框架封装,以满足适配器使用。
* **说明**
### _abstract property_ `server_app`
启动驱动框架
驱动 APP 对象
### _abstract property_ `asgi`
* **参数**
* `host: Optional[str]`: 驱动绑定 IP
驱动 ASGI 对象
* `post: Optional[int]`: 驱动绑定端口
* `*args`
* `**kwargs`
### _abstract async_ `_handle_http()`
### _abstract async_ `_handle_http(*args, **kwargs)`
用于处理 HTTP 类型请求的函数
### _abstract async_ `_handle_ws_reverse()`
### _abstract async_ `_handle_ws_reverse(*args, **kwargs)`
用于处理 WebSocket 类型请求的函数
## _class_ `HTTPRequest`
基类:`object`
HTTP 请求封装。参考 [asgi http scope](https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope)。
## _class_ `HTTPResponse`
基类:`object`
HTTP 响应封装。参考 [asgi http scope](https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope)。
## _class_ `WebSocket`
基类:`object`

View File

@ -79,7 +79,7 @@ FastAPI 驱动框架设置,详情参考 FastAPI 文档
## _class_ `Driver`
基类:[`nonebot.drivers.Driver`](README.md#nonebot.drivers.Driver)
基类:[`nonebot.drivers.ReverseDriver`](README.md#nonebot.drivers.ReverseDriver)
FastAPI 驱动框架

View File

@ -12,7 +12,7 @@ sidebarDepth: 0
## _class_ `Driver`
基类:[`nonebot.drivers.Driver`](README.md#nonebot.drivers.Driver)
基类:[`nonebot.drivers.ReverseDriver`](README.md#nonebot.drivers.ReverseDriver)
Quart 驱动框架

View File

@ -35,6 +35,21 @@ sidebarDepth: 0
### `module`
* **类型**
`Optional[ModuleType]`
* **说明**
事件响应器所在模块
### `plugin_name`
* **类型**
`Optional[str]`
@ -43,7 +58,37 @@ sidebarDepth: 0
* **说明**
事件响应器所在模块名称
事件响应器所在插件名
### `module_name`
* **类型**
`Optional[str]`
* **说明**
事件响应器所在模块名
### `module_prefix`
* **类型**
`Optional[str]`
* **说明**
事件响应器所在模块前缀

View File

@ -50,7 +50,7 @@ sidebarDepth: 0
* **说明**: 插件模块对象
### `export`
### _property_ `export`
* **类型**: `Export`
@ -282,7 +282,7 @@ sidebarDepth: 0
## `on_startswith(msg, rule=None, **kwargs)`
## `on_startswith(msg, rule=None, ignorecase=False, **kwargs)`
* **说明**
@ -294,12 +294,15 @@ sidebarDepth: 0
* **参数**
* `msg: str`: 指定消息开头内容
* `msg: Union[str, Tuple[str, ...]]`: 指定消息开头内容
* `rule: Optional[Union[Rule, T_RuleChecker]]`: 事件响应规则
* `ignorecase: bool`: 是否忽略大小写
* `permission: Optional[Permission]`: 事件响应权限
@ -329,7 +332,7 @@ sidebarDepth: 0
## `on_endswith(msg, rule=None, **kwargs)`
## `on_endswith(msg, rule=None, ignorecase=False, **kwargs)`
* **说明**
@ -341,12 +344,15 @@ sidebarDepth: 0
* **参数**
* `msg: str`: 指定消息结尾内容
* `msg: Union[str, Tuple[str, ...]]`: 指定消息结尾内容
* `rule: Optional[Union[Rule, T_RuleChecker]]`: 事件响应规则
* `ignorecase: bool`: 是否忽略大小写
* `permission: Optional[Permission]`: 事件响应权限
@ -663,7 +669,7 @@ sidebarDepth: 0
* `cmd: Union[str, Tuple[str, ...]]`: 命令前缀
* `**kwargs`: 其他传递给 `on_command` 的参数,将会覆盖命令组默认值
* `**kwargs`: 其他传递给 `on_shell_command` 的参数,将会覆盖命令组默认值
@ -940,7 +946,10 @@ sidebarDepth: 0
* **参数**
* `msg: str`: 指定消息开头内容
* `msg: Union[str, Tuple[str, ...]]`: 指定消息开头内容
* `ignorecase: bool`: 是否忽略大小写
* `rule: Optional[Union[Rule, T_RuleChecker]]`: 事件响应规则
@ -987,7 +996,10 @@ sidebarDepth: 0
* **参数**
* `msg: str`: 指定消息结尾内容
* `msg: Union[str, Tuple[str, ...]]`: 指定消息结尾内容
* `ignorecase: bool`: 是否忽略大小写
* `rule: Optional[Union[Rule, T_RuleChecker]]`: 事件响应规则

View File

@ -91,7 +91,7 @@ Rule(async_function, run_sync(sync_function))
## `startswith(msg)`
## `startswith(msg, ignorecase=False)`
* **说明**
@ -107,7 +107,7 @@ Rule(async_function, run_sync(sync_function))
## `endswith(msg)`
## `endswith(msg, ignorecase=False)`
* **说明**

View File

@ -46,7 +46,7 @@ sidebarDepth: 0
## `T_WebSocketConnectionHook`
## `T_BotConnectionHook`
* **类型**
@ -57,12 +57,12 @@ sidebarDepth: 0
* **说明**
WebSocket 连接建立时执行的函数
Bot 连接建立时执行的函数
## `T_WebSocketDisconnectionHook`
## `T_BotDisconnectionHook`
* **类型**
@ -73,7 +73,7 @@ sidebarDepth: 0
* **说明**
WebSocket 连接断开时执行的函数
Bot 连接断开时执行的函数

View File

@ -13,10 +13,10 @@ pip install nonebot-adapter-cqhttp
QQ 协议端举例:
- [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) (基于 [MiraiGo](https://github.com/Mrs4s/MiraiGo))
- [cqhttp-mirai-embedded](https://github.com/yyuueexxiinngg/cqhttp-mirai/tree/embedded)
- [Mirai](https://github.com/mamoe/mirai) + [cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai)
- [onebot-kotlin](https://github.com/yyuueexxiinngg/onebot-kotlin)
- [Mirai](https://github.com/mamoe/mirai) + [onebot-mirai](https://github.com/yyuueexxiinngg/onebot-kotlin)
- [Mirai](https://github.com/mamoe/mirai) + [Mirai Native](https://github.com/iTXTech/mirai-native) + [CQHTTP](https://github.com/richardchien/coolq-http-api)
- [OICQ-http-api](https://github.com/takayama-lily/onebot) (基于 [OICQ](https://github.com/takayama-lily/oicq))
- [node-onebot](https://github.com/takayama-lily/node-onebot) (基于 [abot](https://github.com/takayama-lily/abot), [OICQ](https://github.com/takayama-lily/oicq))
这里以 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 为例
@ -24,59 +24,74 @@ QQ 协议端举例:
2. 运行 exe 文件或者使用 `./go-cqhttp` 启动
3. 生成默认配置文件并修改默认配置
```hjson{2,3,35-36,42}
{
```yml{2,3,18,57,58}
account:
uin: 机器人QQ号
password: 机器人密码
encrypt_password: false
password_encrypted: ""
enable_db: true
access_token: ""
relogin: {
enabled: true
relogin_delay: 3
max_relogin_times: 0
}
_rate_limit: {
password: "机器人密码"
encrypt: false
relogin:
disabled: false
delay: 3
interval: 0
max-times: 0
use-sso-address: true
heartbeat:
disabled: false
interval: 5
message:
post-format: array
ignore-invalid-cqcode: false
force-fragment: false
fix-url: false
proxy-rewrite: ""
report-self-message: false
remove-reply-at: false
extra-reply-data: false
output:
log-level: warn
debug: false
default-middlewares: &default
access-token: ""
filter: ""
rate-limit:
enabled: false
frequency: 1
bucket_size: 1
}
ignore_invalid_cqcode: false
force_fragmented: false
heartbeat_interval: 0
http_config: {
enabled: false
host: "0.0.0.0"
port: 5700
timeout: 0
post_urls: {}
}
ws_config: {
enabled: false
host: "0.0.0.0"
port: 6700
}
ws_reverse_servers: [
{
enabled: true
reverse_url: ws://127.0.0.1:8080/cqhttp/ws
reverse_api_url: ws://you_websocket_api.server
reverse_event_url: ws://you_websocket_event.server
reverse_reconnect_interval: 3000
}
]
post_message_format: array
use_sso_address: false
debug: false
log_level: ""
web_ui: {
enabled: false
host: 127.0.0.1
web_ui_port: 9999
web_input: false
}
}
bucket: 1
servers:
- http:
disabled: true
host: 127.0.0.1
port: 5700
timeout: 5
middlewares:
<<: *default
post:
- ws:
disabled: true
host: 127.0.0.1
port: 6700
middlewares:
<<: *default
- ws-reverse:
disabled: false
universal: ws://127.0.0.1:8080/cqhttp/ws
api: ws://your_websocket_api.server
event: ws://your_websocket_event.server
reconnect-interval: 3000
middlewares:
<<: *default
database:
leveldb:
enable: true
```
其中 `ws://127.0.0.1:8080/cqhttp/ws` 中的 `127.0.0.1` 和 `8080` 应分别对应 nonebot 配置的 HOST 和 PORT。

View File

@ -8,7 +8,7 @@
nb plugin new
```
插件通常有两种形式,下面分别介绍
下面分别对两种通常的插件形式做具体介绍
## 单文件形式

View File

@ -37,7 +37,8 @@ AweSome-Bot
:::warning 提示
如果您使用如 `VSCode` / `PyCharm` 等 IDE 启动 nonebot请检查 IDE 当前工作空间目录是否与当前侧边栏打开目录一致。
* 在二者不一致的环境下可能导致 nonebot 读取配置文件和插件等不符合预期
- 注意:在二者不一致的环境下可能导致 nonebot 读取配置文件和插件等不符合预期
:::
通过 `nb-cli`

View File

@ -103,15 +103,15 @@ async def raw_handler(bot: DingBot, event: MessageEvent):
![机器人所在群的 Webhook 地址](./images/ding/webhook.png)
获取到Webhook地址后用户可以向这个地址发起HTTP POST 请求,即可实现给该钉钉群发送消息。
获取到 Webhook 地址后,用户可以向这个地址发起 HTTP POST 请求,即可实现给该钉钉群发送消息。
对于这种通过 Webhook 推送的消息,钉钉需要开发者进行安全方面的设置(目前有3种安全设置方式,请根据需要选择一种),如下:
对于这种通过 Webhook 推送的消息,钉钉需要开发者进行安全方面的设置(目前有 3 种安全设置方式,请根据需要选择一种),如下:
1. **自定义关键词:** 最多可以设置10个关键词消息中至少包含其中1个关键词才可以发送成功。
1. **自定义关键词:** 最多可以设置 10 个关键词,消息中至少包含其中 1 个关键词才可以发送成功。
例如添加了一个自定义关键词:监控报警,则这个机器人所发送的消息,必须包含监控报警这个词,才能发送成功。
2. **加签:** 发送请求时带上验签的值,可以在机器人设置里看到密钥。
![加签密钥](./images/ding/jiaqian.png)
3. **IP地址** 设定后只有来自IP地址范围内的请求才会被正常处理。支持两种设置方式IP地址和IP地址段暂不支持IPv6地址白名单。
3. **IP 地址(段):** 设定后,只有来自 IP 地址范围内的请求才会被正常处理。支持两种设置方式IP 地址和 IP 地址段,暂不支持 IPv6 地址白名单。
如果你选择 1/3 两种安全设置,你需要自己确认当前网络和发送的消息能被钉钉接受,然后使用 `bot.send` 的时候将 webhook 地址传入 webhook 参数即可。

View File

@ -72,7 +72,7 @@ pip install . # 不推荐
适配器可以通过 `nb-cli` 在创建项目时根据你的选择自动安装,也可以自行使用 `pip` 安装
```bash
pip install nonebot-adapter-<adapter-name>
pip install <adapter-name>
```
```bash
@ -88,9 +88,9 @@ nb adapter list
# 列出所有的插件
nb plugin list
# 搜索插件
nb plugin search xxx
nb plugin search <plugin-name>
# 安装插件
nb plugin install xxx
nb plugin install <plugin-name>
```
如果急于上线 Bot 或想要使用现成的插件,以下插件可作为参考:
@ -106,4 +106,10 @@ nb plugin install xxx
### 其他插件
还有更多的插件在 [这里](/plugin-store.md) 等着你发现~
还有更多的插件在 [这里](/store.html) 等着你发现~
## 安装开发环境(可选)
NoneBot v2 全程使用 `VSCode` 搭配 `Pylance` 的开发环境进行开发在严格的类型检查下NoneBot v2 具有完善的类型设计与声明。
在围绕 NoneBot v2 进行开发时,使用 `VSCode` 搭配 `Pylance` 进行类型检查是非常推荐的。这有利于统一代码风格及避免低级错误的发生。

View File

@ -39,10 +39,11 @@ if __name__ == "__main__":
在 `bot.py` 文件中添加以下行:
```python{5}
```python{6}
import nonebot
nonebot.init()
# 加载插件目录,该目录下为各插件,以下划线开头的插件将不会被加载
nonebot.load_plugins("awesome_bot/plugins")
@ -68,10 +69,11 @@ if __name__ == "__main__":
在 `bot.py` 文件中添加以下行:
```python{5,7}
```python{6,8}
import nonebot
nonebot.init()
# 加载一个 pip 安装的插件
nonebot.load_plugin("nonebot_plugin_status")
# 加载本地的单独插件
@ -83,6 +85,63 @@ if __name__ == "__main__":
nonebot.run()
```
## 从 json 文件中加载插件
在 `bot.py` 文件中添加以下行:
```python{6}
import nonebot
nonebot.init()
# 从 plugin.json 加载插件
nonebot.load_from_json("plugin.json")
app = nonebot.get_asgi()
if __name__ == "__main__":
nonebot.run()
```
**json 文件示例**
```json
{
"plugins": ["nonebot_plugin_status", "awesome_bot.plugins.xxx"],
"plugin_dirs": ["awesome_bot/plugins"]
}
```
## 从 toml 文件中加载插件
在 `bot.py` 文件中添加以下行:
```python{6}
import nonebot
nonebot.init()
# 从 pyproject.toml 加载插件
nonebot.load_from_toml("pyproject.toml")
app = nonebot.get_asgi()
if __name__ == "__main__":
nonebot.run()
```
**toml 文件示例:**
```toml
[nonebot.plugins]
plugins = ["nonebot_plugin_status", "awesome_bot.plugins.xxx"]
plugin_dirs = ["awesome_bot/plugins"]
```
::: tip
nb-cli 默认使用 `pyproject.toml` 加载插件。
:::
## 子插件(嵌套插件)
在插件中同样可以加载子插件,例如如下插件目录结构:

View File

@ -67,6 +67,12 @@ pip install nonebot-adapter-mirai
4. 修改配置文件
::: warning
由于NoneBot2的架构设计等原因, 部分功能的支持可能需要推迟到MAH 2.0正式发布后再完成
:::
::: tip
在此之前, 你可能需要了解我们为 MAH 设计的两种通信方式
@ -91,6 +97,13 @@ pip install nonebot-adapter-mirai
:::
- 这是当使用正向 Websocket 时的配置举例
::: warning
在默认情况下, NoneBot和MAH会同时监听8080端口, 这会导致端口冲突的错误
请确保二者配置不在同一端口下
:::
- MAH 的`setting.yml`文件
@ -106,9 +119,12 @@ pip install nonebot-adapter-mirai
- `.env`文件
- ```shell
PORT=2333
MIRAI_AUTH_KEY=1234567890
MIRAI_HOST=127.0.0.1 # 当MAH运行在本机时
MIRAI_PORT=8080 # MAH的监听端口
PORT=2333 # 防止与MAH接口冲突
```
- `bot.py`文件
@ -155,7 +171,7 @@ pip install nonebot-adapter-mirai
- ```shell
HOST=127.0.0.1 # 当MAH运行在本机时
PORT=2333
PORT=2333 # 防止与MAH接口冲突
MIRAI_AUTH_KEY=1234567890
MIRAI_HOST=127.0.0.1 # 当MAH运行在本机时