nonebot-plugin-onebot-luckperms(OBLP)
LuckPerms 风格的权限节点管理系统,专为 NoneBot2 + OneBot 适配器设计。
English: README_EN.md
目录
安装
通过 NB-CLI(推荐)
nb plugin install nonebot-plugin-onebot-luckperms
通过 pip
pip install nonebot-plugin-onebot-luckperms
如需 Redis 后端:
pip install nonebot-plugin-onebot-luckperms[redis]
全部安装:
pip install nonebot-plugin-onebot-luckperms[all]
快速开始
在 NoneBot2 的 pyproject.toml 或 .env 中添加插件:
[tool.nonebot]
plugins = ["nonebot_plugin_onebot_luckperms"]
插件加载后,所有 /lp 命令默认仅 SUPERUSER(在 env 中配置 SUPERUSER=123456)可执行。
给用户一个权限
/lp user 123456 permission set myplugin.ban true
创建一个组并分配权限
/lp creategroup admin 100
/lp group admin permission set myplugin.kick true
/lp user 123456 parent add admin
设置仅在特定群生效的权限
/lp user 123456 permission set myplugin.mute true group_id=987654
临时权限(30 分钟后自动过期)
/lp user 123456 permission settemp myplugin.ban true 30m
打开 Web Editor
/lp editor
在群聊中打开时,editor 会自动附带该群所有成员 QQ 到用户列表。
配置
在 .env 或 pyproject.toml 中(前缀 OBLP_):
| 环境变量 | 默认值 | 说明 |
|---|---|---|
OBLP_STORE_TYPE |
sqlite |
存储后端:memory / sqlite / redis |
OBLP_REDIS_URL |
redis://localhost:6379/0 |
Redis 连接 URL |
OBLP_DEFAULT_GROUP_OWNER |
["luckperms.help"] |
群主自动继承的权限节点 |
OBLP_DEFAULT_GROUP_ADMIN |
[] |
群管理自动继承的权限节点 |
OBLP_DEFAULT_GROUP_MEMBER |
[] |
普通成员自动继承的权限节点 |
OBLP_SUPERUSER_INHERIT |
["luckperms.*"] |
SUPERUSER 自动继承的权限节点 |
OBLP_CACHE_TTL |
300 |
权限缓存时间(秒),0 禁用缓存 |
配置示例
SUPERUSER=123456
OBLP_STORE_TYPE=sqlite
OBLP_DEFAULT_GROUP_ADMIN=["myplugin.mute","myplugin.kick"]
OBLP_DEFAULT_GROUP_MEMBER=[]
数据存储
SQLite 数据库与自定义回复消息文件存放在 nonebot-plugin-localstore 管理的数据目录下(可用
LOCALSTORE_* 系列环境变量自定义,例如 LOCALSTORE_PLUGIN_DATA_DIR)。
命令列表
所有命令均以 /lp 开头。每个命令都受对应的 luckperms.* 权限节点保护。
SUPERUSER 默认拥有 luckperms.*(全部权限)。群主默认拥有 luckperms.help(仅能看帮助)。
通用命令
| 命令 | 所需权限节点 | 说明 |
|---|---|---|
/lp help |
luckperms.help |
显示帮助 |
/lp sync |
luckperms.sync |
重新加载数据 |
/lp info |
luckperms.info |
显示统计信息 |
/lp editor |
luckperms.editor |
打开 LuckPerms Web Editor |
/lp applyedits <code> |
luckperms.applyedits |
应用 Web Editor 的 edits |
用户管理
| 命令 | 所需权限节点 | 说明 |
|---|---|---|
/lp user <id> info |
luckperms.user.info |
查看用户详情 |
/lp user <id> permission ... |
luckperms.user.permission |
管理用户权限节点 |
/lp user <id> parent ... |
luckperms.user.parent |
管理用户组 |
/lp user <id> promote <track> |
luckperms.user.promote |
晋升 |
/lp user <id> demote <track> |
luckperms.user.demote |
降级 |
/lp user <id> clear [ctx...] |
luckperms.user.clear |
清空所有权限节点 |
/lp user <id> clone <target> |
luckperms.user.clone |
克隆用户 |
/lp user <id> editor |
luckperms.editor |
在 editor 中编辑此用户 |
/lp user create <id> |
luckperms.user.create |
创建用户 |
/lp user delete <id> |
luckperms.user.delete |
删除用户 |
/lp user list |
luckperms.user.list |
列出所有用户 |
组管理
| 命令 | 所需权限节点 | 说明 |
|---|---|---|
/lp group <name> info |
luckperms.group.info |
查看组详情 |
/lp group <name> permission ... |
luckperms.group.permission |
管理组权限 |
/lp group <name> parent ... |
luckperms.group.parent |
继承管理 |
/lp group <name> setweight <weight> |
luckperms.group.setweight |
设置权重 |
/lp group <name> setdisplayname <name> |
luckperms.group.setdisplayname |
设置显示名 |
/lp group <name> clear [ctx...] |
luckperms.group.clear |
清空权限 |
/lp group <name> rename <new> |
luckperms.group.rename |
重命名组 |
/lp group <name> clone <new> |
luckperms.group.clone |
克隆组 |
/lp group <name> listmembers |
luckperms.group.listmembers |
列出组成员 |
/lp group <name> editor |
luckperms.editor |
在 editor 中编辑此组 |
/lp creategroup <name> [weight] |
luckperms.group.create |
创建组 |
/lp deletegroup <name> |
luckperms.group.delete |
删除组 |
/lp listgroups |
luckperms.group.list |
列出所有组 |
轨道管理(预留)
| 命令 | 所需权限节点 | 说明 |
|---|---|---|
/lp track <name> ... |
luckperms.* |
轨道操作 |
系统命令
| 命令 | 所需权限节点 | 说明 |
|---|---|---|
/lp check <user> <node> [ctx...] |
luckperms.check |
模拟权限检查 |
/lp tree [scope] |
luckperms.tree |
权限继承树可视化 |
命令执行反馈
无权限时(用户没有所需的 luckperms.xxx 节点),bot 回复 deny 消息。
自定义回复消息
所有用户可见的回复文本均存储在插件数据目录下的 messages.yml 文件中。
插件首次运行时会自动生成此文件。你可以编辑它来自定义所有回复,支持占位符:
# messages.yml (位于插件数据目录)
deny: "你没有权限执行此命令。"
deny_hint: "请联系管理员开通对应权限节点。"
perm_set: "{entity}: {action} {node}"
perm_temp: "{entity}: 临时{action} {node} ({duration})"
editor_opened: "Web 编辑器已开启: {url}"
可用占位符:
| 占位符 | 说明 |
|---|---|
{user_id} |
用户 ID |
{node} |
权限节点名 |
{entity} |
用户或组 ID |
{action} |
grant 或 deny |
{duration} |
持续时间 |
{context} |
上下文键值对 |
{url} |
Editor URL |
{code} |
Edit code |
{error} |
错误描述 |
{name} |
组名 |
{weight} |
组权重 |
有权限时的执行反馈示例:
/lp sync
→ Data reloaded
/lp user 123456 permission set myplugin.ban true
→ 123456: grant myplugin.ban
/lp user 123456 permission settemp myplugin.kick false 30m
→ 123456: temp deny myplugin.kick (30m)
/lp group admin permission set myplugin.mute true group_id=987654
→ admin: grant myplugin.mute (ctx: {'group_id': '987654'})
/lp check 123456 myplugin.ban
→ Check: user=123456, node=myplugin.ban
Context: (empty)
Result: ALLOW
Resolved nodes (2):
myplugin.ban=grant
luckperms.*=grant
默认角色权限
| 角色 | 默认拥有的节点 | 说明 |
|---|---|---|
| SUPERUSER | luckperms.* |
全部命令 |
| 群主 (owner) | luckperms.help |
仅可看帮助(可配置) |
| 管理 (admin) | (空) | 无内建命令权限(可配置) |
| 成员 (member) | (空) | 无内建命令权限(可配置) |
可通过 OBLP_DEFAULT_GROUP_OWNER、OBLP_DEFAULT_GROUP_ADMIN、OBLP_DEFAULT_GROUP_MEMBER 配置。
临时权限 duration 格式
| 写法 | 含义 |
|---|---|
30s |
30 秒 |
5m |
5 分钟 |
2h |
2 小时 |
1d |
1 天 |
内建 Context 键
权限节点可以通过 key=value 附加上下文约束,使节点仅在特定环境中生效。由系统自动注入:
| Context 键 | 类型 | 来源 | 示例值 |
|---|---|---|---|
platform |
str |
适配器类型 | onebot_v11, onebot_v12 |
user_id |
str |
发送者 ID | 123456 |
group_id |
str |
群号(群聊时) | 987654 |
role |
str |
群内角色 | owner, admin, member, superuser |
第三方插件可通过 ContextProvider(见下文)注册自定义 Context 键。
Context 使用示例
仅群 123456 中有效:
/lp user 123456 permission set myplugin.ban true group_id=123456
仅群管理时有效:
/lp user 123456 permission set myplugin.kick true role=admin
仅群 123456 且为群主时有效:
/lp group admin permission set myplugin.ban true group_id=123456 role=owner
权限节点注册(面向开发者)
基本用法
from nonebot import on_command
from nonebot_plugin_onebot_luckperms import register_node, require
# 在插件加载时注册节点
register_node("myplugin.ban", "禁言用户", default=False)
# 绑定到命令
ban = on_command("ban", permission=require("myplugin.ban"))
@ban.handle()
async def _():
await ban.send("已执行")
带默认上下文的注册
from nonebot_plugin_onebot_luckperms import register_node, ContextSet
# 仅群主默认拥有此权限
register_node("myplugin.admincmd", "管理命令", default=True,
contexts=ContextSet({"role": "owner"}))
# 仅在特定群 + admin 时默认拥有
register_node("myplugin.vipcmd", "VIP 命令", default=True,
contexts=ContextSet({"group_id": "123456", "role": "admin"}))
require / require_any / require_all
from nonebot_plugin_onebot_luckperms import require, require_any, require_all
from nonebot.adapters.onebot.v11.permission import GROUP_ADMIN
# 单节点
cmd = on_command("cmd", permission=require("myplugin.cmd"))
# 多节点 OR
cmd = on_command("cmd", permission=require_any("node.a", "node.b"))
# 多节点 AND
cmd = on_command("cmd", permission=require_all("node.a", "node.b"))
# 与原生权限组合
cmd = on_command("cmd", permission=require("myplugin.cmd") | GROUP_ADMIN)
获取权限上下文
from nonebot_plugin_onebot_luckperms import get_context
@cmd.handle()
async def _():
ctx = get_context()
if not ctx:
return
print(ctx.user.user_id) # "123456"
print(ctx.identity.role) # "admin"
print(ctx.resolved_nodes) # {"myplugin.ban": True, ...}
ContextProvider(面向开发者)
ContextProvider 允许第三方插件向全局权限判定环境注入自定义 Context 键值对。
定义并注册
from nonebot_plugin_onebot_luckperms import register_context_provider
class BindProvider:
context_keys = {"bind"} # 声明此 provider 会注入的键
async def __call__(self, bot, event, current_ctx):
# 从数据库或 API 查询用户的绑定状态
return {"bind": "true"} # 键值对会合并到判定上下文中
register_context_provider(BindProvider())
注册后,其他所有插件都可以利用这个 Context 来控制权限生效范围:
register_node("someplugin.premium", default=True,
contexts=ContextSet({"bind": "true"}))
冲突检测
如果两个不同的 Provider 声明了相同的 context_keys,后者注册时会抛出 DuplicateProviderError:
ProviderA: context_keys = {"bind"} # 注册成功
ProviderB: context_keys = {"bind"} # → DuplicateProviderError!
API 参考
用户端函数
| 函数 | 说明 |
|---|---|
require(node_key, contexts=None) -> Permission |
单节点权限检查器 |
require_any(*node_keys, contexts=None) -> Permission |
OR 权限检查器 |
require_all(*node_keys, contexts=None) -> Permission |
AND 权限检查器 |
get_context() -> Optional[LPContext] |
在 Handler 中获取权限上下文 |
get_store() -> Optional[PermissionStore] |
获取当前存储后端 |
开发者端函数
| 函数 | 说明 |
|---|---|
register_node(key, description="", default=False, contexts=None) |
注册权限节点 |
register_context_provider(provider) |
注册全局 ContextProvider |
set_resolver(resolver) |
覆盖 IdentityResolver |
ContextSet(data={}) |
上下文集合 |
PermissionNode(key, value=True, expiry=None, contexts=ContextSet()) |
权限节点 |
模型类
@dataclass(frozen=True)
class ContextSet:
data: Dict[str, str]
def with_context(self, key, value) -> ContextSet
def matches(self, requirement) -> bool
def is_empty(self) -> bool
@dataclass
class PermissionNode:
key: str
value: bool
expiry: Optional[int]
contexts: ContextSet
def is_expired(self) -> bool
def applies_in(self, ctx) -> bool
@dataclass(frozen=True)
class LPContext:
user: User
identity: Identity
query_options: QueryOptions
resolved_nodes: Dict[str, bool]
matched_node: Optional[str]
timestamp: float
测试
pytest tests/ -v
当前 91 项测试全部通过。
架构
Layer 4: NoneBot Integration (adapter/) — require(), IdentityResolver, LPContext
Layer 3: Core Engine (core/) — 纯 Python,不依赖 NoneBot
Layer 2: Storage (storage/) — Memory / SQLite / Redis
Layer 1: Config & Bootstrap (config/) — Pydantic 配置
License
MIT
Release files for nonebot-plugin-onebot-luckperms 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nonebot_plugin_onebot_luckperms-0.1.2.tar.gz | 40.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nonebot_plugin_onebot_luckperms-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 79.6 kB
Release files / nonebot_plugin_onebot_luckperms-0.1.2.tar.gz
| Download URL | nonebot_plugin_onebot_luckperms-0.1.2.tar.gz |
|---|---|
| Size | 40.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
017c9049af31a2570bfd037ff129af3b12ff4682cecf7e5f4569681f97a100fb
|
|
BLAKE2b-256 checksum How to use checksums |
9eb75e590dbd4f72e7a1d9e710b5afa4b50e61e9c2db1a411596bb6add54395c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nonebot_plugin_onebot_luckperms-0.1.2-py3-none-any.whl
| Download URL | nonebot_plugin_onebot_luckperms-0.1.2-py3-none-any.whl |
|---|---|
| Size | 39.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7b8aea73c0ee4e1efe6d3ede8ffa1160759d5f36a3575f8f5e1da3a00fc85a78
|
|
BLAKE2b-256 checksum How to use checksums |
1ae5aa7dc37a8a54424a242fd47c15c412911fd8d27648daf7da8fddb0f9cbf3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|