配置与数据 Mixin
约 922 字大约 3 分钟
2026-03-19
ConfigMixin 提供双层 YAML 配置模型,DataMixin 提供 JSON 数据持久化——让插件零配置拥有持久化能力。
目录
设计理念
NcatBotPlugin 通过多继承组合 6 个 Mixin,每个 Mixin 提供一类独立能力:
class NcatBotPlugin(BasePlugin, EventMixin, TimeTaskMixin, RBACMixin, DispatchFilterMixin, ConfigMixin, DataMixin):
pass- 每个 Mixin 通过
_mixin_load()/_mixin_unload()参与 加载流程 - 各 Mixin 之间互不依赖,可独立使用
- 你不需要手动初始化任何 Mixin——继承
NcatBotPlugin即可自动获得全部能力
ConfigMixin — 配置持久化
ConfigMixin 提供双层配置模型:
- 低优先级:插件源码目录下的
config.yaml(开发者随附默认值) - 高优先级:全局
config.yaml的plugin.plugin_configs.<name>(用户覆盖 + 运行时持久化)
基本用法
class MyPlugin(NcatBotPlugin):
name = "my_plugin"
version = "1.0.0"
async def on_load(self):
# 补充缺失的默认配置(仅内存,不持久化)
self.init_defaults({
"prefix": "/",
"welcome_msg": "欢迎使用!",
"enabled": True,
})
@registrar.on_group_command("设置前缀")
async def on_set_prefix(self, event: GroupMessageEvent, new_prefix: str):
"""修改配置 — CommandHook 自动提取参数"""
self.set_config("prefix", new_prefix)
await event.reply(f"命令前缀已更新为: {new_prefix}")
@registrar.on_group_command("查看配置")
async def on_view_config(self, event: GroupMessageEvent):
"""遍历当前配置"""
lines = ["📋 当前配置:"]
for key, value in self.config.items():
lines.append(f" {key}: {value}")
await event.reply("\n".join(lines))API
| 方法 | 说明 |
|---|---|
get_config(key, default=None) | 读取配置值 |
set_config(key, value) | 设置配置值(立即保存到全局 config.yaml) |
update_config(updates: dict) | 批量更新配置 |
remove_config(key) -> bool | 删除配置项 |
init_defaults(defaults: dict) | 补充缺失的默认配置项(仅内存,不持久化) |
self.config | 配置字典(Dict[str, Any]) |
配置文件位置
双层配置模型的文件布局:
plugins/
└── my_plugin/
├── manifest.toml
├── main.py
└── config.yaml ← 低优先级:开发者随附默认值
config.yaml ← 高优先级:用户覆盖
└── plugin:
└── plugin_configs:
└── my_plugin:
└── prefix: "!"set_config() / update_config() 写入全局 config.yaml 的 plugin.plugin_configs 部分,立即持久化。
全局配置覆盖
在项目的 config.yaml 中,可以通过 plugin.plugin_configs 为插件预设配置:
plugin:
plugin_configs:
my_plugin:
prefix: "!"
enabled: falseConfigMixin 在 _mixin_load() 时会自动合并全局覆盖配置。
DataMixin — 数据持久化
DataMixin 提供 JSON 格式的通用数据持久化,数据保存在 workspace/data.json。
基本用法
class MyPlugin(NcatBotPlugin):
name = "my_plugin"
version = "1.0.0"
async def on_load(self):
# self.data 在 _mixin_load 时已从 data.json 恢复
self.data.setdefault("total_messages", 0)
self.data.setdefault("user_counts", {})
LOG.info("累计消息: %d", self.data["total_messages"])
@registrar.on_group_message(priority=100)
async def count_message(self, event: GroupMessageEvent):
"""每条群消息都计数"""
self.data["total_messages"] += 1
uid = str(event.user_id)
counts = self.data.setdefault("user_counts", {})
counts[uid] = counts.get(uid, 0) + 1
@registrar.on_group_command("统计")
async def on_stats(self, event: GroupMessageEvent):
total = self.data.get("total_messages", 0)
user_counts = self.data.get("user_counts", {})
top_users = sorted(user_counts.items(), key=lambda x: x[1], reverse=True)[:5]
lines = ["📊 消息统计:", f" 总消息数: {total}"]
if top_users:
lines.append(" 活跃用户 Top 5:")
for uid, count in top_users:
lines.append(f" {uid}: {count} 条")
await event.reply("\n".join(lines))
@registrar.on_group_command("重置统计")
async def on_reset_stats(self, event: GroupMessageEvent):
self.data["total_messages"] = 0
self.data["user_counts"] = {}
await event.reply("统计数据已重置 🗑️")API
| 方法/属性 | 说明 |
|---|---|
self.data | 数据字典(Dict[str, Any]),直接读写 |
自动持久化
- 加载:
_mixin_load()自动从data.json加载 - 卸载:
_mixin_unload()自动保存到data.json - 手动保存:修改
self.data后,数据会在插件卸载时自动保存;如果需要立即保存可调用self._save_data()
ConfigMixin vs DataMixin
| 维度 | ConfigMixin | DataMixin |
|---|---|---|
| 文件格式 | YAML | JSON |
| 典型用途 | 用户可配置的选项 | 运行时数据、统计、状态 |
| 保存时机 | set_config() 立即保存 | 卸载时自动保存 |
| 外部可编辑 | ✅ 是(YAML 可读性好) | ⚠️ 可以但不推荐 |
下一步
- 权限、定时任务与事件 Mixin — RBACMixin、TimeTaskMixin、EventMixin
- Hook 基础 — 了解过滤器和中间件原理
版权所有
版权归属:MI
