mirror of
https://github.com/hyb-oyqq/FRAISEMOE-Addons-Installer-NEXT.git
synced 2025-12-20 13:58:37 +00:00
feat(core): 集成日志记录功能以增强调试和错误处理
- 在多个模块中添加日志记录功能,替代原有的打印输出,提升调试信息的管理。 - 更新主窗口、下载管理器、离线模式管理器等,确保在关键操作中记录详细日志。 - 优化异常处理逻辑,确保在发生错误时能够记录相关信息,便于后续排查。 - 增强用户体验,通过日志记录提供更清晰的操作反馈和状态信息。
This commit is contained in:
@@ -6,6 +6,10 @@ from PySide6.QtGui import QIcon, QPixmap
|
|||||||
|
|
||||||
from utils import msgbox_frame, resource_path
|
from utils import msgbox_frame, resource_path
|
||||||
from workers import IpOptimizerThread
|
from workers import IpOptimizerThread
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("cloudflare_optimizer")
|
||||||
|
|
||||||
|
|
||||||
class CloudflareOptimizer:
|
class CloudflareOptimizer:
|
||||||
@@ -77,7 +81,7 @@ class CloudflareOptimizer:
|
|||||||
# 判断是否继续优选的逻辑
|
# 判断是否继续优选的逻辑
|
||||||
if existing_ips and self.has_optimized_in_session:
|
if existing_ips and self.has_optimized_in_session:
|
||||||
# 如果本次会话中已执行过优选且hosts中存在记录,则跳过优选过程
|
# 如果本次会话中已执行过优选且hosts中存在记录,则跳过优选过程
|
||||||
print(f"发现hosts文件中已有域名 {hostname} 的优选IP记录且本次会话已优选过,跳过优选过程")
|
logger.info(f"发现hosts文件中已有域名 {hostname} 的优选IP记录且本次会话已优选过,跳过优选过程")
|
||||||
|
|
||||||
# 设置标记为已优选完成
|
# 设置标记为已优选完成
|
||||||
self.optimization_done = True
|
self.optimization_done = True
|
||||||
@@ -92,12 +96,12 @@ class CloudflareOptimizer:
|
|||||||
if ipv6_entries:
|
if ipv6_entries:
|
||||||
self.optimized_ipv6 = ipv6_entries[0]
|
self.optimized_ipv6 = ipv6_entries[0]
|
||||||
|
|
||||||
print(f"使用已存在的优选IP - IPv4: {self.optimized_ip}, IPv6: {self.optimized_ipv6}")
|
logger.info(f"使用已存在的优选IP - IPv4: {self.optimized_ip}, IPv6: {self.optimized_ipv6}")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# 如果本次会话尚未优选过,或hosts中没有记录,则显示优选窗口
|
# 如果本次会话尚未优选过,或hosts中没有记录,则显示优选窗口
|
||||||
if existing_ips:
|
if existing_ips:
|
||||||
print(f"发现hosts文件中已有域名 {hostname} 的优选IP记录,但本次会话尚未优选过")
|
logger.info(f"发现hosts文件中已有域名 {hostname} 的优选IP记录,但本次会话尚未优选过")
|
||||||
# 清理已有的hosts记录,准备重新优选
|
# 清理已有的hosts记录,准备重新优选
|
||||||
self.hosts_manager.clean_hostname_entries(hostname)
|
self.hosts_manager.clean_hostname_entries(hostname)
|
||||||
|
|
||||||
@@ -175,7 +179,7 @@ class CloudflareOptimizer:
|
|||||||
|
|
||||||
# 如果启用IPv6,同时启动IPv6优化线程
|
# 如果启用IPv6,同时启动IPv6优化线程
|
||||||
if use_ipv6:
|
if use_ipv6:
|
||||||
print("IPv6已启用,将同时优选IPv6地址")
|
logger.info("IPv6已启用,将同时优选IPv6地址")
|
||||||
self.ipv6_optimizer_thread = IpOptimizerThread(url, use_ipv6=True)
|
self.ipv6_optimizer_thread = IpOptimizerThread(url, use_ipv6=True)
|
||||||
self.ipv6_optimizer_thread.finished.connect(self.on_ipv6_optimization_finished)
|
self.ipv6_optimizer_thread.finished.connect(self.on_ipv6_optimization_finished)
|
||||||
self.ipv6_optimizer_thread.start()
|
self.ipv6_optimizer_thread.start()
|
||||||
@@ -225,11 +229,11 @@ class CloudflareOptimizer:
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.optimized_ip = ip
|
self.optimized_ip = ip
|
||||||
print(f"IPv4优选完成,结果: {ip if ip else '未找到合适的IP'}")
|
logger.info(f"IPv4优选完成,结果: {ip if ip else '未找到合适的IP'}")
|
||||||
|
|
||||||
# 检查是否还有IPv6优化正在运行
|
# 检查是否还有IPv6优化正在运行
|
||||||
if hasattr(self, 'ipv6_optimizer_thread') and self.ipv6_optimizer_thread and self.ipv6_optimizer_thread.isRunning():
|
if hasattr(self, 'ipv6_optimizer_thread') and self.ipv6_optimizer_thread and self.ipv6_optimizer_thread.isRunning():
|
||||||
print("等待IPv6优选完成...")
|
logger.info("等待IPv6优选完成...")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 所有优选都已完成,继续处理
|
# 所有优选都已完成,继续处理
|
||||||
@@ -256,11 +260,11 @@ class CloudflareOptimizer:
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.optimized_ipv6 = ipv6
|
self.optimized_ipv6 = ipv6
|
||||||
print(f"IPv6优选完成,结果: {ipv6 if ipv6 else '未找到合适的IPv6'}")
|
logger.info(f"IPv6优选完成,结果: {ipv6 if ipv6 else '未找到合适的IPv6'}")
|
||||||
|
|
||||||
# 检查IPv4优化是否已完成
|
# 检查IPv4优化是否已完成
|
||||||
if hasattr(self, 'ip_optimizer_thread') and self.ip_optimizer_thread and self.ip_optimizer_thread.isRunning():
|
if hasattr(self, 'ip_optimizer_thread') and self.ip_optimizer_thread and self.ip_optimizer_thread.isRunning():
|
||||||
print("等待IPv4优选完成...")
|
logger.info("等待IPv4优选完成...")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 所有优选都已完成,继续处理
|
# 所有优选都已完成,继续处理
|
||||||
|
|||||||
@@ -2,8 +2,12 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
from data.config import LOG_FILE
|
from data.config import LOG_FILE
|
||||||
|
from utils.logger import setup_logger
|
||||||
from utils import Logger
|
from utils import Logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("debug_manager")
|
||||||
|
|
||||||
class DebugManager:
|
class DebugManager:
|
||||||
def __init__(self, main_window):
|
def __init__(self, main_window):
|
||||||
"""初始化调试管理器
|
"""初始化调试管理器
|
||||||
@@ -52,7 +56,7 @@ class DebugManager:
|
|||||||
Args:
|
Args:
|
||||||
checked: 是否启用调试模式
|
checked: 是否启用调试模式
|
||||||
"""
|
"""
|
||||||
print(f"Toggle debug mode: {checked}")
|
logger.info(f"Toggle debug mode: {checked}")
|
||||||
self.main_window.config["debug_mode"] = checked
|
self.main_window.config["debug_mode"] = checked
|
||||||
self.main_window.save_config(self.main_window.config)
|
self.main_window.save_config(self.main_window.config)
|
||||||
|
|
||||||
@@ -70,7 +74,7 @@ class DebugManager:
|
|||||||
|
|
||||||
# 如果配置中已设置离线模式,则在调试模式下强制启用
|
# 如果配置中已设置离线模式,则在调试模式下强制启用
|
||||||
if offline_mode_enabled:
|
if offline_mode_enabled:
|
||||||
print("DEBUG: 调试模式下强制启用离线模式")
|
logger.debug("DEBUG: 调试模式下强制启用离线模式")
|
||||||
self.main_window.offline_mode_manager.set_offline_mode(True)
|
self.main_window.offline_mode_manager.set_offline_mode(True)
|
||||||
|
|
||||||
# 更新UI中的离线模式选项
|
# 更新UI中的离线模式选项
|
||||||
@@ -79,7 +83,7 @@ class DebugManager:
|
|||||||
self.ui_manager.online_mode_action.setChecked(False)
|
self.ui_manager.online_mode_action.setChecked(False)
|
||||||
else:
|
else:
|
||||||
self.stop_logging()
|
self.stop_logging()
|
||||||
|
|
||||||
def start_logging(self):
|
def start_logging(self):
|
||||||
"""启动日志记录"""
|
"""启动日志记录"""
|
||||||
if self.logger is None:
|
if self.logger is None:
|
||||||
@@ -93,7 +97,7 @@ class DebugManager:
|
|||||||
self.logger = Logger(LOG_FILE, self.original_stdout)
|
self.logger = Logger(LOG_FILE, self.original_stdout)
|
||||||
sys.stdout = self.logger
|
sys.stdout = self.logger
|
||||||
sys.stderr = self.logger
|
sys.stderr = self.logger
|
||||||
print("--- Debug mode enabled ---")
|
logger.info("--- Debug mode enabled ---")
|
||||||
except (IOError, OSError) as e:
|
except (IOError, OSError) as e:
|
||||||
QtWidgets.QMessageBox.critical(self.main_window, "错误", f"无法创建日志文件: {e}")
|
QtWidgets.QMessageBox.critical(self.main_window, "错误", f"无法创建日志文件: {e}")
|
||||||
self.logger = None
|
self.logger = None
|
||||||
@@ -101,7 +105,7 @@ class DebugManager:
|
|||||||
def stop_logging(self):
|
def stop_logging(self):
|
||||||
"""停止日志记录"""
|
"""停止日志记录"""
|
||||||
if self.logger:
|
if self.logger:
|
||||||
print("--- Debug mode disabled ---")
|
logger.info("--- Debug mode disabled ---")
|
||||||
sys.stdout = self.original_stdout
|
sys.stdout = self.original_stdout
|
||||||
sys.stderr = self.original_stderr
|
sys.stderr = self.original_stderr
|
||||||
self.logger.close()
|
self.logger.close()
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ from workers import IpOptimizerThread
|
|||||||
from core.cloudflare_optimizer import CloudflareOptimizer
|
from core.cloudflare_optimizer import CloudflareOptimizer
|
||||||
from core.download_task_manager import DownloadTaskManager
|
from core.download_task_manager import DownloadTaskManager
|
||||||
from core.extraction_handler import ExtractionHandler
|
from core.extraction_handler import ExtractionHandler
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("download_manager")
|
||||||
|
|
||||||
class DownloadManager:
|
class DownloadManager:
|
||||||
def __init__(self, main_window):
|
def __init__(self, main_window):
|
||||||
@@ -67,8 +71,8 @@ class DownloadManager:
|
|||||||
install_path = os.path.join(game_dir, os.path.basename(info["install_path"]))
|
install_path = os.path.join(game_dir, os.path.basename(info["install_path"]))
|
||||||
install_paths[game] = install_path
|
install_paths[game] = install_path
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 使用识别到的游戏目录 {game}: {game_dir}")
|
logger.debug(f"DEBUG: 使用识别到的游戏目录 {game}: {game_dir}")
|
||||||
print(f"DEBUG: 安装路径设置为: {install_path}")
|
logger.debug(f"DEBUG: 安装路径设置为: {install_path}")
|
||||||
|
|
||||||
return install_paths
|
return install_paths
|
||||||
|
|
||||||
@@ -88,7 +92,7 @@ class DownloadManager:
|
|||||||
try:
|
try:
|
||||||
if self.main_window.cloud_config:
|
if self.main_window.cloud_config:
|
||||||
if self.is_debug_mode():
|
if self.is_debug_mode():
|
||||||
print("--- Using pre-fetched cloud config ---")
|
logger.info("--- Using pre-fetched cloud config ---")
|
||||||
config_data = self.main_window.cloud_config
|
config_data = self.main_window.cloud_config
|
||||||
else:
|
else:
|
||||||
headers = {"User-Agent": UA}
|
headers = {"User-Agent": UA}
|
||||||
@@ -102,7 +106,7 @@ class DownloadManager:
|
|||||||
if self.is_debug_mode():
|
if self.is_debug_mode():
|
||||||
# 创建安全版本的配置数据用于调试输出
|
# 创建安全版本的配置数据用于调试输出
|
||||||
safe_config = self._create_safe_config_for_logging(config_data)
|
safe_config = self._create_safe_config_for_logging(config_data)
|
||||||
print(f"DEBUG: Parsed JSON data: {json.dumps(safe_config, indent=2)}")
|
logger.debug(f"DEBUG: Parsed JSON data: {json.dumps(safe_config, indent=2)}")
|
||||||
|
|
||||||
urls = {}
|
urls = {}
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
@@ -138,8 +142,8 @@ class DownloadManager:
|
|||||||
safe_urls[key] = f"{domain}/***隐藏URL路径***"
|
safe_urls[key] = f"{domain}/***隐藏URL路径***"
|
||||||
else:
|
else:
|
||||||
safe_urls[key] = "***隐藏URL***"
|
safe_urls[key] = "***隐藏URL***"
|
||||||
print(f"DEBUG: Extracted URLs: {safe_urls}")
|
logger.debug(f"DEBUG: Extracted URLs: {safe_urls}")
|
||||||
print("--- Finished getting download URL successfully ---")
|
logger.info("--- Finished getting download URL successfully ---")
|
||||||
return urls
|
return urls
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
@@ -153,7 +157,7 @@ class DownloadManager:
|
|||||||
json_message = "配置文件异常,无法解析错误信息"
|
json_message = "配置文件异常,无法解析错误信息"
|
||||||
|
|
||||||
if self.is_debug_mode():
|
if self.is_debug_mode():
|
||||||
print(f"ERROR: Failed to get download config due to RequestException: {e}")
|
logger.error(f"ERROR: Failed to get download config due to RequestException: {e}")
|
||||||
|
|
||||||
QtWidgets.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
self.main_window,
|
self.main_window,
|
||||||
@@ -163,7 +167,7 @@ class DownloadManager:
|
|||||||
return {}
|
return {}
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
if self.is_debug_mode():
|
if self.is_debug_mode():
|
||||||
print(f"ERROR: Failed to parse download config due to ValueError: {e}")
|
logger.error(f"ERROR: Failed to parse download config due to ValueError: {e}")
|
||||||
|
|
||||||
QtWidgets.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
self.main_window,
|
self.main_window,
|
||||||
@@ -204,17 +208,17 @@ class DownloadManager:
|
|||||||
if hasattr(self.main_window, 'game_detector') and hasattr(self.main_window.game_detector, 'clear_directory_cache'):
|
if hasattr(self.main_window, 'game_detector') and hasattr(self.main_window.game_detector, 'clear_directory_cache'):
|
||||||
self.main_window.game_detector.clear_directory_cache()
|
self.main_window.game_detector.clear_directory_cache()
|
||||||
if self.is_debug_mode():
|
if self.is_debug_mode():
|
||||||
print("DEBUG: 已清除游戏目录缓存,确保获取最新状态")
|
logger.debug("DEBUG: 已清除游戏目录缓存,确保获取最新状态")
|
||||||
|
|
||||||
game_dirs = self.main_window.game_detector.identify_game_directories_improved(self.selected_folder)
|
game_dirs = self.main_window.game_detector.identify_game_directories_improved(self.selected_folder)
|
||||||
|
|
||||||
debug_mode = self.is_debug_mode()
|
debug_mode = self.is_debug_mode()
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 开始下载流程, 识别到 {len(game_dirs)} 个游戏目录")
|
logger.debug(f"DEBUG: 开始下载流程, 识别到 {len(game_dirs)} 个游戏目录")
|
||||||
|
|
||||||
if not game_dirs:
|
if not game_dirs:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 未识别到任何游戏目录,设置目录未找到错误")
|
logger.warning("DEBUG: 未识别到任何游戏目录,设置目录未找到错误")
|
||||||
self.main_window.last_error_message = "directory_not_found"
|
self.main_window.last_error_message = "directory_not_found"
|
||||||
QtWidgets.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self.main_window,
|
self.main_window,
|
||||||
@@ -259,18 +263,18 @@ class DownloadManager:
|
|||||||
# 检查游戏是否已安装补丁
|
# 检查游戏是否已安装补丁
|
||||||
if self.main_window.installed_status.get(game_version, False):
|
if self.main_window.installed_status.get(game_version, False):
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: {game_version} 已安装补丁,不需要再次安装")
|
logger.info(f"DEBUG: {game_version} 已安装补丁,不需要再次安装")
|
||||||
already_installed_games.append(game_version)
|
already_installed_games.append(game_version)
|
||||||
else:
|
else:
|
||||||
# 检查是否存在被禁用的补丁
|
# 检查是否存在被禁用的补丁
|
||||||
is_disabled, disabled_path = self.main_window.patch_manager.check_patch_disabled(game_dir, game_version)
|
is_disabled, disabled_path = self.main_window.patch_manager.check_patch_disabled(game_dir, game_version)
|
||||||
if is_disabled:
|
if is_disabled:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: {game_version} 存在被禁用的补丁: {disabled_path}")
|
logger.info(f"DEBUG: {game_version} 存在被禁用的补丁: {disabled_path}")
|
||||||
disabled_patch_games.append(game_version)
|
disabled_patch_games.append(game_version)
|
||||||
else:
|
else:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: {game_version} 未安装补丁,可以安装")
|
logger.info(f"DEBUG: {game_version} 未安装补丁,可以安装")
|
||||||
installable_games.append(game_version)
|
installable_games.append(game_version)
|
||||||
|
|
||||||
status_message = ""
|
status_message = ""
|
||||||
@@ -292,7 +296,7 @@ class DownloadManager:
|
|||||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||||
# 用户选择启用补丁
|
# 用户选择启用补丁
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 用户选择启用被禁用的补丁")
|
logger.debug(f"DEBUG: 用户选择启用被禁用的补丁")
|
||||||
|
|
||||||
# 为每个禁用的游戏创建目录映射
|
# 为每个禁用的游戏创建目录映射
|
||||||
disabled_game_dirs = {game: game_dirs[game] for game in disabled_patch_games}
|
disabled_game_dirs = {game: game_dirs[game] for game in disabled_patch_games}
|
||||||
@@ -315,7 +319,7 @@ class DownloadManager:
|
|||||||
already_installed_games.append(game_version)
|
already_installed_games.append(game_version)
|
||||||
else:
|
else:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 用户选择不启用被禁用的补丁,这些游戏将被添加到可安装列表")
|
logger.info(f"DEBUG: 用户选择不启用被禁用的补丁,这些游戏将被添加到可安装列表")
|
||||||
# 用户选择不启用,将这些游戏视为可以安装补丁
|
# 用户选择不启用,将这些游戏视为可以安装补丁
|
||||||
installable_games.extend(disabled_patch_games)
|
installable_games.extend(disabled_patch_games)
|
||||||
|
|
||||||
@@ -382,7 +386,7 @@ class DownloadManager:
|
|||||||
|
|
||||||
selected_games = [item.text() for item in list_widget.selectedItems()]
|
selected_games = [item.text() for item in list_widget.selectedItems()]
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 用户选择了以下游戏进行安装: {selected_games}")
|
logger.debug(f"DEBUG: 用户选择了以下游戏进行安装: {selected_games}")
|
||||||
|
|
||||||
selected_game_dirs = {game: game_dirs[game] for game in selected_games if game in game_dirs}
|
selected_game_dirs = {game: game_dirs[game] for game in selected_games if game in game_dirs}
|
||||||
|
|
||||||
@@ -395,7 +399,7 @@ class DownloadManager:
|
|||||||
|
|
||||||
if is_offline_mode:
|
if is_offline_mode:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 使用离线模式,跳过网络配置获取")
|
logger.info("DEBUG: 使用离线模式,跳过网络配置获取")
|
||||||
self._fill_offline_download_queue(selected_game_dirs)
|
self._fill_offline_download_queue(selected_game_dirs)
|
||||||
else:
|
else:
|
||||||
config = self.get_download_url()
|
config = self.get_download_url()
|
||||||
@@ -416,7 +420,7 @@ class DownloadManager:
|
|||||||
# 如果是离线模式,直接开始下一个下载任务
|
# 如果是离线模式,直接开始下一个下载任务
|
||||||
if is_offline_mode:
|
if is_offline_mode:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 离线模式,跳过Cloudflare优化")
|
logger.info("DEBUG: 离线模式,跳过Cloudflare优化")
|
||||||
self.next_download_task()
|
self.next_download_task()
|
||||||
else:
|
else:
|
||||||
self._show_cloudflare_option()
|
self._show_cloudflare_option()
|
||||||
@@ -435,7 +439,7 @@ class DownloadManager:
|
|||||||
|
|
||||||
debug_mode = self.is_debug_mode()
|
debug_mode = self.is_debug_mode()
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 填充下载队列, 游戏目录: {game_dirs}")
|
logger.debug(f"DEBUG: 填充下载队列, 游戏目录: {game_dirs}")
|
||||||
|
|
||||||
for i in range(1, 5):
|
for i in range(1, 5):
|
||||||
game_version = f"NEKOPARA Vol.{i}"
|
game_version = f"NEKOPARA Vol.{i}"
|
||||||
@@ -445,7 +449,7 @@ class DownloadManager:
|
|||||||
|
|
||||||
game_folder = game_dirs[game_version]
|
game_folder = game_dirs[game_version]
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 使用识别到的游戏目录 {game_version}: {game_folder}")
|
logger.debug(f"DEBUG: 使用识别到的游戏目录 {game_version}: {game_folder}")
|
||||||
|
|
||||||
_7z_path = os.path.join(PLUGIN, f"vol.{i}.7z")
|
_7z_path = os.path.join(PLUGIN, f"vol.{i}.7z")
|
||||||
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
||||||
@@ -458,7 +462,7 @@ class DownloadManager:
|
|||||||
if url:
|
if url:
|
||||||
game_folder = game_dirs[game_version]
|
game_folder = game_dirs[game_version]
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 使用识别到的游戏目录 {game_version}: {game_folder}")
|
logger.debug(f"DEBUG: 使用识别到的游戏目录 {game_version}: {game_folder}")
|
||||||
|
|
||||||
_7z_path = os.path.join(PLUGIN, "after.7z")
|
_7z_path = os.path.join(PLUGIN, "after.7z")
|
||||||
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
||||||
@@ -478,12 +482,12 @@ class DownloadManager:
|
|||||||
|
|
||||||
debug_mode = self.is_debug_mode()
|
debug_mode = self.is_debug_mode()
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 填充离线下载队列, 游戏目录: {game_dirs}")
|
logger.debug(f"DEBUG: 填充离线下载队列, 游戏目录: {game_dirs}")
|
||||||
|
|
||||||
# 检查是否有离线模式管理器
|
# 检查是否有离线模式管理器
|
||||||
if not hasattr(self.main_window, 'offline_mode_manager'):
|
if not hasattr(self.main_window, 'offline_mode_manager'):
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 离线模式管理器未初始化,无法使用离线模式")
|
logger.warning("DEBUG: 离线模式管理器未初始化,无法使用离线模式")
|
||||||
return
|
return
|
||||||
|
|
||||||
for i in range(1, 5):
|
for i in range(1, 5):
|
||||||
@@ -493,13 +497,13 @@ class DownloadManager:
|
|||||||
offline_patch_path = self.main_window.offline_mode_manager.get_offline_patch_path(game_version)
|
offline_patch_path = self.main_window.offline_mode_manager.get_offline_patch_path(game_version)
|
||||||
if not offline_patch_path:
|
if not offline_patch_path:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 未找到 {game_version} 的离线补丁文件,跳过")
|
logger.warning(f"DEBUG: 未找到 {game_version} 的离线补丁文件,跳过")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
game_folder = game_dirs[game_version]
|
game_folder = game_dirs[game_version]
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 使用识别到的游戏目录 {game_version}: {game_folder}")
|
logger.debug(f"DEBUG: 使用识别到的游戏目录 {game_version}: {game_folder}")
|
||||||
print(f"DEBUG: 使用离线补丁文件: {offline_patch_path}")
|
logger.debug(f"DEBUG: 使用离线补丁文件: {offline_patch_path}")
|
||||||
|
|
||||||
_7z_path = os.path.join(PLUGIN, f"vol.{i}.7z")
|
_7z_path = os.path.join(PLUGIN, f"vol.{i}.7z")
|
||||||
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
||||||
@@ -515,8 +519,8 @@ class DownloadManager:
|
|||||||
if offline_patch_path:
|
if offline_patch_path:
|
||||||
game_folder = game_dirs[game_version]
|
game_folder = game_dirs[game_version]
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 使用识别到的游戏目录 {game_version}: {game_folder}")
|
logger.debug(f"DEBUG: 使用识别到的游戏目录 {game_version}: {game_folder}")
|
||||||
print(f"DEBUG: 使用离线补丁文件: {offline_patch_path}")
|
logger.debug(f"DEBUG: 使用离线补丁文件: {offline_patch_path}")
|
||||||
|
|
||||||
_7z_path = os.path.join(PLUGIN, "after.7z")
|
_7z_path = os.path.join(PLUGIN, "after.7z")
|
||||||
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
plugin_path = os.path.join(PLUGIN, GAME_INFO[game_version]["plugin_path"])
|
||||||
@@ -525,7 +529,7 @@ class DownloadManager:
|
|||||||
self.download_queue.append((offline_patch_path, game_folder, game_version, _7z_path, plugin_path))
|
self.download_queue.append((offline_patch_path, game_folder, game_version, _7z_path, plugin_path))
|
||||||
self.main_window.download_queue_history.append(game_version)
|
self.main_window.download_queue_history.append(game_version)
|
||||||
elif debug_mode:
|
elif debug_mode:
|
||||||
print(f"DEBUG: 未找到 {game_version} 的离线补丁文件,跳过")
|
logger.warning(f"DEBUG: 未找到 {game_version} 的离线补丁文件,跳过")
|
||||||
|
|
||||||
def _show_cloudflare_option(self):
|
def _show_cloudflare_option(self):
|
||||||
"""显示Cloudflare加速选择对话框"""
|
"""显示Cloudflare加速选择对话框"""
|
||||||
@@ -537,7 +541,7 @@ class DownloadManager:
|
|||||||
existing_ips = self.cloudflare_optimizer.hosts_manager.get_hostname_entries(hostname)
|
existing_ips = self.cloudflare_optimizer.hosts_manager.get_hostname_entries(hostname)
|
||||||
|
|
||||||
if existing_ips:
|
if existing_ips:
|
||||||
print(f"发现hosts文件中已有域名 {hostname} 的优选IP记录,跳过询问直接使用")
|
logger.info(f"发现hosts文件中已有域名 {hostname} 的优选IP记录,跳过询问直接使用")
|
||||||
|
|
||||||
self.cloudflare_optimizer.optimization_done = True
|
self.cloudflare_optimizer.optimization_done = True
|
||||||
self.cloudflare_optimizer.countdown_finished = True
|
self.cloudflare_optimizer.countdown_finished = True
|
||||||
@@ -629,12 +633,12 @@ class DownloadManager:
|
|||||||
|
|
||||||
debug_mode = self.is_debug_mode()
|
debug_mode = self.is_debug_mode()
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 准备下载游戏 {game_version}")
|
logger.debug(f"DEBUG: 准备下载游戏 {game_version}")
|
||||||
print(f"DEBUG: 游戏文件夹: {game_folder}")
|
logger.debug(f"DEBUG: 游戏文件夹: {game_folder}")
|
||||||
|
|
||||||
# 隐藏敏感URL
|
# 隐藏敏感URL
|
||||||
safe_url = "***URL protection***" # 完全隐藏URL
|
safe_url = "***URL protection***" # 完全隐藏URL
|
||||||
print(f"DEBUG: 下载URL: {safe_url}")
|
logger.debug(f"DEBUG: 下载URL: {safe_url}")
|
||||||
|
|
||||||
game_exe_exists = True
|
game_exe_exists = True
|
||||||
|
|
||||||
@@ -643,9 +647,9 @@ class DownloadManager:
|
|||||||
or self.main_window.installed_status[game_version]
|
or self.main_window.installed_status[game_version]
|
||||||
):
|
):
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 跳过下载游戏 {game_version}")
|
logger.debug(f"DEBUG: 跳过下载游戏 {game_version}")
|
||||||
print(f"DEBUG: 游戏存在: {game_exe_exists}")
|
logger.debug(f"DEBUG: 游戏存在: {game_exe_exists}")
|
||||||
print(f"DEBUG: 已安装补丁: {self.main_window.installed_status[game_version]}")
|
logger.debug(f"DEBUG: 已安装补丁: {self.main_window.installed_status[game_version]}")
|
||||||
self.main_window.installed_status[game_version] = False if not game_exe_exists else True
|
self.main_window.installed_status[game_version] = False if not game_exe_exists else True
|
||||||
self.next_download_task()
|
self.next_download_task()
|
||||||
return
|
return
|
||||||
@@ -658,7 +662,7 @@ class DownloadManager:
|
|||||||
# 如果是离线模式且URL是本地文件路径
|
# 如果是离线模式且URL是本地文件路径
|
||||||
if is_offline_mode and os.path.isfile(url):
|
if is_offline_mode and os.path.isfile(url):
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 离线模式,复制本地补丁文件 {url} 到 {_7z_path}")
|
logger.debug(f"DEBUG: 离线模式,复制本地补丁文件 {url} 到 {_7z_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 确保目标目录存在
|
# 确保目标目录存在
|
||||||
@@ -672,24 +676,24 @@ class DownloadManager:
|
|||||||
hash_valid = False
|
hash_valid = False
|
||||||
if hasattr(self.main_window, 'offline_mode_manager'):
|
if hasattr(self.main_window, 'offline_mode_manager'):
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 开始验证补丁文件哈希: {_7z_path}")
|
logger.debug(f"DEBUG: 开始验证补丁文件哈希: {_7z_path}")
|
||||||
hash_valid = self.main_window.offline_mode_manager.verify_patch_hash(game_version, _7z_path)
|
hash_valid = self.main_window.offline_mode_manager.verify_patch_hash(game_version, _7z_path)
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 补丁文件哈希验证结果: {'成功' if hash_valid else '失败'}")
|
logger.debug(f"DEBUG: 补丁文件哈希验证结果: {'成功' if hash_valid else '失败'}")
|
||||||
else:
|
else:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 离线模式管理器不可用,跳过哈希验证")
|
logger.warning("DEBUG: 离线模式管理器不可用,跳过哈希验证")
|
||||||
hash_valid = True # 如果没有离线模式管理器,假设验证成功
|
hash_valid = True # 如果没有离线模式管理器,假设验证成功
|
||||||
|
|
||||||
if hash_valid:
|
if hash_valid:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 成功复制并验证补丁文件 {_7z_path}")
|
logger.info(f"DEBUG: 成功复制并验证补丁文件 {_7z_path}")
|
||||||
# 直接进入解压阶段
|
# 直接进入解压阶段
|
||||||
self.main_window.extraction_handler.start_extraction(_7z_path, game_folder, plugin_path, game_version)
|
self.main_window.extraction_handler.start_extraction(_7z_path, game_folder, plugin_path, game_version)
|
||||||
self.main_window.extraction_handler.extraction_finished.connect(self.on_extraction_finished)
|
self.main_window.extraction_handler.extraction_finished.connect(self.on_extraction_finished)
|
||||||
else:
|
else:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 补丁文件哈希验证失败")
|
logger.warning(f"DEBUG: 补丁文件哈希验证失败")
|
||||||
# 显示错误消息
|
# 显示错误消息
|
||||||
QtWidgets.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
self.main_window,
|
self.main_window,
|
||||||
@@ -700,7 +704,7 @@ class DownloadManager:
|
|||||||
self.next_download_task()
|
self.next_download_task()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 复制补丁文件失败: {e}")
|
logger.error(f"DEBUG: 复制补丁文件失败: {e}")
|
||||||
# 显示错误消息
|
# 显示错误消息
|
||||||
QtWidgets.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
self.main_window,
|
self.main_window,
|
||||||
@@ -715,9 +719,9 @@ class DownloadManager:
|
|||||||
|
|
||||||
self.optimized_ip = self.cloudflare_optimizer.get_optimized_ip()
|
self.optimized_ip = self.cloudflare_optimizer.get_optimized_ip()
|
||||||
if self.optimized_ip:
|
if self.optimized_ip:
|
||||||
print(f"已为 {game_version} 获取到优选IP: {self.optimized_ip}")
|
logger.info(f"已为 {game_version} 获取到优选IP: {self.optimized_ip}")
|
||||||
else:
|
else:
|
||||||
print(f"未能为 {game_version} 获取优选IP,将使用默认线路。")
|
logger.info(f"未能为 {game_version} 获取优选IP,将使用默认线路。")
|
||||||
|
|
||||||
self.download_task_manager.start_download(url, _7z_path, game_version, game_folder, plugin_path)
|
self.download_task_manager.start_download(url, _7z_path, game_version, game_folder, plugin_path)
|
||||||
|
|
||||||
@@ -738,9 +742,9 @@ class DownloadManager:
|
|||||||
self.main_window.progress_window = None
|
self.main_window.progress_window = None
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
print(f"--- Download Failed: {game_version} ---")
|
logger.error(f"--- Download Failed: {game_version} ---")
|
||||||
print(error)
|
logger.error(error)
|
||||||
print("------------------------------------")
|
logger.error("------------------------------------")
|
||||||
|
|
||||||
self.main_window.setEnabled(True)
|
self.main_window.setEnabled(True)
|
||||||
|
|
||||||
@@ -793,7 +797,7 @@ class DownloadManager:
|
|||||||
self.main_window.progress_window.reject()
|
self.main_window.progress_window.reject()
|
||||||
self.main_window.progress_window = None
|
self.main_window.progress_window = None
|
||||||
|
|
||||||
print("下载已全部停止。")
|
logger.info("下载已全部停止。")
|
||||||
|
|
||||||
self.main_window.setEnabled(True)
|
self.main_window.setEnabled(True)
|
||||||
self.main_window.ui.start_install_text.setText("开始安装")
|
self.main_window.ui.start_install_text.setText("开始安装")
|
||||||
|
|||||||
@@ -3,10 +3,15 @@ import hashlib
|
|||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import py7zr
|
import py7zr
|
||||||
|
import traceback
|
||||||
from PySide6.QtWidgets import QMessageBox
|
from PySide6.QtWidgets import QMessageBox
|
||||||
|
|
||||||
from data.config import PLUGIN, PLUGIN_HASH, GAME_INFO
|
from data.config import PLUGIN, PLUGIN_HASH, GAME_INFO
|
||||||
from utils import msgbox_frame
|
from utils import msgbox_frame
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("offline_mode_manager")
|
||||||
|
|
||||||
class OfflineModeManager:
|
class OfflineModeManager:
|
||||||
"""离线模式管理器,用于管理离线模式下的补丁安装和检测"""
|
"""离线模式管理器,用于管理离线模式下的补丁安装和检测"""
|
||||||
@@ -57,7 +62,7 @@ class OfflineModeManager:
|
|||||||
|
|
||||||
debug_mode = self._is_debug_mode()
|
debug_mode = self._is_debug_mode()
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 扫描离线补丁文件,目录: {directory}")
|
logger.debug(f"DEBUG: 扫描离线补丁文件,目录: {directory}")
|
||||||
|
|
||||||
# 要查找的补丁文件名
|
# 要查找的补丁文件名
|
||||||
patch_files = ["vol.1.7z", "vol.2.7z", "vol.3.7z", "vol.4.7z", "after.7z"]
|
patch_files = ["vol.1.7z", "vol.2.7z", "vol.3.7z", "vol.4.7z", "after.7z"]
|
||||||
@@ -72,7 +77,7 @@ class OfflineModeManager:
|
|||||||
patch_name = file.lower()
|
patch_name = file.lower()
|
||||||
found_patches[patch_name] = file_path
|
found_patches[patch_name] = file_path
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 找到离线补丁文件: {patch_name} 路径: {file_path}")
|
logger.debug(f"DEBUG: 找到离线补丁文件: {patch_name} 路径: {file_path}")
|
||||||
|
|
||||||
self.offline_patches = found_patches
|
self.offline_patches = found_patches
|
||||||
return found_patches
|
return found_patches
|
||||||
@@ -110,7 +115,7 @@ class OfflineModeManager:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 已启用离线模式(调试模式下允许强制启用)")
|
logger.debug("DEBUG: 已启用离线模式(调试模式下允许强制启用)")
|
||||||
|
|
||||||
self.is_offline_mode = enabled
|
self.is_offline_mode = enabled
|
||||||
|
|
||||||
@@ -125,7 +130,7 @@ class OfflineModeManager:
|
|||||||
self.main_window.ui.title_label.setText(f"{APP_NAME} v{APP_VERSION} {mode_indicator}")
|
self.main_window.ui.title_label.setText(f"{APP_NAME} v{APP_VERSION} {mode_indicator}")
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 离线模式已{'启用' if enabled else '禁用'}")
|
logger.debug(f"DEBUG: 离线模式已{'启用' if enabled else '禁用'}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -187,12 +192,12 @@ class OfflineModeManager:
|
|||||||
shutil.copy2(source_path, target_path)
|
shutil.copy2(source_path, target_path)
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 已复制离线补丁文件 {source_path} 到 {target_path}")
|
logger.debug(f"DEBUG: 已复制离线补丁文件 {source_path} 到 {target_path}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 复制离线补丁文件失败: {e}")
|
logger.error(f"DEBUG: 复制离线补丁文件失败: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def verify_patch_hash(self, game_version, file_path):
|
def verify_patch_hash(self, game_version, file_path):
|
||||||
@@ -220,66 +225,65 @@ class OfflineModeManager:
|
|||||||
expected_hash = PLUGIN_HASH.get("after", "")
|
expected_hash = PLUGIN_HASH.get("after", "")
|
||||||
|
|
||||||
if not expected_hash:
|
if not expected_hash:
|
||||||
print(f"DEBUG: 未找到 {game_version} 的预期哈希值")
|
logger.warning(f"DEBUG: 未找到 {game_version} 的预期哈希值")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
debug_mode = self._is_debug_mode()
|
debug_mode = self._is_debug_mode()
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 开始验证离线补丁文件: {file_path}")
|
logger.debug(f"DEBUG: 开始验证离线补丁文件: {file_path}")
|
||||||
print(f"DEBUG: 游戏版本: {game_version}")
|
logger.debug(f"DEBUG: 游戏版本: {game_version}")
|
||||||
print(f"DEBUG: 预期哈希值: {expected_hash}")
|
logger.debug(f"DEBUG: 预期哈希值: {expected_hash}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 检查文件是否存在
|
# 检查文件是否存在
|
||||||
if not os.path.exists(file_path):
|
if not os.path.exists(file_path):
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 补丁文件不存在: {file_path}")
|
logger.warning(f"DEBUG: 补丁文件不存在: {file_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 检查文件大小
|
# 检查文件大小
|
||||||
file_size = os.path.getsize(file_path)
|
file_size = os.path.getsize(file_path)
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 补丁文件大小: {file_size} 字节")
|
logger.debug(f"DEBUG: 补丁文件大小: {file_size} 字节")
|
||||||
|
|
||||||
if file_size == 0:
|
if file_size == 0:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 补丁文件大小为0,无效文件")
|
logger.warning(f"DEBUG: 补丁文件大小为0,无效文件")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 创建临时目录用于解压文件
|
# 创建临时目录用于解压文件
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 创建临时目录: {temp_dir}")
|
logger.debug(f"DEBUG: 创建临时目录: {temp_dir}")
|
||||||
|
|
||||||
# 解压补丁文件
|
# 解压补丁文件
|
||||||
try:
|
try:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 开始解压文件: {file_path}")
|
logger.debug(f"DEBUG: 开始解压文件: {file_path}")
|
||||||
|
|
||||||
with py7zr.SevenZipFile(file_path, mode="r") as archive:
|
with py7zr.SevenZipFile(file_path, mode="r") as archive:
|
||||||
# 获取压缩包内文件列表
|
# 获取压缩包内文件列表
|
||||||
file_list = archive.getnames()
|
file_list = archive.getnames()
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 压缩包内文件列表: {file_list}")
|
logger.debug(f"DEBUG: 压缩包内文件列表: {file_list}")
|
||||||
|
|
||||||
# 解压所有文件
|
# 解压所有文件
|
||||||
archive.extractall(path=temp_dir)
|
archive.extractall(path=temp_dir)
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 解压完成")
|
logger.debug(f"DEBUG: 解压完成")
|
||||||
# 列出解压后的文件
|
# 列出解压后的文件
|
||||||
extracted_files = []
|
extracted_files = []
|
||||||
for root, dirs, files in os.walk(temp_dir):
|
for root, dirs, files in os.walk(temp_dir):
|
||||||
for file in files:
|
for file in files:
|
||||||
extracted_files.append(os.path.join(root, file))
|
extracted_files.append(os.path.join(root, file))
|
||||||
print(f"DEBUG: 解压后的文件列表: {extracted_files}")
|
logger.debug(f"DEBUG: 解压后的文件列表: {extracted_files}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 解压补丁文件失败: {e}")
|
logger.error(f"DEBUG: 解压补丁文件失败: {e}")
|
||||||
print(f"DEBUG: 错误类型: {type(e).__name__}")
|
logger.error(f"DEBUG: 错误类型: {type(e).__name__}")
|
||||||
import traceback
|
logger.error(f"DEBUG: 错误堆栈: {traceback.format_exc()}")
|
||||||
print(f"DEBUG: 错误堆栈: {traceback.format_exc()}")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 获取补丁文件路径
|
# 获取补丁文件路径
|
||||||
@@ -297,7 +301,7 @@ class OfflineModeManager:
|
|||||||
|
|
||||||
if not patch_file or not os.path.exists(patch_file):
|
if not patch_file or not os.path.exists(patch_file):
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 未找到解压后的补丁文件: {patch_file}")
|
logger.warning(f"DEBUG: 未找到解压后的补丁文件: {patch_file}")
|
||||||
# 尝试查找可能的替代文件
|
# 尝试查找可能的替代文件
|
||||||
alternative_files = []
|
alternative_files = []
|
||||||
for root, dirs, files in os.walk(temp_dir):
|
for root, dirs, files in os.walk(temp_dir):
|
||||||
@@ -305,18 +309,18 @@ class OfflineModeManager:
|
|||||||
if file.endswith('.xp3') or file.endswith('.int'):
|
if file.endswith('.xp3') or file.endswith('.int'):
|
||||||
alternative_files.append(os.path.join(root, file))
|
alternative_files.append(os.path.join(root, file))
|
||||||
if alternative_files:
|
if alternative_files:
|
||||||
print(f"DEBUG: 找到可能的替代文件: {alternative_files}")
|
logger.debug(f"DEBUG: 找到可能的替代文件: {alternative_files}")
|
||||||
|
|
||||||
# 检查解压目录结构
|
# 检查解压目录结构
|
||||||
print(f"DEBUG: 检查解压目录结构:")
|
logger.debug(f"DEBUG: 检查解压目录结构:")
|
||||||
for root, dirs, files in os.walk(temp_dir):
|
for root, dirs, files in os.walk(temp_dir):
|
||||||
print(f"DEBUG: 目录: {root}")
|
logger.debug(f"DEBUG: 目录: {root}")
|
||||||
print(f"DEBUG: 子目录: {dirs}")
|
logger.debug(f"DEBUG: 子目录: {dirs}")
|
||||||
print(f"DEBUG: 文件: {files}")
|
logger.debug(f"DEBUG: 文件: {files}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 找到解压后的补丁文件: {patch_file}")
|
logger.debug(f"DEBUG: 找到解压后的补丁文件: {patch_file}")
|
||||||
|
|
||||||
# 计算补丁文件哈希值
|
# 计算补丁文件哈希值
|
||||||
try:
|
try:
|
||||||
@@ -327,22 +331,21 @@ class OfflineModeManager:
|
|||||||
result = file_hash.lower() == expected_hash.lower()
|
result = file_hash.lower() == expected_hash.lower()
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 补丁文件 {patch_file} 哈希值验证: {'成功' if result else '失败'}")
|
logger.debug(f"DEBUG: 补丁文件 {patch_file} 哈希值验证: {'成功' if result else '失败'}")
|
||||||
print(f"DEBUG: 预期哈希值: {expected_hash}")
|
logger.debug(f"DEBUG: 预期哈希值: {expected_hash}")
|
||||||
print(f"DEBUG: 实际哈希值: {file_hash}")
|
logger.debug(f"DEBUG: 实际哈希值: {file_hash}")
|
||||||
|
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 计算补丁文件哈希值失败: {e}")
|
logger.error(f"DEBUG: 计算补丁文件哈希值失败: {e}")
|
||||||
print(f"DEBUG: 错误类型: {type(e).__name__}")
|
logger.error(f"DEBUG: 错误类型: {type(e).__name__}")
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 验证补丁哈希值失败: {e}")
|
logger.error(f"DEBUG: 验证补丁哈希值失败: {e}")
|
||||||
print(f"DEBUG: 错误类型: {type(e).__name__}")
|
logger.error(f"DEBUG: 错误类型: {type(e).__name__}")
|
||||||
import traceback
|
logger.error(f"DEBUG: 错误堆栈: {traceback.format_exc()}")
|
||||||
print(f"DEBUG: 错误堆栈: {traceback.format_exc()}")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_offline_mode_available(self):
|
def is_offline_mode_available(self):
|
||||||
@@ -378,11 +381,11 @@ class OfflineModeManager:
|
|||||||
debug_mode = self._is_debug_mode()
|
debug_mode = self._is_debug_mode()
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 开始离线安装流程,选择的游戏: {selected_games}")
|
logger.debug(f"DEBUG: 开始离线安装流程,选择的游戏: {selected_games}")
|
||||||
|
|
||||||
if not self.is_in_offline_mode():
|
if not self.is_in_offline_mode():
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 当前不是离线模式,无法使用离线安装")
|
logger.warning("DEBUG: 当前不是离线模式,无法使用离线安装")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 确保已扫描过补丁文件
|
# 确保已扫描过补丁文件
|
||||||
@@ -391,7 +394,7 @@ class OfflineModeManager:
|
|||||||
|
|
||||||
if not self.offline_patches:
|
if not self.offline_patches:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 未找到任何离线补丁文件")
|
logger.warning("DEBUG: 未找到任何离线补丁文件")
|
||||||
msgbox_frame(
|
msgbox_frame(
|
||||||
f"离线安装错误 - {self.app_name}",
|
f"离线安装错误 - {self.app_name}",
|
||||||
"\n未找到任何离线补丁文件,无法进行离线安装。\n\n请将补丁文件放置在软件所在目录后再尝试。\n",
|
"\n未找到任何离线补丁文件,无法进行离线安装。\n\n请将补丁文件放置在软件所在目录后再尝试。\n",
|
||||||
@@ -406,7 +409,7 @@ class OfflineModeManager:
|
|||||||
|
|
||||||
if not game_dirs:
|
if not game_dirs:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 未识别到任何游戏目录")
|
logger.warning("DEBUG: 未识别到任何游戏目录")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 显示文件检验窗口
|
# 显示文件检验窗口
|
||||||
@@ -453,11 +456,11 @@ class OfflineModeManager:
|
|||||||
if self.get_offline_patch_path(game_version):
|
if self.get_offline_patch_path(game_version):
|
||||||
installable_games.append(game_version)
|
installable_games.append(game_version)
|
||||||
elif debug_mode:
|
elif debug_mode:
|
||||||
print(f"DEBUG: 未找到 {game_version} 的离线补丁文件,跳过")
|
logger.warning(f"DEBUG: 未找到 {game_version} 的离线补丁文件,跳过")
|
||||||
|
|
||||||
if not installable_games:
|
if not installable_games:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 没有需要安装的游戏或未找到对应的离线补丁")
|
logger.info("DEBUG: 没有需要安装的游戏或未找到对应的离线补丁")
|
||||||
msgbox_frame(
|
msgbox_frame(
|
||||||
f"离线安装信息 - {self.app_name}",
|
f"离线安装信息 - {self.app_name}",
|
||||||
"\n没有需要安装的游戏或未找到对应的离线补丁文件。\n",
|
"\n没有需要安装的游戏或未找到对应的离线补丁文件。\n",
|
||||||
@@ -468,7 +471,7 @@ class OfflineModeManager:
|
|||||||
|
|
||||||
# 开始安装流程
|
# 开始安装流程
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 开始离线安装流程,安装游戏: {installable_games}")
|
logger.info(f"DEBUG: 开始离线安装流程,安装游戏: {installable_games}")
|
||||||
|
|
||||||
# 创建安装任务列表
|
# 创建安装任务列表
|
||||||
install_tasks = []
|
install_tasks = []
|
||||||
@@ -522,7 +525,7 @@ class OfflineModeManager:
|
|||||||
if not install_tasks:
|
if not install_tasks:
|
||||||
# 所有任务完成,进行后检查
|
# 所有任务完成,进行后检查
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 所有离线安装任务完成,进行后检查")
|
logger.info("DEBUG: 所有离线安装任务完成,进行后检查")
|
||||||
self.main_window.after_hash_compare()
|
self.main_window.after_hash_compare()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -530,9 +533,9 @@ class OfflineModeManager:
|
|||||||
patch_file, game_folder, game_version, _7z_path, plugin_path = install_tasks.pop(0)
|
patch_file, game_folder, game_version, _7z_path, plugin_path = install_tasks.pop(0)
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 处理离线安装任务: {game_version}")
|
logger.debug(f"DEBUG: 处理离线安装任务: {game_version}")
|
||||||
print(f"DEBUG: 补丁文件: {patch_file}")
|
logger.debug(f"DEBUG: 补丁文件: {patch_file}")
|
||||||
print(f"DEBUG: 游戏目录: {game_folder}")
|
logger.debug(f"DEBUG: 游戏目录: {game_folder}")
|
||||||
|
|
||||||
# 确保目标目录存在
|
# 确保目标目录存在
|
||||||
os.makedirs(os.path.dirname(_7z_path), exist_ok=True)
|
os.makedirs(os.path.dirname(_7z_path), exist_ok=True)
|
||||||
@@ -542,8 +545,8 @@ class OfflineModeManager:
|
|||||||
shutil.copy2(patch_file, _7z_path)
|
shutil.copy2(patch_file, _7z_path)
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 已复制补丁文件到缓存目录: {_7z_path}")
|
logger.debug(f"DEBUG: 已复制补丁文件到缓存目录: {_7z_path}")
|
||||||
print(f"DEBUG: 开始验证补丁文件哈希值")
|
logger.debug(f"DEBUG: 开始验证补丁文件哈希值")
|
||||||
|
|
||||||
# 获取预期的哈希值
|
# 获取预期的哈希值
|
||||||
expected_hash = None
|
expected_hash = None
|
||||||
@@ -559,7 +562,7 @@ class OfflineModeManager:
|
|||||||
expected_hash = PLUGIN_HASH.get("after", "")
|
expected_hash = PLUGIN_HASH.get("after", "")
|
||||||
|
|
||||||
if debug_mode and expected_hash:
|
if debug_mode and expected_hash:
|
||||||
print(f"DEBUG: 预期哈希值: {expected_hash}")
|
logger.debug(f"DEBUG: 预期哈希值: {expected_hash}")
|
||||||
|
|
||||||
# 显示哈希验证窗口 - 使用离线特定消息
|
# 显示哈希验证窗口 - 使用离线特定消息
|
||||||
self.main_window.hash_msg_box = self.main_window.hash_manager.hash_pop_window(check_type="offline_verify", is_offline=True)
|
self.main_window.hash_msg_box = self.main_window.hash_manager.hash_pop_window(check_type="offline_verify", is_offline=True)
|
||||||
@@ -574,7 +577,7 @@ class OfflineModeManager:
|
|||||||
|
|
||||||
if hash_valid:
|
if hash_valid:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 补丁文件哈希验证成功,开始解压")
|
logger.info(f"DEBUG: 补丁文件哈希验证成功,开始解压")
|
||||||
|
|
||||||
# 显示解压窗口 - 使用离线特定消息
|
# 显示解压窗口 - 使用离线特定消息
|
||||||
self.main_window.hash_msg_box = self.main_window.hash_manager.hash_pop_window(check_type="offline_extraction", is_offline=True)
|
self.main_window.hash_msg_box = self.main_window.hash_manager.hash_pop_window(check_type="offline_extraction", is_offline=True)
|
||||||
@@ -596,7 +599,7 @@ class OfflineModeManager:
|
|||||||
extraction_thread.start()
|
extraction_thread.start()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 创建或启动解压线程失败: {e}")
|
logger.error(f"DEBUG: 创建或启动解压线程失败: {e}")
|
||||||
|
|
||||||
# 关闭解压窗口
|
# 关闭解压窗口
|
||||||
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
if self.main_window.hash_msg_box and self.main_window.hash_msg_box.isVisible():
|
||||||
@@ -614,7 +617,7 @@ class OfflineModeManager:
|
|||||||
self.process_next_offline_install_task(install_tasks)
|
self.process_next_offline_install_task(install_tasks)
|
||||||
else:
|
else:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 补丁文件哈希验证失败")
|
logger.warning(f"DEBUG: 补丁文件哈希验证失败")
|
||||||
|
|
||||||
# 显示错误消息
|
# 显示错误消息
|
||||||
msgbox_frame(
|
msgbox_frame(
|
||||||
@@ -627,7 +630,7 @@ class OfflineModeManager:
|
|||||||
self.process_next_offline_install_task(install_tasks)
|
self.process_next_offline_install_task(install_tasks)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 离线安装任务处理失败: {e}")
|
logger.error(f"DEBUG: 离线安装任务处理失败: {e}")
|
||||||
|
|
||||||
# 显示错误消息
|
# 显示错误消息
|
||||||
msgbox_frame(
|
msgbox_frame(
|
||||||
@@ -656,9 +659,9 @@ class OfflineModeManager:
|
|||||||
self.main_window.hash_msg_box = None
|
self.main_window.hash_msg_box = None
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 离线解压完成,状态: {'成功' if success else '失败'}")
|
logger.debug(f"DEBUG: 离线解压完成,状态: {'成功' if success else '失败'}")
|
||||||
if not success:
|
if not success:
|
||||||
print(f"DEBUG: 错误信息: {error_message}")
|
logger.error(f"DEBUG: 错误信息: {error_message}")
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
# 显示错误消息
|
# 显示错误消息
|
||||||
@@ -686,7 +689,7 @@ class OfflineModeManager:
|
|||||||
debug_mode = self._is_debug_mode()
|
debug_mode = self._is_debug_mode()
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print("DEBUG: 离线解压完成,继续处理下一个任务")
|
logger.debug("DEBUG: 离线解压完成,继续处理下一个任务")
|
||||||
|
|
||||||
# 处理下一个任务
|
# 处理下一个任务
|
||||||
self.process_next_offline_install_task(remaining_tasks)
|
self.process_next_offline_install_task(remaining_tasks)
|
||||||
@@ -5,6 +5,10 @@ import os
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("privacy_policy")
|
||||||
|
|
||||||
# 隐私协议的缩略版内容
|
# 隐私协议的缩略版内容
|
||||||
PRIVACY_POLICY_BRIEF = """
|
PRIVACY_POLICY_BRIEF = """
|
||||||
@@ -83,14 +87,14 @@ def get_local_privacy_policy():
|
|||||||
try:
|
try:
|
||||||
date_obj = datetime.strptime(date_str, '%Y年%m月%d日')
|
date_obj = datetime.strptime(date_str, '%Y年%m月%d日')
|
||||||
date_version = date_obj.strftime('%Y.%m.%d')
|
date_version = date_obj.strftime('%Y.%m.%d')
|
||||||
print(f"成功读取本地隐私协议文件: {path}, 版本: {date_version}")
|
logger.info(f"成功读取本地隐私协议文件: {path}, 版本: {date_version}")
|
||||||
return content, date_version, ""
|
return content, date_version, ""
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print(f"本地隐私协议日期格式解析错误: {path}")
|
logger.error(f"本地隐私协议日期格式解析错误: {path}")
|
||||||
else:
|
else:
|
||||||
print(f"本地隐私协议未找到更新日期: {path}")
|
logger.warning(f"本地隐私协议未找到更新日期: {path}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"读取本地隐私协议失败 {path}: {str(e)}")
|
logger.error(f"读取本地隐私协议失败 {path}: {str(e)}")
|
||||||
|
|
||||||
# 所有路径都尝试失败,使用默认版本
|
# 所有路径都尝试失败,使用默认版本
|
||||||
return PRIVACY_POLICY_BRIEF, PRIVACY_POLICY_VERSION, "无法读取本地隐私协议文件"
|
return PRIVACY_POLICY_BRIEF, PRIVACY_POLICY_VERSION, "无法读取本地隐私协议文件"
|
||||||
@@ -6,6 +6,10 @@ from PySide6.QtWidgets import (
|
|||||||
from PySide6.QtCore import QObject
|
from PySide6.QtCore import QObject
|
||||||
from PySide6.QtGui import QFont
|
from PySide6.QtGui import QFont
|
||||||
from utils import msgbox_frame
|
from utils import msgbox_frame
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("patch_toggle_handler")
|
||||||
|
|
||||||
class PatchToggleHandler(QObject):
|
class PatchToggleHandler(QObject):
|
||||||
"""
|
"""
|
||||||
@@ -41,7 +45,7 @@ class PatchToggleHandler(QObject):
|
|||||||
return # 用户取消了选择
|
return # 用户取消了选择
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 禁/启用功能 - 用户选择了目录: {selected_folder}")
|
logger.debug(f"DEBUG: 禁/启用功能 - 用户选择了目录: {selected_folder}")
|
||||||
|
|
||||||
# 首先尝试将选择的目录视为上级目录,使用增强的目录识别功能
|
# 首先尝试将选择的目录视为上级目录,使用增强的目录识别功能
|
||||||
game_dirs = self.game_detector.identify_game_directories_improved(selected_folder)
|
game_dirs = self.game_detector.identify_game_directories_improved(selected_folder)
|
||||||
@@ -60,7 +64,7 @@ class PatchToggleHandler(QObject):
|
|||||||
debug_mode: 是否为调试模式
|
debug_mode: 是否为调试模式
|
||||||
"""
|
"""
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 禁/启用功能 - 在上级目录中找到以下游戏: {list(game_dirs.keys())}")
|
logger.debug(f"DEBUG: 禁/启用功能 - 在上级目录中找到以下游戏: {list(game_dirs.keys())}")
|
||||||
|
|
||||||
# 查找已安装补丁的游戏,只处理那些已安装补丁的游戏
|
# 查找已安装补丁的游戏,只处理那些已安装补丁的游戏
|
||||||
games_with_patch = {}
|
games_with_patch = {}
|
||||||
@@ -75,7 +79,7 @@ class PatchToggleHandler(QObject):
|
|||||||
"status": status
|
"status": status
|
||||||
}
|
}
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 禁/启用功能 - {game_version} 已安装补丁,当前状态: {status}")
|
logger.debug(f"DEBUG: 禁/启用功能 - {game_version} 已安装补丁,当前状态: {status}")
|
||||||
|
|
||||||
# 检查是否有已安装补丁的游戏
|
# 检查是否有已安装补丁的游戏
|
||||||
if not games_with_patch:
|
if not games_with_patch:
|
||||||
@@ -126,13 +130,13 @@ class PatchToggleHandler(QObject):
|
|||||||
"""
|
"""
|
||||||
# 未找到游戏目录,尝试将选择的目录作为游戏目录
|
# 未找到游戏目录,尝试将选择的目录作为游戏目录
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 禁/启用功能 - 未在上级目录找到游戏,尝试将选择的目录视为游戏目录")
|
logger.debug(f"DEBUG: 禁/启用功能 - 未在上级目录找到游戏,尝试将选择的目录视为游戏目录")
|
||||||
|
|
||||||
game_version = self.game_detector.identify_game_version(selected_folder)
|
game_version = self.game_detector.identify_game_version(selected_folder)
|
||||||
|
|
||||||
if game_version:
|
if game_version:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 禁/启用功能 - 识别为游戏: {game_version}")
|
logger.debug(f"DEBUG: 禁/启用功能 - 识别为游戏: {game_version}")
|
||||||
|
|
||||||
# 检查是否已安装补丁
|
# 检查是否已安装补丁
|
||||||
if self.patch_manager.check_patch_installed(selected_folder, game_version):
|
if self.patch_manager.check_patch_installed(selected_folder, game_version):
|
||||||
@@ -162,7 +166,7 @@ class PatchToggleHandler(QObject):
|
|||||||
else:
|
else:
|
||||||
# 两种方式都未识别到游戏
|
# 两种方式都未识别到游戏
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 禁/启用功能 - 无法识别游戏")
|
logger.debug(f"DEBUG: 禁/启用功能 - 无法识别游戏")
|
||||||
|
|
||||||
msg_box = msgbox_frame(
|
msg_box = msgbox_frame(
|
||||||
f"错误 - {self.app_name}",
|
f"错误 - {self.app_name}",
|
||||||
@@ -380,7 +384,7 @@ class PatchToggleHandler(QObject):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 切换 {game_version} 补丁状态时出错: {str(e)}")
|
logger.error(f"DEBUG: 切换 {game_version} 补丁状态时出错: {str(e)}")
|
||||||
fail_count += 1
|
fail_count += 1
|
||||||
results.append({
|
results.append({
|
||||||
"version": game_version,
|
"version": game_version,
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ from PySide6.QtWidgets import (
|
|||||||
from PySide6.QtCore import QObject
|
from PySide6.QtCore import QObject
|
||||||
from PySide6.QtGui import QFont
|
from PySide6.QtGui import QFont
|
||||||
from utils import msgbox_frame
|
from utils import msgbox_frame
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("uninstall_handler")
|
||||||
|
|
||||||
class UninstallHandler(QObject):
|
class UninstallHandler(QObject):
|
||||||
"""
|
"""
|
||||||
@@ -41,7 +45,7 @@ class UninstallHandler(QObject):
|
|||||||
return # 用户取消了选择
|
return # 用户取消了选择
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 卸载功能 - 用户选择了目录: {selected_folder}")
|
logger.debug(f"DEBUG: 卸载功能 - 用户选择了目录: {selected_folder}")
|
||||||
|
|
||||||
# 首先尝试将选择的目录视为上级目录,使用增强的目录识别功能
|
# 首先尝试将选择的目录视为上级目录,使用增强的目录识别功能
|
||||||
game_dirs = self.game_detector.identify_game_directories_improved(selected_folder)
|
game_dirs = self.game_detector.identify_game_directories_improved(selected_folder)
|
||||||
@@ -60,7 +64,7 @@ class UninstallHandler(QObject):
|
|||||||
debug_mode: 是否为调试模式
|
debug_mode: 是否为调试模式
|
||||||
"""
|
"""
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 卸载功能 - 在上级目录中找到以下游戏: {list(game_dirs.keys())}")
|
logger.debug(f"DEBUG: 卸载功能 - 在上级目录中找到以下游戏: {list(game_dirs.keys())}")
|
||||||
|
|
||||||
# 查找已安装补丁的游戏,只处理那些已安装补丁的游戏
|
# 查找已安装补丁的游戏,只处理那些已安装补丁的游戏
|
||||||
games_with_patch = {}
|
games_with_patch = {}
|
||||||
@@ -68,7 +72,7 @@ class UninstallHandler(QObject):
|
|||||||
if self.patch_manager.check_patch_installed(game_dir, game_version):
|
if self.patch_manager.check_patch_installed(game_dir, game_version):
|
||||||
games_with_patch[game_version] = game_dir
|
games_with_patch[game_version] = game_dir
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 卸载功能 - {game_version} 已安装补丁")
|
logger.debug(f"DEBUG: 卸载功能 - {game_version} 已安装补丁")
|
||||||
|
|
||||||
# 检查是否有已安装补丁的游戏
|
# 检查是否有已安装补丁的游戏
|
||||||
if not games_with_patch:
|
if not games_with_patch:
|
||||||
@@ -116,13 +120,13 @@ class UninstallHandler(QObject):
|
|||||||
"""
|
"""
|
||||||
# 未找到游戏目录,尝试将选择的目录作为游戏目录
|
# 未找到游戏目录,尝试将选择的目录作为游戏目录
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 卸载功能 - 未在上级目录找到游戏,尝试将选择的目录视为游戏目录")
|
logger.debug(f"DEBUG: 卸载功能 - 未在上级目录找到游戏,尝试将选择的目录视为游戏目录")
|
||||||
|
|
||||||
game_version = self.game_detector.identify_game_version(selected_folder)
|
game_version = self.game_detector.identify_game_version(selected_folder)
|
||||||
|
|
||||||
if game_version:
|
if game_version:
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 卸载功能 - 识别为游戏: {game_version}")
|
logger.debug(f"DEBUG: 卸载功能 - 识别为游戏: {game_version}")
|
||||||
|
|
||||||
# 检查是否已安装补丁
|
# 检查是否已安装补丁
|
||||||
if self.patch_manager.check_patch_installed(selected_folder, game_version):
|
if self.patch_manager.check_patch_installed(selected_folder, game_version):
|
||||||
@@ -151,7 +155,7 @@ class UninstallHandler(QObject):
|
|||||||
else:
|
else:
|
||||||
# 两种方式都未识别到游戏
|
# 两种方式都未识别到游戏
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 卸载功能 - 无法识别游戏")
|
logger.debug(f"DEBUG: 卸载功能 - 无法识别游戏")
|
||||||
|
|
||||||
msg_box = msgbox_frame(
|
msg_box = msgbox_frame(
|
||||||
f"错误 - {self.app_name}",
|
f"错误 - {self.app_name}",
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ from core import (
|
|||||||
)
|
)
|
||||||
from core.ipv6_manager import IPv6Manager
|
from core.ipv6_manager import IPv6Manager
|
||||||
from handlers import PatchToggleHandler, UninstallHandler
|
from handlers import PatchToggleHandler, UninstallHandler
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("main_window")
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -768,77 +772,52 @@ class MainWindow(QMainWindow):
|
|||||||
self.download_manager.file_dialog()
|
self.download_manager.file_dialog()
|
||||||
|
|
||||||
def check_and_set_offline_mode(self):
|
def check_and_set_offline_mode(self):
|
||||||
"""检查是否有离线补丁文件,如果有则自动切换到离线模式"""
|
"""检查是否有离线补丁文件,如果有则自动启用离线模式
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功切换到离线模式
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# 检查是否有离线补丁文件
|
# 初始化离线模式管理器
|
||||||
has_offline_patches = self.offline_mode_manager.has_offline_patches()
|
if not hasattr(self, 'offline_mode_manager') or self.offline_mode_manager is None:
|
||||||
|
from core.offline_mode_manager import OfflineModeManager
|
||||||
|
self.offline_mode_manager = OfflineModeManager(self)
|
||||||
|
|
||||||
# 获取调试模式状态
|
# 扫描离线补丁文件
|
||||||
debug_mode = False
|
self.offline_mode_manager.scan_for_offline_patches()
|
||||||
if hasattr(self.debug_manager, '_is_debug_mode'):
|
|
||||||
debug_mode = self.debug_manager._is_debug_mode()
|
|
||||||
|
|
||||||
# 检查配置中是否已设置离线模式
|
# 如果找到离线补丁文件,启用离线模式
|
||||||
offline_mode_enabled = False
|
if self.offline_mode_manager.has_offline_patches():
|
||||||
if isinstance(self.config, dict):
|
|
||||||
offline_mode_enabled = self.config.get("offline_mode", False)
|
|
||||||
|
|
||||||
# 如果有离线补丁文件或者调试模式下强制启用离线模式
|
|
||||||
if has_offline_patches or (debug_mode and offline_mode_enabled):
|
|
||||||
# 设置离线模式
|
|
||||||
self.offline_mode_manager.set_offline_mode(True)
|
self.offline_mode_manager.set_offline_mode(True)
|
||||||
|
|
||||||
# 更新UI中的离线模式选项
|
# 启用开始安装按钮
|
||||||
if hasattr(self.ui_manager, 'offline_mode_action') and self.ui_manager.offline_mode_action:
|
|
||||||
self.ui_manager.offline_mode_action.setChecked(True)
|
|
||||||
self.ui_manager.online_mode_action.setChecked(False)
|
|
||||||
|
|
||||||
# 更新配置
|
|
||||||
self.config["offline_mode"] = True
|
|
||||||
self.save_config(self.config)
|
|
||||||
|
|
||||||
# 在离线模式下始终启用开始安装按钮
|
|
||||||
self.set_start_button_enabled(True)
|
self.set_start_button_enabled(True)
|
||||||
|
|
||||||
# 清除版本警告标志
|
logger.debug(f"DEBUG: 已自动切换到离线模式,找到离线补丁文件: {list(self.offline_mode_manager.offline_patches.keys())}")
|
||||||
self.version_warning = False
|
logger.debug(f"DEBUG: 离线模式下启用开始安装按钮")
|
||||||
|
return True
|
||||||
if debug_mode:
|
|
||||||
print(f"DEBUG: 已自动切换到离线模式,找到离线补丁文件: {list(self.offline_mode_manager.offline_patches.keys())}")
|
|
||||||
print(f"DEBUG: 离线模式下启用开始安装按钮")
|
|
||||||
else:
|
else:
|
||||||
# 如果没有离线补丁文件,确保使用在线模式
|
# 如果没有找到离线补丁文件,禁用离线模式
|
||||||
self.offline_mode_manager.set_offline_mode(False)
|
self.offline_mode_manager.set_offline_mode(False)
|
||||||
|
|
||||||
# 更新UI中的在线模式选项
|
# 检查是否有云端配置,如果没有则禁用开始安装按钮
|
||||||
if hasattr(self.ui_manager, 'online_mode_action') and self.ui_manager.online_mode_action:
|
if not self.config_valid:
|
||||||
self.ui_manager.online_mode_action.setChecked(True)
|
self.set_start_button_enabled(False)
|
||||||
self.ui_manager.offline_mode_action.setChecked(False)
|
|
||||||
|
|
||||||
# 更新配置
|
|
||||||
self.config["offline_mode"] = False
|
|
||||||
self.save_config(self.config)
|
|
||||||
|
|
||||||
# 如果当前版本过低,设置版本警告标志
|
logger.debug("DEBUG: 未找到离线补丁文件,使用在线模式")
|
||||||
if hasattr(self, 'last_error_message') and self.last_error_message == "update_required":
|
return False
|
||||||
# 设置版本警告标志
|
|
||||||
self.version_warning = True
|
|
||||||
|
|
||||||
if debug_mode:
|
|
||||||
print("DEBUG: 未找到离线补丁文件,使用在线模式")
|
|
||||||
|
|
||||||
# 确保标题标签显示正确的模式
|
|
||||||
if hasattr(self, 'ui') and hasattr(self.ui, 'title_label'):
|
|
||||||
from data.config import APP_NAME, APP_VERSION
|
|
||||||
mode_indicator = "[离线模式]" if self.offline_mode_manager.is_in_offline_mode() else "[在线模式]"
|
|
||||||
self.ui.title_label.setText(f"{APP_NAME} v{APP_VERSION} {mode_indicator}")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 捕获任何异常,确保程序不会崩溃
|
# 如果出现异常,禁用离线模式
|
||||||
print(f"错误: 检查离线模式时发生异常: {e}")
|
if hasattr(self, 'offline_mode_manager') and self.offline_mode_manager is not None:
|
||||||
# 默认使用在线模式
|
self.offline_mode_manager.set_offline_mode(False)
|
||||||
if hasattr(self, 'offline_mode_manager'):
|
|
||||||
self.offline_mode_manager.is_offline_mode = False
|
# 检查是否有云端配置,如果没有则禁用开始安装按钮
|
||||||
|
if not self.config_valid:
|
||||||
|
self.set_start_button_enabled(False)
|
||||||
|
|
||||||
|
logger.error(f"错误: 检查离线模式时发生异常: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def select_all_games(self, game_checkboxes, checked):
|
def select_all_games(self, game_checkboxes, checked):
|
||||||
"""选择或取消选择所有游戏
|
"""选择或取消选择所有游戏
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
from .logger import Logger
|
from .logger import Logger
|
||||||
|
from .url_censor import censor_url
|
||||||
from .helpers import (
|
from .helpers import (
|
||||||
load_base64_image, HashManager, AdminPrivileges, msgbox_frame,
|
load_base64_image, HashManager, AdminPrivileges, msgbox_frame,
|
||||||
load_config, save_config, HostsManager, censor_url, resource_path,
|
load_config, save_config, HostsManager, resource_path,
|
||||||
load_image_from_file
|
load_image_from_file
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ from PySide6 import QtCore, QtWidgets
|
|||||||
import re
|
import re
|
||||||
from PySide6.QtGui import QIcon, QPixmap
|
from PySide6.QtGui import QIcon, QPixmap
|
||||||
from data.config import APP_NAME, CONFIG_FILE
|
from data.config import APP_NAME, CONFIG_FILE
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("helpers")
|
||||||
|
|
||||||
def resource_path(relative_path):
|
def resource_path(relative_path):
|
||||||
"""获取资源的绝对路径,适用于开发环境和Nuitka打包环境"""
|
"""获取资源的绝对路径,适用于开发环境和Nuitka打包环境"""
|
||||||
@@ -83,7 +87,7 @@ def save_config(config):
|
|||||||
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
||||||
json.dump(config, f, indent=4)
|
json.dump(config, f, indent=4)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print(f"Error saving config: {e}")
|
logger.error(f"Error saving config: {e}")
|
||||||
|
|
||||||
|
|
||||||
class HashManager:
|
class HashManager:
|
||||||
@@ -109,7 +113,7 @@ class HashManager:
|
|||||||
results[file_path] = future.result()
|
results[file_path] = future.result()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
results[file_path] = None # Mark as failed
|
results[file_path] = None # Mark as failed
|
||||||
print(f"Error calculating hash for {file_path}: {e}")
|
logger.error(f"Error calculating hash for {file_path}: {e}")
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def hash_pop_window(self, check_type="default", is_offline=False):
|
def hash_pop_window(self, check_type="default", is_offline=False):
|
||||||
@@ -166,7 +170,7 @@ class HashManager:
|
|||||||
if not os.path.exists(install_path):
|
if not os.path.exists(install_path):
|
||||||
status_copy[game_version] = False
|
status_copy[game_version] = False
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 哈希预检查 - {game_version} 补丁文件不存在: {install_path}")
|
logger.debug(f"DEBUG: 哈希预检查 - {game_version} 补丁文件不存在: {install_path}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -174,11 +178,11 @@ class HashManager:
|
|||||||
file_hash = self.hash_calculate(install_path)
|
file_hash = self.hash_calculate(install_path)
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 哈希预检查 - {game_version}")
|
logger.debug(f"DEBUG: 哈希预检查 - {game_version}")
|
||||||
print(f"DEBUG: 文件路径: {install_path}")
|
logger.debug(f"DEBUG: 文件路径: {install_path}")
|
||||||
print(f"DEBUG: 预期哈希值: {expected_hash}")
|
logger.debug(f"DEBUG: 预期哈希值: {expected_hash}")
|
||||||
print(f"DEBUG: 实际哈希值: {file_hash}")
|
logger.debug(f"DEBUG: 实际哈希值: {file_hash}")
|
||||||
print(f"DEBUG: 哈希匹配: {file_hash == expected_hash}")
|
logger.debug(f"DEBUG: 哈希匹配: {file_hash == expected_hash}")
|
||||||
|
|
||||||
if file_hash == expected_hash:
|
if file_hash == expected_hash:
|
||||||
status_copy[game_version] = True
|
status_copy[game_version] = True
|
||||||
@@ -187,7 +191,7 @@ class HashManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
status_copy[game_version] = False
|
status_copy[game_version] = False
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 哈希预检查异常 - {game_version}: {str(e)}")
|
logger.debug(f"DEBUG: 哈希预检查异常 - {game_version}: {str(e)}")
|
||||||
|
|
||||||
return status_copy
|
return status_copy
|
||||||
|
|
||||||
@@ -213,15 +217,15 @@ class HashManager:
|
|||||||
file_hash = hash_results.get(file_path)
|
file_hash = hash_results.get(file_path)
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 哈希后检查 - {game}")
|
logger.debug(f"DEBUG: 哈希后检查 - {game}")
|
||||||
print(f"DEBUG: 文件路径: {file_path}")
|
logger.debug(f"DEBUG: 文件路径: {file_path}")
|
||||||
print(f"DEBUG: 预期哈希值: {expected_hash}")
|
logger.debug(f"DEBUG: 预期哈希值: {expected_hash}")
|
||||||
print(f"DEBUG: 实际哈希值: {file_hash if file_hash else '计算失败'}")
|
logger.debug(f"DEBUG: 实际哈希值: {file_hash if file_hash else '计算失败'}")
|
||||||
|
|
||||||
if file_hash is None:
|
if file_hash is None:
|
||||||
installed_status[game] = False
|
installed_status[game] = False
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 哈希后检查失败 - 无法计算文件哈希值: {game}")
|
logger.debug(f"DEBUG: 哈希后检查失败 - 无法计算文件哈希值: {game}")
|
||||||
return {
|
return {
|
||||||
"passed": False,
|
"passed": False,
|
||||||
"game": game,
|
"game": game,
|
||||||
@@ -231,7 +235,7 @@ class HashManager:
|
|||||||
if file_hash != expected_hash:
|
if file_hash != expected_hash:
|
||||||
installed_status[game] = False
|
installed_status[game] = False
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 哈希后检查失败 - 哈希值不匹配: {game}")
|
logger.debug(f"DEBUG: 哈希后检查失败 - 哈希值不匹配: {game}")
|
||||||
return {
|
return {
|
||||||
"passed": False,
|
"passed": False,
|
||||||
"game": game,
|
"game": game,
|
||||||
@@ -239,7 +243,7 @@ class HashManager:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if debug_mode:
|
if debug_mode:
|
||||||
print(f"DEBUG: 哈希后检查通过 - 所有文件哈希值匹配")
|
logger.debug(f"DEBUG: 哈希后检查通过 - 所有文件哈希值匹配")
|
||||||
return {"passed": True}
|
return {"passed": True}
|
||||||
|
|
||||||
class AdminPrivileges:
|
class AdminPrivileges:
|
||||||
@@ -351,7 +355,7 @@ class HostsManager:
|
|||||||
with open(self.hosts_path, 'r', encoding='utf-8') as f:
|
with open(self.hosts_path, 'r', encoding='utf-8') as f:
|
||||||
self.original_content = f.read()
|
self.original_content = f.read()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"读取hosts文件失败: {e}")
|
logger.error(f"读取hosts文件失败: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# 解析hosts文件中的每一行
|
# 解析hosts文件中的每一行
|
||||||
@@ -377,22 +381,22 @@ class HostsManager:
|
|||||||
return ip_addresses
|
return ip_addresses
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"获取hosts记录失败: {e}")
|
logger.error(f"获取hosts记录失败: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def backup(self):
|
def backup(self):
|
||||||
if not AdminPrivileges().is_admin():
|
if not AdminPrivileges().is_admin():
|
||||||
print("需要管理员权限来备份hosts文件。")
|
logger.warning("需要管理员权限来备份hosts文件。")
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
with open(self.hosts_path, 'r', encoding='utf-8') as f:
|
with open(self.hosts_path, 'r', encoding='utf-8') as f:
|
||||||
self.original_content = f.read()
|
self.original_content = f.read()
|
||||||
with open(self.backup_path, 'w', encoding='utf-8') as f:
|
with open(self.backup_path, 'w', encoding='utf-8') as f:
|
||||||
f.write(self.original_content)
|
f.write(self.original_content)
|
||||||
print(f"Hosts文件已备份到: {self.backup_path}")
|
logger.info(f"Hosts文件已备份到: {self.backup_path}")
|
||||||
return True
|
return True
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print(f"备份hosts文件失败: {e}")
|
logger.error(f"备份hosts文件失败: {e}")
|
||||||
msg_box = msgbox_frame(f"错误 - {APP_NAME}", f"\n无法备份hosts文件,请检查权限。\n\n【错误信息】:{e}\n", QtWidgets.QMessageBox.StandardButton.Ok)
|
msg_box = msgbox_frame(f"错误 - {APP_NAME}", f"\n无法备份hosts文件,请检查权限。\n\n【错误信息】:{e}\n", QtWidgets.QMessageBox.StandardButton.Ok)
|
||||||
msg_box.exec()
|
msg_box.exec()
|
||||||
return False
|
return False
|
||||||
@@ -412,11 +416,11 @@ class HostsManager:
|
|||||||
|
|
||||||
# 确保original_content不为None
|
# 确保original_content不为None
|
||||||
if not self.original_content:
|
if not self.original_content:
|
||||||
print("无法读取hosts文件内容,操作中止。")
|
logger.error("无法读取hosts文件内容,操作中止。")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not AdminPrivileges().is_admin():
|
if not AdminPrivileges().is_admin():
|
||||||
print("需要管理员权限来修改hosts文件。")
|
logger.warning("需要管理员权限来修改hosts文件。")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -425,7 +429,7 @@ class HostsManager:
|
|||||||
|
|
||||||
# 如果没有变化,不需要写入
|
# 如果没有变化,不需要写入
|
||||||
if len(new_lines) == len(lines):
|
if len(new_lines) == len(lines):
|
||||||
print(f"Hosts文件中没有找到 {hostname} 的记录")
|
logger.info(f"Hosts文件中没有找到 {hostname} 的记录")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
with open(self.hosts_path, 'w', encoding='utf-8') as f:
|
with open(self.hosts_path, 'w', encoding='utf-8') as f:
|
||||||
@@ -433,10 +437,10 @@ class HostsManager:
|
|||||||
|
|
||||||
# 更新原始内容
|
# 更新原始内容
|
||||||
self.original_content = '\n'.join(new_lines)
|
self.original_content = '\n'.join(new_lines)
|
||||||
print(f"已从hosts文件中清理 {hostname} 的记录")
|
logger.info(f"已从hosts文件中清理 {hostname} 的记录")
|
||||||
return True
|
return True
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print(f"清理hosts文件失败: {e}")
|
logger.error(f"清理hosts文件失败: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def apply_ip(self, hostname, ip_address, clean=True):
|
def apply_ip(self, hostname, ip_address, clean=True):
|
||||||
@@ -445,11 +449,11 @@ class HostsManager:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if not self.original_content: # 再次检查,确保backup成功
|
if not self.original_content: # 再次检查,确保backup成功
|
||||||
print("无法读取hosts文件内容,操作中止。")
|
logger.error("无法读取hosts文件内容,操作中止。")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not AdminPrivileges().is_admin():
|
if not AdminPrivileges().is_admin():
|
||||||
print("需要管理员权限来修改hosts文件。")
|
logger.warning("需要管理员权限来修改hosts文件。")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -471,10 +475,10 @@ class HostsManager:
|
|||||||
self.modified = True
|
self.modified = True
|
||||||
# 记录被修改的主机名,用于最终清理
|
# 记录被修改的主机名,用于最终清理
|
||||||
self.modified_hostnames.add(hostname)
|
self.modified_hostnames.add(hostname)
|
||||||
print(f"Hosts文件已更新: {new_entry}")
|
logger.info(f"Hosts文件已更新: {new_entry}")
|
||||||
return True
|
return True
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print(f"修改hosts文件失败: {e}")
|
logger.error(f"修改hosts文件失败: {e}")
|
||||||
msg_box = msgbox_frame(f"错误 - {APP_NAME}", f"\n无法修改hosts文件,请检查权限。\n\n【错误信息】:{e}\n", QtWidgets.QMessageBox.StandardButton.Ok)
|
msg_box = msgbox_frame(f"错误 - {APP_NAME}", f"\n无法修改hosts文件,请检查权限。\n\n【错误信息】:{e}\n", QtWidgets.QMessageBox.StandardButton.Ok)
|
||||||
msg_box.exec()
|
msg_box.exec()
|
||||||
return False
|
return False
|
||||||
@@ -502,10 +506,10 @@ class HostsManager:
|
|||||||
# 保存配置
|
# 保存配置
|
||||||
save_config(config)
|
save_config(config)
|
||||||
|
|
||||||
print(f"已{'禁用' if disabled else '启用'}自动还原hosts")
|
logger.info(f"已{'禁用' if disabled else '启用'}自动还原hosts")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"设置自动还原hosts状态失败: {e}")
|
logger.error(f"设置自动还原hosts状态失败: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_auto_restore_disabled(self):
|
def is_auto_restore_disabled(self):
|
||||||
@@ -528,11 +532,11 @@ class HostsManager:
|
|||||||
"""
|
"""
|
||||||
# 如果禁用了自动还原,则不执行清理操作
|
# 如果禁用了自动还原,则不执行清理操作
|
||||||
if self.is_auto_restore_disabled():
|
if self.is_auto_restore_disabled():
|
||||||
print("已禁用自动还原hosts,跳过清理操作")
|
logger.info("已禁用自动还原hosts,跳过清理操作")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if not AdminPrivileges().is_admin():
|
if not AdminPrivileges().is_admin():
|
||||||
print("需要管理员权限来检查和清理hosts文件。")
|
logger.warning("需要管理员权限来检查和清理hosts文件。")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -560,24 +564,24 @@ class HostsManager:
|
|||||||
|
|
||||||
# 检查是否有变化
|
# 检查是否有变化
|
||||||
if len(new_lines) == len(lines):
|
if len(new_lines) == len(lines):
|
||||||
print("Hosts文件中没有找到由本应用添加的记录")
|
logger.info("Hosts文件中没有找到由本应用添加的记录")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# 写回清理后的内容
|
# 写回清理后的内容
|
||||||
with open(self.hosts_path, 'w', encoding='utf-8') as f:
|
with open(self.hosts_path, 'w', encoding='utf-8') as f:
|
||||||
f.write('\n'.join(new_lines))
|
f.write('\n'.join(new_lines))
|
||||||
|
|
||||||
print(f"已清理所有由 {APP_NAME} 添加的hosts记录")
|
logger.info(f"已清理所有由 {APP_NAME} 添加的hosts记录")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print(f"检查和清理hosts文件失败: {e}")
|
logger.error(f"检查和清理hosts文件失败: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def restore(self):
|
def restore(self):
|
||||||
# 如果禁用了自动还原,则不执行还原操作
|
# 如果禁用了自动还原,则不执行还原操作
|
||||||
if self.is_auto_restore_disabled():
|
if self.is_auto_restore_disabled():
|
||||||
print("已禁用自动还原hosts,跳过还原操作")
|
logger.info("已禁用自动还原hosts,跳过还原操作")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if not self.modified:
|
if not self.modified:
|
||||||
@@ -591,7 +595,7 @@ class HostsManager:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
if not AdminPrivileges().is_admin():
|
if not AdminPrivileges().is_admin():
|
||||||
print("需要管理员权限来恢复hosts文件。")
|
logger.warning("需要管理员权限来恢复hosts文件。")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.original_content:
|
if self.original_content:
|
||||||
@@ -599,7 +603,7 @@ class HostsManager:
|
|||||||
with open(self.hosts_path, 'w', encoding='utf-8') as f:
|
with open(self.hosts_path, 'w', encoding='utf-8') as f:
|
||||||
f.write(self.original_content)
|
f.write(self.original_content)
|
||||||
self.modified = False
|
self.modified = False
|
||||||
print("Hosts文件已从内存恢复。")
|
logger.info("Hosts文件已从内存恢复。")
|
||||||
if os.path.exists(self.backup_path):
|
if os.path.exists(self.backup_path):
|
||||||
try:
|
try:
|
||||||
os.remove(self.backup_path)
|
os.remove(self.backup_path)
|
||||||
@@ -608,15 +612,15 @@ class HostsManager:
|
|||||||
# 恢复后再检查一次是否有残留
|
# 恢复后再检查一次是否有残留
|
||||||
self.check_and_clean_all_entries()
|
self.check_and_clean_all_entries()
|
||||||
return True
|
return True
|
||||||
except IOError as e:
|
except (IOError, OSError) as e:
|
||||||
print(f"从内存恢复hosts文件失败: {e}")
|
logger.error(f"从内存恢复hosts文件失败: {e}")
|
||||||
return self.restore_from_backup_file()
|
return self.restore_from_backup_file()
|
||||||
else:
|
else:
|
||||||
return self.restore_from_backup_file()
|
return self.restore_from_backup_file()
|
||||||
|
|
||||||
def restore_from_backup_file(self):
|
def restore_from_backup_file(self):
|
||||||
if not os.path.exists(self.backup_path):
|
if not os.path.exists(self.backup_path):
|
||||||
print("未找到hosts备份文件,无法恢复。")
|
logger.warning("未找到hosts备份文件,无法恢复。")
|
||||||
# 即使没有备份文件,也尝试清理可能的残留
|
# 即使没有备份文件,也尝试清理可能的残留
|
||||||
self.check_and_clean_all_entries()
|
self.check_and_clean_all_entries()
|
||||||
return False
|
return False
|
||||||
@@ -627,30 +631,14 @@ class HostsManager:
|
|||||||
hf.write(backup_content)
|
hf.write(backup_content)
|
||||||
os.remove(self.backup_path)
|
os.remove(self.backup_path)
|
||||||
self.modified = False
|
self.modified = False
|
||||||
print("Hosts文件已从备份文件恢复。")
|
logger.info("Hosts文件已从备份文件恢复。")
|
||||||
# 恢复后再检查一次是否有残留
|
# 恢复后再检查一次是否有残留
|
||||||
self.check_and_clean_all_entries()
|
self.check_and_clean_all_entries()
|
||||||
return True
|
return True
|
||||||
except (IOError, OSError) as e:
|
except (IOError, OSError) as e:
|
||||||
print(f"从备份文件恢复hosts失败: {e}")
|
logger.error(f"从备份文件恢复hosts失败: {e}")
|
||||||
msg_box = msgbox_frame(f"警告 - {APP_NAME}", f"\n自动恢复hosts文件失败,请手动从 {self.backup_path} 恢复。\n\n【错误信息】:{e}\n", QtWidgets.QMessageBox.StandardButton.Ok)
|
msg_box = msgbox_frame(f"警告 - {APP_NAME}", f"\n自动恢复hosts文件失败,请手动从 {self.backup_path} 恢复。\n\n【错误信息】:{e}\n", QtWidgets.QMessageBox.StandardButton.Ok)
|
||||||
msg_box.exec()
|
msg_box.exec()
|
||||||
# 尽管恢复失败,仍然尝试清理可能的残留
|
# 尽管恢复失败,仍然尝试清理可能的残留
|
||||||
self.check_and_clean_all_entries()
|
self.check_and_clean_all_entries()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def censor_url(text):
|
|
||||||
"""Censors URLs in a given text string, replacing them with a protection message.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
text: 要处理的文本
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: 处理后的文本,URL被完全隐藏
|
|
||||||
"""
|
|
||||||
if not isinstance(text, str):
|
|
||||||
text = str(text)
|
|
||||||
|
|
||||||
# 匹配URL并替换为固定文本
|
|
||||||
url_pattern = re.compile(r'https?://[^\s/$.?#].[^\s]*')
|
|
||||||
return url_pattern.sub('***URL protection***', text)
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from .helpers import censor_url
|
from .url_censor import censor_url
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from data.config import CACHE
|
from data.config import CACHE
|
||||||
|
|||||||
17
source/utils/url_censor.py
Normal file
17
source/utils/url_censor.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
def censor_url(text):
|
||||||
|
"""Censors URLs in a given text string, replacing them with a protection message.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: 要处理的文本
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 处理后的文本,URL被完全隐藏
|
||||||
|
"""
|
||||||
|
if not isinstance(text, str):
|
||||||
|
text = str(text)
|
||||||
|
|
||||||
|
# 匹配URL并替换为固定文本
|
||||||
|
url_pattern = re.compile(r'https?://[^\s/$.?#].[^\s]*')
|
||||||
|
return url_pattern.sub('***URL protection***', text)
|
||||||
@@ -4,6 +4,11 @@ import webbrowser
|
|||||||
from PySide6.QtCore import QThread, Signal
|
from PySide6.QtCore import QThread, Signal
|
||||||
from PySide6.QtWidgets import QMessageBox
|
from PySide6.QtWidgets import QMessageBox
|
||||||
import sys
|
import sys
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
from utils.url_censor import censor_url
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("config_fetch")
|
||||||
|
|
||||||
class ConfigFetchThread(QThread):
|
class ConfigFetchThread(QThread):
|
||||||
finished = Signal(object, str) # data, error_message
|
finished = Signal(object, str) # data, error_message
|
||||||
@@ -17,28 +22,27 @@ class ConfigFetchThread(QThread):
|
|||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
if self.debug_mode:
|
if self.debug_mode:
|
||||||
print("--- Starting to fetch cloud config ---")
|
logger.info("--- Starting to fetch cloud config ---")
|
||||||
# 完全隐藏URL
|
# 完全隐藏URL
|
||||||
print(f"DEBUG: Requesting URL: ***URL protection***")
|
logger.debug(f"DEBUG: Requesting URL: ***URL protection***")
|
||||||
print(f"DEBUG: Using Headers: {self.headers}")
|
logger.debug(f"DEBUG: Using Headers: {self.headers}")
|
||||||
|
|
||||||
response = requests.get(self.url, headers=self.headers, timeout=10)
|
response = requests.get(self.url, headers=self.headers, timeout=10)
|
||||||
|
|
||||||
if self.debug_mode:
|
if self.debug_mode:
|
||||||
print(f"DEBUG: Response Status Code: {response.status_code}")
|
logger.debug(f"DEBUG: Response Status Code: {response.status_code}")
|
||||||
print(f"DEBUG: Response Headers: {response.headers}")
|
logger.debug(f"DEBUG: Response Headers: {response.headers}")
|
||||||
|
|
||||||
# 解析并隐藏响应中的敏感URL
|
# 解析并隐藏响应中的敏感URL
|
||||||
try:
|
try:
|
||||||
response_data = response.json()
|
response_data = response.json()
|
||||||
# 创建安全版本用于日志输出
|
# 创建安全版本用于日志输出
|
||||||
safe_response = self._create_safe_config_for_logging(response_data)
|
safe_response = self._create_safe_config_for_logging(response_data)
|
||||||
print(f"DEBUG: Response Text: {json.dumps(safe_response, indent=2)}")
|
logger.debug(f"DEBUG: Response Text: {json.dumps(safe_response, indent=2)}")
|
||||||
except:
|
except:
|
||||||
# 如果不是JSON,直接打印文本
|
# 如果不是JSON,直接打印文本
|
||||||
from utils.helpers import censor_url
|
|
||||||
censored_text = censor_url(response.text)
|
censored_text = censor_url(response.text)
|
||||||
print(f"DEBUG: Response Text: {censored_text}")
|
logger.debug(f"DEBUG: Response Text: {censored_text}")
|
||||||
|
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
@@ -74,7 +78,7 @@ class ConfigFetchThread(QThread):
|
|||||||
self.finished.emit(None, error_msg)
|
self.finished.emit(None, error_msg)
|
||||||
finally:
|
finally:
|
||||||
if self.debug_mode:
|
if self.debug_mode:
|
||||||
print("--- Finished fetching cloud config ---")
|
logger.info("--- Finished fetching cloud config ---")
|
||||||
|
|
||||||
def _create_safe_config_for_logging(self, config_data):
|
def _create_safe_config_for_logging(self, config_data):
|
||||||
"""创建用于日志记录的安全配置副本,隐藏敏感URL
|
"""创建用于日志记录的安全配置副本,隐藏敏感URL
|
||||||
|
|||||||
@@ -8,9 +8,14 @@ from PySide6.QtCore import (Qt, Signal, QThread, QTimer)
|
|||||||
from PySide6.QtWidgets import (QLabel, QProgressBar, QVBoxLayout, QDialog, QHBoxLayout)
|
from PySide6.QtWidgets import (QLabel, QProgressBar, QVBoxLayout, QDialog, QHBoxLayout)
|
||||||
from utils import resource_path
|
from utils import resource_path
|
||||||
from data.config import APP_NAME, UA
|
from data.config import APP_NAME, UA
|
||||||
|
from utils.logger import setup_logger
|
||||||
import signal
|
import signal
|
||||||
import ctypes
|
import ctypes
|
||||||
import time
|
import time
|
||||||
|
from utils.url_censor import censor_url
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("download")
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
kernel32 = ctypes.windll.kernel32
|
kernel32 = ctypes.windll.kernel32
|
||||||
@@ -49,7 +54,7 @@ class DownloadThread(QThread):
|
|||||||
try:
|
try:
|
||||||
subprocess.run(['taskkill', '/F', '/T', '/PID', str(self.process.pid)], check=True, creationflags=subprocess.CREATE_NO_WINDOW)
|
subprocess.run(['taskkill', '/F', '/T', '/PID', str(self.process.pid)], check=True, creationflags=subprocess.CREATE_NO_WINDOW)
|
||||||
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
||||||
print(f"停止下载进程时出错: {e}")
|
logger.error(f"停止下载进程时出错: {e}")
|
||||||
|
|
||||||
def _get_process_threads(self, pid):
|
def _get_process_threads(self, pid):
|
||||||
"""获取进程的所有线程ID"""
|
"""获取进程的所有线程ID"""
|
||||||
@@ -80,7 +85,7 @@ class DownloadThread(QThread):
|
|||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
self.threads = self._get_process_threads(self.process.pid)
|
self.threads = self._get_process_threads(self.process.pid)
|
||||||
if not self.threads:
|
if not self.threads:
|
||||||
print("未找到可暂停的线程")
|
logger.warning("未找到可暂停的线程")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
for thread_id in self.threads:
|
for thread_id in self.threads:
|
||||||
@@ -90,15 +95,15 @@ class DownloadThread(QThread):
|
|||||||
kernel32.CloseHandle(h_thread)
|
kernel32.CloseHandle(h_thread)
|
||||||
|
|
||||||
self._is_paused = True
|
self._is_paused = True
|
||||||
print(f"下载进程已暂停: PID {self.process.pid}, 线程数: {len(self.threads)}")
|
logger.info(f"下载进程已暂停: PID {self.process.pid}, 线程数: {len(self.threads)}")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
os.kill(self.process.pid, signal.SIGSTOP)
|
os.kill(self.process.pid, signal.SIGSTOP)
|
||||||
self._is_paused = True
|
self._is_paused = True
|
||||||
print(f"下载进程已暂停: PID {self.process.pid}")
|
logger.info(f"下载进程已暂停: PID {self.process.pid}")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"暂停下载进程时出错: {e}")
|
logger.error(f"暂停下载进程时出错: {e}")
|
||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -114,15 +119,15 @@ class DownloadThread(QThread):
|
|||||||
kernel32.CloseHandle(h_thread)
|
kernel32.CloseHandle(h_thread)
|
||||||
|
|
||||||
self._is_paused = False
|
self._is_paused = False
|
||||||
print(f"下载进程已恢复: PID {self.process.pid}, 线程数: {len(self.threads)}")
|
logger.info(f"下载进程已恢复: PID {self.process.pid}, 线程数: {len(self.threads)}")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
os.kill(self.process.pid, signal.SIGCONT)
|
os.kill(self.process.pid, signal.SIGCONT)
|
||||||
self._is_paused = False
|
self._is_paused = False
|
||||||
print(f"下载进程已恢复: PID {self.process.pid}")
|
logger.info(f"下载进程已恢复: PID {self.process.pid}")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"恢复下载进程时出错: {e}")
|
logger.error(f"恢复下载进程时出错: {e}")
|
||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -155,7 +160,7 @@ class DownloadThread(QThread):
|
|||||||
if hasattr(self.parent(), 'config'):
|
if hasattr(self.parent(), 'config'):
|
||||||
ipv6_enabled = self.parent().config.get("ipv6_enabled", False)
|
ipv6_enabled = self.parent().config.get("ipv6_enabled", False)
|
||||||
|
|
||||||
print(f"IPv6支持状态: {ipv6_enabled}")
|
logger.info(f"IPv6支持状态: {ipv6_enabled}")
|
||||||
|
|
||||||
command.extend([
|
command.extend([
|
||||||
'--dir', download_dir,
|
'--dir', download_dir,
|
||||||
@@ -192,9 +197,9 @@ class DownloadThread(QThread):
|
|||||||
|
|
||||||
if not ipv6_enabled:
|
if not ipv6_enabled:
|
||||||
command.append('--disable-ipv6=true')
|
command.append('--disable-ipv6=true')
|
||||||
print("已禁用IPv6支持")
|
logger.info("已禁用IPv6支持")
|
||||||
else:
|
else:
|
||||||
print("已启用IPv6支持")
|
logger.info("已启用IPv6支持")
|
||||||
|
|
||||||
command.append('--check-certificate=false')
|
command.append('--check-certificate=false')
|
||||||
|
|
||||||
@@ -208,7 +213,7 @@ class DownloadThread(QThread):
|
|||||||
if isinstance(url, str) and url.startswith("http"):
|
if isinstance(url, str) and url.startswith("http"):
|
||||||
safe_command[-1] = "***URL protection***"
|
safe_command[-1] = "***URL protection***"
|
||||||
|
|
||||||
print(f"即将执行的 Aria2c 命令: {' '.join(safe_command)}")
|
logger.info(f"即将执行的 Aria2c 命令: {' '.join(safe_command)}")
|
||||||
|
|
||||||
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
||||||
self.process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, encoding='utf-8', errors='replace', creationflags=creation_flags)
|
self.process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, encoding='utf-8', errors='replace', creationflags=creation_flags)
|
||||||
@@ -229,10 +234,9 @@ class DownloadThread(QThread):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 处理输出行,隐藏可能包含的URL
|
# 处理输出行,隐藏可能包含的URL
|
||||||
from utils.helpers import censor_url
|
|
||||||
censored_line = censor_url(line)
|
censored_line = censor_url(line)
|
||||||
full_output.append(censored_line)
|
full_output.append(censored_line)
|
||||||
print(censored_line.strip())
|
logger.debug(censored_line.strip())
|
||||||
|
|
||||||
match = progress_pattern.search(line)
|
match = progress_pattern.search(line)
|
||||||
if match:
|
if match:
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ from urllib.parse import urlparse
|
|||||||
|
|
||||||
from PySide6.QtCore import QThread, Signal
|
from PySide6.QtCore import QThread, Signal
|
||||||
from utils import resource_path
|
from utils import resource_path
|
||||||
|
from utils.logger import setup_logger
|
||||||
|
from utils.url_censor import censor_url
|
||||||
|
|
||||||
|
# 初始化logger
|
||||||
|
logger = setup_logger("ip_optimizer")
|
||||||
|
|
||||||
class IpOptimizer:
|
class IpOptimizer:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -25,7 +30,7 @@ class IpOptimizer:
|
|||||||
try:
|
try:
|
||||||
cst_path = resource_path("cfst.exe")
|
cst_path = resource_path("cfst.exe")
|
||||||
if not os.path.exists(cst_path):
|
if not os.path.exists(cst_path):
|
||||||
print(f"错误: cfst.exe 未在资源路径中找到。")
|
logger.error(f"错误: cfst.exe 未在资源路径中找到。")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ip_txt_path = resource_path("ip.txt")
|
ip_txt_path = resource_path("ip.txt")
|
||||||
@@ -51,8 +56,8 @@ class IpOptimizer:
|
|||||||
|
|
||||||
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
||||||
|
|
||||||
print("--- CloudflareSpeedTest 开始执行 ---")
|
logger.info("--- CloudflareSpeedTest 开始执行 ---")
|
||||||
print(f"执行命令: {' '.join(safe_command)}")
|
logger.info(f"执行命令: {' '.join(safe_command)}")
|
||||||
|
|
||||||
self.process = subprocess.Popen(
|
self.process = subprocess.Popen(
|
||||||
command,
|
command,
|
||||||
@@ -74,7 +79,7 @@ class IpOptimizer:
|
|||||||
|
|
||||||
stdout = self.process.stdout
|
stdout = self.process.stdout
|
||||||
if not stdout:
|
if not stdout:
|
||||||
print("错误: 无法获取子进程的输出流。")
|
logger.error("错误: 无法获取子进程的输出流。")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
optimal_ip = None
|
optimal_ip = None
|
||||||
@@ -94,7 +99,7 @@ class IpOptimizer:
|
|||||||
if not ready or not line:
|
if not ready or not line:
|
||||||
timeout_counter += 1
|
timeout_counter += 1
|
||||||
if timeout_counter > max_timeout:
|
if timeout_counter > max_timeout:
|
||||||
print("超时: CloudflareSpeedTest 响应超时")
|
logger.warning("超时: CloudflareSpeedTest 响应超时")
|
||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
continue
|
continue
|
||||||
@@ -102,18 +107,17 @@ class IpOptimizer:
|
|||||||
timeout_counter = 0
|
timeout_counter = 0
|
||||||
|
|
||||||
# 处理输出行,隐藏可能包含的URL
|
# 处理输出行,隐藏可能包含的URL
|
||||||
from utils.helpers import censor_url
|
|
||||||
cleaned_line = censor_url(line.strip())
|
cleaned_line = censor_url(line.strip())
|
||||||
if cleaned_line:
|
if cleaned_line:
|
||||||
print(cleaned_line)
|
logger.debug(cleaned_line)
|
||||||
|
|
||||||
if "IP 地址" in cleaned_line and "平均延迟" in cleaned_line:
|
if "IP 地址" in cleaned_line and "平均延迟" in cleaned_line:
|
||||||
print("检测到IP结果表头,准备获取IP地址...")
|
logger.info("检测到IP结果表头,准备获取IP地址...")
|
||||||
found_header = True
|
found_header = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if "完整测速结果已写入" in cleaned_line or "按下 回车键 或 Ctrl+C 退出" in cleaned_line:
|
if "完整测速结果已写入" in cleaned_line or "按下 回车键 或 Ctrl+C 退出" in cleaned_line:
|
||||||
print("检测到测速完成信息")
|
logger.info("检测到测速完成信息")
|
||||||
found_completion = True
|
found_completion = True
|
||||||
|
|
||||||
if optimal_ip:
|
if optimal_ip:
|
||||||
@@ -123,17 +127,17 @@ class IpOptimizer:
|
|||||||
match = ip_pattern.search(cleaned_line)
|
match = ip_pattern.search(cleaned_line)
|
||||||
if match and not optimal_ip:
|
if match and not optimal_ip:
|
||||||
optimal_ip = match.group(1)
|
optimal_ip = match.group(1)
|
||||||
print(f"找到最优 IP: {optimal_ip}")
|
logger.info(f"找到最优 IP: {optimal_ip}")
|
||||||
break
|
break
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"读取输出时发生错误: {e}")
|
logger.error(f"读取输出时发生错误: {e}")
|
||||||
break
|
break
|
||||||
|
|
||||||
if self.process and self.process.poll() is None:
|
if self.process and self.process.poll() is None:
|
||||||
try:
|
try:
|
||||||
if self.process.stdin and not self.process.stdin.closed:
|
if self.process.stdin and not self.process.stdin.closed:
|
||||||
print("发送退出信号...")
|
logger.debug("发送退出信号...")
|
||||||
self.process.stdin.write('\n')
|
self.process.stdin.write('\n')
|
||||||
self.process.stdin.flush()
|
self.process.stdin.flush()
|
||||||
except:
|
except:
|
||||||
@@ -141,11 +145,11 @@ class IpOptimizer:
|
|||||||
|
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
print("--- CloudflareSpeedTest 执行结束 ---")
|
logger.info("--- CloudflareSpeedTest 执行结束 ---")
|
||||||
return optimal_ip
|
return optimal_ip
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"执行 CloudflareSpeedTest 时发生错误: {e}")
|
logger.error(f"执行 CloudflareSpeedTest 时发生错误: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_optimal_ipv6(self, url: str) -> str | None:
|
def get_optimal_ipv6(self, url: str) -> str | None:
|
||||||
@@ -161,12 +165,12 @@ class IpOptimizer:
|
|||||||
try:
|
try:
|
||||||
cst_path = resource_path("cfst.exe")
|
cst_path = resource_path("cfst.exe")
|
||||||
if not os.path.exists(cst_path):
|
if not os.path.exists(cst_path):
|
||||||
print(f"错误: cfst.exe 未在资源路径中找到。")
|
logger.error(f"错误: cfst.exe 未在资源路径中找到。")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ipv6_txt_path = resource_path("data/ipv6.txt")
|
ipv6_txt_path = resource_path("data/ipv6.txt")
|
||||||
if not os.path.exists(ipv6_txt_path):
|
if not os.path.exists(ipv6_txt_path):
|
||||||
print(f"错误: ipv6.txt 未在资源路径中找到。")
|
logger.error(f"错误: ipv6.txt 未在资源路径中找到。")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 隐藏敏感URL
|
# 隐藏敏感URL
|
||||||
@@ -190,8 +194,8 @@ class IpOptimizer:
|
|||||||
|
|
||||||
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
||||||
|
|
||||||
print("--- CloudflareSpeedTest IPv6 开始执行 ---")
|
logger.info("--- CloudflareSpeedTest IPv6 开始执行 ---")
|
||||||
print(f"执行命令: {' '.join(safe_command)}")
|
logger.info(f"执行命令: {' '.join(safe_command)}")
|
||||||
|
|
||||||
self.process = subprocess.Popen(
|
self.process = subprocess.Popen(
|
||||||
command,
|
command,
|
||||||
@@ -213,7 +217,7 @@ class IpOptimizer:
|
|||||||
|
|
||||||
stdout = self.process.stdout
|
stdout = self.process.stdout
|
||||||
if not stdout:
|
if not stdout:
|
||||||
print("错误: 无法获取子进程的输出流。")
|
logger.error("错误: 无法获取子进程的输出流。")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
optimal_ipv6 = None
|
optimal_ipv6 = None
|
||||||
@@ -233,7 +237,7 @@ class IpOptimizer:
|
|||||||
if not ready or not line:
|
if not ready or not line:
|
||||||
timeout_counter += 1
|
timeout_counter += 1
|
||||||
if timeout_counter > max_timeout:
|
if timeout_counter > max_timeout:
|
||||||
print("超时: CloudflareSpeedTest IPv6 响应超时")
|
logger.warning("超时: CloudflareSpeedTest IPv6 响应超时")
|
||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
continue
|
continue
|
||||||
@@ -241,18 +245,17 @@ class IpOptimizer:
|
|||||||
timeout_counter = 0
|
timeout_counter = 0
|
||||||
|
|
||||||
# 处理输出行,隐藏可能包含的URL
|
# 处理输出行,隐藏可能包含的URL
|
||||||
from utils.helpers import censor_url
|
|
||||||
cleaned_line = censor_url(line.strip())
|
cleaned_line = censor_url(line.strip())
|
||||||
if cleaned_line:
|
if cleaned_line:
|
||||||
print(cleaned_line)
|
logger.debug(cleaned_line)
|
||||||
|
|
||||||
if "IP 地址" in cleaned_line and "平均延迟" in cleaned_line:
|
if "IP 地址" in cleaned_line and "平均延迟" in cleaned_line:
|
||||||
print("检测到IPv6结果表头,准备获取IPv6地址...")
|
logger.info("检测到IPv6结果表头,准备获取IPv6地址...")
|
||||||
found_header = True
|
found_header = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if "完整测速结果已写入" in cleaned_line or "按下 回车键 或 Ctrl+C 退出" in cleaned_line:
|
if "完整测速结果已写入" in cleaned_line or "按下 回车键 或 Ctrl+C 退出" in cleaned_line:
|
||||||
print("检测到IPv6测速完成信息")
|
logger.info("检测到IPv6测速完成信息")
|
||||||
found_completion = True
|
found_completion = True
|
||||||
|
|
||||||
if optimal_ipv6:
|
if optimal_ipv6:
|
||||||
@@ -262,17 +265,17 @@ class IpOptimizer:
|
|||||||
match = ipv6_pattern.search(cleaned_line)
|
match = ipv6_pattern.search(cleaned_line)
|
||||||
if match and not optimal_ipv6:
|
if match and not optimal_ipv6:
|
||||||
optimal_ipv6 = match.group(1)
|
optimal_ipv6 = match.group(1)
|
||||||
print(f"找到最优 IPv6: {optimal_ipv6}")
|
logger.info(f"找到最优 IPv6: {optimal_ipv6}")
|
||||||
break
|
break
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"读取输出时发生错误: {e}")
|
logger.error(f"读取输出时发生错误: {e}")
|
||||||
break
|
break
|
||||||
|
|
||||||
if self.process and self.process.poll() is None:
|
if self.process and self.process.poll() is None:
|
||||||
try:
|
try:
|
||||||
if self.process.stdin and not self.process.stdin.closed:
|
if self.process.stdin and not self.process.stdin.closed:
|
||||||
print("发送退出信号...")
|
logger.debug("发送退出信号...")
|
||||||
self.process.stdin.write('\n')
|
self.process.stdin.write('\n')
|
||||||
self.process.stdin.flush()
|
self.process.stdin.flush()
|
||||||
except:
|
except:
|
||||||
@@ -280,16 +283,16 @@ class IpOptimizer:
|
|||||||
|
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
print("--- CloudflareSpeedTest IPv6 执行结束 ---")
|
logger.info("--- CloudflareSpeedTest IPv6 执行结束 ---")
|
||||||
return optimal_ipv6
|
return optimal_ipv6
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"执行 CloudflareSpeedTest IPv6 时发生错误: {e}")
|
logger.error(f"执行 CloudflareSpeedTest IPv6 时发生错误: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
if self.process and self.process.poll() is None:
|
if self.process and self.process.poll() is None:
|
||||||
print("正在终止 CloudflareSpeedTest 进程...")
|
logger.info("正在终止 CloudflareSpeedTest 进程...")
|
||||||
try:
|
try:
|
||||||
if self.process.stdin and not self.process.stdin.closed:
|
if self.process.stdin and not self.process.stdin.closed:
|
||||||
self.process.stdin.write('\n')
|
self.process.stdin.write('\n')
|
||||||
@@ -304,7 +307,7 @@ class IpOptimizer:
|
|||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
self.process.kill()
|
self.process.kill()
|
||||||
self.process.wait()
|
self.process.wait()
|
||||||
print("CloudflareSpeedTest 进程已终止。")
|
logger.info("CloudflareSpeedTest 进程已终止。")
|
||||||
|
|
||||||
|
|
||||||
class IpOptimizerThread(QThread):
|
class IpOptimizerThread(QThread):
|
||||||
|
|||||||
Reference in New Issue
Block a user