From 88ef0545a585eec0a997185513a665925106b70f Mon Sep 17 00:00:00 2001 From: qsc20001102 Date: Fri, 12 Dec 2025 16:23:35 +0800 Subject: [PATCH] 11 --- _conf_schema.json | 6 ++-- core/aiosqlite.py | 83 ++++++++++++++++++++++++++++++++------------- core/async_task.py | 2 +- core/jx3_service.py | 34 +++++++++---------- 4 files changed, 80 insertions(+), 45 deletions(-) diff --git a/_conf_schema.json b/_conf_schema.json index 7731b6e..adb1fee 100644 --- a/_conf_schema.json +++ b/_conf_schema.json @@ -6,13 +6,13 @@ "enable": { "description": "开服监控功能开关", "type": "bool", - "default": true, + "default": false, "hint": "是否启用剑网三开服监控功能。" }, "time": { "description": "开服监控循环时间", "type": "int", - "default": 10, + "default": 60, "hint": "请求服务器状态的循环时间,单位秒。" }, "umos": { @@ -23,7 +23,7 @@ "type": "string", "description": "会话唯一ID" }, - "default": ["default:GroupMessage:768280021","default:GroupMessage:690665795"] + "default": ["QQ:GroupMessage:768280021","QQ:GroupMessage:690665795"] } } } diff --git a/core/aiosqlite.py b/core/aiosqlite.py index e1a6cb6..d379be4 100644 --- a/core/aiosqlite.py +++ b/core/aiosqlite.py @@ -1,4 +1,10 @@ import aiosqlite +import logging +import re + +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger("AsyncSQLite") + class AsyncSQLite: def __init__(self, db_path: str): @@ -15,28 +21,65 @@ class AsyncSQLite: await self.conn.close() self.conn = None - async def fetch_one(self, sql: str, params=None): + def _format_sql(self, sql: str, params): + """生成完整 SQL(安全打印)""" + + if not params: + return sql + + def escape(value): + if value is None: + return "NULL" + if isinstance(value, (int, float)): + return str(value) + # 转义单引号 + value = str(value).replace("'", "''") + return f"'{value}'" + + final_sql = sql + for v in params: + final_sql = final_sql.replace("?", escape(v), 1) + + return final_sql + + async def _log_and_execute(self, sql: str, params=None, fetch: str = None): await self.init() - async with self.conn.execute(sql, params or ()) as cursor: # type: ignore - row = await cursor.fetchone() - return dict(row) if row else None + + # 打印原始 SQL 和参数 + logger.debug(f"[SQLite] SQL Raw: {sql}") + logger.debug(f"[SQLite] Params: {params}") + + # 打印最终执行 SQL + final_sql = self._format_sql(sql, params or ()) + logger.debug(f"[SQLite] SQL Final: {final_sql}") + + async with self.conn.execute(sql, params or ()) as cursor: + if fetch == "one": + row = await cursor.fetchone() + return dict(row) if row else None + + if fetch == "all": + rows = await cursor.fetchall() + return [dict(r) for r in rows] + + await self.conn.commit() + return True + + async def fetch_one(self, sql: str, params=None): + return await self._log_and_execute(sql, params, fetch="one") async def fetch_all(self, sql: str, params=None): - await self.init() - async with self.conn.execute(sql, params or ()) as cursor: # type: ignore - rows = await cursor.fetchall() - return [dict(r) for r in rows] + return await self._log_and_execute(sql, params, fetch="all") async def execute(self, sql: str, params=None): - await self.init() - async with self.conn.execute(sql, params or ()): # type: ignore - await self.conn.commit() # type: ignore - return True + return await self._log_and_execute(sql, params) async def executemany(self, sql: str, params_list): await self.init() - await self.conn.executemany(sql, params_list) # type: ignore - await self.conn.commit() # type: ignore + logger.debug(f"[SQLite] SQL (executemany): {sql}") + logger.debug(f"[SQLite] Params List: {params_list}") + await self.conn.executemany(sql, params_list) + await self.conn.commit() return True async def insert_record(self, table: str, data: dict): @@ -58,13 +101,5 @@ class AsyncSQLite: return await self.execute(sql, tuple(where.values())) async def clear_table(self, table: str): - """ - 清空指定表中的所有记录。 - Args: - table: 要清空的表名。 - Returns: - 如果操作成功则返回 True。 - """ - sql = f"DELETE FROM `{table}`" - # 使用 execute 函数执行 DELETE 语句 - return await self.execute(sql) \ No newline at end of file + sql = f"DELETE FROM `{table}`" + return await self.execute(sql) diff --git a/core/async_task.py b/core/async_task.py index 8d93cf2..903f0a1 100644 --- a/core/async_task.py +++ b/core/async_task.py @@ -49,7 +49,7 @@ class AsyncTask: # 获取最新服务状态 data = await self.jx3fun.kaifu("梦江南") self.kfjk_server_state_new = data["status"] - logger.info(f"开服监控功能循环中,上次询问服务器状态{self.kfjk_server_state},本次询问的服务器状态{self.kfjk_server_state_new}") + logger.debug(f"开服监控功能循环中,上次询问服务器状态{self.kfjk_server_state},本次询问的服务器状态{self.kfjk_server_state_new}") # 判断状态是否变化 if self.kfjk_server_state != self.kfjk_server_state_new: logger.info(f"开服监控功能循环中,上次询问服务器状态{self.kfjk_server_state},本次询问的服务器状态{self.kfjk_server_state_new}") diff --git a/core/jx3_service.py b/core/jx3_service.py index d4eed33..12ef28b 100644 --- a/core/jx3_service.py +++ b/core/jx3_service.py @@ -376,10 +376,25 @@ class JX3Service: searchId = None # 2. 确定外观名称和 ID - if search_data and search_data.get("total", 0) > 0 and search_data.get("list"): + + # 从 DB 查找名称和 ID + logger.info("尝试从数据库查询外观信息") + try: + sql = "SELECT showName, searchId FROM searchdata WHERE name LIKE ? OR showName LIKE ?" + sqldata = await self._db.fetch_one(sql, (f"%{Name}%", f"%{Name}%")) + if sqldata: + showName = sqldata["showName"] + searchId = sqldata["searchId"] + else: + raise ValueError("DB did not find data.") + except Exception as e: + logger.error(f"获取外观信息错误: {e}") + return_data["msg"] = "数据库未找到该外观信息,尝试从魔盒查询" + logger.info("尝试从魔盒查询外观信息") + params_search = {"keyword": Name} + search_data: Optional[Dict[str, Any]] = await self._base_request("jx3box_exterior", "GET", params=params_search) # 从 API 获取名称 showName = search_data["list"][0].get("name", "") - # 进一步从 DB 查找 ID try: sql = "SELECT searchId FROM searchdata WHERE showName=?" @@ -387,21 +402,6 @@ class JX3Service: searchId = sqldata["searchId"] if sqldata else None except Exception as e: logger.warning(f"从 DB 获取外观ID错误: {e}") # 警告而非错误,因为可能数据库同步失败 - - elif search_data and search_data.get("total", 0) == 0: - # 从 DB 查找名称和 ID - try: - sql = "SELECT showName, searchId FROM searchdata WHERE name = ? OR showName = ?" - sqldata = await self._db.fetch_one(sql, (Name, Name)) - if sqldata: - showName = sqldata["showName"] - searchId = sqldata["searchId"] - else: - raise ValueError("DB did not find data.") - except Exception as e: - logger.error(f"获取外观信息错误: {e}") - return_data["msg"] = "未找到该外观信息" - return return_data if not showName or not searchId: return_data["msg"] = "无法确定外观名称或ID"