Files
DanDingNoneBot/.trellis/tasks/08-16-standalone-sign-in-plugin/prd.md
Mr.Xia 9ee5545cac feat(sign_in): 新增独立每日签到插件,与抽卡签到共用同一份签到数据
- 群聊命令「签到」(别名: 每日签到/打卡),白名单群聊或管理员可用
- 复用 xapi /bot/gacha/sign-in + /bot/points/add,与抽卡/WPF 共用 bot_gacha_daily_sign_in 表
- 积分随机 1-100,流水沿用 gacha_sign/抽卡签到;先到先得,重复签到提示已签到
- 新增 10 个单元测试,ruff 通过;更新 PLUGINS.md / README.md
2026-08-16 09:02:11 +08:00

7.2 KiB
Raw Blame History

独立每日签到插件(与抽卡签到共用数据)

Goal

在 danding-bot 中新增独立「签到」插件用户发送「签到」命令即可完成每日签到并领取积分抽卡插件onmyoji_gacha的「抽卡后自动签到」保持原功能不变两个入口与 WPF 客户端共用同一份签到数据xapi bot_gacha_daily_sign_in 表,每用户每天一条,先到先得)。

What I already know

  • 签到数据唯一权威源xapi DanDing 库 bot_gacha_daily_sign_in 表,UNIQUE(bot_user_id, sign_date)WPF 与 QQ Bot 已共用xapi docs/bot-api.md L126、Application/Bot/gacha_router.py L203-284、Application/DanDing/wpf_gacha.py L183-226
  • QQ 抽卡签到现状:onmyoji_gacha 插件在抽卡/三连抽成功后调用 POST /bot/gacha/sign-inBody: user/token/user_id/points_awarded → data: {success, signed_already, signed_today, sign_date, points_awarded})记录签到,再调用 /bot/points/add 发积分source=gacha_signreason=抽卡签到,随机 1-100 分)。
  • WPF 签到:POST /DD/gacha/sign-in 在同一事务内写签到记录 + 发 Bot 积分(BOT_GACHA_WPF_SIGN_IN_POINTS 默认 20source=gacha_signreason=抽卡签到)。重复签到返回 signed_already=true 且不重复发积分。
  • xapi 无 GET /bot/gacha/sign-in 状态查询路由(只有内部 helper但写接口返回 signed_already,重复签到可直接提示"今天已签到"。
  • 客户端 HTTP 封装已有现成模式:onmyoji_gacha/data_manager.pyDataManager._request 模式)与 danding_points/api.pyPointsAPI.add_points → POST /bot/points/add
  • 权限模式:onmyoji_gacha 用白名单ALLOWED_GROUP_ID=621016172 / ALLOWED_USER_ID=1424473282的 check_permission Rule。
  • 本任务不需要改 xapi复用现有 /bot/gacha/sign-in + /bot/points/add 即可实现共用数据),不涉及跨端契约新增。

Requirements

  • 新增独立签到插件(目录 danding_bot/plugins/sign_in/
  • 群聊命令「签到」别名每日签到、打卡白名单权限ALLOWED_GROUP_ID / ALLOWED_USER_ID与抽卡一致
  • 命令触发签到:调用 xapi POST /bot/gacha/sign-in 记录签到,成功后调用 /bot/points/add 发放积分
  • 积分规则:随机 1-100与抽卡签到一致
  • 积分流水 source=gacha_sign、reason=抽卡签到(沿用现有标记,与 WPF/抽卡共用事件语义)
  • 重复签到signed_already=true提示"今天已签到",不发积分
  • onmyoji_gacha 抽卡签到保持现状,不做任何改动
  • 不新增「签到状态」查询命令(保持最小范围;重复签到提示利用响应自带的 sign_date/points_awarded
  • 更新 PLUGINS.md / README.md 文档

Acceptance Criteria

  • 发送「签到」:首次签到成功,返回签到成功 + 积分 + 当前余额
  • 同一天再次「签到」:提示已签到,不重复发积分
  • 抽卡签到与新命令签到互斥(共用 daily_sign_in 去重),先到先得:先抽卡后命令 → 命令提示已签到;先命令后抽卡 → 抽卡不重复发积分(抽卡插件原有逻辑已处理)
  • 权限:白名单外的群/用户收到无权限提示Rule 拒绝后命令不触发)
  • 测试覆盖10 个 unit testsmock xapi aiohttp 调用,全部通过)
  • ruff lint 通过(新文件 0 违规)

实现状态2026-08-16

  • 已实现:danding_bot/plugins/danding_sign_in/init/config/api/service/rules 5 文件)
  • 已实现:tests/test_danding_sign_in_plugin.py10 用例全绿)
  • 已更新文档PLUGINS.md新增 #14 + 抽卡章节交叉引用、README.md新增 #8
  • 测试环境:无 conda bot 环境,用 xapi envpytest 9.0.2 + aiohttp + pydantic 2.13)跑通;无 nonebot 环境rules.py 采用延迟导入 nonebot 保证可测
  • 代码复用决策:编排逻辑(先记录后发积分)未从 onmyoji_gacha 复制,而是自包含实现同模式 —— 避免 import onmyoji_gacha 包触发其 init matcher/路由注册耦合;若将来出现第 3 个签到入口,再提取共享模块(规则三)
  • 既有测试套件72 通过 + 1 失败test_danding_qqpush_article_render 中文编码问题,与本任务无关,环境性失败)

Definition of Done (team quality bar)

  • Tests added/updated (unit/integration where appropriate)
  • Lint / typecheck / CI green
  • Docs/notes updated if behavior changes
  • Rollout/rollback considered if risky

Technical Approach

  • 新插件 danding_bot/plugins/sign_in/,模块结构仿照现有插件惯例:
    • __init__.pyNoneBot matcher 注册on_command("签到", aliases={每日签到, 打卡}, priority=5, rule=check_permission())+ handler
    • config.pyPydantic 配置API host/token/白名单/积分区间,复用 onmyoji_gacha 配置命名惯例)
    • api.pyxapi 客户端(封装 POST /bot/gacha/sign-in,仿 DataManager._request 模式)
    • service.py 或直接编排:记录签到 → 发积分 → 格式化消息(先记录后发积分,避免重复发积分,复用 onmyoji_gacha/sign_in.py 的 award_daily_sign_in_points 模式)
  • 数据共用:直接调用与抽卡插件相同的 xapi 端点(/bot/gacha/sign-in + /bot/points/add),天然共用 bot_gacha_daily_sign_in 表,无需改动 onmyoji_gacha 插件。
  • 可复用现有代码:points_apidanding_points/api.py 的 PointsAPI直接 import签到编排可直接复用 onmyoji_gacha/sign_in.pyaward_daily_sign_in_points(或独立实现同模式)。
  • 测试:tests/test_sign_in_plugin.py,仿 tests/test_onmyoji_gacha_http_api.py 的 FakeSession/FakeResponse 模式 mock aiohttp。

Decision (ADR-lite)

Context: 用户需要独立签到命令,且与抽卡签到共用数据、不破坏抽卡签到。 Decision: 新插件复用 xapi 现有 /bot/gacha/sign-in + /bot/points/add 端点(与抽卡插件同源),数据自然共用;积分 source/reason 沿用 gacha_sign/抽卡签到;命令仅群聊 + 白名单;积分随机 1-100。 Consequences: 零 xapi 改动、零契约新增;抽卡插件零改动(回归风险最低);流水无法区分签到触发入口(可接受,因为每天只有一次签到);「签到状态/连续天数」查询能力暂缺,后续需要时另开任务(契约先行)。

Out of Scope

  • 不改 xapi无新增端点
  • 不做签到排行榜/连续签到统计/签到状态查询命令
  • 不迁移签到数据表位置
  • 不改 onmyoji_gacha 抽卡签到逻辑

Technical Notes

  • xapi 契约:C:\Users\14244\source\repos\Danding_Webs\xapi_new_web\docs\bot-api.md L114-126
  • 表结构:bot_gacha_daily_sign_inmigrations/DanDing/013_create_bot_data_migration_tables.py L99-109
  • 客户端参考:danding_bot/plugins/onmyoji_gacha/data_manager.py_request 模式)、danding_bot/plugins/onmyoji_gacha/sign_in.py(先记录后发积分编排)、danding_bot/plugins/danding_points/api.pyPointsAPI.add_points
  • 测试模式参考:tests/test_onmyoji_gacha_http_api.pyFakeSession/FakeResponse mock aiohttp
  • 任务创建于 2026-08-16Trellis 自动加日期前缀)