Files
astrbot_plugin_jx3/README.md
T
2026-07-26 17:57:44 +08:00

520 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# astrbot_plugin_jx3
基于 [AstrBot](https://docs.astrbot.app/) 框架开发的剑网三游戏数据查询插件。插件主要通过 JX3API、JX3BOX、茶馆等外部接口获取游戏数据,整理为文本消息、富媒体消息,或通过 `HTML + Jinja2` 模板渲染成图片后发送。
当前插件以“查询型功能”为主,覆盖日常、官方、角色、职业、休闲、阵营、副本、活动、交易、杂项、排行、推送和本地避雷等场景。部分功能需要配置 JX3API Token,少量职业/角色类接口还需要推栏 ticket。
## 功能概览
插件内置 `功能` 指令,会以图片形式展示完整指令列表、参数说明和是否需要令牌。当前帮助页按 13 个功能分组维护,约 88 条指令。
主要功能包括:
- 日常功能:日常、月历、名望、诛恶。
- 官方功能:公告、维护、技改、区服、开服、状态。
- 角色功能:角色、资历、名片、所有名片、奇遇、未做奇遇、战绩、精耐。
- 职业功能:小药、宏、配装、阵眼、奇穴、技能。
- 休闲功能:烟花、拜师、收徒、随机名片、攻略、奇遇统计、近期奇遇、奇遇汇总。
- 阵营功能:沙盘、阵营拍卖、阵营事件、关隘首领、帮战记录、统战 YY。
- 副本功能:百战、招募、掉落、解密。
- 活动功能:扶摇、本日赤兔、本周赤兔、刷马、的卢。
- 交易功能:金价、物价、交易行、贴吧物价。
- 杂项功能:科举、花价、装饰、器物、八卦、骗子、骚话。
- 排行功能:名剑统计、名剑排行、资历排行、试炼排行和各类风云录榜单。
- 推送功能:开服推送、新闻推送、刷马推送、赤兔推送。
- 避雷功能:避雷查看、添加、删除、修改、查询。
## 安装与依赖
将插件目录放入 AstrBot 的插件目录中,例如:
```text
data/plugins/astrbot_plugin_jx3
```
安装依赖:
```bash
pip install -r requirements.txt
```
当前依赖:
- `aiohttp`:异步 HTTP 请求。
- `aiofiles`:异步文件处理。
- `aiosqlite`:本地 SQLite 数据库。
- `apscheduler`:后台推送任务调度。
- `matplotlib`:部分图像/数据展示依赖。
插件元信息在 `metadata.yaml` 中维护,当前版本为 `v2.7`,要求 AstrBot 版本 `>=4.11.0`
## 插件配置
配置结构由 `_conf_schema.json` 定义,主要配置项如下。
### 指令前缀
```json
{
"prefix": {
"enable": true,
"text": "剑三"
}
}
```
- `enable`:是否启用指令前缀检查。
- `text`:指令前缀内容,默认 `剑三`
启用后,用户需要发送类似 `剑三 日常``剑三 奇遇 角色名` 才能触发。关闭后可直接发送 `日常``奇遇 角色名`
### 默认服务器
```json
{
"server": "梦江南"
}
```
许多指令都带有 `[服务器]` 可选参数。用户未填写服务器时,插件会使用这里配置的默认服务器。
示例:
```text
奇遇 飞翔大野猪
```
等价于:
```text
奇遇 飞翔大野猪 梦江南
```
前提是默认服务器配置为 `梦江南`
### JX3API Token
```json
{
"jx3api_token": ""
}
```
需要令牌的功能必须配置该字段。Token 需要在 [JX3API](https://www.jx3api.com/) 注册并购买后获取。
帮助页中标记为“需令牌”的指令,如果未配置 Token,可能无法正常返回数据。
### 推栏 Ticket
```json
{
"jx3api_ticket": ""
}
```
部分接口需要推栏 ticket,例如部分职业、角色、学校类接口。该值通常需要通过抓包推栏 App 的请求参数获得。
### 推送配置
插件支持 4 类后台推送:
- `kfts`:开服监控。
- `xwts`:新闻资讯。
- `smts`:刷马消息。
- `ctts`:赤兔消息。
每类推送配置都包含:
- `enable`:是否启用。
- `time`:轮询间隔,单位秒。
- `umos`:推送目标会话 ID 列表。
示例:
```json
{
"kfts": {
"enable": false,
"time": 60,
"umos": ["QQ:GroupMessage:123456"]
}
}
```
`umos` 需要填写完整会话 ID,可通过 AstrBot 的 `/std` 等方式获取。推送本质是后台定时请求接口,检测状态变化后向配置的会话发送消息,不建议将轮询间隔设置得过短。
## 使用方式
发送:
```text
功能
```
即可获取完整指令帮助图。
如果开启了指令前缀,则发送:
```text
剑三 功能
```
指令参数说明:
- `[]` 表示可选参数。
- `[服务器]` 未填写时使用插件默认服务器。
- 数量、天数、模式等参数未填写时使用对应功能的默认值。
示例:
```text
日常
诛恶
资历 飞翔大野猪
交易行 五行石 梦江南
奇遇 飞翔大野猪
未做奇遇 飞翔大野猪 梦江南
战绩 飞翔大野猪 梦江南 33
名剑排行 50 33
贴吧物价 狐金 5 梦江南
统战 梦江南
```
## 目录结构
```text
astrbot_plugin_jx3/
├─ main.py # AstrBot 插件入口,初始化配置、资源、服务和指令分发
├─ metadata.yaml # 插件元信息
├─ _conf_schema.json # AstrBot 后台配置 schema
├─ requirements.txt # Python 依赖
├─ data/
│ ├─ api_config.json # 服务基地址、Adapter、端点相对路径和默认参数
│ └─ plugin_data.db # 插件随包数据,主要用于内置数据
├─ core/
│ ├─ 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 # 通用 HTTP 客户端,不包含任何上游业务规则
│ ├─ async_task.py # APScheduler 后台推送任务
│ ├─ bilei_data.py # 本地避雷数据增删改查
│ ├─ sqlite.py # SQLite 异步封装
│ └─ fun_basic.py # 模板加载、图片 base64、通用格式化工具
└─ templates/
├─ helps.html # 功能帮助页
├─ *.html # 各图片指令的 HTML/Jinja2 模板
├─ img/ # 通用图片资源
├─ sect/ # 门派/心法图标
└─ serendipity/ # 奇遇图标
```
## 核心实现逻辑
### 1. 插件初始化
`main.py` 中的 `Jx3ApiPlugin` 是插件入口。
初始化时会完成以下工作:
1. 读取 AstrBot 插件配置,包括前缀、默认服务器、Token、Ticket 和推送配置。
2. 计算本地数据目录、插件数据目录、模板目录和接口配置文件路径。
3. 加载 `templates/img``templates/sect``templates/serendipity` 中的图片,并转为 base64,供 HTML 模板直接引用。
4. 初始化 SQLite、JX3Service、AsyncTask、BiLeidata、MessageBuilder。
5. 在异步初始化阶段创建本地表,并启动后台推送任务。
6. 构建 `command_map`,将中文触发词映射到对应的消息处理函数。
### 2. 指令分发
用户消息进入插件后,`main.py` 会:
1. 根据配置判断是否需要指令前缀。
2. 将消息按空格切分为 `指令 + 参数`
3.`command_map` 中查找对应处理函数。
4. 使用 `inspect.signature` 根据函数参数数量自动传入用户参数。
5. 找不到指令时不处理,参数错误时返回提示。
### 3. 消息构建
`core/message.py``MessageBuilder` 负责把业务数据发出去,主要有几类输出:
- `plain_msg()`:发送纯文本。
- `T2I_image_msg()`:把业务数据传入 HTML 模板,调用 AstrBot 的 HTML 渲染能力生成图片。
- `image_msg()`:直接发送图片 URL 或图片数据。
- `plain_chain()`:发送文本 + 图片等富媒体消息链。
- `handler_plain_image_msg()`:先发文本,再发图片,适用于部分组合型功能。
- `handler_zili_msg()`:资历查询专用两轮会话,先发送 `0-18` 分类菜单,再按用户选择渲染资历进度图片。
所有可选服务器参数都会通过 `serverdefault()` 补齐默认服务器。
### 4. 数据请求与业务处理
`core/jx3_data.py` 只组合领域 Service 并管理共享 HTTP Client。业务方法按
功能归入 `core/services/`,例如:
```python
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`,新方法推荐直接返回统一结果:
```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()` 返回统一结果。
标准返回结构大致为:
```python
{
"code": 0,
"msg": "错误提示",
"data": {},
"temp": "",
"icons": {}
}
```
### 5. 接口请求封装
请求链路按职责拆分为:
```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`
- 默认校验 HTTPS 证书,并限制连接池和响应体大小。
- 分别设置总超时、连接超时和读取超时。
- 支持 GET、JSON POST、表单 POST、自定义 Header。
- 对超时、连接异常、HTTP 429 和部分 5xx 做有限退避重试。
- 自动识别 JSON、图片或二进制响应。
- 日志默认只记录参数字段名;需要记录参数值时也会清理 Token、Ticket 等敏感字段。
- 使用结构化异常区分网络、HTTP、响应大小和响应格式错误。
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. 图片渲染
图片输出功能使用 `templates/*.html`
典型数据流:
```text
JX3Service 整理数据
MessageBuilder.T2I_image_msg()
注入 icons
html_renderer.render_custom_template()
发送图片
```
模板里可以使用:
- `icons.img`:通用图标。
- `icons.sect`:门派/心法图标。
- `icons.serendipity`:奇遇图标。
例如门派图标常见写法:
```jinja2
{% set icon = icons.sect.get(item.forceName) %}
{% if icon %}
<img src="{{ icon }}">
{% endif %}
```
### 7. 本地数据库
插件使用两个 SQLite 数据库:
- 插件目录下的 `data/plugin_data.db`:随插件提供的内置数据。
- AstrBot 数据目录中的 `local_data.db`:运行期本地数据。
本地数据主要用于:
- 避雷记录。
- 推送任务状态缓存。
- 资历菜单与资历点数基础数据缓存,默认缓存 30 天,接口失败时可使用旧缓存兜底。
- 交易行物品库基础数据缓存,默认缓存 30 天,接口失败时可使用旧缓存兜底。
`core/sqlite.py` 封装了异步增删改查;`core/bilei_data.py` 基于该封装实现避雷数据管理。
### 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 新增的两轮对话功能。
第一轮会发送固定分类菜单,用户输入 `0-18` 后进入第二轮:
- `0`:展示角色资历总览,并列出 18 个大类的完成进度。
- `1-18`:展示对应大类总览,并列出该大类下所有子类的完成进度。
实现流程:
1. 通过角色信息接口 `jx3_jueshexinxi` 获取角色 `globalId`
2.`globalId` 请求 JX3BOX 角色资历接口,获取已完成资历 ID 列表。
3. 从资历菜单接口和资历点数接口读取基础数据,并缓存到本地 SQLite。
4. 展开菜单中单个 ID 和数组 ID,按资历点数计算 `已完成点数 / 总点数` 与百分比。
5. 使用 `templates/zili.html` 渲染进度条图片。
### 10. 交易行查询
`交易行 物品名称 [服务器]` 在 2.7 中完成重构,属于交易功能,免令牌,输出为图片。
实现流程:
1. 从 JX3BOX 交易行物品库接口读取所有可查询物品,并缓存到本地 SQLite。
2. 用户输入物品名后,在本地物品库中按名称进行模糊匹配。
3. 匹配结果按“完全匹配、前缀匹配、包含匹配”排序,默认最多取前 50 个物品 ID。
4. 调用 `https://next2.jx3box.com/api/auction/` 批量查询指定服务器的交易行价格。
5. 价格接口未返回的物品不展示;全部无价格数据时直接返回文本提示。
6. 使用 `templates/jiaoyihang.html` 渲染列表图片,展示物品图标、物品名称、价格、数量和数据时间。
价格单位按铜钱换算为砖、金、银、铜,并使用 `templates/img` 下的 `zhuang.png``jin.png``yin.png``tong.png` 图标展示;0 砖不会显示砖图标。
### 11. 后台推送
`core/async_task.py` 使用 APScheduler 实现轮询推送。
当前支持:
- 开服监控。
- 新闻资讯。
- 刷马消息。
- 赤兔消息。
推送逻辑是:
1. 初始化时读取配置和本地旧状态。
2. 对启用且配置了推送目标的任务创建 interval job。
3. 定时调用对应业务方法。
4. 比较新旧状态。
5. 状态变化时向配置会话发送消息,并更新本地状态。
## 新增功能开发流程
新增一个查询功能通常需要改动 4 到 5 个位置:
1.`data/api_config.json` 添加接口配置。
2.`core/services/` 对应领域文件添加业务方法,完成请求和数据整理。
3.`core/message.py` 添加消息包装方法,选择文本、图片或富媒体输出。
4.`main.py``command_map` 注册中文触发指令。
5. 如果是图片输出,新增 `templates/xxx.html`
6.`templates/helps.html` 增加帮助卡片并更新统计。
建议保持以下约定:
- 方法名使用拼音或稳定英文名,避免与现有方法冲突。
- 接口配置 key 使用 `jx3_功能名` 形式。
- 文本功能失败时返回清晰的 `msg`
- 图片功能返回空数据时不要渲染空图,直接返回文本提示。
- 可选服务器统一通过 `MessageBuilder.serverdefault()` 处理。
- 时间戳尽量在业务层格式化后传给模板。
## 注意事项
- 本插件依赖多个外部接口,接口变更、网络异常、Token 权限不足都会影响结果。
- JX3API 数据源可能存在延迟或遗漏,奇遇、掉落、排行榜等数据不保证 100% 完整。
- Token 与 Ticket 属于敏感配置,不要提交到仓库或公开日志。
- 后台推送会持续请求接口,轮询间隔不要设置过短。
- HTML 模板渲染依赖 AstrBot 的文转图能力,运行环境需要支持对应渲染服务。
## License
本项目遵循仓库内 `LICENSE` 文件声明的许可协议。