mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-07-27 16:21:28 +00:00
Merge branch 'dev' into richardchien-patch-1
This commit is contained in:
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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("私聊消息事件响应成功!")
|
||||
```
|
||||
|
||||
只有触发事件符合的函数才会触发装饰器。
|
||||
|
@ -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` 会自动包裹同步函数为异步函数。
|
||||
|
@ -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` 的导入方式即可完成迁移。
|
||||
|
||||
## 安装插件
|
||||
|
||||
|
@ -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`
|
||||
|
||||
消息数组
|
||||
|
||||
|
@ -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 模块
|
||||
|
||||
|
||||
|
@ -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 适配。
|
||||
|
||||
|
@ -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 适配
|
||||
|
||||
|
@ -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`
|
||||
|
||||
|
||||
|
@ -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`
|
||||
|
@ -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 驱动框架
|
||||
|
||||
|
@ -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 驱动框架
|
||||
|
||||
|
@ -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]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器所在模块前缀
|
||||
|
||||
|
||||
|
||||
|
@ -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]]`: 事件响应规则
|
||||
|
@ -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)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
@ -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 连接断开时执行的函数
|
||||
|
||||
|
||||
|
||||
|
@ -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。
|
||||
|
@ -8,7 +8,7 @@
|
||||
nb plugin new
|
||||
```
|
||||
|
||||
插件通常有两种形式,下面分别介绍
|
||||
下面分别对两种通常的插件形式做具体介绍
|
||||
|
||||
## 单文件形式
|
||||
|
||||
|
@ -37,7 +37,8 @@ AweSome-Bot
|
||||
:::warning 提示
|
||||
如果您使用如 `VSCode` / `PyCharm` 等 IDE 启动 nonebot,请检查 IDE 当前工作空间目录是否与当前侧边栏打开目录一致。
|
||||
|
||||
* 在二者不一致的环境下可能导致 nonebot 读取配置文件和插件等不符合预期
|
||||
- 注意:在二者不一致的环境下可能导致 nonebot 读取配置文件和插件等不符合预期
|
||||
|
||||
:::
|
||||
|
||||
通过 `nb-cli`
|
||||
|
@ -103,15 +103,15 @@ async def raw_handler(bot: DingBot, event: MessageEvent):
|
||||
|
||||

|
||||
|
||||
获取到Webhook地址后,用户可以向这个地址发起HTTP POST 请求,即可实现给该钉钉群发送消息。
|
||||
获取到 Webhook 地址后,用户可以向这个地址发起 HTTP POST 请求,即可实现给该钉钉群发送消息。
|
||||
|
||||
对于这种通过 Webhook 推送的消息,钉钉需要开发者进行安全方面的设置(目前有3种安全设置方式,请根据需要选择一种),如下:
|
||||
对于这种通过 Webhook 推送的消息,钉钉需要开发者进行安全方面的设置(目前有 3 种安全设置方式,请根据需要选择一种),如下:
|
||||
|
||||
1. **自定义关键词:** 最多可以设置10个关键词,消息中至少包含其中1个关键词才可以发送成功。
|
||||
1. **自定义关键词:** 最多可以设置 10 个关键词,消息中至少包含其中 1 个关键词才可以发送成功。
|
||||
例如添加了一个自定义关键词:监控报警,则这个机器人所发送的消息,必须包含监控报警这个词,才能发送成功。
|
||||
2. **加签:** 发送请求时带上验签的值,可以在机器人设置里看到密钥。
|
||||

|
||||
3. **IP地址(段):** 设定后,只有来自IP地址范围内的请求才会被正常处理。支持两种设置方式:IP地址和IP地址段,暂不支持IPv6地址白名单。
|
||||
3. **IP 地址(段):** 设定后,只有来自 IP 地址范围内的请求才会被正常处理。支持两种设置方式:IP 地址和 IP 地址段,暂不支持 IPv6 地址白名单。
|
||||
|
||||
如果你选择 1/3 两种安全设置,你需要自己确认当前网络和发送的消息能被钉钉接受,然后使用 `bot.send` 的时候将 webhook 地址传入 webhook 参数即可。
|
||||
|
||||
|
@ -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` 进行类型检查是非常推荐的。这有利于统一代码风格及避免低级错误的发生。
|
||||
|
@ -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` 加载插件。
|
||||
:::
|
||||
|
||||
## 子插件(嵌套插件)
|
||||
|
||||
在插件中同样可以加载子插件,例如如下插件目录结构:
|
||||
|
@ -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运行在本机时
|
||||
|
Reference in New Issue
Block a user