# astrbot_plugin_jx3
基于 AstrBot 的剑网三综合数据查询插件
`astrbot_plugin_jx3` 通过 JX3API、JX3BOX 等数据源查询《剑网3》游戏数据,并按功能输出纯文本、远程图片、HTML 渲染图片、图文消息或两轮交互结果;同时提供会话区服绑定、会话访问控制、实时事件推送、会话隔离避雷记录以及可视化缓存管理。 ## 功能特点 - 中文触发词覆盖活动、名剑、排行、交易、阵营、角色、奇遇、百战、家园、社区等场景。 - 支持纯文本、远程图片、HTML/Jinja2 渲染图片和图文消息链。 - 支持 `宏`、`资历` 以及帮会、阵营、其他排行榜的 15 秒两轮交互,超时默认选择第一项。 - 查询图片统一使用浅色高对比主题,并可在插件配置页调整渲染清晰度、输出格式和 JPEG 质量;所有 HTML 渲染图片都会在底部显示数据时间。 - 本地避雷记录按 AstrBot 会话严格隔离,旧版公共记录可在 WebUI 中迁移到指定会话。 - 支持按 AstrBot 会话分别开启总开关和具体 JX3API 实时事件订阅。 - 复用 `aiohttp.ClientSession`,统一处理 GET、POST、JSON、图片和分页请求。 - JX3BOX 的 Node、Next2、CMS 请求统一封装,交易行基础物品数据支持本地快照缓存和过期兜底。 - JX3API 查询使用内存与 SQLite 两级 JSON 缓存,HTML 查询图片使用本地文件缓存;缓存时间、接口内存容量、SQLite 接口缓存条数及图片缓存总容量均可在 WebUI 配置。 - 内置 97 个中文触发指令和 51 个页面片段,通过公共布局与样式在本地组装为完整 HTML,并附带通用、沙盘、门派/心法和奇遇图标资源。 ## 数据来源 | 数据源 | 代码入口 | 主要用途 | | --- | --- | --- | | [JX3API](https://www.jx3api.com/) | `core/jx3api_data.py`、`core/event_push.py` | 游戏查询、资历分布、沙盘据点数据及 WebSocket 实时事件 | | [JX3BOX](https://www.jx3box.com/) | `core/jx3box_data.py` | 奇遇攻略、配装、宏及交易行 | | 本地 SQLite | `core/sqlite.py`、`core/bilei_data.py`、`core/cache.py` | 会话配置、别名、避雷记录、事件订阅、接口缓存及图片缓存索引 | 外部数据源的可用性、数据时效和字段结构均不由本插件控制。接口变更、网络异常、凭据权限不足或上游限流都可能导致查询失败。 ## 安装 ### 环境要求 - AstrBot `>= 4.24.1`(管理页依赖 Plugin Pages) - 能够运行当前 AstrBot 版本的 Python 环境 - 能够访问插件使用的外部数据源 - 图片类指令需要 AstrBot 的 HTML 渲染能力正常可用 ### 安装插件 将仓库放入 AstrBot 的插件目录: ```text data/plugins/astrbot_plugin_jx3 ``` 也可以在 AstrBot 根目录执行: ```bash git clone https://github.com/qsc20001102/astrbot_plugin_jx3.git data/plugins/astrbot_plugin_jx3 ``` 使用 AstrBot 所在的 Python 环境安装依赖: ```bash pip install -r data/plugins/astrbot_plugin_jx3/requirements.txt ``` 随后重启 AstrBot 或重新加载插件,并在 AstrBot 管理面板中完成插件配置。 ### Python 依赖 | 依赖 | 用途 | | --- | --- | | `aiohttp` | 异步 HTTP 请求与连接复用 | | `aiofiles` | 异步读取 HTML 模板 | | `aiosqlite` | 异步访问本地 SQLite 数据库 | | `matplotlib` | 当前依赖清单保留的绘图依赖;v3.4.8 业务代码未直接导入 | ## 插件配置 配置结构由 `_conf_schema.json` 定义。 | 配置项 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `prefix.enable` | `bool` | `false` | 是否启用指令前缀检查 | | `prefix.text` | `string` | `剑三` | 指令前缀内容;开启前缀但内容为空或只有空格时按未开启处理 | | `jx3api_token` | `string` | 空 | JX3API Token | | `jx3api_ticket` | `string` | 空 | 部分名剑和心法接口需要的推栏 Ticket | | `jx3api_wss` | `string` | `wss://socket.nicemoe.cn` | JX3API 事件通道地址 | | `jx3api_wss_token` | `string` | 空 | 事件版令牌;免费事件无需填写 | | `tls_verify` | `bool` | `true` | 验证 JX3API、JX3BOX 和事件推送连接的 TLS 证书;仅建议在受信任的调试环境中临时关闭 | | `image_render_quality.device_scale_factor` | `string` | `1.0` | 渲染清晰度,可选 `1.0`、`1.3`、`1.8` | | `image_render_quality.format` | `string` | `jpeg` | 图片输出格式,可选 `jpeg`、`png` | | `image_render_quality.jpeg_quality` | `int` | `100` | JPEG 图片质量,范围 `1-100`,PNG 下不生效 | 会话控制、区服绑定、区服/心法别名、避雷记录、事件订阅及缓存配置均保存在本地 SQLite。修改 WebSocket 地址、事件版令牌或 TLS 证书验证开关后需要重新加载插件。 ### Token 与 Ticket JX3API Token 可从 [JX3API](https://www.jx3api.com/) 获取。推栏 Ticket 通常来自推栏客户端的登录请求,属于敏感凭据。 当前代码会同时传入 Token 和 Ticket 的指令有: - `战绩`、`名剑排行`、`名剑统计` - `阵眼`、`资历排行`、`技能`、`奇穴` 其余在下方标记为“Token”的指令只传入 JX3API Token。是否还需要对应接口权限,以数据提供方的实际规则为准。 ## 使用方式 如已启用指令前缀,可发送: ```text 剑三 功能 剑三 日常 剑三 战绩 梦江南 角色名 33 ``` 前缀与指令之间的空格可以省略,例如 `剑三日常` 也能触发。默认关闭前缀检查,可直接发送 `日常`;启用且配置了非空前缀后才要求使用配置的前缀。开启前缀但内容为空或只有空格时自动按未开启处理,普通指令仍可直接触发。 参数规则: - 指令和参数使用空白字符分隔。 - 会话绑定区服后可省略指令中的区服参数;在区服位置填写 `全区` 可显式查询全区数据。 - `[参数]` 表示该参数可以不写,省略后采用默认值;指令表中的 `服务器` 或 `区服` 不使用方括号,其可省略条件以上一条会话绑定规则为准。 - 当前分发器按空白切分消息,因此角色名、物品名、备注等单个参数不能包含空格。 - 未识别的消息会被忽略;已识别的指令会停止继续传播给其他插件。 - 缺少必填参数、数字转换失败或执行异常时,入口层统一回复 `参数错误或执行失败`。 - 未绑定区服时必须按指令表提供服务器。绑定后可以省略 `server` 参数;显式填写完整参数时仍优先使用本次输入的区服。 - 标准区服名和 WebUI 中配置的别名都可用于查询。对于区服后的可选参数,分发器通过当前有效区服目录和别名判断首个参数是显式区服还是后续参数。 - 心法类指令会在入口层把标准心法名或 WebUI 配置的心法别名统一解析为标准名称;当前适用于试炼排行、阵眼、配装、技能、奇穴、小药和宏。门派筛选参数不参与心法别名解析。 ### 会话区服绑定 | 指令 | 作用 | | --- | --- | | `绑定区服` | 查看当前会话的绑定状态 | | `绑定区服 梦江南` | 将当前会话绑定到指定区服;支持区服别名 | | `解绑区服` | 解除当前会话绑定 | 例如会话已经绑定 `梦江南` 后,`战绩 角色名 33` 等价于 `战绩 梦江南 角色名 33`;仍可发送 `战绩 唯我独尊 角色名 33` 临时查询其他区服,或发送 `战绩 全区 角色名 33` 查询全区数据。 ## 指令参考 凭据列含义: - **无**:当前实现不会向该查询传入 `jx3api_token` 或 `jx3api_ticket`。 - **Token**:当前实现会传入 `jx3api_token`。 - **Token + Ticket**:当前实现会同时传入两项凭据。 - 本地功能和任务状态查询不访问对应的游戏查询接口。 所有标记为“图片”的 HTML 渲染结果都会在页面底部显示统一的“数据时间”。JX3API 查询优先显示接口缓存最初写入时间,其他页面显示本次数据生成时间;命中最终图片缓存时,图片中的时间保持不变,因此可以直接判断当前结果使用的是哪一时刻的数据。 ### 帮助与活动情报 | 指令 | 说明与输出 | 凭据 | | --- | --- | --- | | `功能` | 渲染完整功能帮助图 | 无 | | `日常 [延后天数]` | 查询指定偏移天数的活动日历,默认当天;文本 | 无 | | `日常预测` | 查询未来 15 天日历;图片 | 无 | | `穹野卫`、`披风会`、`云从社`、`楚天社` | 查询对应地图活动;图片 | 无 | | `关隘` | 查询关隘首领状态;图片 | Token | | `赤兔`、`本周赤兔` | 查询当日或本周赤兔记录;文本 | Token | | `阵营奉献 [阵营]` | 查询阵营奉献事件,固定最多 50 条;图片 | Token | | `烟花 服务器 [角色] [条数]` | 查询指定服务器的烟花记录;角色可省略,条数默认为 50,非正整数或其他无效输入自动使用默认值;已绑定会话可省略服务器;图片 | Token | | `刷马 服务器` | 查询刷马聊天情报;文本 | Token | | `马场 服务器` | 查询未过期马场记录;文本 | Token | ### 名剑与排行榜 | 指令 | 说明与输出 | 凭据 | | --- | --- | --- | | `战绩 服务器 角色 [模式]` | 角色名剑战绩,模式可选 `22`、`33`、`55`,默认 `33`;图片 | Token + Ticket | | `名剑排行 [模式] [数量]` | 名剑大会排行,默认 `33`、50 条;图片 | Token + Ticket | | `名剑统计 [模式]` | 名剑门派统计,模式默认 `33`;图片 | Token + Ticket | | `跨服名剑 服务器 [模式]` | 跨服名剑队伍榜单,模式可选 `22`、`33`、`55`,分别映射接口模式 `0`、`1`、`2`,默认 `33`;无效输入使用默认值;图片 | Token(LV.2) | | `武林争霸 服务器 [阵营]` | 武林争霸赛帮会榜,阵营可选 `浩气盟`、`恶人谷`,分别映射接口阵营 `1`、`2`,默认 `浩气盟`;无效输入使用默认值;图片 | Token(LV.2) | | `捕快荣誉 服务器` | 捕快荣誉榜,展示角色、帮会、门派、阵营和抓捕数;图片 | Token(LV.2) | | `江湖浪客 服务器` | 江湖浪客榜,展示角色、帮会、门派、阵营、抓捕数和敌对数;图片 | Token(LV.2) | | `决斗挑战 服务器 [模式]` | 决斗挑战悬赏榜;当前入口实际统一按公开模式查询,模式参数无法切换到私密;图片 | Token(LV.2) | | `帮会排行 服务器` | 回复序号选择神兵宝甲或爱心帮会榜单,最多保留前 50 条;图片 | Token | | `阵营排行 服务器` | 回复序号选择赛季、上周或本周阵营榜单,最多保留前 50 条;图片 | Token | | `其他排行 服务器` | 回复序号选择名士、老江湖、名师等其他榜单,最多保留前 50 条;图片 | Token | | `试炼排行 服务器 心法` | 试炼之地排行;图片 | Token | 三个聚合排行榜指令都会先发送可选榜单菜单;回复对应序号后才查询并渲染结果。已绑定区服的会话可以省略服务器参数。 ### 物价与交易 | 指令 | 说明与输出 | 凭据 | | --- | --- | --- | | `阵营拍卖 服务器 [物品] [数量]` | 阵营拍卖记录,默认最多 50 条;图片 | Token | | `的卢 服务器` | 的卢拍卖记录;图片 | Token | | `金价 服务器 [数量]` | 金价行情,默认 15 条;图片 | Token | | `物价 外观名称 服务器` | 外观价格记录;图片 | Token | | `成本 服务器 物品名称 [来源]` | 制造成本,来源默认 `0`;图片 | Token | | `看号 万宝楼编号` | 万宝楼账号详情;文本 | Token | | `交易行 服务器 物品` | 本地模糊匹配物品后批量查询 JX3BOX 交易行价格;图片 | 无 | `交易行` 会按“完全匹配、前缀匹配、包含匹配”排序,最多取 50 个物品 ID。基础物品分组会缓存 30 天;价格结果展示物品图标、砖/金/银/铜价格、样本数量和数据时间。 ### 阵营战场 | 指令 | 说明与输出 | 凭据 | | --- | --- | --- | | `帮战 服务器` | 帮战记录;图片 | 无 | | `沙盘 服务器` | 查询 JX3API 据点归属并使用本地图层渲染阵营沙盘;已绑定会话可省略服务器 | Token | | `诛恶 服务器` | 诛恶事件,固定最多 20 条;图片 | Token | ### 角色名片与奇遇 | 指令 | 说明与输出 | 凭据 | | --- | --- | --- | | `名片 服务器 角色` | 缓存名片,发送文字与角色图片 | Token | | `全名片 服务器 角色` | 历史名片,发送文字与多张图片 | Token | | `随机秀 服务器 [门派] [体型]` | 随机角色秀;图文消息 | Token | | `奇遇 服务器 角色` | 角色奇遇记录;图片 | Token | | `查询 服务器 角色` | `奇遇` 的别名 | Token | | `未出 服务器 角色` | 未触发奇遇;图片 | Token | | `汇总 服务器 [天数]` | 区服奇遇汇总,默认 7 天;图片 | Token | | `近期 服务器 [数量]` | 区服近期奇遇,默认 20 条;图片 | Token | | `统计 奇遇 服务器 [数量]` | 指定奇遇的触发统计,默认 20 条;图片 | Token | | `攻略 奇遇` | 从 JX3BOX 获取奇遇攻略正文并渲染;图片 | 无 | ### 百战、角色与心法 | 指令 | 说明与输出 | 凭据 | | --- | --- | --- | | `精耐 服务器 角色` | 角色百战精耐记录;图片 | Token | | `百战` | 本周百战首领;图片 | Token | | `成就 服务器 角色 成就` | 查询指定成就;图片 | Token | | `角色 服务器 名称` | 查询角色详情与历史信息;文本 | Token | | `阵眼 心法` | 查询阵眼效果;文本 | Token + Ticket | | `配装 心法 [类型]` | 从 JX3BOX 获取推荐配装链接;文本。当前 `类型` 参数已接收但尚未用于请求筛选 | 无 | | `资历排行 服务器 [门派]` | 资历排行榜;图片 | Token + Ticket | | `技能 心法` | 心法技能;图片 | Token + Ticket | | `奇穴 心法` | 心法奇穴;图片 | Token + Ticket | | `宏 心法` | 先返回动态宏列表,15 秒内回复序号后返回宏文本和帖子内容;超时默认选择热度第一项 | 无 | | `资历 服务器 角色` | 返回固定资历分类菜单,15 秒内回复序号后通过 JX3API 渲染资历进度图 | Token + Ticket | `资历` 的 `1` 表示总览,`2-19` 固定对应杂闻、武学、修为、装备、技艺、阅读、任务、足迹、战斗、声望、秘境、帮会、阵营、节日、活动、风雨江湖路、家园和剑侠录,不再使用本地资历菜单和点数缓存。第二轮只需回复数字,不需要再次添加插件前缀;15 秒未选择时默认把首项 `{"1": "总览"}` 交给次轮查询并继续渲染。 ### 游戏社区与休闲 | 指令 | 说明与输出 | 凭据 | | --- | --- | --- | | `发言 服务器 角色 [条数] [页数]` | 角色发言记录,默认 20 条、第 1 页;图片 | Token | | `统战 服务器` | 统战频道统计;文本 | 无 | | `小药 [心法]` | 小吃小药推荐;图片 | 无 | | `骗子 UID 服务器` | 查询欺诈记录;文本 | Token | | `花价 服务器 [名称] [地图]` | 家园鲜花价格;图片 | 无 | | `装饰 名称` | 家园装饰信息;图片 | 无 | | `器物 地图名称` | 器物图谱;图片 | 无 | | `拜师 服务器 [关键词]` | 师父列表,固定最多 50 条;图片 | Token | | `收徒 服务器 [关键词]` | 徒弟列表,固定最多 50 条;图片 | Token | | `维护 [数量]` | 维护公告,默认 5 条;文本 | 无 | | `新闻 [数量]` | 新闻资讯,默认 5 条;文本 | 无 | | `招募 服务器 [副本]` | 团队招募,固定最多 50 条;图片 | Token | | `团长 服务器 [名称]` | 按团长搜索招募;图片 | Token | | `团牌 服务器 [内容]` | 按团牌内容搜索招募;图片 | Token | | `答案之书` | 随机答案;文本 | 无 | | `舔狗语录` | 随机语录;文本 | 无 | | `疯狂星期四`、`彩虹屁`、`毒鸡汤`、`朋友圈` | 指定类型的文案;文本 | Token | | `喝什么`、`吃什么`、`骚话`、`渣男语录` | 随机文案;文本 | 无 | ### 百度贴吧、系统工具与副本 | 指令 | 说明与输出 | 凭据 | | --- | --- | --- | | `贴吧物价 名称 服务器 [数量]` | 贴吧物价记录,默认 5 条;文本 | Token | | `818 服务器 [数量]` | 随机 818 内容,默认 10 条;文本 | Token | | `科举 题目 [条数]` | 科举题目搜索,默认 5 条;文本 | 无 | | `区服` | 全区服状态;图片 | 无 | | `开服 服务器` | 指定服务器开服状态;文本 | 无 | | `技改` | 最近技改记录;文本 | 无 | | `解密` | 当前秘境解密信息;文本 | Token | | `掉落 物品 服务器 [数量]` | 副本掉落统计,默认 20 条;图片 | Token | ### 本地避雷 | 指令 | 说明与输出 | | --- | --- | | `避雷添加 名称 备注` | 向当前会话写入名称、备注、当前时间和发送者名称 | | `避雷查看` | 查看当前会话的全部记录;图片 | | `避雷查询 名称` | 在当前会话内按名称模糊查询;图片 | | `避雷修改 ID 名称 备注` | 按当前会话和 ID 更新记录,同时覆盖修改时间和修改人 | | `避雷删除 ID` | 按当前会话和 ID 删除记录 | 避雷数据按 AstrBot 的 `unified_msg_origin` 严格隔离,一个会话无法查看或操作其他会话的记录。升级前已有的避雷记录会自动保留在普通会话不可访问的“历史公共数据”区。避雷功能没有会话内的用户角色校验;在“会话控制”放行的同一会话中,只要能够触发插件指令,当前实现就允许新增、修改和删除该会话的记录。如需限制到指定管理员,仍应在 AstrBot 或消息平台层配置权限。 ### 实时事件推送 | 指令 | 作用 | | --- | --- | | `事件推送`、`事件推送 状态` | 查看当前会话的总开关和已订阅事件 | | `事件推送 开启` | 开启当前会话的事件推送总开关 | | `事件推送 关闭` | 关闭总开关;保留各事件的订阅选择 | | `事件推送 2001 开启` | 为当前会话订阅事件 `2001` | | `事件推送 2001 关闭` | 为当前会话取消订阅事件 `2001` | | `事件推送 列表` | 查看支持的全部事件编号 | 总开关和具体事件开关必须同时开启,消息才会发送到当前会话。事件正文包含 `server` 时,只向绑定该区服和未绑定区服的订阅会话发送;不含服务器的新闻、版本更新等事件不受区服过滤影响。插件已覆盖 JX3API 当前 39 种 WebSocket 事件,并按各事件的官方字段输出可读中文消息。免费事件为:`2001` 开服状态、`2002` 官方新闻、`2003` 版本更新、`2004` 八卦速报、`2005` 关隘首领、`2006` 云丛预告;其他事件需要独立的事件版令牌,可通过 `事件推送 列表` 查看全部编号。 ### WebUI 插件管理 AstrBot 插件详情页中的“剑网三插件管理”通过 Plugin Pages 桥接调用插件 Web API,不直接访问 Dashboard 凭据。当前共有七个页签: | 页签 | 当前功能 | | --- | --- | | 会话控制 | 默认页签;在全部会话、白名单和黑名单之间切换,并维护会话 ID 与备注。空白名单不放行任何会话,空黑名单放行全部会话,策略同时作用于查询指令与事件推送 | | 事件推送 | 新增、编辑和删除会话推送配置;设置总开关并勾选具体事件,支持全选和清空选择,关闭总开关保留订阅选择 | | 区服绑定 | 使用自定义会话 ID 新增绑定;区服只能从标准区服下拉框选择,已有会话 ID 不可编辑 | | 区服别名 | 查看标准区服并行内维护别名;可使用随插件分发的 JSON 种子恢复默认 | | 心法别名 | 查看标准心法并维护最多 5 个别名;配装 ID 不在页面显示,可恢复默认 | | 缓存管理 | 分别配置接口数据和最终图片缓存时间、容量限制,查看占用并清理单项或全部缓存 | | 避雷迁移 | 把升级前保留在“历史公共数据”区的避雷记录迁移到指定会话 | 事件推送配置保存后立即用于后续事件分发,仍受会话访问模式和绑定区服限制。新增时可以选择已有会话或输入完整的 AstrBot 会话 ID,重复新增会提示编辑已有配置;编辑时会话 ID 只读。空事件选择表示不接收任何事件;删除仅移除该会话的推送配置,保留区服绑定、访问名单和其他会话数据。免费事件与令牌事件分组展示,令牌事件仍需配置 `jx3api_wss_token`。 页面顶部通过 JX3API `POST /token/stats` 展示当前 Token 的等级、已用次数、剩余次数和有效状态,成功结果在进程内保留 30 秒。WebUI 的全部区服选项直接读取本地 `server_aliases` 表中的标准区服,顶部“刷新数据”只重新读取管理页数据,不会请求 `/server/status/check`。插件初始化时仍会执行一次 `server_list()` 建立用于指令参数消歧的有效区服目录:缓存有效时读取接口缓存,缓存不存在或已过期时才请求上游。 缓存管理的接口默认时间为 300 秒,图片默认时间为 600 秒;每个 JX3API 接口和每个图片指令都可以单独覆盖,填写 `0` 表示关闭,恢复默认则重新继承全局时间。图片指令优先查询最终图片缓存,命中后不会再调用上游接口或重新渲染;图文结果会连同正文一起复用。单独清除接口会同时删除该路径所有参数组合的内存与 SQLite 缓存,单独清除图片会删除该指令生成的缓存文件,两种操作均不改变已配置时间。 如果需要某条图片指令立即使用最新上游数据,应同时清除(或临时关闭)对应的接口缓存和图片缓存。只把接口缓存设为 `0` 时,已有最终图片仍可能直接命中;只把图片缓存设为 `0` 时,页面会重新渲染,但仍可能使用尚未过期的接口数据。 接口内存缓存默认最多占用 16 MB,按 JSON 的 UTF-8 字节数统计并按最近最少使用顺序淘汰,WebUI 同时展示当前占用和缓存条数。SQLite 接口缓存独立按条数限制,默认最多 256 条;旧版接口条数配置会自动继承为 SQLite 上限。内存命中也会更新 SQLite 的访问时间,修改上限和插件启动时立即清理超额记录。SQLite 条数限制不是磁盘字节容量;删除记录后释放的页可供后续写入复用,数据库文件不一定立即缩小。图片二进制保存在 AstrBot 插件数据目录,默认总容量为 512 MB,超出后按最近最少使用顺序清理。每 60 秒自动清理过期接口和图片缓存,无需打开 WebUI;接口请求失败时不再返回过期数据。随机名片、随机语录、吃喝选择和随机贴吧等接口默认不缓存,避雷查看和避雷查询也默认不缓存最终图片;这些项目仍可在 WebUI 中显式覆盖。 ## 业务流程 ```mermaid flowchart LR A["AstrBot 消息事件"] --> B["前缀检查与空白切分"] B --> C["command_map 查找处理器"] C --> K{"会话控制是否放行"} K -->|是| D["MessageBuilder 参数适配"] K -->|否| X["停止处理"] D --> E1["JX3APIService"] D --> E2["JX3BOXService"] D --> E3["BiLeidata / EventPushService / KungfuAliasService"] E1 --> F["APIClient"] E2 --> F F --> G["外部 HTTP 数据源"] E3 --> H["local_data.db"] E1 --> I["标准返回对象"] E2 --> I E3 --> I I --> J1["纯文本"] I --> J2["HTML 模板渲染图片"] I --> J3["远程图片或图文消息链"] E1 <--> L["内存 / SQLite 接口缓存"] J2 <--> M["本地最终图片缓存"] ``` ### 1. 初始化与销毁 `main.py` 中的 `Jx3ApiPlugin` 是插件入口。构造阶段完成以下工作: 1. 读取前缀、Token、Ticket 和 WebSocket 配置。 2. 计算插件目录、AstrBot 数据目录、本地 SQLite 和模板目录路径。 3. 把 `templates/img`、`templates/img/sand`、`templates/sect`、`templates/serendipity` 中的图片读取为 base64 Data URL。 4. 创建本地数据库、两个数据服务、心法别名服务、会话控制服务、避雷服务、事件推送服务、WebUI 服务和消息构建器。 异步初始化阶段会连接数据库并创建以下本地表: - `bilei`:按 AstrBot 会话保存避雷记录;升级前记录迁移到不可由普通会话访问的历史公共数据区。 - `event_push_subscriptions`:按 AstrBot 会话保存事件总开关和每个事件编号的订阅开关。 - `session_server_bindings`:两列结构,保存会话 ID 与绑定区服。 - `session_control_settings`:保存当前会话控制模式,首次初始化默认为 `all`。 - `session_control_entries`:保存白名单或黑名单会话 ID 及备注。 - `server_aliases`:保存标准区服名及其 JSON 别名列表。 - `kungfu`:保存 JX3BOX 配装 ID、标准心法名及最多 5 个别名。 - `trade_item_cache`:JX3BOX 交易行基础物品数据缓存及更新时间。 - `cache_settings`:接口与图片指令的默认时间和单项覆盖配置。 - `cache_limits`:接口内存缓存总容量、SQLite 接口缓存最大条数及图片缓存总容量配置。 - `api_response_cache`:JX3API 原始 JSON、创建时间、过期时间和最近访问时间。 - `image_render_cache`:本地渲染图片文件的索引、大小、过期时间、最近访问时间及图文消息正文。 `kungfu` 表首次创建时从 `data/kungfu.json` 幂等导入 32 条默认心法,`server_aliases` 表从 `data/server_aliases.json` 幂等导入默认区服别名;已存在的本地记录均不会被覆盖。随后启动 JX3API WebSocket 事件通道并建立指令映射。插件停用时会关闭事件通道、两个 HTTP Session 和本地 SQLite 连接。 ### 2. 指令分发 入口监听全部消息事件: 1. `parse_message()` 检查前缀并使用 `str.split()` 切分消息。 2. 第一段作为指令,其余段作为位置参数。 3. `command_map` 将中文触发词映射到 `MessageBuilder` 方法。 4. `_prepare_server_args()` 和 `_prepare_kungfu_args()` 根据处理器参数名统一补齐区服绑定并解析区服、心法别名。 5. `_call_with_auto_args()` 通过 `inspect.signature()` 读取参数签名,按注解转换 `int` 和 `float`。 6. 找不到指令时忽略消息;找到指令后停止事件继续传播并调用处理器。 分发器不会检查多余参数,多出的参数会被忽略。缺少必填参数会抛出异常并返回统一错误提示。 ### 3. 数据服务 两个数据服务按上游来源拆分: - `JX3APIService`:以 `https://www.jx3api.com` 为根地址,通过 GET 请求实现主体功能、资历分布和沙盘据点查询。 - `JX3BOXService`:通过统一请求入口访问 JX3BOX 的 Node、CMS 和 Next2 服务,负责攻略、配装、宏及交易行。 服务方法通常返回统一结构: ```python { "code": 0, "msg": "功能函数未执行", "data": {}, "temp": "", "icons": {} } ``` 成功时设置 `code=200`;失败时保留非 200 状态并在 `msg` 中返回原因。图片功能会在 `temp` 中放入已加载的 HTML 模板正文,在 `data` 中放入模板上下文。 ### 4. HTTP 请求层 `core/request.py` 中的 `APIClient`: - 延迟创建并复用一个 `aiohttp.ClientSession`。 - 默认总超时时间为 10 秒。 - 支持 GET、JSON POST 和分页拉取。 - 根据 `Content-Type` 自动返回 JSON 或二进制数据。 - 兼容 JX3API 常见成功码 `200`、`"0"`、`0`、`1`。 - 可通过 `out_key` 提取响应中的指定字段。 - 网络、HTTP、JSON 和业务码异常统一记录日志并返回 `None`。 业务服务在 `APIClient` 之上维护各自的基础请求方法。`JX3APIService` 以 `https://www.jx3api.com` 为固定根地址;`JX3BOXService._base_request()` 根据 `node`、`next2`、`cms` 数据源选择基础地址,并统一转发 GET/POST 参数和 `out` 返回字段。JX3BOX 业务代码只传接口路径,不再重复拼接完整域名。 ### 5. 消息与图片渲染 `core/message.py` 根据业务结果选择输出方式: - `plain_msg()`:纯文本。 - `T2I_image_msg()`:向模板注入业务数据和本地图标,再调用 AstrBot HTML 渲染器按插件配置生成图片。 - `image_msg()`:直接发送远程图片 URL 或图片数据。 - `plain_chain()`:直接发送业务服务返回的富媒体消息链。 - `plain_image_msg()`:发送正文文本,并把业务服务返回的 HTML 正文渲染为附图;正文会和最终图片一起缓存。 - `handler_plain_image_msg()`:通用两轮会话;首轮函数直接返回 `{"1": "总览", "2": "杂闻"}` 形式的数字键值对(无 `code`、`msg`、`data` 外层),处理器据此生成序号文本;选择后裁剪为只含所选项的新字典交给次轮函数,再由注入的输出器发送结果;超时固定选择第一项。 - `hong()`、`zili()` 及三类聚合排行榜入口:保持统一调用结构接入上述两轮会话处理器,并按各自需要选择图文消息链或标准图片流程输出结果。 按当前 `_conf_schema.json`,图片默认使用 JPEG 质量 `100`、完整页面截图和 `1.0` 倍设备像素比。可以在插件配置页的“图片渲染质量”分组切换 JPEG/PNG、调整 JPEG 质量,并选择 `1.0`、`1.3`、`1.8` 设置渲染清晰度。模板可通过 `icons.img`、`icons.sect`、`icons.serendipity` 访问通用、门派/心法和奇遇图标。 所有经 `_render_image_file()` 生成的 HTML 图片都会注入统一的数据时间页脚。JX3API 返回对象带有接口缓存创建时间时优先使用该时间;JX3BOX、本地数据库和帮助页等没有接口缓存元数据的页面使用本次数据生成时间。最终图片缓存命中时直接发送原文件,因此不会把时间错误更新为本次发送时间。时间统一按 `Asia/Shanghai` 格式化。 AstrBot 的渲染接口接收完整 HTML 字符串,因此插件不会依赖渲染端读取本地 CSS 文件。`core/template.py` 会异步读取并缓存公共布局、设计变量、基础样式和组件样式,再按需读取页面专属样式及页面片段,组装完成后把单个完整字符串交给渲染器。共享资源只在首次请求时读取一次;标准页面没有同名 CSS 文件也可以正常组合。 `styles/components.css` 是公共组件的唯一来源,内部使用 `@component` 标记划分表格、网格、能力卡片等组件块。页面通过顶部元数据声明需要的组件,加载器只把声明过的样式块注入最终 HTML,不会让只使用表格的页面同时携带技能卡片、器物卡片等无关 CSS: ```html {# template-title: 角色榜单 #} {# template-components: data-table #} ``` 样式职责如下: - `styles/tokens.css`:颜色、间距、圆角、字体和各页面内容宽度。 - `styles/base.css`:固定图片画布的页面背景、外框、数据时间页脚和基础排版。 - `styles/components.css`:统一维护数据表格、列状态、排行、统计卡片、可配置列数网格、技能/奇穴卡片、奇遇卡片、器物详情、标签和空数据等跨页面组件。 - `styles/pages/*.css`:可选,仅保留成本计算、成就、副本记录、沙盘等无法合理复用的复杂页面布局。当前 51 个页面中有 14 个需要专属 CSS。 沙盘坐标集中在 `templates/pages/shapan.html`。搜索 `data-castle="据点名"` 后,同一段内第一个 `