From ef8a48ea0fbfa6793fce4b22bacddfaf433b02e3 Mon Sep 17 00:00:00 2001 From: zhinianboke <115088296+zhinianboke@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:02:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=8A=A8=E7=82=B9?= =?UTF-8?q?=E5=87=BB=E5=8F=91=E8=B4=A7=E6=8C=89=E9=92=AE=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- XianyuAutoAsync.py | 135 ++++++++++++++++++++++++++------------------- cookie_manager.py | 28 +++++++++- db_manager.py | 48 ++++++++++++++-- reply_server.py | 68 ++++++++++++++++++++++- static/index.html | 90 ++++++++++++++++++++++++++++-- 5 files changed, 301 insertions(+), 68 deletions(-) diff --git a/XianyuAutoAsync.py b/XianyuAutoAsync.py index 6e8c961..a879e1f 100644 --- a/XianyuAutoAsync.py +++ b/XianyuAutoAsync.py @@ -110,6 +110,15 @@ class XianyuLive: self.session = None # 用于API调用的aiohttp session + def is_auto_confirm_enabled(self) -> bool: + """检查当前账号是否启用自动确认发货""" + try: + from db_manager import db_manager + return db_manager.get_auto_confirm(self.cookie_id) + except Exception as e: + logger.error(f"【{self.cookie_id}】获取自动确认发货设置失败: {self._safe_str(e)}") + return True # 出错时默认启用 + def can_auto_delivery(self, item_id: str) -> bool: """检查是否可以进行自动发货(防重复发货)""" current_time = time.time() @@ -2017,14 +2026,30 @@ class XianyuLive: # 如果成功获取到orderId,进行自动确认发货 if order_id: - # 检查是否已经确认过这个订单 - current_time = time.time() - if order_id in self.confirmed_orders: - last_confirm_time = self.confirmed_orders[order_id] - if current_time - last_confirm_time < self.order_confirm_cooldown: - logger.info(f'[{msg_time}] 【{self.cookie_id}】⏭️ 订单 {order_id} 已在 {self.order_confirm_cooldown} 秒内确认过,跳过重复确认') + # 检查是否启用自动确认发货 + if not self.is_auto_confirm_enabled(): + logger.info(f'[{msg_time}] 【{self.cookie_id}】自动确认发货已关闭,跳过订单 {order_id}') + else: + # 检查是否已经确认过这个订单 + current_time = time.time() + if order_id in self.confirmed_orders: + last_confirm_time = self.confirmed_orders[order_id] + if current_time - last_confirm_time < self.order_confirm_cooldown: + logger.info(f'[{msg_time}] 【{self.cookie_id}】⏭️ 订单 {order_id} 已在 {self.order_confirm_cooldown} 秒内确认过,跳过重复确认') + else: + # 超过冷却时间,可以重新确认 + try: + logger.info(f'[{msg_time}] 【{self.cookie_id}】开始自动确认发货,订单ID: {order_id}') + confirm_result = await self.auto_confirm(order_id) + if confirm_result.get('success'): + self.confirmed_orders[order_id] = current_time + logger.info(f'[{msg_time}] 【{self.cookie_id}】🎉 自动确认发货成功!订单ID: {order_id}') + else: + logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 自动确认发货失败: {confirm_result.get("error", "未知错误")}') + except Exception as confirm_e: + logger.error(f'[{msg_time}] 【{self.cookie_id}】自动确认发货异常: {self._safe_str(confirm_e)}') else: - # 超过冷却时间,可以重新确认 + # 首次确认这个订单 try: logger.info(f'[{msg_time}] 【{self.cookie_id}】开始自动确认发货,订单ID: {order_id}') confirm_result = await self.auto_confirm(order_id) @@ -2035,18 +2060,6 @@ class XianyuLive: logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 自动确认发货失败: {confirm_result.get("error", "未知错误")}') except Exception as confirm_e: logger.error(f'[{msg_time}] 【{self.cookie_id}】自动确认发货异常: {self._safe_str(confirm_e)}') - else: - # 首次确认这个订单 - try: - logger.info(f'[{msg_time}] 【{self.cookie_id}】开始自动确认发货,订单ID: {order_id}') - confirm_result = await self.auto_confirm(order_id) - if confirm_result.get('success'): - self.confirmed_orders[order_id] = current_time - logger.info(f'[{msg_time}] 【{self.cookie_id}】🎉 自动确认发货成功!订单ID: {order_id}') - else: - logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 自动确认发货失败: {confirm_result.get("error", "未知错误")}') - except Exception as confirm_e: - logger.error(f'[{msg_time}] 【{self.cookie_id}】自动确认发货异常: {self._safe_str(confirm_e)}') else: logger.warning(f'[{msg_time}] 【{self.cookie_id}】❌ 未能提取到订单ID') @@ -2139,14 +2152,30 @@ class XianyuLive: # 如果成功获取到orderId,进行自动确认发货 if order_id: - # 检查是否已经确认过这个订单 - current_time = time.time() - if order_id in self.confirmed_orders: - last_confirm_time = self.confirmed_orders[order_id] - if current_time - last_confirm_time < self.order_confirm_cooldown: - logger.info(f'[{msg_time}] 【{self.cookie_id}】⏭️ 订单 {order_id} 已在 {self.order_confirm_cooldown} 秒内确认过,跳过重复确认') + # 检查是否启用自动确认发货 + if not self.is_auto_confirm_enabled(): + logger.info(f'[{msg_time}] 【{self.cookie_id}】自动确认发货已关闭,跳过订单 {order_id}') + else: + # 检查是否已经确认过这个订单 + current_time = time.time() + if order_id in self.confirmed_orders: + last_confirm_time = self.confirmed_orders[order_id] + if current_time - last_confirm_time < self.order_confirm_cooldown: + logger.info(f'[{msg_time}] 【{self.cookie_id}】⏭️ 订单 {order_id} 已在 {self.order_confirm_cooldown} 秒内确认过,跳过重复确认') + else: + # 超过冷却时间,可以重新确认 + try: + logger.info(f'[{msg_time}] 【{self.cookie_id}】开始自动确认发货,订单ID: {order_id}') + confirm_result = await self.auto_confirm(order_id) + if confirm_result.get('success'): + self.confirmed_orders[order_id] = current_time + logger.info(f'[{msg_time}] 【{self.cookie_id}】🎉 自动确认发货成功!订单ID: {order_id}') + else: + logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 自动确认发货失败: {confirm_result.get("error", "未知错误")}') + except Exception as confirm_e: + logger.error(f'[{msg_time}] 【{self.cookie_id}】自动确认发货异常: {self._safe_str(confirm_e)}') else: - # 超过冷却时间,可以重新确认 + # 首次确认这个订单 try: logger.info(f'[{msg_time}] 【{self.cookie_id}】开始自动确认发货,订单ID: {order_id}') confirm_result = await self.auto_confirm(order_id) @@ -2157,18 +2186,6 @@ class XianyuLive: logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 自动确认发货失败: {confirm_result.get("error", "未知错误")}') except Exception as confirm_e: logger.error(f'[{msg_time}] 【{self.cookie_id}】自动确认发货异常: {self._safe_str(confirm_e)}') - else: - # 首次确认这个订单 - try: - logger.info(f'[{msg_time}] 【{self.cookie_id}】开始自动确认发货,订单ID: {order_id}') - confirm_result = await self.auto_confirm(order_id) - if confirm_result.get('success'): - self.confirmed_orders[order_id] = current_time - logger.info(f'[{msg_time}] 【{self.cookie_id}】🎉 自动确认发货成功!订单ID: {order_id}') - else: - logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 自动确认发货失败: {confirm_result.get("error", "未知错误")}') - except Exception as confirm_e: - logger.error(f'[{msg_time}] 【{self.cookie_id}】自动确认发货异常: {self._safe_str(confirm_e)}') else: logger.warning(f'[{msg_time}] 【{self.cookie_id}】❌ 未能提取到订单ID') @@ -2285,14 +2302,30 @@ class XianyuLive: # 如果成功获取到orderId,进行自动确认发货 if order_id: - # 检查是否已经确认过这个订单 - current_time = time.time() - if order_id in self.confirmed_orders: - last_confirm_time = self.confirmed_orders[order_id] - if current_time - last_confirm_time < self.order_confirm_cooldown: - logger.info(f'[{msg_time}] 【{self.cookie_id}】⏭️ 订单 {order_id} 已在 {self.order_confirm_cooldown} 秒内确认过,跳过重复确认') + # 检查是否启用自动确认发货 + if not self.is_auto_confirm_enabled(): + logger.info(f'[{msg_time}] 【{self.cookie_id}】自动确认发货已关闭,跳过小刀成功订单 {order_id}') + else: + # 检查是否已经确认过这个订单 + current_time = time.time() + if order_id in self.confirmed_orders: + last_confirm_time = self.confirmed_orders[order_id] + if current_time - last_confirm_time < self.order_confirm_cooldown: + logger.info(f'[{msg_time}] 【{self.cookie_id}】⏭️ 订单 {order_id} 已在 {self.order_confirm_cooldown} 秒内确认过,跳过重复确认') + else: + # 超过冷却时间,可以重新确认 + try: + logger.info(f'[{msg_time}] 【{self.cookie_id}】小刀成功,开始自动确认发货,订单ID: {order_id}') + confirm_result = await self.auto_confirm(order_id) + if confirm_result.get('success'): + self.confirmed_orders[order_id] = current_time + logger.info(f'[{msg_time}] 【{self.cookie_id}】🎉 小刀成功,自动确认发货成功!订单ID: {order_id}') + else: + logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 小刀成功,自动确认发货失败: {confirm_result.get("error", "未知错误")}') + except Exception as confirm_e: + logger.error(f'[{msg_time}] 【{self.cookie_id}】小刀成功,自动确认发货异常: {self._safe_str(confirm_e)}') else: - # 超过冷却时间,可以重新确认 + # 首次确认这个订单 try: logger.info(f'[{msg_time}] 【{self.cookie_id}】小刀成功,开始自动确认发货,订单ID: {order_id}') confirm_result = await self.auto_confirm(order_id) @@ -2303,18 +2336,6 @@ class XianyuLive: logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 小刀成功,自动确认发货失败: {confirm_result.get("error", "未知错误")}') except Exception as confirm_e: logger.error(f'[{msg_time}] 【{self.cookie_id}】小刀成功,自动确认发货异常: {self._safe_str(confirm_e)}') - else: - # 首次确认这个订单 - try: - logger.info(f'[{msg_time}] 【{self.cookie_id}】小刀成功,开始自动确认发货,订单ID: {order_id}') - confirm_result = await self.auto_confirm(order_id) - if confirm_result.get('success'): - self.confirmed_orders[order_id] = current_time - logger.info(f'[{msg_time}] 【{self.cookie_id}】🎉 小刀成功,自动确认发货成功!订单ID: {order_id}') - else: - logger.warning(f'[{msg_time}] 【{self.cookie_id}】⚠️ 小刀成功,自动确认发货失败: {confirm_result.get("error", "未知错误")}') - except Exception as confirm_e: - logger.error(f'[{msg_time}] 【{self.cookie_id}】小刀成功,自动确认发货异常: {self._safe_str(confirm_e)}') else: logger.warning(f'[{msg_time}] 【{self.cookie_id}】❌ 小刀成功但未能提取到订单ID') diff --git a/cookie_manager.py b/cookie_manager.py index be721fb..f61736c 100644 --- a/cookie_manager.py +++ b/cookie_manager.py @@ -16,6 +16,7 @@ class CookieManager: self.tasks: Dict[str, asyncio.Task] = {} self.keywords: Dict[str, List[Tuple[str, str]]] = {} self.cookie_status: Dict[str, bool] = {} # 账号启用状态 + self.auto_confirm_settings: Dict[str, bool] = {} # 自动确认发货设置 self._load_from_db() def _load_from_db(self): @@ -27,11 +28,15 @@ class CookieManager: self.keywords = db_manager.get_all_keywords() # 加载所有Cookie状态(默认启用) self.cookie_status = db_manager.get_all_cookie_status() - # 为没有状态记录的Cookie设置默认启用状态 + # 加载所有auto_confirm设置 + self.auto_confirm_settings = {} for cookie_id in self.cookies.keys(): + # 为没有状态记录的Cookie设置默认启用状态 if cookie_id not in self.cookie_status: self.cookie_status[cookie_id] = True - logger.info(f"从数据库加载了 {len(self.cookies)} 个Cookie、{len(self.keywords)} 组关键字和 {len(self.cookie_status)} 个状态记录") + # 加载auto_confirm设置 + self.auto_confirm_settings[cookie_id] = db_manager.get_auto_confirm(cookie_id) + logger.info(f"从数据库加载了 {len(self.cookies)} 个Cookie、{len(self.keywords)} 组关键字、{len(self.cookie_status)} 个状态记录和 {len(self.auto_confirm_settings)} 个自动确认设置") except Exception as e: logger.error(f"从数据库加载数据失败: {e}") @@ -273,6 +278,25 @@ class CookieManager: except Exception as e: logger.error(f"停止Cookie任务失败: {cookie_id}, {e}") + def update_auto_confirm_setting(self, cookie_id: str, auto_confirm: bool): + """实时更新账号的自动确认发货设置""" + try: + # 更新内存中的设置 + self.auto_confirm_settings[cookie_id] = auto_confirm + logger.info(f"更新账号 {cookie_id} 自动确认发货设置: {'开启' if auto_confirm else '关闭'}") + + # 如果账号正在运行,通知XianyuLive实例更新设置 + if cookie_id in self.tasks and not self.tasks[cookie_id].done(): + # 这里可以通过某种方式通知正在运行的XianyuLive实例 + # 由于XianyuLive会从数据库读取设置,所以数据库已经更新就足够了 + logger.info(f"账号 {cookie_id} 正在运行,自动确认发货设置已实时生效") + except Exception as e: + logger.error(f"更新自动确认发货设置失败: {cookie_id}, {e}") + + def get_auto_confirm_setting(self, cookie_id: str) -> bool: + """获取账号的自动确认发货设置""" + return self.auto_confirm_settings.get(cookie_id, True) # 默认开启 + # 在 Start.py 中会把此变量赋值为具体实例 manager: Optional[CookieManager] = None \ No newline at end of file diff --git a/db_manager.py b/db_manager.py index 0959903..413e5d1 100644 --- a/db_manager.py +++ b/db_manager.py @@ -106,12 +106,13 @@ class DBManager: ) ''') - # 创建cookies表(添加user_id字段) + # 创建cookies表(添加user_id字段和auto_confirm字段) cursor.execute(''' CREATE TABLE IF NOT EXISTS cookies ( id TEXT PRIMARY KEY, value TEXT NOT NULL, user_id INTEGER NOT NULL, + auto_confirm INTEGER DEFAULT 1, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ) @@ -367,6 +368,17 @@ class DBManager: # user_id列存在,更新NULL值 self._execute_sql(cursor, "UPDATE cookies SET user_id = ? WHERE user_id IS NULL", (admin_user_id,)) + # 为cookies表添加auto_confirm字段(如果不存在) + try: + self._execute_sql(cursor, "SELECT auto_confirm FROM cookies LIMIT 1") + except sqlite3.OperationalError: + # auto_confirm列不存在,需要添加并设置默认值 + self._execute_sql(cursor, "ALTER TABLE cookies ADD COLUMN auto_confirm INTEGER DEFAULT 1") + self._execute_sql(cursor, "UPDATE cookies SET auto_confirm = 1 WHERE auto_confirm IS NULL") + else: + # auto_confirm列存在,更新NULL值 + self._execute_sql(cursor, "UPDATE cookies SET auto_confirm = 1 WHERE auto_confirm IS NULL") + # 为delivery_rules表添加user_id字段(如果不存在) try: self._execute_sql(cursor, "SELECT user_id FROM delivery_rules LIMIT 1") @@ -576,23 +588,51 @@ class DBManager: return None def get_cookie_details(self, cookie_id: str) -> Optional[Dict[str, any]]: - """获取Cookie的详细信息,包括user_id""" + """获取Cookie的详细信息,包括user_id和auto_confirm""" with self.lock: try: cursor = self.conn.cursor() - self._execute_sql(cursor, "SELECT id, value, user_id, created_at FROM cookies WHERE id = ?", (cookie_id,)) + self._execute_sql(cursor, "SELECT id, value, user_id, auto_confirm, created_at FROM cookies WHERE id = ?", (cookie_id,)) result = cursor.fetchone() if result: return { 'id': result[0], 'value': result[1], 'user_id': result[2], - 'created_at': result[3] + 'auto_confirm': bool(result[3]), + 'created_at': result[4] } return None except Exception as e: logger.error(f"获取Cookie详细信息失败: {e}") return None + + def update_auto_confirm(self, cookie_id: str, auto_confirm: bool) -> bool: + """更新Cookie的自动确认发货设置""" + with self.lock: + try: + cursor = self.conn.cursor() + self._execute_sql(cursor, "UPDATE cookies SET auto_confirm = ? WHERE id = ?", (int(auto_confirm), cookie_id)) + self.conn.commit() + logger.info(f"更新账号 {cookie_id} 自动确认发货设置: {'开启' if auto_confirm else '关闭'}") + return True + except Exception as e: + logger.error(f"更新自动确认发货设置失败: {e}") + return False + + def get_auto_confirm(self, cookie_id: str) -> bool: + """获取Cookie的自动确认发货设置""" + with self.lock: + try: + cursor = self.conn.cursor() + self._execute_sql(cursor, "SELECT auto_confirm FROM cookies WHERE id = ?", (cookie_id,)) + result = cursor.fetchone() + if result: + return bool(result[0]) + return True # 默认开启 + except Exception as e: + logger.error(f"获取自动确认发货设置失败: {e}") + return True # 出错时默认开启 # -------------------- 关键字操作 -------------------- def save_keywords(self, cookie_id: str, keywords: List[Tuple[str, str]]) -> bool: diff --git a/reply_server.py b/reply_server.py index a0b3f11..d0baa45 100644 --- a/reply_server.py +++ b/reply_server.py @@ -899,10 +899,12 @@ def get_cookies_details(current_user: Dict[str, Any] = Depends(get_current_user) result = [] for cookie_id, cookie_value in user_cookies.items(): cookie_enabled = cookie_manager.manager.get_cookie_status(cookie_id) + auto_confirm = db_manager.get_auto_confirm(cookie_id) result.append({ 'id': cookie_id, 'value': cookie_value, - 'enabled': cookie_enabled + 'enabled': cookie_enabled, + 'auto_confirm': auto_confirm }) return result @@ -1314,6 +1316,70 @@ def remove_cookie(cid: str, current_user: Dict[str, Any] = Depends(get_current_u raise HTTPException(status_code=400, detail=str(e)) +class AutoConfirmUpdate(BaseModel): + auto_confirm: bool + + +@app.put("/cookies/{cid}/auto-confirm") +def update_auto_confirm(cid: str, update_data: AutoConfirmUpdate, current_user: Dict[str, Any] = Depends(get_current_user)): + """更新账号的自动确认发货设置""" + if cookie_manager.manager is None: + raise HTTPException(status_code=500, detail="CookieManager 未就绪") + try: + # 检查cookie是否属于当前用户 + user_id = current_user['user_id'] + from db_manager import db_manager + user_cookies = db_manager.get_all_cookies(user_id) + + if cid not in user_cookies: + raise HTTPException(status_code=403, detail="无权限操作该Cookie") + + # 更新数据库中的auto_confirm设置 + success = db_manager.update_auto_confirm(cid, update_data.auto_confirm) + if not success: + raise HTTPException(status_code=500, detail="更新自动确认发货设置失败") + + # 通知CookieManager更新设置(如果账号正在运行) + if hasattr(cookie_manager.manager, 'update_auto_confirm_setting'): + cookie_manager.manager.update_auto_confirm_setting(cid, update_data.auto_confirm) + + return { + "msg": "success", + "auto_confirm": update_data.auto_confirm, + "message": f"自动确认发货已{'开启' if update_data.auto_confirm else '关闭'}" + } + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + +@app.get("/cookies/{cid}/auto-confirm") +def get_auto_confirm(cid: str, current_user: Dict[str, Any] = Depends(get_current_user)): + """获取账号的自动确认发货设置""" + if cookie_manager.manager is None: + raise HTTPException(status_code=500, detail="CookieManager 未就绪") + try: + # 检查cookie是否属于当前用户 + user_id = current_user['user_id'] + from db_manager import db_manager + user_cookies = db_manager.get_all_cookies(user_id) + + if cid not in user_cookies: + raise HTTPException(status_code=403, detail="无权限操作该Cookie") + + # 获取auto_confirm设置 + auto_confirm = db_manager.get_auto_confirm(cid) + return { + "auto_confirm": auto_confirm, + "message": f"自动确认发货当前{'开启' if auto_confirm else '关闭'}" + } + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + diff --git a/static/index.html b/static/index.html index aa5a720..be9e777 100644 --- a/static/index.html +++ b/static/index.html @@ -1341,12 +1341,13 @@ 账号ID - Cookie值 + Cookie值 关键词 状态 - 默认回复 - AI回复 - 操作 + 默认回复 + AI回复 + 自动确认发货 + 操作 @@ -3553,6 +3554,9 @@ 'AI启用' : 'AI禁用'; + // 自动确认发货状态(默认开启) + const autoConfirm = cookie.auto_confirm === undefined ? true : cookie.auto_confirm; + tr.innerHTML = `