# WARDOGS 服务器联 ban API 服务地址:https://api.kaedeori.com 管理面板:https://server.kaedeori.com 运行 SDK 需要 Node.js 22.13 或更高版本,无第三方依赖。 ## 公共查询 | GET 路径 | 内容 | | --- | --- | | /behavior | 当前有效的行为违规封禁 | | /cheater | 当前有效的外挂作弊封禁 | | /all | 当前所有有效封禁及去重后的 SteamID | | /history?steamId=76561198000000001 | 该 SteamID 所有独立封禁记录,包括到期、撤销及当前有效记录 | 前三个接口支持可选 steamId 精确筛选;历史接口必须提供 steamId。 均无需密钥,允许跨域 GET。不限制分页,不会悄悄截断有效名单。 成功响应格式为 { "code": 200, "data": ... };HTTP 错误对应稳定的大写 error 字段。 data.steamIds 为去重后的字符串数组,data.items 为完整记录,data.total 是记录数量。 历史额外返回 occurrenceCount(封禁次数)和 activeCount(目前有效次数)。 同一 SteamID 可有多条历史记录或来自不同服务器的记录,请使用记录 id 去重,不能只按 SteamID 覆盖。 总览中的历史记录数包含有效、已撤销及已到期记录。 示例(以下是结构示例,不是真实玩家记录): ~~~json { "code": 200, "data": { "steamIds": ["76561198000000001"], "items": [{ "id": "记录 UUID", "steamId": "76561198000000001", "category": "behavior", "reason": "恶意伤害队友,多次提醒无效", "images": [{ "id": "图片 ID", "url": "https://distro.kaedeori.com/assets/wardogs/federation/evidence/内容哈希.png", "contentType": "image/png", "size": 12345 }], "server": { "id": "来源服务器 ID", "name": "服务器名称" }, "startsAt": "2026-09-24T02:00:00.000Z", "endsAt": null, "expiresAt": null, "createdAt": "2026-09-24T02:00:01.000Z", "status": "active", "revokedAt": null, "revokeReason": "" }], "total": 1, "updatedAt": "2026-09-24T02:00:02.000Z" } } ~~~ SteamID 必须按字符串读取和提交,不要转为 JavaScript Number。 时间统一是 ISO 8601 UTC,显示时转换为自己的时区。 startsAt 为封禁开始;endsAt 为计划结束,null 表示永久。expiresAt 是 endsAt 的兼容字段。 createdAt 为录入时间。revokedAt 是实际撤销时间,不会覆盖原计划期限。 status 为 active / revoked / expired。 旧记录 startTimeSource=first_observed 表示只知道首次收录时间,不能当作可确认的实际封禁开始。 按原面板执行日志能确定时间时标为 source_event;手工创建记录的开始时间由提交者负责。 消费者建议每 30–60 秒刷新完整有效名单。只有成功 HTTP 200 且 JSON 结构有效时才替换本地副本。 记录到期或撤销后从有效接口消失;消费者应移除由联 ban 导入且已失效的封禁,但不要误删自己单独添加的封禁。 503 LEGACY_SOURCE_UNAVAILABLE 表示某个原面板来源不可读,请保留上次成功数据并稍后重试。 有效名单响应缓存最长 15 秒,历史查询禁止缓存,原面板同步缓存最长 5 秒;到期过滤实时执行。 历史接口不应用作“全部自动封禁”名单。 所有公开接口始终排除 `isTest: true` 的接入测试记录;不能通过查询参数包含测试记录。 ## 自动上传 管理员先在面板创建服务器账号。该账号完成首次设置后,在“自动化接入”创建 API 密钥。 密钥只显示一次,只保存于自己的面板后端环境变量 WARDOGS_FEDERATION_TOKEN。 发送 Authorization: Bearer ,不要发送管理员密码、Cookie 或 X-CSRF-Token。 来源服务器由密钥绑定的账号决定,不能通过请求伪造。 密钥可以读取 /v1/bans、/v1/stats,以及上传图片、创建封禁、撤销自己的封禁;不能管理账号或其他人的密钥。 ### 1. 上传证据 POST /v1/images,Content-Type: application/json: ~~~json { "filename": "evidence.png", "contentType": "image/png", "base64": "文件的纯 base64,不包含 data: 前缀" } ~~~ 返回 data={id,url,contentType,size}。支持 PNG/JPEG/WebP,单张最大 5 MiB。 上传前遮盖无关个人信息,图片会公开分发。文件名不能包含路径,实际对象路径由服务端内容哈希决定。 ### 2. 创建封禁 POST /v1/bans: ~~~json { "requestId": "08c3c88e-c2d9-4f74-90f6-bc7cd5f9c413", "steamId": "76561198000000001", "category": "behavior", "reason": "说明违规行为和封禁依据", "images": ["图片 ID"], "startsAt": "2026-09-24T02:00:00.000Z", "endsAt": "2026-09-27T02:00:00.000Z" } ~~~ 图片 1–5 张,必须是同一服务器账号上传的图片。reason 为 3–2000 字符。 startsAt 可省略(当前时间),不得在未来;endsAt 可为空(永久),必须晚于开始。 可提交已经结束的封禁,用于补充历史。 同一服务器同一 SteamID 同一分类只能有一条有效封禁;需先撤销旧记录再新建下一次记录。 requestId 必须是固定 UUID。每条原始封禁映射一个 UUID,重试时复用相同字段及图片 ID。 同 requestId 同内容返回原记录和 replayed=true;不同内容返回 409 REQUEST_ID_CONFLICT。 保存返回的 ban.id,用于后续撤销。 ### 接入自检 经过用户授权,可使用非真实指控的测试说明、明确标注的测试图片和 `isTest: true` 验证上传链路。先检查 `GET /health` 的 `data.capabilities.testRecords === true`,旧版服务可能忽略未知字段,不能向旧版发送虚构记录。 `isTest` 是可选布尔值,默认为 false;创建后不可更改,重试必须保持相同值。测试记录只在登录后的列表中显示,不进入 `/all`、`/behavior`、`/cheater`、`/history` 或正式统计。图片仍会实际上传到公开 CDN,测试图片不要包含个人信息。 验证上传、相同 requestId 重放、登录后的读取、公开查询排除,然后调用撤销接口。测试不能触发游戏 RCON 封禁。 `GET /v1/bans?mine=true&isTest=true&steamId=...&offset=0&limit=100` 查询本服务器测试记录,`isTest=false` 仅查询正式记录;省略则包括两类。响应记录包含 `requestId` 和 `isTest`。分页上限100,继续读取时递增 offset。 `GET /v1/stats` 正式计数排除测试,测试单独在 `data.testRecords={total,active,mine:{total,active}}` 返回。 ### 3. 撤销 POST /v1/bans/:id/revoke,JSON { "reason": "误封复核通过,现予撤销" }。 仅能撤销自己服务器上传的记录,已撤销记录可重复请求。 撤销不会删除历史或证据。原 /manage 同步的记录应在原面板解封,状态会同步过来。 ## Node.js SDK 与命令行 下载同目录 wardogs-federation.mjs,放在自己面板的服务端。 导入 createFederationClient 可直接调用 uploadImage、createBan、revokeBan、query、listBans、stats。 默认地址为正式 API;测试可用 WARDOGS_FEDERATION_URL 设置 HTTPS 地址或本地回环 HTTP。 API 密钥不应发送到不可信地址。 CLI: ~~~sh node wardogs-federation.mjs query all node wardogs-federation.mjs query history 76561198000000001 node wardogs-federation.mjs submit ban.json node wardogs-federation.mjs revoke BAN_ID "复核后撤销" ~~~ ban.json 的字段与创建封禁相同,但 images 填本地图片路径(相对于 ban.json): ~~~json { "requestId": "08c3c88e-c2d9-4f74-90f6-bc7cd5f9c413", "steamId": "76561198000000001", "category": "behavior", "reason": "说明封禁依据", "images": ["proof.png"], "endsAt": null } ~~~ submit 会保存 ban.json.federation-state.json,其中只含重试所需的图片 ID、请求 ID、接口地址、指纹和结果,不含 Token。 保留该文件;重试相同命令将复用已上传图片和 requestId。同一来源记录的操作应串行执行。 已经成功提交后不要修改原文件并强行复用请求 ID。字段改动会停止并返回 STATE_INPUT_CHANGED。 外部面板可在封禁成功后把原记录写入上传队列,异步调用 SDK;失败保留队列重试,成功持久化返回的 ban.id。 不要在每次网络重试时生成新 requestId,否则会破坏幂等性。 API 返回 401/403 时停止自动重试并检查密钥;429 尊重 Retry-After;网络错误/503 延迟重试最多三次,再交给持久队列。 ## 面板账号 kaedeori 是初始管理员账号。首次登录强制设置用户名和至少 12 位新密码,之后方可查看管理数据和创建密钥。 管理员能创建 admin/member 账号、停用其他账号。普通账号只能修改自己的联 ban 数据。 停用账号会使它的会话和 API 密钥失效。密钥可以单独撤销。 使用自己的用户名和服务器名称,避免将密码、密钥写入上传原因或操作备注。