This commit is contained in:
2026-07-26 17:57:44 +08:00
parent a555f785ba
commit 069f1bafe1
27 changed files with 4893 additions and 3846 deletions
+115 -25
View File
@@ -189,12 +189,30 @@ astrbot_plugin_jx3/
├─ _conf_schema.json # AstrBot 后台配置 schema
├─ requirements.txt # Python 依赖
├─ data/
│ ├─ api_config.json # 外部接口配置,按功能 key 维护 URL、method、默认参数
│ ├─ api_config.json # 服务基地址、Adapter、端点相对路径和默认参数
│ └─ plugin_data.db # 插件随包数据,主要用于内置数据
├─ core/
│ ├─ jx3_data.py # 业务数据层,调用接口、整理数据、选择模板
│ ├─ jx3_data.py # 领域 Service 组合与 HTTP 生命周期
│ ├─ api_config.py # API 服务/端点配置校验与 URL 解析
│ ├─ adapters/
│ │ ├─ base.py # 通用端点请求与结构化 Adapter 异常
│ │ ├─ jx3api.py # JX3API 凭证注入、业务码校验和 data 提取
│ │ ├─ jx3box.py # JX3BOX 响应与分页规则
│ │ └─ router.py # 根据服务配置选择 Adapter
│ ├─ services/
│ │ ├─ base.py # ServiceResult、请求、模板和公共领域能力
│ │ ├─ cache.py # 通用 JSON 缓存仓储
│ │ ├─ calendar.py # 日常、活动和事件
│ │ ├─ character.py # 角色、名片、奇穴和技能
│ │ ├─ adventure.py # 奇遇查询、统计和攻略
│ │ ├─ faction.py # 阵营、排行、沙盘和帮战
│ │ ├─ arena.py # 战绩、名剑和招募
│ │ ├─ achievement.py # 资历数据与进度计算
│ │ ├─ trade.py # 金价、物价、交易行和掉落
│ │ ├─ information.py # 新闻、区服和通用资料
│ │ └─ content.py # 帮助、八卦、宏和配装
│ ├─ message.py # 消息构建层,负责文本、图片、富媒体回复
│ ├─ request.py # aiohttp 请求封装,统一处理 GET/POST 和接口返回
│ ├─ request.py # 通用 HTTP 客户端,不包含任何上游业务规则
│ ├─ async_task.py # APScheduler 后台推送任务
│ ├─ bilei_data.py # 本地避雷数据增删改查
│ ├─ sqlite.py # SQLite 异步封装
@@ -247,23 +265,35 @@ astrbot_plugin_jx3/
### 4. 数据请求与业务处理
`core/jx3_data.py` 是主要业务层。每个功能通常对应一个异步方法,例如:
`core/jx3_data.py` 只组合领域 Service 并管理共享 HTTP Client。业务方法按
功能归入 `core/services/`,例如:
```python
async def jinqiqiyu(self, server: str) -> Dict[str, Any]:
...
await services.calendar.richang(server, num)
await services.character.jueshe(name, server)
await services.adventure.jinqiqiyu(server)
await services.trade.jiaoyihang(name, server)
```
业务方法通常遵循统一结
所有领域 Service 共享 `BaseDomainService`,新方法推荐直接返回统一结
1. 调用 `_init_return_data()` 创建标准返回对象。
2. 构造接口参数,填入 `server``name``token``ticket` 等。
3. 通过 `_base_request(config_key, method, params)` 读取 `data/api_config.json` 中的接口配置并发起请求。
4. 判断接口返回是否为空或结构异常。
5. 整理时间戳、字段名、分组、列表、统计值等模板需要的数据。
6. 文本功能直接写入 `return_data["data"]`
7. 图片功能额外加载对应 HTML 模板并写入 `return_data["temp"]`
8. 成功时设置 `return_data["code"] = 200`
```python
if not isinstance(data, dict):
return self.failure("接口响应格式异常")
return self.success(view_data)
# 需要模板时
return await self.template_result("example.html", view_data)
```
领域方法通常遵循统一结构:
1. 构造游戏业务参数,例如 `server``name`Token/Ticket 由 Adapter 注入。
2. 通过基类请求入口读取端点配置并发起请求。
3. 明确区分请求失败、合法空结果和响应结构异常。
4. 整理时间戳、字段名、分组、列表、统计值等模板需要的数据。
5. 使用 `success()``failure()``template_result()` 返回统一结果。
标准返回结构大致为:
@@ -279,22 +309,50 @@ async def jinqiqiyu(self, server: str) -> Dict[str, Any]:
### 5. 接口请求封装
`core/request.py` 中的 `APIClient` 负责实际 HTTP 请求。
请求链路按职责拆分为:
```text
MessageBuilder
JX3Service(组合领域服务)
Calendar / Character / Adventure / Trade 等 Domain Service
BaseDomainService(统一请求、结果、模板)
APIAdapterRouter(按服务选择 Adapter
├─ JX3ApiAdapter(业务码、Token/Ticket、data
├─ JX3BoxAdapter(响应结构、分页)
└─ EndpointAdapter(其他通用上游)
APIClientSession、TLS、连接池、超时、HTTP、重试)
```
`core/request.py` 中的 `APIClient` 只负责通用 HTTP 能力。
实现特点:
- 复用 `aiohttp.ClientSession`
- 支持 GET 和 POST
- 默认校验 HTTPS 证书,并限制连接池和响应体大小
- 分别设置总超时、连接超时和读取超时。
- 支持 GET、JSON POST、表单 POST、自定义 Header。
- 对超时、连接异常、HTTP 429 和部分 5xx 做有限退避重试。
- 自动识别 JSON、图片或二进制响应。
- 对 JX3API 常见返回结构做基础校验
- 支持通过 `out_key` 抽取返回对象中的指定字段,默认通常取 `data`
- 日志默认只记录参数字段名;需要记录参数值时也会清理 Token、Ticket 等敏感字段
- 使用结构化异常区分网络、HTTP、响应大小和响应格式错误
`JX3Service._base_request()` 会在业务层进一步统一
Adapter 层负责
- 根据 `data/api_config.json` 查找接口。
- 组合服务基地址、公共路径前缀和端点相对路径。
- 合并接口默认参数和运行时参数。
- 根据配置 method 调用 GET 或 POST。
- 捕获异常并输出日志
- `JX3ApiAdapter` 集中注入 Token/Ticket、校验业务码并提取 `data`
- `JX3BoxAdapter` 集中处理 JX3BOX 响应与分页停止规则。
`BaseDomainService.request()` 将端点请求交给 Router,并把结构化请求异常
转换为业务层约定的 `None`。领域服务统一使用 `new_result()``success()`
`failure()``attach_template()``template_result()` 构造结果。
### 6. 图片渲染
@@ -345,7 +403,39 @@ html_renderer.render_custom_template()
`core/sqlite.py` 封装了异步增删改查;`core/bilei_data.py` 基于该封装实现避雷数据管理。
### 8. 资历查询
### 8. API 地址配置
`data/api_config.json` 将服务地址和端点路径分开维护:
```json
{
"_services": {
"jx3api": {
"base_url": "https://www.jx3api.com",
"path_prefix": "",
"adapter": "jx3api"
}
},
"jx3_richang": {
"service": "jx3api",
"path": "active/calendar",
"method": "GET"
}
}
```
- `base_url`:服务协议和域名。
- `path_prefix`:该服务所有接口共享的路径前缀。
- `adapter`:该服务的响应与鉴权适配器,可用值为 `jx3api``jx3box``generic`
- `path`:单个端点的相对路径。
服务公共路径变化时只需修改 `path_prefix`,域名变化时只修改 `base_url`
动态端点可以在 `path` 中使用占位符,例如
`serendipity/{dw_id}/achievement`。每个端点必须显式声明 `service`
相对 `path`,不接受端点级绝对 `url`
### 9. 资历查询
`资历 角色名称 [服务器]` 是 2.6 新增的两轮对话功能。
@@ -362,7 +452,7 @@ html_renderer.render_custom_template()
4. 展开菜单中单个 ID 和数组 ID,按资历点数计算 `已完成点数 / 总点数` 与百分比。
5. 使用 `templates/zili.html` 渲染进度条图片。
### 9. 交易行查询
### 10. 交易行查询
`交易行 物品名称 [服务器]` 在 2.7 中完成重构,属于交易功能,免令牌,输出为图片。
@@ -377,7 +467,7 @@ html_renderer.render_custom_template()
价格单位按铜钱换算为砖、金、银、铜,并使用 `templates/img` 下的 `zhuang.png``jin.png``yin.png``tong.png` 图标展示;0 砖不会显示砖图标。
### 10. 后台推送
### 11. 后台推送
`core/async_task.py` 使用 APScheduler 实现轮询推送。
@@ -401,7 +491,7 @@ html_renderer.render_custom_template()
新增一个查询功能通常需要改动 4 到 5 个位置:
1.`data/api_config.json` 添加接口配置。
2.`core/jx3_data.py` 添加业务方法,完成请求数据整理和错误处理
2.`core/services/` 对应领域文件添加业务方法,完成请求数据整理。
3.`core/message.py` 添加消息包装方法,选择文本、图片或富媒体输出。
4.`main.py``command_map` 注册中文触发指令。
5. 如果是图片输出,新增 `templates/xxx.html`