Add HeXi bot codebase: custom plugins, web frontends, tests

- hexi core: message handling, rate limiting, cooldown, plugin manager
- Custom plugins: BF stats, daily check-in, quotes, persona cards, etc.
- Community plugins vendored under hexi/plugins with local fixes
- Web admin frontends (learning-chat, persona-admin), unified hexi/web
- Tests for rate_limit/cooldown/memes/persona; poetry.lock

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-09-01 13:13:40 +08:00
co-authored by Claude
parent 1783c60afa
commit b61d09f09f
3201 changed files with 160436 additions and 171 deletions
@@ -0,0 +1,231 @@
# Helldivers 自部署 API 说明
> 本文档基于对自部署实例 **`http://192.168.2.15:18080`** 的实际探测整理(字段以真实返回为准)。
> 用途:弄清这个代理能拿到哪些数据,以及战报卡片**还没利用**的部分。
---
## 0. 基础信息
**Base URL**:`http://192.168.2.15:18080`
**请求头**(两个 `X-Super-*` 必须都带,否则公共实例会直接 400):
```http
Accept-Language: en-US,zh-Hans;q=0.5
X-Super-Client: <你的客户端名>
X-Super-Contact: <联系方式>
```
- `Accept-Language` 决定返回文案语言(`en-US` / `zh-Hans`/`zh-Hant` 等)。
- 返回均为 JSON。
**注意(坑)**:
- `/api/v1/war` 的 `now` 返回 `1972-...`,疑似该代理的数据有误(`started/ended` 是 2024→2028 也偏大)。用真实时间请自己取 `time.time()`,别信 `war.now`。
- `/api/v1/planet-events` 返回的是**单颗星球对象**(数组里只有 index 130),不是事件列表——疑似别名或代理异常。真正的星球事件在 `/raw/.../Status` 的 `planetEvents`。
- 接口返回可能被外层包裹成 `{data:[...]}` 或 `{planets:[...]}`,`/api/v1/*` 目前探测到是**裸数组/裸对象**。
---
## 1. 接口总览
| 端点 | 形状 | 说明 |
|---|---|---|
| `GET /api/v1/war` | `object` | 星系战况概要 |
| `GET /api/v1/assignments` | `array[1]` | 重要指令(最高指令 MAJOR ORDER) |
| `GET /api/v1/campaigns` | `array[35]` | 当前战役(参战星球) |
| `GET /api/v1/planets` | `array[273]` | 全星球表 |
| `GET /api/v1/planets/{index}` | `object` | 单星球详细情况 |
| `GET /raw/api/WarSeason/801/Status` | `object` | 原始战争状态(最全) |
> 以下 `/api/v1/*` 均 **404**:`attacks`、`galaxy`、`galaxy-war`、`global-events`、`news`、`statistics`、`space-stations`、`space_stations`、`war/status`、`war/statistics`、`war/summary`、`planet-effects`、`steam/war`、`version`。
> `/raw/api/WarSeason/801/*` 只有 `Status` 可用(`Planets`、`Assignments`、`Campaigns`、`News`、`Statistics`、`GlobalEvents`、`SuperEarthWarResults`、`Planets/224`、`Planet/224/Statistics` 均 404)。
---
## 2. 各端点字段详解
### 2.1 `GET /api/v1/war` — 星系战况概要
```json
{
"started": "2024-01-23T20:05:13Z",
"ended": "2028-02-08T20:04:55Z",
"now": "1972-07-14T16:19:50Z",
"clientVersion": "0.3.0",
"factions": ["Humans", "Terminids", "Automaton", "Illuminate"],
"impactMultiplier": 0.019517466,
"statistics": {
"missionsWon": 1011049334, "missionsLost": 98505230, "missionTime": 3325809094530,
"terminidKills": 216600333572, "automatonKills": 114998420419, "illuminateKills": 75823458605,
"bulletsFired": 1944890521255, "bulletsHit": 2131033542437, "timePlayed": 3325809094530,
"deaths": 8728394343, "revives": 2, "friendlies": 1009517116,
"missionSuccessRate": 91, "accuracy": 100, "playerCount": 57302
}
}
```
| 字段 | 说明 |
|---|---|
| `factions` | 参战阵营英文名(Humans/Terminids/Automaton/Illuminate) |
| `impactMultiplier` | 全局影响倍数 |
| `statistics` | 全局累计统计(任务/击杀/子弹/命中/死亡/胜率/命中率/玩家数) |
**可自定义用途**:顶部全局统计、累计击杀对比、胜利/失败率。
### 2.2 `GET /api/v1/assignments` — 重要指令(最高指令)
```json
{
"id": 3348823937,
"progress": [1, 0, 0],
"title": "MAJOR ORDER",
"briefing": "Liberate the designated enemy planets, ...",
"description": null,
"tasks": [
{ "type": 11, "values": [1, 1, 171], "valueTypes": [3, 11, 12] },
{ "type": 11, "values": [1, 1, 172], "valueTypes": [3, 11, 12] },
{ "type": 11, "values": [1, 1, 268], "valueTypes": [3, 11, 12] }
],
"reward": { "type": 1, "amount": 50 },
"rewards": [ { "type": 1, "amount": 50 } ],
"expiration": "2026-08-31T12:03:32.7346799Z",
"flags": 0
}
```
| 字段 | 说明 |
|---|---|
| `title` | 指令名(MAJOR ORDER / 玩家自定义战役等) |
| `briefing` | 指令说明文本(英文) |
| `progress` | 各目标进度(与 `tasks` 对位) |
| `tasks[].type` | 任务类型(11 = 解放/进攻某星球类) |
| `tasks[].values` | 与 `valueTypes` 对位:如 `[1,1,171]`,其中 `171/172/268` 为目标星球 index |
| `tasks[].valueTypes` | 各 `values` 的含义(3 疑似星球 index,11/12 为计数类;**需再对照官方定义**) |
| `reward` / `rewards` | 奖励:`type`(1=奖章/2=征用券/3=超级货币/4=补助/5=经验) + `amount` |
| `expiration` | 指令截止时间 |
**说明**:战报卡片的「重要指令」已用 `title/briefing/expiration`;`progress/tasks/rewards` 目前基本没用上,可用来做**进度条**(解放了 1/3 颗目标星)和**奖励展示**。
### 2.3 `GET /api/v1/campaigns` — 当前战役(参战星球)
```json
{
"id": 51413,
"type": 0,
"count": 10,
"faction": "Humans",
"planet": {
"index": 7, "name": "...", "sector": "...",
"biome": { "name": "...", "description": "..." },
"hazards": [ { "name": "Tremors", "description": "..." } ],
"maxHealth": ..., "health": ..., "regenPerSecond": ...,
"currentOwner": "...", "initialOwner": "...",
"event": null,
"statistics": { ... }, "attacking": [], "regions": []
}
}
```
| 字段 | 说明 |
|---|---|
| `faction` | 战役阵营(Humans/Terminids/Automaton/Illuminate)。**解放战**=当前占据的敌方;**防守战**=进攻的敌方 |
| `type` | 战役类型(0 = 解放/常规;`campaign.type` 1 可能 = 防守) |
| `count` | 战役数量(参与该星球的战役条目数,通常为 1) |
| `planet` | **完整星球对象**(同 `/api/v1/planets/{index}`,含 biome/hazards/event/statistics/attacking/regions) |
**可自定义用途**:`faction` 决定阵营色、`type` 区分解放/防守、`planet.hazards` 是危害来源(卡片已用)、`planet.event` 是侵攻事件。
### 2.4 `GET /api/v1/planets` / `GET /api/v1/planets/{index}` — 星球
```json
{
"index": 224, "name": "RD-4", "sector": "Orion",
"biome": { "name": "Moon", "description": "...", "icon": "..." },
"hazards": [ { "name": "Meteor Storms", "description": "...", "icon": "..." } ],
"hash": 1234567890,
"position": { "x": 0.29, "y": -0.87 },
"waypoints": [],
"maxHealth": 1000000, "health": 1000000,
"disabled": false, "initialOwner": "Illuminate", "currentOwner": "Illuminate",
"regenPerSecond": 1.1111112,
"event": null,
"statistics": {
"missionsWon": 1290109, "missionsLost": 152477, "missionTime": 4488281762,
"terminidKills": 1344, "automatonKills": 3656, "illuminateKills": 604567039,
"bulletsFired": 3286403648, "bulletsHit": 3218310824, "timePlayed": 4488281762,
"deaths": 9153248, "revives": 0, "friendlies": 1324721,
"missionSuccessRate": 89, "accuracy": 97, "playerCount": 71
},
"attacking": [],
"regions": []
}
```
| 字段 | 说明 |
|---|---|
| `index` / `name` | 星球编号 / 英文名 |
| `sector` | 星区英文名(战报里显示中文分区名) |
| `biome` | 地形(英文名 + 描述;`_translate` 加 i18n→中文) |
| `hazards[]` | **气象危害**(每颗星一个数组,可能多个;`name` 为英文,加 i18n→中文) |
| `maxHealth/health/regenPerSecond` | 战役血量 / 现值 / 回复速度(解放进度 = `(max-health)/max`) |
| `currentOwner/initialOwner` | 当前/初始阵营(英文名) |
| `event` | 进攻事件(空则无) |
| `statistics` | 星球累计统计(击杀/胜率/命中率/玩家数) |
| `attacking` | 正在进攻的条目(当前数据为空数组) |
| `regions` | 行星区域权属(当前为空数组) |
**提示**:`hazards` 才是「环境事件」,且**一个星球可出现多个**;战报卡片的「环境事件」槽位已支持多危害图标+名称展示。
### 2.5 `GET /raw/api/WarSeason/801/Status` — 原始战争状态(最全)
顶层键:`warId, time, impactMultiplier, storyBeatId32, planetStatus, planetAttacks, campaigns, communityTargets, jointOperations, planetEvents, planetActiveEffects, planetRegions, activeElectionPolicyEffects, globalEvents, superEarthWarResults, spaceStations, layoutVersion`
| 子数组 | 形状 | 样例 / 字段 |
|---|---|---|
| `planetStatus` `[273]` | `{index, owner, health, regenPerSecond, players, position:{x,y}}` | 每颗星实时状态(比 `/api/v1/planets` 更轻、更新) |
| `planetAttacks` `[50]` | `{source, target}` | 进攻路线(source 星 → target 星) |
| `campaigns` `[35]` | `{id, planetIndex, type, count, race}` | 战役(`race` 数字阵营、`type` 0/1) |
| `planetEvents` `[1]` | `{id, planetIndex, eventType, race, health, maxHealth, startTime, expireTime, campaignId, jointOperationIds, potentialBuildUp}` | **被攻星球的进攻事件**(最完整:含 maxHealth / expireTime / 联合作战) |
| `planetActiveEffects` `[154]` | `{index, galacticEffectId}` | 星球生效效果(`galacticEffectId` → 效果图标) |
| `planetRegions` `[40]` | `{planetIndex, regionIndex, owner, health, regerPerSecond, availabilityFactor, isAvailable, players}` | **行星区域**权属/血量/玩家(可做区域细览) |
| `spaceStations` `[1]` | `{id32, planetIndex, activeEffectIds[], currentElectionEndWarTime, flags}` | 空间站(DSS):所在星 + 生效效果列表 |
| `jointOperations` `[1]` | `{id, planetIndex, hqNodeIndex}` | 联合作战节点 |
| `globalEvents` `[2]` | `{eventId, id32, portraitId32, title, titleId32, message, ...}` | 战争级事件公告(战役成功等) |
| `communityTargets` | `[]`(空) | 社区目标(当前无) |
| `activeElectionPolicyEffects` | `[]`(空) | 选举政策效果(当前无) |
| `superEarthWarResults` | `[]`(空) | 战争结果(当前无) |
**说明**:`planetStatus[].owner` 是数字阵营(0=人类/1=终结族/2=机器人/3=光能族 之类),与 `/api/v1/planets` 的英文字符串阵营对应关系需要你确认——原生 HD2 里 `owner` 数字:`1=Humans, 2=Terminids, 3=Automaton, 4=Illuminate`。
---
## 3. 战报卡片:已用 / 未利用
### 已利用
- `war` → 顶部标题信息
- `assignments` → 重要指令(title/briefing/expiration)
- `campaigns[].planet` → 战役卡片(进度/危害/地形/效果)
- `planets`(en-US 星名)→ 匹配高清地形背景
- `raw.planetActiveEffects` → `planet_effects`(星球效果槽位)
- `raw.spaceStations` → `space_stations`(DSS 增益)
### 还有可利用(建议关注)
| 数据 | 来源 | 可做什么 |
|---|---|---|
| `planetEvents`(maxHealth/expireTime) | `/raw/Status` | **更准的入侵进度 + 倒计时**(目前卡片从 `campaign.planet.event` 取,缺 maxHealth/expireTime 时精度差) |
| `planetAttacks`(source→target) | `/raw/Status` | **战线图/进攻箭头**:可视化谁正在打谁 |
| `planetRegions` | `/raw/Status` | **星球区域占领细览**(每区域 owner/health/players) |
| `globalEvents` | `/raw/Status` | **战报滚动公告**(战役成功/事件推送) |
| `planetStatus[].owner/regen/players` | `/raw/Status` | 全星系战况概览(比全量星球更轻) |
| `planet.statistics` | `/api/v1/planets/{i}` | 星球数据卡(击杀/胜率/命中率/玩家数) |
| `war.statistics` | `/api/v1/war` | 顶部全局累计统计 |
| `assignment.progress/tasks/rewards` | `/api/v1/assignments` | **重要指令进度条**(解放了几颗目标星)+ 奖励展示 |
---
## 4. 状态码 / 异常
- `200`:正常(返回 JSON)。
- `400`:缺 `X-Super-Client` / `X-Super-Contact`(或头格式错误)。
- `404`:接口不存在(见上表 404 清单)。
- 某些异常时可能返回 JSON `{error: ...}` 或带 `Message` 字段;建议调用方对非 200 抛出带 `resp.text[:400]` 的错误(`hd2_api._get_json` 已如此处理)。
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff