5.4 KiB
Danding Points 插件
全局积分/虚拟货币服务层,为其他插件提供统一的积分管理能力。用户在一个插件中获得的积分可以在另一个插件中消费。
本插件不包含任何用户交互命令(无 NoneBot matcher),纯 API 服务层,供其他插件直接 import 调用。
目录结构
danding_points/
├── __init__.py # 插件元数据 & points_api 单例导出
├── config.py # 配置类
└── api.py # PointsAPI 核心
配置选项
在 .env 文件或 NoneBot 配置文件中添加(均带 DANDING_ 前缀):
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
DANDING_POINTS_API_HOST |
str | https://api.danding.vip/bot/points |
xapi 积分 API 地址 |
DANDING_BOT_USER |
str | 1424473282 |
xapi Bot 鉴权用户 |
DANDING_BOT_TOKEN |
str | 空 | xapi Bot 鉴权 Token,未设置时读取 DANDING_API_TOKEN / BOT_TOKEN |
积分余额上限与单次操作上限由 xapi BOT_POINTS_MAX_BALANCE / BOT_POINTS_MAX_PER_OPERATION 控制,nonebot 本地不再持有阈值。
API 接口
所有方法均为 async,通过 points_api 单例调用。
get_balance(user_id: str) -> int
查询用户积分余额。用户不存在时自动返回 0,不会创建账户。
balance = await points_api.get_balance("123456")
add_points(user_id, amount, source, reason=None) -> Tuple[bool, int]
为用户增加积分。用户不存在时自动建户。
amount: 正整数,必须 > 0source: 来源标识,不能为空(用于流水追踪)reason: 变动原因,可选- 返回
(success, new_balance),失败时success=False
触发校验:操作上限 → 余额上限。任一校验失败均返回 (False, 当前余额)。
ok, balance = await points_api.add_points("123456", 100, "gacha", "抽卡奖励")
if ok:
print(f"充值成功,当前余额: {balance}")
spend_points(user_id, amount, source, reason=None) -> Tuple[bool, int]
消费用户积分。余额不足时返回 (False, 当前余额)。
amount: 正整数,必须 > 0- 流水中
amount记录为负数
ok, balance = await points_api.spend_points("123456", 30, "shop", "购买道具")
if not ok:
print("余额不足")
set_points(user_id, amount, source, reason=None) -> Tuple[bool, int]
直接设定用户积分。绕过 操作上限和余额上限约束。
amount: 非负整数,必须 >= 0- 新值等于旧值时不写流水,直接返回
(True, amount) total_earned仅累加正向差额(设低不影响)
ok, balance = await points_api.set_points("123456", 500, "admin", "管理员调整")
get_transactions(user_id, limit=20, offset=0) -> List[dict]
查询用户积分流水记录,按时间倒序。
limit: 1~100,超出范围自动裁剪offset: 分页偏移量,>= 0
返回字段:id, user_id, amount, balance_after, source, reason, created_at
txs = await points_api.get_transactions("123456", limit=10, offset=0)
for tx in txs:
print(f"{tx['created_at']} {tx['amount']:+d} 余额:{tx['balance_after']}")
get_ranking(limit=10, order_by="points") -> List[dict]
查询积分排行榜。
limit: 1~100order_by:"points"(按余额)或"total_earned"(按累计获得),其他值回退为"points"- 使用
RANK()窗口函数,同分并列,次级排序按user_id字母序
返回字段:rank, user_id, points, total_earned, total_spent
ranking = await points_api.get_ranking(limit=10, order_by="points")
for r in ranking:
print(f"#{r['rank']} {r['user_id']} {r['points']}分")
其他插件对接
基本用法
在需要积分功能的插件中 import 单例即可:
from nonebot import require
require("danding_points")
from danding_bot.plugins.danding_points import points_api
示例:抽卡插件发放奖励
# 在 onmyoji_gacha 插件中
from danding_bot.plugins.danding_points import points_api
async def reward_user(user_id: str):
ok, balance = await points_api.add_points(
user_id, 50, "onmyoji_gacha", "SSR 抽到奖励"
)
return balance
示例:商店插件消费积分
# 在 shop 插件中
from danding_bot.plugins.danding_points import points_api
async def buy_item(user_id: str, cost: int):
ok, balance = await points_api.spend_points(
user_id, cost, "shop", "购买商品"
)
if not ok:
return "积分不足"
return f"购买成功,剩余 {balance} 积分"
示例:管理员插件调整积分
# 在 danding_api 插件中
from danding_bot.plugins.danding_points import points_api
async def admin_set(user_id: str, amount: int):
ok, balance = await points_api.set_points(
user_id, amount, "danding_api", "管理员手动调整"
)
return balance
source 命名建议
source 参数用于标识积分变动来源,建议各插件使用自身插件名作为 source:
| 插件 | source 值 |
|---|---|
| onmyoji_gacha 签到 | "gacha_sign" |
| group_horse_racing | "horse_race" |
| 管理调整 | "admin" |
数据库
本插件不再写入本地 SQLite。积分账户与流水由 xapi MySQL bot_user_points / bot_point_transactions 承载,nonebot 只通过 /bot/points/* HTTP API 读写。