From d8ceb93ea77e77174fe574a5bc44209cbc55bfbe Mon Sep 17 00:00:00 2001 From: qsc20001102 Date: Wed, 24 Jun 2026 13:01:52 +0800 Subject: [PATCH] ok --- CHANGELOG.md | 12 +- README.md | 51 ++- core/jx3_data.py | 269 ++++++++++++++- core/message.py | 86 +++++ data/api_config.json | 17 + main.py | 21 +- metadata.yaml | 2 +- templates/helps.html | 758 ++++++++++++++++++++----------------------- templates/zili.html | 206 ++++++++++++ 9 files changed, 996 insertions(+), 426 deletions(-) create mode 100644 templates/zili.html diff --git a/CHANGELOG.md b/CHANGELOG.md index f3f975c..7851945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ ## 更新记录 +### version: 2.6: + +新增 **资历 角色名称 [服务器]** 指令,支持两轮对话选择资历总览或分类总览,并以图片形式展示角色资历点数完成进度。 + +新增资历菜单与点数基础数据缓存,减少长期稳定接口的重复请求。 + +调整功能帮助页分类,指令分组改为日常、官方、角色、职业、休闲、阵营、副本、活动、交易、杂项、排行、推送和避雷。 + +调整指令触发词:**诛恶事件** 改为 **诛恶**,**排行** 改为 **名剑排行**。 + ### version: 2.5: 增加部分新指令,调整功能页面 @@ -58,4 +68,4 @@ ### version: 1.0.0: -大部分重要功能已经实现 \ No newline at end of file +大部分重要功能已经实现 diff --git a/README.md b/README.md index 65f413c..c035a19 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,27 @@ 基于 [AstrBot](https://docs.astrbot.app/) 框架开发的剑网三游戏数据查询插件。插件主要通过 JX3API、JX3BOX、茶馆等外部接口获取游戏数据,整理为文本消息、富媒体消息,或通过 `HTML + Jinja2` 模板渲染成图片后发送。 -当前插件以“查询型功能”为主,覆盖日常、奇遇、名剑、阵营、交易、职业、排行、副本、活动、名片、百战、推送和本地避雷等场景。部分功能需要配置 JX3API Token,少量职业/角色类接口还需要推栏 ticket。 +当前插件以“查询型功能”为主,覆盖日常、官方、角色、职业、休闲、阵营、副本、活动、交易、杂项、排行、推送和本地避雷等场景。部分功能需要配置 JX3API Token,少量职业/角色类接口还需要推栏 ticket。 ## 功能概览 -插件内置 `功能` 指令,会以图片形式展示完整指令列表、参数说明和是否需要令牌。当前帮助页按 16 个功能分组维护,约 87 条指令。 +插件内置 `功能` 指令,会以图片形式展示完整指令列表、参数说明和是否需要令牌。当前帮助页按 13 个功能分组维护,约 88 条指令。 主要功能包括: -- 日常与官方:日常、月历、名望、公告、维护、区服、开服、状态、技改。 -- 职业与角色:角色、阵眼、奇穴、技能、小药、宏、配装、资历排行、试炼排行。 -- 奇遇:角色奇遇、未做奇遇、奇遇统计、近期奇遇、奇遇汇总、奇遇攻略。 -- 名剑:战绩、名剑排行、名剑统计。 -- 阵营:沙盘、阵营拍卖、阵营事件、关隘首领、帮战记录、统战 YY。 -- 交易:金价、外观物价、交易行、贴吧物价。 -- 活动:扶摇、诛恶事件、本日赤兔、本周赤兔、刷马、的卢。 -- 其他:拜师、收徒、名片、百战、精耐、招募、掉落、解密、八卦、骗子查询。 -- 本地功能:避雷添加、查看、查询、修改、删除。 +- 日常功能:日常、月历、名望、诛恶。 +- 官方功能:公告、维护、技改、区服、开服、状态。 +- 角色功能:角色、资历、名片、所有名片、奇遇、未做奇遇、战绩、精耐。 +- 职业功能:小药、宏、配装、阵眼、奇穴、技能。 +- 休闲功能:烟花、拜师、收徒、随机名片、攻略、奇遇统计、近期奇遇、奇遇汇总。 +- 阵营功能:沙盘、阵营拍卖、阵营事件、关隘首领、帮战记录、统战 YY。 +- 副本功能:百战、招募、掉落、解密。 +- 活动功能:扶摇、本日赤兔、本周赤兔、刷马、的卢。 +- 交易功能:金价、物价、交易行、贴吧物价。 +- 杂项功能:科举、花价、装饰、器物、八卦、骗子、骚话。 +- 排行功能:名剑统计、名剑排行、资历排行、试炼排行和各类风云录榜单。 - 推送功能:开服推送、新闻推送、刷马推送、赤兔推送。 +- 避雷功能:避雷查看、添加、删除、修改、查询。 ## 安装与依赖 @@ -43,7 +46,7 @@ pip install -r requirements.txt - `apscheduler`:后台推送任务调度。 - `matplotlib`:部分图像/数据展示依赖。 -插件元信息在 `metadata.yaml` 中维护,要求 AstrBot 版本 `>=4.11.0`。 +插件元信息在 `metadata.yaml` 中维护,当前版本为 `v2.6`,要求 AstrBot 版本 `>=4.11.0`。 ## 插件配置 @@ -166,9 +169,12 @@ pip install -r requirements.txt ```text 日常 +诛恶 +资历 飞翔大野猪 奇遇 飞翔大野猪 未做奇遇 飞翔大野猪 梦江南 战绩 飞翔大野猪 梦江南 33 +名剑排行 50 33 贴吧物价 狐金 5 梦江南 统战 梦江南 ``` @@ -234,6 +240,7 @@ astrbot_plugin_jx3/ - `image_msg()`:直接发送图片 URL 或图片数据。 - `plain_chain()`:发送文本 + 图片等富媒体消息链。 - `handler_plain_image_msg()`:先发文本,再发图片,适用于部分组合型功能。 +- `handler_zili_msg()`:资历查询专用两轮会话,先发送 `0-18` 分类菜单,再按用户选择渲染资历进度图片。 所有可选服务器参数都会通过 `serverdefault()` 补齐默认服务器。 @@ -332,10 +339,28 @@ html_renderer.render_custom_template() - 避雷记录。 - 推送任务状态缓存。 +- 资历菜单与资历点数基础数据缓存,默认缓存 30 天,接口失败时可使用旧缓存兜底。 `core/sqlite.py` 封装了异步增删改查;`core/bilei_data.py` 基于该封装实现避雷数据管理。 -### 8. 后台推送 +### 8. 资历查询 + +`资历 角色名称 [服务器]` 是 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` 渲染进度条图片。 + +### 9. 后台推送 `core/async_task.py` 使用 APScheduler 实现轮询推送。 diff --git a/core/jx3_data.py b/core/jx3_data.py index 5b19866..117af7d 100644 --- a/core/jx3_data.py +++ b/core/jx3_data.py @@ -1,5 +1,5 @@ import json -from datetime import datetime +from datetime import datetime, timedelta from typing import Dict, Any, Optional, List, Union from collections import defaultdict @@ -34,8 +34,32 @@ TONG_RANK_NAMES = { "本周浩气五十强", } +ACHIEVEMENT_CHOICES = [ + (0, None, "资历总览"), + (1, "1", "杂闻总览"), + (2, "2", "武学总览"), + (3, "3", "修为总览"), + (4, "4", "装备总览"), + (5, "5", "技艺总览"), + (6, "6", "阅读总览"), + (7, "7", "任务总览"), + (8, "8", "足迹总览"), + (9, "9", "战斗总览"), + (10, "10", "声望总览"), + (11, "11", "秘境总览"), + (12, "12", "帮会总览"), + (13, "13", "阵营总览"), + (14, "15", "节日总览"), + (15, "16", "活动总览"), + (16, "17", "风雨江湖路总览"), + (17, "40", "家园总览"), + (18, "41", "剑侠录总览"), +] + +ACHIEVEMENT_CHOICE_MAP = {index: (menu_id, title) for index, menu_id, title in ACHIEVEMENT_CHOICES} + class JX3Service: - def __init__(self, api_data_path: str, config: AstrBotConfig, sqlite: AsyncSQLiteDB): + def __init__(self, api_data_path: str, config: AstrBotConfig, sqlite: AsyncSQLiteDB, cache_sqlite: Optional[AsyncSQLiteDB] = None): # 加载API配置文件 try: with open(api_data_path, 'r', encoding='utf-8') as f: @@ -49,6 +73,7 @@ class JX3Service: self._config = config # 引用sqlite self._sql_db = sqlite + self._cache_db = cache_sqlite or sqlite # 获取配置中的 Token self.token = self._config.get("jx3api_token", "") @@ -2386,6 +2411,244 @@ class JX3Service: return return_data + async def _load_achievement_cache(self, key: str) -> tuple[Optional[Dict[str, Any]], bool]: + """读取资历基础数据缓存,返回数据和是否已过期""" + try: + row = await self._cache_db.select_one("achievement_cache", "key=?", (key,)) + except Exception as e: + logger.error(f"读取资历缓存失败: {e}") + return None, True + + if not row: + return None, True + + try: + payload = json.loads(row.get("content", "{}")) + updated_at = datetime.strptime(row.get("updated_at", ""), "%Y-%m-%d %H:%M:%S") + expired = datetime.now() - updated_at > timedelta(days=30) + return payload, expired + except Exception as e: + logger.error(f"解析资历缓存失败: {e}") + return None, True + + + async def _save_achievement_cache(self, key: str, payload: Dict[str, Any]): + """写入资历基础数据缓存""" + try: + await self._cache_db.execute( + """ + INSERT INTO achievement_cache (key, content, updated_at) + VALUES (?, ?, ?) + ON CONFLICT(key) DO UPDATE SET + content=excluded.content, + updated_at=excluded.updated_at + """, + ( + key, + json.dumps(payload, ensure_ascii=False), + datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + ), + ) + except Exception as e: + logger.error(f"写入资历缓存失败: {e}") + + + async def _get_achievement_base_data(self, cache_key: str, config_key: str) -> Optional[Dict[str, Any]]: + """获取资历菜单或点数数据,优先使用未过期缓存""" + cached, expired = await self._load_achievement_cache(cache_key) + if cached and not expired: + return cached + + data: Optional[Dict[str, Any]] = await self._base_request(config_key, "GET") + if data and isinstance(data, dict): + await self._save_achievement_cache(cache_key, data) + return data + + if cached: + logger.warning(f"资历基础数据接口失败,使用旧缓存: {cache_key}") + return cached + + return None + + + def _flatten_achievement_ids(self, values: Any) -> list[int]: + """展开菜单中的单个资历 ID 和数组资历 ID""" + result = [] + + if isinstance(values, list): + for item in values: + result.extend(self._flatten_achievement_ids(item)) + return result + + try: + result.append(int(values)) + except (TypeError, ValueError): + pass + + return result + + + def _category_achievement_ids(self, category: Dict[str, Any]) -> list[int]: + """提取分类及其子分类包含的资历 ID""" + ids = self._flatten_achievement_ids(category.get("achievements", [])) + for child in category.get("children", []) or []: + if isinstance(child, dict): + ids.extend(self._flatten_achievement_ids(child.get("achievements", []))) + return ids + + + def _build_achievement_progress( + self, + name: str, + achievement_ids: list[int], + point_map: Dict[str, Any], + completed_ids: set[int], + ) -> Dict[str, Any]: + """按资历点数计算完成进度""" + unique_ids = set(achievement_ids) + total_points = 0 + completed_points = 0 + completed_count = 0 + + for achievement_id in unique_ids: + try: + point = int(point_map.get(str(achievement_id), 0) or 0) + except (TypeError, ValueError): + point = 0 + + total_points += point + if achievement_id in completed_ids: + completed_count += 1 + completed_points += point + + percent = round(completed_points / total_points * 100, 2) if total_points else 0 + + return { + "name": name, + "total_points": total_points, + "completed_points": completed_points, + "percent": percent, + "percent_text": f"{percent:.2f}%", + "achievement_count": len(unique_ids), + "completed_count": completed_count, + } + + + async def zili(self, name: str, server: str, choice: int) -> Dict[str, Any]: + """角色资历""" + return_data = self._init_return_data() + + if choice not in ACHIEVEMENT_CHOICE_MAP: + return_data["msg"] = "无效序号,结束会话" + return return_data + + role_params = {"server": server, "name": name, "token": self.token} + role_data: Optional[Dict[str, Any]] = await self._base_request( + "jx3_jueshexinxi", "GET", params=role_params + ) + if not role_data or not isinstance(role_data, dict): + return_data["msg"] = "未查询到角色" + return return_data + + global_id = role_data.get("globalId") + if not global_id: + return_data["msg"] = "无法获取角色全区 ID" + return return_data + + achievement_data = await self._api.get( + "https://next2.jx3box.com/api/next2/user-achievements", + params={"jx3id": global_id}, + out_key="data", + ) + if not achievement_data or not isinstance(achievement_data, dict): + return_data["msg"] = "未查询到资历数据" + return return_data + + completed_ids = set() + achievements = achievement_data.get("achievements") or "" + if isinstance(achievements, str): + for item in achievements.split(","): + try: + completed_ids.add(int(item.strip())) + except ValueError: + continue + elif isinstance(achievements, list): + completed_ids = set(self._flatten_achievement_ids(achievements)) + + menu_payload = await self._get_achievement_base_data( + "achievement_menus", + "jx3box_achievement_menus", + ) + point_payload = await self._get_achievement_base_data( + "achievement_points", + "jx3box_achievement_points", + ) + if not menu_payload or not point_payload: + return_data["msg"] = "基础资历数据获取失败" + return return_data + + menus = menu_payload.get("menus", {}) + points = point_payload.get("points", {}) + if not isinstance(menus, dict) or not isinstance(points, dict): + return_data["msg"] = "基础资历数据格式异常" + return return_data + + selected_menu_id, selected_title = ACHIEVEMENT_CHOICE_MAP[choice] + items = [] + + if choice == 0: + total_ids = [] + for _, menu_id, title in ACHIEVEMENT_CHOICES[1:]: + category = menus.get(str(menu_id), {}) + if not isinstance(category, dict): + continue + category_ids = self._category_achievement_ids(category) + total_ids.extend(category_ids) + items.append( + self._build_achievement_progress(title, category_ids, points, completed_ids) + ) + summary = self._build_achievement_progress(selected_title, total_ids, points, completed_ids) + else: + category = menus.get(str(selected_menu_id), {}) + if not isinstance(category, dict) or not category: + return_data["msg"] = "未找到该资历分类" + return return_data + + category_ids = self._category_achievement_ids(category) + summary = self._build_achievement_progress(selected_title, category_ids, points, completed_ids) + for child in category.get("children", []) or []: + if not isinstance(child, dict): + continue + child_ids = self._flatten_achievement_ids(child.get("achievements", [])) + items.append( + self._build_achievement_progress(child.get("name", "未命名"), child_ids, points, completed_ids) + ) + + try: + return_data["temp"] = await load_template("zili.html") + except FileNotFoundError as e: + logger.error(f"加载模板失败: {e}") + return_data["msg"] = "系统错误:模板文件不存在" + return return_data + + return_data["data"] = { + "title": selected_title, + "summary": summary, + "items": items, + "role_name": role_data.get("roleName", name), + "server": role_data.get("serverName", server), + "zone": role_data.get("zoneName", ""), + "force_name": role_data.get("forceName", "无"), + "camp_name": role_data.get("campName", "无"), + "tong_name": role_data.get("tongName", "无"), + "updated_at": achievement_data.get("updated_at", ""), + "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + } + return_data["code"] = 200 + + return return_data + + async def jueshe(self,name: str, server: str) -> Dict[str, Any]: """角色""" return_data = self._init_return_data() @@ -2408,7 +2671,7 @@ class JX3Service: f"服务器:{data.get('zoneName', '无')}·{data.get('serverName', '无')}\n" f"名称:{data.get('roleName', '无')}\n" f"角色ID:{data.get('roleId', '无')}\n" - f"全区ID:{data.get('globalRoleId', '无')}\n" + f"全区ID:{data.get('globalId', '无')}\n" f"职业:{data.get('forceName', '无')}·{data.get('bodyName', '无')}\n" f"帮会:{data.get('tongName', '无')}\n" f"阵营:{data.get('campName', '无')}\n" diff --git a/core/message.py b/core/message.py index 27fa47e..f3cfb28 100644 --- a/core/message.py +++ b/core/message.py @@ -13,6 +13,29 @@ from .bilei_data import BiLeidata class MessageBuilder: """回复消息构建""" + ZILI_MENU_TEXT = ( + "请选择资历查询类型:\n" + "0:资历总览\n" + "1:杂闻总览\n" + "2:武学总览\n" + "3:修为总览\n" + "4:装备总览\n" + "5:技艺总览\n" + "6:阅读总览\n" + "7:任务总览\n" + "8:足迹总览\n" + "9:战斗总览\n" + "10:声望总览\n" + "11:秘境总览\n" + "12:帮会总览\n" + "13:阵营总览\n" + "14:节日总览\n" + "15:活动总览\n" + "16:风雨江湖路总览\n" + "17:家园总览\n" + "18:剑侠录总览" + ) + def __init__(self, server: str, jx3api: JX3Service, bilei: BiLeidata, jx3at: AsyncTask, icons: dict[str, dict[str, str]]): self.server = server self.jx3api = jx3api @@ -187,6 +210,64 @@ class MessageBuilder: await event.send(event.plain_result("猪脑过载,请稍后再试")) + async def handler_zili_msg(self, event: AstrMessageEvent, name: str, server: str): + """资历查询专用两轮会话,第一轮文本菜单,第二轮图片""" + try: + await event.send(event.plain_result(self.ZILI_MENU_TEXT)) + user_id = event.get_sender_id() + + @session_waiter(timeout=30) + async def zili_select_waiter(controller: SessionController, new_event: AstrMessageEvent): + if new_event.get_sender_id() != user_id: + return + + msg = new_event.get_message_str().strip() + if not msg.isdigit(): + await new_event.send(MessageChain().message("输入异常,结束会话")) + controller.stop() + return + + choice = int(msg) + if choice < 0 or choice > 18: + await new_event.send(MessageChain().message("无效序号,结束会话")) + controller.stop() + return + + try: + data = await self.jx3api.zili(name, server, choice) + if data["code"] != 200: + await new_event.send(MessageChain().message(data.get("msg", "获取资历数据失败"))) + controller.stop() + return + + options = { + "quality": 100, + "device_scale_factor_level": "normal", + "full_page": True, + "omit_background": False, + "type": "jpeg" + } + data["data"]["icons"] = self.icons + url = await self.html_render(data["temp"], data["data"], options=options) + await new_event.send(new_event.image_result(url)) + except Exception as e: + logger.error(f"资历查询执行错误: {e}") + await new_event.send(MessageChain().message("猪脑过载,请稍后再试")) + + controller.stop() + + try: + await zili_select_waiter(event) + except TimeoutError: + await event.send(event.plain_result("选择超时,已结束会话")) + except Exception: + logger.error("资历选择发生异常", exc_info=True) + + except Exception as e: + logger.error(f"资历会话执行错误: {e}") + await event.send(event.plain_result("猪脑过载,请稍后再试")) + + async def jx3_helps(self, event: AstrMessageEvent): """剑三 功能""" return await self.T2I_image_msg(event, self.jx3api.helps) @@ -292,6 +373,11 @@ class MessageBuilder: return await self.plain_msg(event, self.jx3api.shaohua) + async def jx3_zili(self, event: AstrMessageEvent, name: str, server: str = ""): + """剑三 资历 角色名称 服务器""" + return await self.handler_zili_msg(event, name, self.serverdefault(server)) + + async def jx3_jiemi(self, event: AstrMessageEvent): """剑三 解密""" return await self.plain_msg(event, self.jx3api.jiemi) diff --git a/data/api_config.json b/data/api_config.json index 655d768..e0f74cb 100644 --- a/data/api_config.json +++ b/data/api_config.json @@ -591,6 +591,23 @@ "mount": "", "star": "1" } + }, + "jx3box_achievement_menus":{ + "url":"https://node.jx3box.com/api/node/achievement/menus", + "method":"GET", + "description":"魔盒资历菜单列表", + "params":{ + "general": "1", + "client": "std" + } + }, + "jx3box_achievement_points":{ + "url":"https://node.jx3box.com/api/node/achievement/points", + "method":"GET", + "description":"魔盒资历点数列表", + "params":{ + "client": "std" + } } diff --git a/main.py b/main.py index dd1f268..dc86607 100644 --- a/main.py +++ b/main.py @@ -17,7 +17,7 @@ from .core.fun_basic import load_as_base64 @register("astrbot_plugin_jx3", "fxdyz", "通过调用剑网三API接口获取游戏数据,处理发送。", - "2.5", + "2.6", "https://github.com/qsc20001102/astrbot_plugin_jx3api" ) class Jx3ApiPlugin(Star): @@ -57,6 +57,7 @@ class Jx3ApiPlugin(Star): # 数据库初始化 await self.init_bilei_data() await self.init_tuishong_data() + await self.init_achievement_cache_data() # 连接插件数据 await self.plugin_sql_db.connect() @@ -142,7 +143,7 @@ class Jx3ApiPlugin(Star): self.plugin_sql_db = AsyncSQLiteDB(str(self.plugin_data_path)) # 剑网三功能实例化 self.bilei = BiLeidata(self.local_sql_db) - self.jx3api = JX3Service(str(self.api_data_path), self.conf, self.plugin_sql_db) + self.jx3api = JX3Service(str(self.api_data_path), self.conf, self.plugin_sql_db, self.local_sql_db) self.jx3at = AsyncTask(cast(Context, self.context), self.conf, self.jx3api, self.local_sql_db) self.jx3cmd = MessageBuilder(self.server, self.jx3api, self.bilei, self.jx3at, self.icons) self.jx3cmd = MessageBuilder(self.server, self.jx3api, self.bilei, self.jx3at, self.icons) @@ -182,6 +183,17 @@ class Jx3ApiPlugin(Star): """) + async def init_achievement_cache_data(self): + """初始化资历基础数据缓存表""" + await self.local_sql_db.execute(""" + CREATE TABLE IF NOT EXISTS achievement_cache( + key TEXT PRIMARY KEY, + content TEXT NOT NULL, + updated_at TEXT NOT NULL + ) + """) + + def ini_command_map(self): """初始化指令集""" self.command_map = { @@ -206,6 +218,7 @@ class Jx3ApiPlugin(Star): "资历排行": self.jx3cmd.jx3_zilipaixing, "试炼排行": self.jx3cmd.jx3_shilianpaixing, "骚话": self.jx3cmd.jx3_shaohua, + "资历": self.jx3cmd.jx3_zili, "解密": self.jx3cmd.jx3_jiemi, "沙盘": self.jx3cmd.jx3_shapan, "攻略": self.jx3cmd.jx3_qiyugonglue, @@ -213,7 +226,7 @@ class Jx3ApiPlugin(Star): "配装": self.jx3cmd.jx3_peizhuang, "百战": self.jx3cmd.jx3_baizhan, "扶摇": self.jx3cmd.jx3_fuyaojjiutian, - "诛恶事件": self.jx3cmd.jx3_zhueevent, + "诛恶": self.jx3cmd.jx3_zhueevent, "本日赤兔": self.jx3cmd.jx3_benrichitu, "本周赤兔": self.jx3cmd.jx3_benzhouchitu, "拍卖": self.jx3cmd.jx3_zhengyingpaimai, @@ -230,7 +243,7 @@ class Jx3ApiPlugin(Star): "近期奇遇": self.jx3cmd.jx3_jinqiqiyu, "奇遇汇总": self.jx3cmd.jx3_qiyuhuizong, "战绩": self.jx3cmd.jx3_zhanji, - "排行": self.jx3cmd.jx3_mingjianpaihang, + "名剑排行": self.jx3cmd.jx3_mingjianpaihang, "名剑统计": self.jx3cmd.jx3_mingjiantongji, "招募": self.jx3cmd.jx3_tuanduizhaomu, "拜师": self.jx3cmd.jx3_baishi, diff --git a/metadata.yaml b/metadata.yaml index 7bed29e..34c33ae 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,7 +1,7 @@ name: astrbot_plugin_jx3 display_name: 剑网三游戏数据查询工具 desc: 通过接口调用剑网三API接口获取游戏数据,处理发送。 -version: v2.5 +version: v2.6 author: 飞翔大野猪 repo: https://github.com/qsc20001102/astrbot_plugin_jx3 astrbot_version: ">=4.11.0" diff --git a/templates/helps.html b/templates/helps.html index ce99ee0..6554bd5 100644 --- a/templates/helps.html +++ b/templates/helps.html @@ -369,8 +369,8 @@ body {

剑三机器人功能指令

按使用场景重新分组,保留每条指令的名称、使用示例与说明。卡片底色表示指令是否需要令牌,免令牌与需令牌功能一眼区分。

-
87条指令
-
16个功能分组
+
88条指令
+
13个功能分组
@@ -394,13 +394,13 @@ body {

日常功能

- 3 条 + 4 条 免令牌 3 - + 需令牌 1
- +
日常活动
@@ -409,7 +409,7 @@ body { 日常 [服务器] [天数]

查询指定日期的日常活动。

- +
日常预测
@@ -418,7 +418,7 @@ body { 月历

查看当前日期前后 15 天日常安排。

- +
名望事件
@@ -427,140 +427,16 @@ body { 名望 [穹野卫]

查询指定名望势力事件。

- -
- - -
-
-
- -

休闲功能

-
- -
-
- -
-
-
随机骚话
-
免令牌
-
- 骚话 -

随机返回一句趣味骚话,用于群内互动。

-
- -
-
-
烟花记录
-
需令牌
-
- 烟花 角色名 [服务器] -

查询指定角色烟花记录。

-
- -
-
-
拜师列表
-
需令牌
-
- 拜师 [搜索关键词] [服务器] -

查询徒弟找师傅信息。

-
- -
-
-
收徒列表
-
需令牌
-
- 收徒 [搜索关键词] [服务器] -

查询师傅找徒弟信息。

-
- -
-
- -
-
-
- -

杂项功能

-
- -
-
- -
-
-
科举答题
-
免令牌
-
- 科举 内容 -

按题目关键字查询科举答案。

-
- -
-
-
家园鲜花
-
免令牌
-
- 花价 名称 [服务器] [家园地图] -

查询家园鲜花价格,支持服务器与家园地图筛选。

-
- -
-
-
家园装饰
-
免令牌
-
- 装饰 名称 -

查询家园装饰物名称、来源与相关信息。

-
- -
-
-
器物图谱
-
免令牌
-
- 器物 地图名称 -

查询指定地图可收集的器物图谱。

-
- -
-
-
八卦记录
-
需令牌
-
- 八卦 类型 -

查询 818 / 616 / 避雷等八卦记录。

-
-
解密
+
诛恶
需令牌
- 解密 -

查询当前机关解密结果与下轮时间。

+ 诛恶 +

查询诛恶事件服务器、地图和时间记录。

- -
-
-
骗子查询
-
需令牌
-
- 骗子 QQ号 -

按 QQ 号查询骗子记录。

-
- +
@@ -573,11 +449,10 @@ body {
6 条 免令牌 6 -
- +
新闻资讯
@@ -586,7 +461,7 @@ body { 公告 [数量]

获取最新官方公告,数量默认为 5 条。

- +
维护公告
@@ -595,7 +470,7 @@ body { 维护 [数量]

获取最新官方维护公告,数量默认为 5 条。

- +
最新技改
@@ -604,7 +479,7 @@ body { 技改

获取最近一次官方职业技改内容。

- +
搜索区服
@@ -613,7 +488,7 @@ body { 区服 [服务器]

查询服务器基础信息。

- +
开服查询
@@ -622,7 +497,7 @@ body { 开服 [服务器]

查询指定服务器开服状态。

- +
全服状态
@@ -631,77 +506,41 @@ body { 状态

查询所有服务器当前状态。

- +
- -

交易功能

+ +

角色功能

- +
-
金价查询
+
角色信息
需令牌
- 金价 [服务器] -

查询指定服务器金价行情。

-
- -
-
-
外观物价
-
需令牌
-
- 物价 外观名称 [服务器] -

查询指定外观在服务器内的物价行情。

-
- -
-
-
交易行
-
需令牌
-
- 交易行 物品名称 [服务器] -

查询指定物品交易行价格与挂单信息。

+ 角色 名称 [服务器] +

查询角色基础信息。

-
贴吧物价
+
角色资历
需令牌
- 贴吧物价 物品名称 [记录数量] [服务器] -

查询指定物品的贴吧交易记录。

+ 资历 角色名 [服务器] +

按分类查询角色资历点数完成进度。

- -
-
- -
-
-
- -

名片功能

-
- -
-
- +
角色名片
@@ -710,7 +549,7 @@ body { 名片 角色名 [服务器]

查询角色当前名片。

- +
所有名片
@@ -719,16 +558,43 @@ body { 所有名片 角色名 [服务器]

查询角色已拥有或可展示的全部名片。

- +
-
随机名片
+
角色奇遇
需令牌
- 随机 职业 体型 [服务器] -

按职业、体型、服务器随机抽取名片。

+ 奇遇 角色名 [服务器] +

查询指定角色已触发奇遇。

- + +
+
+
未做奇遇
+
需令牌
+
+ 未做奇遇 角色名 [服务器] +

查询指定角色尚未完成的奇遇。

+
+ +
+
+
名剑战绩
+
需令牌
+
+ 战绩 角色名 [服务器] [模式] +

查询角色名剑大会战绩,支持 22 / 33 模式。

+
+ +
+
+
角色百战
+
需令牌
+
+ 精耐 角色名 [服务器] +

查询角色百战精力、耐力和技能列表。

+
+
@@ -739,13 +605,13 @@ body {

职业功能

- 7 条 + 6 条 免令牌 3 - 需令牌 4 + 需令牌 3
- +
小药推荐
@@ -754,7 +620,7 @@ body { 小药

查询指定心法常用小药、宴席与辅助搭配。

- +
心法宏
@@ -763,7 +629,7 @@ body { 宏 心法

查询指定心法推荐宏设置。

- +
心法配装
@@ -772,16 +638,7 @@ body { 配装 心法 [筛选]

查询指定心法配装,支持 PvP / PvE 筛选。

- -
-
-
角色信息
-
需令牌
-
- 角色 名称 [服务器] -

查询角色基础信息。

-
- +
心法阵眼
@@ -790,7 +647,7 @@ body { 阵眼 心法

查询指定心法阵眼效果。

- +
奇穴详情
@@ -799,7 +656,7 @@ body { 奇穴 心法

查询指定心法奇穴详情。

- +
技能详情
@@ -808,7 +665,96 @@ body { 技能 心法

查询指定心法技能详情。

- + +
+ + +
+
+
+ +

休闲功能

+
+ +
+
+ +
+
+
烟花记录
+
需令牌
+
+ 烟花 角色名 [服务器] +

查询指定角色烟花记录。

+
+ +
+
+
拜师列表
+
需令牌
+
+ 拜师 [搜索关键词] [服务器] +

查询徒弟找师傅信息。

+
+ +
+
+
收徒列表
+
需令牌
+
+ 收徒 [搜索关键词] [服务器] +

查询师傅找徒弟信息。

+
+ +
+
+
随机名片
+
需令牌
+
+ 随机名片 职业 体型 [服务器] +

按职业、体型、服务器随机抽取名片。

+
+ +
+
+
奇遇攻略
+
免令牌
+
+ 攻略 奇遇名称 +

查询指定奇遇的触发条件、奖励与流程攻略。

+
+ +
+
+
奇遇统计
+
需令牌
+
+ 奇遇统计 奇遇名称 [服务器] +

统计指定奇遇触发次数

+
+ +
+
+
近期奇遇
+
需令牌
+
+ 近期奇遇 [服务器] +

查询指定服务器最近触发的奇遇记录

+
+ +
+
+
奇遇汇总
+
需令牌
+
+ 奇遇汇总 [天数] [服务器] +

统计指定服务器最近一段时间的奇遇触发汇总

+
+
@@ -825,7 +771,7 @@ body {
- +
阵营沙盘
@@ -834,7 +780,7 @@ body { 沙盘 [服务器]

查询指定服务器阵营沙盘与据点状态。

- +
阵营拍卖
@@ -843,7 +789,7 @@ body { 拍卖 物品名称 [服务器]

查询阵营拍卖物品及服务器记录。

- +
阵营事件
@@ -852,7 +798,7 @@ body { 阵营事件

查询跨服阵营事件记录。

- +
关隘首领
@@ -879,7 +825,7 @@ body { 统战 [服务器]

查询指定服务器阵营统战 YY 信息。

- +
@@ -890,119 +836,12 @@ body {

副本功能

- 2 条 - - 需令牌 2 + 4 条 + 需令牌 4
- -
-
-
副本招募
-
需令牌
-
- 招募 副本名称 [服务器] -

查询指定服务器副本招募信息。

-
- -
-
-
掉落记录
-
需令牌
-
- 掉落 物品名称 [数量] [服务器] -

查询团队秘境贵重物品掉落记录

-
- -
- - -
-
-
- -

奇遇功能

-
- -
-
- -
-
-
奇遇攻略
-
免令牌
-
- 攻略 奇遇名称 -

查询指定奇遇的触发条件、奖励与流程攻略。

-
- -
-
-
角色奇遇
-
需令牌
-
- 奇遇 角色名 [服务器] -

查询指定角色已触发奇遇。

-
- -
-
-
未做奇遇
-
需令牌
-
- 未做奇遇 角色名 [服务器] -

查询指定角色尚未完成的奇遇。

-
- -
-
-
奇遇统计
-
需令牌
-
- 奇遇统计 奇遇名称 [服务器] -

统计指定奇遇触发次数

-
- -
-
-
近期奇遇
-
需令牌
-
- 近期奇遇 [服务器] -

查询指定服务器最近触发的奇遇记录

-
- -
-
-
奇遇汇总
-
需令牌
-
- 奇遇汇总 [天数] [服务器] -

统计指定服务器最近一段时间的奇遇触发汇总

-
- -
-
- -
-
-
- -

百战功能

-
- -
-
- +
百战首领
@@ -1011,16 +850,34 @@ body { 百战

查询本期百战异闻录首领与关卡信息。

- +
-
角色百战
+
副本招募
需令牌
- 精耐 角色名 [服务器] -

查询角色百战精力、耐力和技能列表。

+ 招募 副本名称 [服务器] +

查询指定服务器副本招募信息。

- + +
+
+
掉落记录
+
需令牌
+
+ 掉落 物品名称 [数量] [服务器] +

查询团队秘境贵重物品掉落记录

+
+ +
+
+
解密
+
需令牌
+
+ 解密 +

查询当前机关解密结果与下轮时间。

+
+
@@ -1031,13 +888,12 @@ body {

活动功能

- 6 条 - - 需令牌 6 + 5 条 + 需令牌 5
- +
扶摇九天
@@ -1046,15 +902,6 @@ body { 扶摇 [服务器]

查询指定服务器扶摇九天活动记录。

- -
-
-
诛恶事件
-
需令牌
-
- 诛恶事件 -

查询诛恶事件服务器、地图和时间记录。

-
@@ -1073,7 +920,7 @@ body { 本周赤兔

查询本周赤兔时间、区服和地图记录。

- +
马场刷新
@@ -1082,7 +929,7 @@ body { 刷马 [服务器]

查询指定服务器马场刷新记录。

- +
的卢记录
@@ -1091,51 +938,139 @@ body { 的卢 [服务器]

查询指定服务器的卢马刷新与捕获记录。

- +
- -

名剑功能

+ +

交易功能

- +
-
名剑战绩
+
金价查询
需令牌
- 战绩 角色名 [服务器] [模式] -

查询角色名剑大会战绩,支持 22 / 33 模式。

+ 金价 [服务器] +

查询指定服务器金价行情。

- +
-
名剑统计
+
外观物价
需令牌
- 名剑统计 [模式] -

统计指定模式名剑大会数据。

+ 物价 外观名称 [服务器] +

查询指定外观在服务器内的物价行情。

- +
-
名剑排行
+
交易行
需令牌
- 排行 [数量] [模式] -

查询名剑大会排名,支持 22 / 33 模式。

+ 交易行 物品名称 [服务器] +

查询指定物品交易行价格与挂单信息。

- + +
+
+
贴吧物价
+
需令牌
+
+ 贴吧物价 物品名称 [记录数量] [服务器] +

查询指定物品的贴吧交易记录。

+
+ +
+
+ +
+
+
+ +

杂项功能

+
+ +
+
+ +
+
+
科举答题
+
免令牌
+
+ 科举 内容 +

按题目关键字查询科举答案。

+
+ +
+
+
家园鲜花
+
免令牌
+
+ 花价 名称 [服务器] [家园地图] +

查询家园鲜花价格,支持服务器与家园地图筛选。

+
+ +
+
+
家园装饰
+
免令牌
+
+ 装饰 名称 +

查询家园装饰物名称、来源与相关信息。

+
+ +
+
+
器物图谱
+
免令牌
+
+ 器物 地图名称 +

查询指定地图可收集的器物图谱。

+
+ +
+
+
八卦记录
+
需令牌
+
+ 八卦 类型 +

查询 818 / 616 / 避雷等八卦记录。

+
+ +
+
+
骗子查询
+
需令牌
+
+ 骗子 QQ号 +

按 QQ 号查询骗子记录。

+
+ +
+
+
随机骚话
+
免令牌
+
+ 骚话 +

随机返回一句趣味骚话,用于群内互动。

+
+
@@ -1146,13 +1081,30 @@ body {

排行功能

- 19 条 - - 需令牌 19 + 21 条 + 需令牌 21
- + +
+
+
名剑统计
+
需令牌
+
+ 名剑统计 [模式] +

统计指定模式名剑大会数据。

+
+ +
+
+
名剑排行
+
需令牌
+
+ 名剑排行 [数量] [模式] +

查询名剑大会排名,支持 22 / 33 模式。

+
+
资历排行
@@ -1170,7 +1122,7 @@ body { 试炼排行 心法 [服务器]

查询指定心法木桩试炼排行榜。

- +
名士五十强
@@ -1179,7 +1131,7 @@ body { 名士五十强 [服务器]

查询风云录排行榜数据。

- +
老江湖五十强
@@ -1188,7 +1140,7 @@ body { 老江湖五十强 [服务器]

查询风云录排行榜数据。

- +
兵甲藏家五十强
@@ -1197,7 +1149,7 @@ body { 兵甲藏家五十强 [服务器]

查询风云录排行榜数据。

- +
名师五十强
@@ -1206,7 +1158,7 @@ body { 名师五十强 [服务器]

查询风云录排行榜数据。

- +
阵营英雄五十强
@@ -1215,7 +1167,7 @@ body { 阵营英雄五十强 [服务器]

查询风云录排行榜数据。

- +
薪火相传五十强
@@ -1224,7 +1176,7 @@ body { 薪火相传五十强 [服务器]

查询风云录排行榜数据。

- +
庐园广记一百强
@@ -1233,7 +1185,7 @@ body { 庐园广记一百强 [服务器]

查询风云录排行榜数据。

- +
浩气神兵宝甲五十强
@@ -1242,7 +1194,7 @@ body { 浩气神兵宝甲五十强 [服务器]

查询风云录排行榜数据。

- +
恶人神兵宝甲五十强
@@ -1251,7 +1203,7 @@ body { 恶人神兵宝甲五十强 [服务器]

查询风云录排行榜数据。

- +
浩气爱心帮会五十强
@@ -1260,7 +1212,7 @@ body { 浩气爱心帮会五十强 [服务器]

查询风云录排行榜数据。

- +
恶人爱心帮会五十强
@@ -1269,7 +1221,7 @@ body { 恶人爱心帮会五十强 [服务器]

查询风云录排行榜数据。

- +
赛季恶人五十强
@@ -1278,7 +1230,7 @@ body { 赛季恶人五十强 [服务器]

查询风云录排行榜数据。

- +
赛季浩气五十强
@@ -1287,7 +1239,7 @@ body { 赛季浩气五十强 [服务器]

查询风云录排行榜数据。

- +
上周恶人五十强
@@ -1296,7 +1248,7 @@ body { 上周恶人五十强 [服务器]

查询风云录排行榜数据。

- +
上周浩气五十强
@@ -1305,7 +1257,7 @@ body { 上周浩气五十强 [服务器]

查询风云录排行榜数据。

- +
本周恶人五十强
@@ -1314,7 +1266,7 @@ body { 本周恶人五十强 [服务器]

查询风云录排行榜数据。

- +
本周浩气五十强
@@ -1323,7 +1275,7 @@ body { 本周浩气五十强 [服务器]

查询风云录排行榜数据。

- +
@@ -1336,11 +1288,10 @@ body {
4 条 免令牌 4 -
- +
开服推送
@@ -1349,7 +1300,7 @@ body { 开服推送

订阅或管理服务器开服状态推送。

- +
新闻推送
@@ -1358,7 +1309,7 @@ body { 新闻推送

订阅或管理官方新闻公告推送。

- +
刷马推送
@@ -1367,7 +1318,7 @@ body { 刷马推送

订阅或管理刷马刷新推送。

- +
赤兔推送
@@ -1376,7 +1327,7 @@ body { 赤兔推送

订阅或管理赤兔马刷新推送。

- +
@@ -1389,11 +1340,10 @@ body {
5 条 免令牌 5 -
- +
避雷查看
@@ -1402,7 +1352,7 @@ body { 避雷查看

查看当前群内避雷记录列表。

- +
避雷添加
@@ -1411,7 +1361,7 @@ body { 避雷添加 名称 备注

新增一条避雷记录。

- +
避雷删除
@@ -1420,7 +1370,7 @@ body { 避雷删除 ID

按 ID 删除避雷记录。

- +
避雷修改
@@ -1429,7 +1379,7 @@ body { 避雷修改 ID 名称 备注

按 ID 修改避雷名称与备注。

- +
避雷查询
@@ -1438,7 +1388,7 @@ body { 避雷查询 名称

按名称关键字查询避雷记录。

- +
diff --git a/templates/zili.html b/templates/zili.html new file mode 100644 index 0000000..309b086 --- /dev/null +++ b/templates/zili.html @@ -0,0 +1,206 @@ + + + + +资历查询 + + + + + +
+
+
+

{{ title }}

+
+ {% if icons.sect.get(force_name) %} + {{ force_name }} + {% endif %} + {{ role_name }} +
+
+
+ {{ zone }} · {{ server }} · {{ force_name }} · {{ camp_name }} · 帮会:{{ tong_name }}
+ 资历更新时间:{{ updated_at or "未知" }} · 查询时间:{{ update_time }} +
+
+ +
+
+
{{ summary.name }}
+
{{ summary.percent_text }}
+
+
+ {{ summary.completed_points }} / {{ summary.total_points }} 点 + · {{ summary.completed_count }} / {{ summary.achievement_count }} 项 +
+
+
+
+
+ +
+ {% for item in items %} +
+
+
{{ item.name }}
+
{{ item.percent_text }}
+
+
+ {{ item.completed_points }} / {{ item.total_points }} 点 + · {{ item.completed_count }} / {{ item.achievement_count }} 项 +
+
+
+
+
+ {% endfor %} +
+
+ + +