This commit is contained in:
zhinianboke 2025-09-27 16:03:40 +08:00
parent 0124fb5f9f
commit 7be1c0cbaf
2 changed files with 130 additions and 24 deletions

View File

@ -780,6 +780,16 @@ class XianyuLive:
) )
return None return None
# 【消息接收检查】检查是否在消息接收后的冷却时间内,与 cookie_refresh_loop 保持一致
current_time = time.time()
time_since_last_message = current_time - self.last_message_received_time
if self.last_message_received_time > 0 and time_since_last_message < self.message_cookie_refresh_cooldown:
remaining_time = self.message_cookie_refresh_cooldown - time_since_last_message
remaining_minutes = int(remaining_time // 60)
remaining_seconds = int(remaining_time % 60)
logger.info(f"{self.cookie_id}】收到消息后冷却中放弃本次token刷新还需等待 {remaining_minutes}{remaining_seconds}")
return None
# 生成更精确的时间戳 # 生成更精确的时间戳
timestamp = str(int(time.time() * 1000)) timestamp = str(int(time.time() * 1000))
@ -870,6 +880,10 @@ class XianyuLive:
self.current_token = new_token self.current_token = new_token
self.last_token_refresh_time = time.time() self.last_token_refresh_time = time.time()
# 【消息接收时间重置】Token刷新成功后重置消息接收标志与 cookie_refresh_loop 保持一致
self.last_message_received_time = 0
logger.debug(f"{self.cookie_id}】Token刷新成功已重置消息接收时间标识")
logger.info(f"{self.cookie_id}】Token刷新成功") logger.info(f"{self.cookie_id}】Token刷新成功")
return new_token return new_token
@ -989,29 +1003,35 @@ class XianyuLive:
"captcha_verification_exception" "captcha_verification_exception"
) )
# 检查是否包含"令牌过期"或"Session过期"且浏览器Cookie刷新标志为True # 检查是否包含"令牌过期"或"Session过期"
if isinstance(res_json, dict): if isinstance(res_json, dict):
res_json_str = json.dumps(res_json, ensure_ascii=False, separators=(',', ':')) res_json_str = json.dumps(res_json, ensure_ascii=False, separators=(',', ':'))
if ('令牌过期' in res_json_str or 'Session过期' in res_json_str) and self.browser_cookie_refreshed: if '令牌过期' in res_json_str or 'Session过期' in res_json_str:
logger.warning(f"{self.cookie_id}】检测到令牌/Session过期且浏览器Cookie已刷新过准备重启实例...") logger.warning(f"{self.cookie_id}】检测到令牌/Session过期准备刷新Cookie并重启实例...")
# 将浏览器Cookie刷新标志设置为False
self.browser_cookie_refreshed = False
logger.info(f"{self.cookie_id}】浏览器Cookie刷新标志已重置为False")
# 记录到日志文件 # 记录到日志文件
log_captcha_event(self.cookie_id, "令牌/Session过期触发实例重启", None, log_captcha_event(self.cookie_id, "令牌/Session过期触发Cookie刷新和实例重启", None,
f"检测到令牌/Session过期且浏览器Cookie已刷新准备重启实例") f"检测到令牌/Session过期准备刷新Cookie并重启实例")
# 调用重启实例方法
try: try:
logger.info(f"{self.cookie_id}】开始重启实例...") # 先调用_refresh_cookies_via_browser刷新Cookie
await self._restart_instance() logger.info(f"{self.cookie_id}】开始通过浏览器刷新Cookie...")
logger.info(f"{self.cookie_id}】实例重启完成") refresh_success = await self._refresh_cookies_via_browser(triggered_by_refresh_token=True)
return None
except Exception as restart_e: if refresh_success:
logger.error(f"{self.cookie_id}】实例重启失败: {self._safe_str(restart_e)}") logger.info(f"{self.cookie_id}】Cookie刷新成功准备重启实例...")
# 重启失败时继续执行原有的失败处理逻辑
# Cookie刷新成功后重启实例
await self._restart_instance()
logger.info(f"{self.cookie_id}】实例重启完成")
return None
else:
logger.error(f"{self.cookie_id}】Cookie刷新失败跳过实例重启")
# Cookie刷新失败时继续执行原有的失败处理逻辑
except Exception as refresh_e:
logger.error(f"{self.cookie_id}】Cookie刷新或实例重启失败: {self._safe_str(refresh_e)}")
# 刷新失败时继续执行原有的失败处理逻辑
logger.error(f"{self.cookie_id}】Token刷新失败: {res_json}") logger.error(f"{self.cookie_id}】Token刷新失败: {res_json}")
@ -2514,8 +2534,8 @@ class XianyuLive:
logger.info(f"📱 QQ通知 - 响应状态: {response.status}") logger.info(f"📱 QQ通知 - 响应状态: {response.status}")
logger.info(f"📱 QQ通知 - 响应内容: {response_text}") logger.info(f"📱 QQ通知 - 响应内容: {response_text}")
if response.status == 200: if response.status == 200 or response.status == 502:
logger.info(f"📱 QQ通知发送成功: {qq_number}") logger.info(f"📱 QQ通知发送成功: {qq_number} (状态码: {response.status})")
else: else:
logger.warning(f"📱 QQ通知发送失败: HTTP {response.status}, 响应: {response_text}") logger.warning(f"📱 QQ通知发送失败: HTTP {response.status}, 响应: {response_text}")
@ -4496,8 +4516,12 @@ class XianyuLive:
remaining_time = max(0, self.qr_cookie_refresh_cooldown - time_since_qr_refresh) remaining_time = max(0, self.qr_cookie_refresh_cooldown - time_since_qr_refresh)
return int(remaining_time) return int(remaining_time)
async def _refresh_cookies_via_browser(self): async def _refresh_cookies_via_browser(self, triggered_by_refresh_token: bool = False):
"""通过浏览器访问指定页面刷新Cookie""" """通过浏览器访问指定页面刷新Cookie
Args:
triggered_by_refresh_token: 是否由refresh_token方法触发如果是True则设置browser_cookie_refreshed标志
"""
playwright = None playwright = None
@ -4770,9 +4794,12 @@ class XianyuLive:
# 更新数据库中的Cookie # 更新数据库中的Cookie
await self.update_config_cookies() await self.update_config_cookies()
# 设置浏览器Cookie刷新成功标志 # 只有当由refresh_token触发时才设置浏览器Cookie刷新成功标志
self.browser_cookie_refreshed = True if triggered_by_refresh_token:
logger.info(f"{self.cookie_id}】浏览器Cookie刷新成功标志已设置为True") self.browser_cookie_refreshed = True
logger.info(f"{self.cookie_id}】由refresh_token触发浏览器Cookie刷新成功标志已设置为True")
else:
logger.info(f"{self.cookie_id}】由定时任务触发不设置浏览器Cookie刷新成功标志")
logger.info(f"{self.cookie_id}】Cookie刷新完成") logger.info(f"{self.cookie_id}】Cookie刷新完成")
return True return True

View File

@ -3946,6 +3946,85 @@ def delete_user(user_id: int, admin_user: Dict[str, Any] = Depends(require_admin
log_with_user('error', f"删除用户异常: {str(e)}", admin_user) log_with_user('error', f"删除用户异常: {str(e)}", admin_user)
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))
@app.get('/admin/risk-control-logs')
async def get_admin_risk_control_logs(
cookie_id: str = None,
limit: int = 100,
offset: int = 0,
admin_user: Dict[str, Any] = Depends(require_admin)
):
"""获取风控日志(管理员专用)"""
try:
log_with_user('info', f"查询风控日志: cookie_id={cookie_id}, limit={limit}, offset={offset}", admin_user)
# 获取风控日志
logs = db_manager.get_risk_control_logs(cookie_id=cookie_id, limit=limit, offset=offset)
total_count = db_manager.get_risk_control_logs_count(cookie_id=cookie_id)
log_with_user('info', f"风控日志查询成功,共 {len(logs)} 条记录,总计 {total_count}", admin_user)
return {
"success": True,
"data": logs,
"total": total_count,
"limit": limit,
"offset": offset
}
except Exception as e:
log_with_user('error', f"查询风控日志失败: {str(e)}", admin_user)
return {"success": False, "message": f"查询失败: {str(e)}", "data": [], "total": 0}
@app.get('/admin/cookies')
def get_admin_cookies(admin_user: Dict[str, Any] = Depends(require_admin)):
"""获取所有Cookie信息管理员专用"""
try:
log_with_user('info', "查询所有Cookie信息", admin_user)
if cookie_manager.manager is None:
return {
"success": True,
"cookies": [],
"message": "CookieManager 未就绪"
}
# 获取所有用户的cookies
from db_manager import db_manager
all_users = db_manager.get_all_users()
all_cookies = []
for user in all_users:
user_id = user['id']
user_cookies = db_manager.get_all_cookies(user_id)
for cookie_id, cookie_value in user_cookies.items():
# 获取cookie详细信息
cookie_details = db_manager.get_cookie_details(cookie_id)
cookie_info = {
'cookie_id': cookie_id,
'user_id': user_id,
'username': user['username'],
'nickname': cookie_details.get('remark', '') if cookie_details else '',
'enabled': cookie_manager.manager.get_cookie_status(cookie_id)
}
all_cookies.append(cookie_info)
log_with_user('info', f"获取到 {len(all_cookies)} 个Cookie", admin_user)
return {
"success": True,
"cookies": all_cookies,
"total": len(all_cookies)
}
except Exception as e:
log_with_user('error', f"获取Cookie信息失败: {str(e)}", admin_user)
return {
"success": False,
"cookies": [],
"message": f"获取失败: {str(e)}"
}
@app.get('/admin/logs') @app.get('/admin/logs')
def get_system_logs(admin_user: Dict[str, Any] = Depends(require_admin), def get_system_logs(admin_user: Dict[str, Any] = Depends(require_admin),
lines: int = 100, lines: int = 100,