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