mirror of
https://github.com/hyb-oyqq/FRAISEMOE-Addons-Installer-NEXT.git
synced 2025-12-17 04:20:28 +00:00
feat(core): 初步添加IPv6支持和优化功能
- 在CloudflareOptimizer中添加IPv6优化功能,支持同时进行IPv4和IPv6的优选。 - 更新UIManager,增加IPv6支持选项,并实现用户切换功能。 - 在下载线程中检查IPv6支持状态,并根据设置决定是否禁用IPv6。 - 在IP优化器中实现获取最优IPv6地址的功能,优化测速参数设置。 - 改进用户提示信息,确保用户了解IPv6优选的时间和效果。
This commit is contained in:
@@ -21,11 +21,13 @@ class CloudflareOptimizer:
|
|||||||
self.main_window = main_window
|
self.main_window = main_window
|
||||||
self.hosts_manager = hosts_manager
|
self.hosts_manager = hosts_manager
|
||||||
self.optimized_ip = None
|
self.optimized_ip = None
|
||||||
|
self.optimized_ipv6 = None
|
||||||
self.optimization_done = False # 标记是否已执行过优选
|
self.optimization_done = False # 标记是否已执行过优选
|
||||||
self.countdown_finished = False # 标记倒计时是否结束
|
self.countdown_finished = False # 标记倒计时是否结束
|
||||||
self.optimizing_msg_box = None
|
self.optimizing_msg_box = None
|
||||||
self.optimization_cancelled = False
|
self.optimization_cancelled = False
|
||||||
self.ip_optimizer_thread = None
|
self.ip_optimizer_thread = None
|
||||||
|
self.ipv6_optimizer_thread = None
|
||||||
|
|
||||||
def is_optimization_done(self):
|
def is_optimization_done(self):
|
||||||
"""检查是否已完成优化
|
"""检查是否已完成优化
|
||||||
@@ -50,6 +52,14 @@ class CloudflareOptimizer:
|
|||||||
str: 优选的IP地址,如果未优选则为None
|
str: 优选的IP地址,如果未优选则为None
|
||||||
"""
|
"""
|
||||||
return self.optimized_ip
|
return self.optimized_ip
|
||||||
|
|
||||||
|
def get_optimized_ipv6(self):
|
||||||
|
"""获取优选的IPv6地址
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 优选的IPv6地址,如果未优选则为None
|
||||||
|
"""
|
||||||
|
return self.optimized_ipv6
|
||||||
|
|
||||||
def start_ip_optimization(self, url):
|
def start_ip_optimization(self, url):
|
||||||
"""开始IP优化过程
|
"""开始IP优化过程
|
||||||
@@ -61,10 +71,55 @@ class CloudflareOptimizer:
|
|||||||
self.optimization_cancelled = False
|
self.optimization_cancelled = False
|
||||||
self.countdown_finished = False
|
self.countdown_finished = False
|
||||||
|
|
||||||
|
# 检查是否启用了IPv6
|
||||||
|
use_ipv6 = False
|
||||||
|
if hasattr(self.main_window, 'config'):
|
||||||
|
use_ipv6 = self.main_window.config.get("ipv6_enabled", False)
|
||||||
|
|
||||||
|
# 如果启用了IPv6,显示警告消息
|
||||||
|
if use_ipv6:
|
||||||
|
ipv6_warning = QtWidgets.QMessageBox(self.main_window)
|
||||||
|
ipv6_warning.setWindowTitle(f"IPv6优选警告 - {self.main_window.APP_NAME}")
|
||||||
|
ipv6_warning.setText("\nIPv6优选比IPv4耗时更长且感知不强(预计耗时10分钟以上),不建议使用。\n\n确定要同时执行IPv6优选吗?\n")
|
||||||
|
ipv6_warning.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
||||||
|
|
||||||
|
# 设置图标
|
||||||
|
icon_path = resource_path(os.path.join("IMG", "ICO", "icon.png"))
|
||||||
|
if os.path.exists(icon_path):
|
||||||
|
pixmap = QPixmap(icon_path)
|
||||||
|
if not pixmap.isNull():
|
||||||
|
ipv6_warning.setWindowIcon(QIcon(pixmap))
|
||||||
|
|
||||||
|
yes_button = ipv6_warning.addButton("是", QtWidgets.QMessageBox.ButtonRole.YesRole)
|
||||||
|
no_button = ipv6_warning.addButton("否,仅使用IPv4", QtWidgets.QMessageBox.ButtonRole.NoRole)
|
||||||
|
cancel_button = ipv6_warning.addButton("取消优选", QtWidgets.QMessageBox.ButtonRole.RejectRole)
|
||||||
|
|
||||||
|
ipv6_warning.setDefaultButton(no_button)
|
||||||
|
ipv6_warning.exec()
|
||||||
|
|
||||||
|
if ipv6_warning.clickedButton() == cancel_button:
|
||||||
|
# 用户取消了优选
|
||||||
|
self.optimization_cancelled = True
|
||||||
|
return
|
||||||
|
|
||||||
|
# 根据用户选择调整IPv6设置
|
||||||
|
if ipv6_warning.clickedButton() == no_button:
|
||||||
|
use_ipv6 = False
|
||||||
|
# 临时覆盖配置(不保存到文件)
|
||||||
|
if hasattr(self.main_window, 'config'):
|
||||||
|
self.main_window.config["ipv6_enabled"] = False
|
||||||
|
|
||||||
|
# 准备提示信息
|
||||||
|
optimization_msg = "\n正在优选Cloudflare IP,请稍候...\n\n"
|
||||||
|
if use_ipv6:
|
||||||
|
optimization_msg += "已启用IPv6支持,同时进行IPv4和IPv6优选。\n这可能需要10分钟以上,请耐心等待喵~\n"
|
||||||
|
else:
|
||||||
|
optimization_msg += "这可能需要5-10分钟,请耐心等待喵~\n"
|
||||||
|
|
||||||
# 使用Cloudflare图标创建消息框
|
# 使用Cloudflare图标创建消息框
|
||||||
self.optimizing_msg_box = msgbox_frame(
|
self.optimizing_msg_box = msgbox_frame(
|
||||||
f"通知 - {self.main_window.APP_NAME}",
|
f"通知 - {self.main_window.APP_NAME}",
|
||||||
"\n正在优选Cloudflare IP,请稍候...\n\n这可能需要5-10分钟,请耐心等待喵~"
|
optimization_msg
|
||||||
)
|
)
|
||||||
# 设置Cloudflare图标
|
# 设置Cloudflare图标
|
||||||
cf_icon_path = resource_path("IMG/ICO/cloudflare_logo_icon.ico")
|
cf_icon_path = resource_path("IMG/ICO/cloudflare_logo_icon.ico")
|
||||||
@@ -82,7 +137,16 @@ class CloudflareOptimizer:
|
|||||||
|
|
||||||
# 创建并启动优化线程
|
# 创建并启动优化线程
|
||||||
self.ip_optimizer_thread = IpOptimizerThread(url)
|
self.ip_optimizer_thread = IpOptimizerThread(url)
|
||||||
self.ip_optimizer_thread.finished.connect(self.on_optimization_finished)
|
self.ip_optimizer_thread.finished.connect(self.on_ipv4_optimization_finished)
|
||||||
|
|
||||||
|
# 如果启用IPv6,同时启动IPv6优化线程
|
||||||
|
if use_ipv6:
|
||||||
|
print("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()
|
||||||
|
|
||||||
|
# 启动IPv4优化线程
|
||||||
self.ip_optimizer_thread.start()
|
self.ip_optimizer_thread.start()
|
||||||
|
|
||||||
# 显示消息框(非模态,不阻塞)
|
# 显示消息框(非模态,不阻塞)
|
||||||
@@ -102,6 +166,9 @@ class CloudflareOptimizer:
|
|||||||
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():
|
||||||
self.ip_optimizer_thread.stop()
|
self.ip_optimizer_thread.stop()
|
||||||
|
|
||||||
|
if hasattr(self, 'ipv6_optimizer_thread') and self.ipv6_optimizer_thread and self.ipv6_optimizer_thread.isRunning():
|
||||||
|
self.ipv6_optimizer_thread.stop()
|
||||||
|
|
||||||
# 恢复主窗口状态
|
# 恢复主窗口状态
|
||||||
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("开始安装")
|
||||||
@@ -112,9 +179,9 @@ class CloudflareOptimizer:
|
|||||||
f"已取消 - {self.main_window.APP_NAME}",
|
f"已取消 - {self.main_window.APP_NAME}",
|
||||||
"\n已取消IP优选和安装过程。\n"
|
"\n已取消IP优选和安装过程。\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_optimization_finished(self, ip):
|
def on_ipv4_optimization_finished(self, ip):
|
||||||
"""IP优化完成后的处理
|
"""IPv4优化完成后的处理
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
ip: 优选的IP地址,如果失败则为空字符串
|
ip: 优选的IP地址,如果失败则为空字符串
|
||||||
@@ -124,6 +191,14 @@ class CloudflareOptimizer:
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.optimized_ip = ip
|
self.optimized_ip = ip
|
||||||
|
print(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优选完成...")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 所有优选都已完成,继续处理
|
||||||
self.optimization_done = True
|
self.optimization_done = True
|
||||||
self.countdown_finished = False # 确保倒计时标志重置
|
self.countdown_finished = False # 确保倒计时标志重置
|
||||||
|
|
||||||
@@ -132,15 +207,70 @@ class CloudflareOptimizer:
|
|||||||
if self.optimizing_msg_box.isVisible():
|
if self.optimizing_msg_box.isVisible():
|
||||||
self.optimizing_msg_box.accept()
|
self.optimizing_msg_box.accept()
|
||||||
self.optimizing_msg_box = None
|
self.optimizing_msg_box = None
|
||||||
|
|
||||||
# 显示优选结果
|
# 处理优选结果
|
||||||
if not ip:
|
self._process_optimization_results()
|
||||||
# 临时启用窗口以显示对话框
|
|
||||||
self.main_window.setEnabled(True)
|
|
||||||
|
|
||||||
|
def on_ipv6_optimization_finished(self, ipv6):
|
||||||
|
"""IPv6优化完成后的处理
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ipv6: 优选的IPv6地址,如果失败则为空字符串
|
||||||
|
"""
|
||||||
|
# 如果已经取消,则不继续处理
|
||||||
|
if hasattr(self, 'optimization_cancelled') and self.optimization_cancelled:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.optimized_ipv6 = ipv6
|
||||||
|
print(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优选完成...")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 所有优选都已完成,继续处理
|
||||||
|
self.optimization_done = True
|
||||||
|
self.countdown_finished = False # 确保倒计时标志重置
|
||||||
|
|
||||||
|
# 关闭提示框
|
||||||
|
if hasattr(self, 'optimizing_msg_box') and self.optimizing_msg_box:
|
||||||
|
if self.optimizing_msg_box.isVisible():
|
||||||
|
self.optimizing_msg_box.accept()
|
||||||
|
self.optimizing_msg_box = None
|
||||||
|
|
||||||
|
# 处理优选结果
|
||||||
|
self._process_optimization_results()
|
||||||
|
|
||||||
|
def _process_optimization_results(self):
|
||||||
|
"""处理优选的IP结果,显示相应提示"""
|
||||||
|
use_ipv6 = False
|
||||||
|
if hasattr(self.main_window, 'config'):
|
||||||
|
use_ipv6 = self.main_window.config.get("ipv6_enabled", False)
|
||||||
|
|
||||||
|
# 判断优选结果
|
||||||
|
ipv4_success = bool(self.optimized_ip)
|
||||||
|
ipv6_success = bool(self.optimized_ipv6) if use_ipv6 else False
|
||||||
|
|
||||||
|
# 临时启用窗口以显示对话框
|
||||||
|
self.main_window.setEnabled(True)
|
||||||
|
|
||||||
|
hostname = urlparse(self.main_window.current_url).hostname if hasattr(self.main_window, 'current_url') else None
|
||||||
|
|
||||||
|
if not ipv4_success and (not use_ipv6 or not ipv6_success):
|
||||||
|
# 两种IP都没有优选成功
|
||||||
msg_box = QtWidgets.QMessageBox(self.main_window)
|
msg_box = QtWidgets.QMessageBox(self.main_window)
|
||||||
msg_box.setWindowTitle(f"优选失败 - {self.main_window.APP_NAME}")
|
msg_box.setWindowTitle(f"优选失败 - {self.main_window.APP_NAME}")
|
||||||
msg_box.setText("\n未能找到合适的Cloudflare IP,将使用默认网络进行下载。\n\n10秒后自动继续...")
|
|
||||||
|
fail_message = "\n未能找到合适的Cloudflare "
|
||||||
|
if use_ipv6:
|
||||||
|
fail_message += "IPv4和IPv6地址"
|
||||||
|
else:
|
||||||
|
fail_message += "IP地址"
|
||||||
|
|
||||||
|
fail_message += ",将使用默认网络进行下载。\n\n10秒后自动继续..."
|
||||||
|
|
||||||
|
msg_box.setText(fail_message)
|
||||||
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
||||||
ok_button = msg_box.addButton("确定 (10)", QtWidgets.QMessageBox.ButtonRole.AcceptRole)
|
ok_button = msg_box.addButton("确定 (10)", QtWidgets.QMessageBox.ButtonRole.AcceptRole)
|
||||||
cancel_button = msg_box.addButton("取消安装", QtWidgets.QMessageBox.ButtonRole.RejectRole)
|
cancel_button = msg_box.addButton("取消安装", QtWidgets.QMessageBox.ButtonRole.RejectRole)
|
||||||
@@ -180,20 +310,32 @@ class CloudflareOptimizer:
|
|||||||
self.countdown_finished = True
|
self.countdown_finished = True
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# 应用优选IP到hosts文件
|
# 至少有一种IP优选成功
|
||||||
hostname = urlparse(self.main_window.current_url).hostname if hasattr(self.main_window, 'current_url') else None
|
success_message = ""
|
||||||
|
if ipv4_success:
|
||||||
|
success_message += f"IPv4: {self.optimized_ip}\n"
|
||||||
|
|
||||||
|
if ipv6_success:
|
||||||
|
success_message += f"IPv6: {self.optimized_ipv6}\n"
|
||||||
|
|
||||||
if hostname:
|
if hostname:
|
||||||
# 先清理可能存在的旧记录
|
# 先清理可能存在的旧记录
|
||||||
self.hosts_manager.clean_hostname_entries(hostname)
|
self.hosts_manager.clean_hostname_entries(hostname)
|
||||||
|
|
||||||
# 临时启用窗口以显示对话框
|
success = False
|
||||||
self.main_window.setEnabled(True)
|
|
||||||
|
|
||||||
if self.hosts_manager.apply_ip(hostname, ip):
|
# 应用优选IP到hosts文件
|
||||||
|
if ipv4_success:
|
||||||
|
success = self.hosts_manager.apply_ip(hostname, self.optimized_ip) or success
|
||||||
|
|
||||||
|
# 如果启用IPv6并且找到了IPv6地址,也应用到hosts
|
||||||
|
if ipv6_success:
|
||||||
|
success = self.hosts_manager.apply_ip(hostname, self.optimized_ipv6) or success
|
||||||
|
|
||||||
|
if success:
|
||||||
msg_box = QtWidgets.QMessageBox(self.main_window)
|
msg_box = QtWidgets.QMessageBox(self.main_window)
|
||||||
msg_box.setWindowTitle(f"成功 - {self.main_window.APP_NAME}")
|
msg_box.setWindowTitle(f"成功 - {self.main_window.APP_NAME}")
|
||||||
msg_box.setText(f"\n已将优选IP ({ip}) 应用到hosts文件。\n\n10秒后自动继续...")
|
msg_box.setText(f"\n已将优选IP应用到hosts文件:\n{success_message}\n10秒后自动继续...")
|
||||||
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Information)
|
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Information)
|
||||||
ok_button = msg_box.addButton("确定 (10)", QtWidgets.QMessageBox.ButtonRole.AcceptRole)
|
ok_button = msg_box.addButton("确定 (10)", QtWidgets.QMessageBox.ButtonRole.AcceptRole)
|
||||||
cancel_button = msg_box.addButton("取消安装", QtWidgets.QMessageBox.ButtonRole.RejectRole)
|
cancel_button = msg_box.addButton("取消安装", QtWidgets.QMessageBox.ButtonRole.RejectRole)
|
||||||
@@ -248,7 +390,12 @@ class CloudflareOptimizer:
|
|||||||
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():
|
||||||
self.ip_optimizer_thread.stop()
|
self.ip_optimizer_thread.stop()
|
||||||
self.ip_optimizer_thread.wait()
|
self.ip_optimizer_thread.wait()
|
||||||
if hasattr(self, 'optimizing_msg_box') and self.optimizing_msg_box:
|
|
||||||
if self.optimizing_msg_box.isVisible():
|
if hasattr(self, 'ipv6_optimizer_thread') and self.ipv6_optimizer_thread and self.ipv6_optimizer_thread.isRunning():
|
||||||
self.optimizing_msg_box.accept()
|
self.ipv6_optimizer_thread.stop()
|
||||||
self.optimizing_msg_box = None
|
self.ipv6_optimizer_thread.wait()
|
||||||
|
|
||||||
|
if hasattr(self, 'optimizing_msg_box') and self.optimizing_msg_box:
|
||||||
|
if self.optimizing_msg_box.isVisible():
|
||||||
|
self.optimizing_msg_box.accept()
|
||||||
|
self.optimizing_msg_box = None
|
||||||
@@ -279,6 +279,21 @@ class UIManager:
|
|||||||
self.hosts_submenu.setFont(menu_font)
|
self.hosts_submenu.setFont(menu_font)
|
||||||
self.hosts_submenu.setStyleSheet(menu_style)
|
self.hosts_submenu.setStyleSheet(menu_style)
|
||||||
|
|
||||||
|
# 添加IPv6支持选项
|
||||||
|
self.ipv6_action = QAction("启用IPv6支持", self.main_window, checkable=True)
|
||||||
|
self.ipv6_action.setFont(menu_font)
|
||||||
|
|
||||||
|
# 检查配置中是否已启用IPv6
|
||||||
|
config = getattr(self.main_window, 'config', {})
|
||||||
|
ipv6_enabled = False
|
||||||
|
if isinstance(config, dict):
|
||||||
|
ipv6_enabled = config.get("ipv6_enabled", False)
|
||||||
|
|
||||||
|
self.ipv6_action.setChecked(ipv6_enabled)
|
||||||
|
|
||||||
|
# 连接IPv6支持切换事件
|
||||||
|
self.ipv6_action.triggered.connect(self.toggle_ipv6_support)
|
||||||
|
|
||||||
# 添加hosts子选项
|
# 添加hosts子选项
|
||||||
self.restore_hosts_action = QAction("还原软件备份的hosts文件", self.main_window)
|
self.restore_hosts_action = QAction("还原软件备份的hosts文件", self.main_window)
|
||||||
self.restore_hosts_action.setFont(menu_font)
|
self.restore_hosts_action.setFont(menu_font)
|
||||||
@@ -350,6 +365,7 @@ class UIManager:
|
|||||||
# 添加Debug子菜单到开发者选项菜单
|
# 添加Debug子菜单到开发者选项菜单
|
||||||
self.dev_menu.addMenu(self.debug_submenu)
|
self.dev_menu.addMenu(self.debug_submenu)
|
||||||
self.dev_menu.addMenu(self.hosts_submenu) # 添加hosts文件选项子菜单
|
self.dev_menu.addMenu(self.hosts_submenu) # 添加hosts文件选项子菜单
|
||||||
|
self.dev_menu.addAction(self.ipv6_action) # 添加IPv6支持选项
|
||||||
|
|
||||||
def show_menu(self, menu, button):
|
def show_menu(self, menu, button):
|
||||||
"""显示菜单
|
"""显示菜单
|
||||||
@@ -539,6 +555,53 @@ class UIManager:
|
|||||||
)
|
)
|
||||||
msg_box.exec()
|
msg_box.exec()
|
||||||
|
|
||||||
|
def toggle_ipv6_support(self, enabled):
|
||||||
|
"""切换IPv6支持
|
||||||
|
|
||||||
|
Args:
|
||||||
|
enabled: 是否启用IPv6支持
|
||||||
|
"""
|
||||||
|
print(f"Toggle IPv6 support: {enabled}")
|
||||||
|
|
||||||
|
# 如果用户尝试启用IPv6,检查系统是否支持IPv6
|
||||||
|
if enabled:
|
||||||
|
# 检查是否可以访问IPv6
|
||||||
|
import socket
|
||||||
|
ipv6_supported = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 尝试创建一个IPv6套接字
|
||||||
|
socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
|
ipv6_supported = True
|
||||||
|
except Exception:
|
||||||
|
ipv6_supported = False
|
||||||
|
|
||||||
|
if not ipv6_supported:
|
||||||
|
msg_box = msgbox_frame(
|
||||||
|
f"错误 - {APP_NAME}",
|
||||||
|
"\n找不到IPv6地址,您的系统可能不支持IPv6。\n",
|
||||||
|
QMessageBox.StandardButton.Ok,
|
||||||
|
)
|
||||||
|
msg_box.exec()
|
||||||
|
|
||||||
|
# 恢复复选框状态
|
||||||
|
self.ipv6_action.setChecked(False)
|
||||||
|
return
|
||||||
|
|
||||||
|
# 保存设置到配置
|
||||||
|
if hasattr(self.main_window, 'config'):
|
||||||
|
self.main_window.config["ipv6_enabled"] = enabled
|
||||||
|
self.main_window.save_config(self.main_window.config)
|
||||||
|
|
||||||
|
# 显示设置已保存的消息
|
||||||
|
status = "启用" if enabled else "禁用"
|
||||||
|
msg_box = msgbox_frame(
|
||||||
|
f"IPv6设置 - {APP_NAME}",
|
||||||
|
f"\nIPv6支持已{status}。新的设置将在下一次下载时生效。\n",
|
||||||
|
QMessageBox.StandardButton.Ok,
|
||||||
|
)
|
||||||
|
msg_box.exec()
|
||||||
|
|
||||||
def clean_hosts_entries(self):
|
def clean_hosts_entries(self):
|
||||||
"""手动删除软件添加的hosts条目"""
|
"""手动删除软件添加的hosts条目"""
|
||||||
if hasattr(self.main_window, 'download_manager') and hasattr(self.main_window.download_manager, 'hosts_manager'):
|
if hasattr(self.main_window, 'download_manager') and hasattr(self.main_window.download_manager, 'hosts_manager'):
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -177,6 +177,14 @@ class DownloadThread(QThread):
|
|||||||
if hasattr(self.parent(), 'download_manager'):
|
if hasattr(self.parent(), 'download_manager'):
|
||||||
# 从下载管理器获取线程数设置
|
# 从下载管理器获取线程数设置
|
||||||
thread_count = self.parent().download_manager.get_download_thread_count()
|
thread_count = self.parent().download_manager.get_download_thread_count()
|
||||||
|
|
||||||
|
# 检查是否启用IPv6支持
|
||||||
|
ipv6_enabled = False
|
||||||
|
if hasattr(self.parent(), 'config'):
|
||||||
|
ipv6_enabled = self.parent().config.get("ipv6_enabled", False)
|
||||||
|
|
||||||
|
# 打印IPv6状态
|
||||||
|
print(f"IPv6支持状态: {ipv6_enabled}")
|
||||||
|
|
||||||
# 将所有的优化参数应用于每个下载任务
|
# 将所有的优化参数应用于每个下载任务
|
||||||
command.extend([
|
command.extend([
|
||||||
@@ -210,9 +218,15 @@ class DownloadThread(QThread):
|
|||||||
'--optimize-concurrent-downloads=true', # 优化并发下载
|
'--optimize-concurrent-downloads=true', # 优化并发下载
|
||||||
'--file-allocation=none', # 禁用文件预分配加快开始
|
'--file-allocation=none', # 禁用文件预分配加快开始
|
||||||
'--async-dns=true', # 使用异步DNS
|
'--async-dns=true', # 使用异步DNS
|
||||||
'--disable-ipv6=true', # 禁用IPv6提高速度
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# 根据IPv6设置决定是否禁用IPv6
|
||||||
|
if not ipv6_enabled:
|
||||||
|
command.append('--disable-ipv6=true')
|
||||||
|
print("已禁用IPv6支持")
|
||||||
|
else:
|
||||||
|
print("已启用IPv6支持")
|
||||||
|
|
||||||
# 证书验证现在总是需要,因为我们依赖hosts文件
|
# 证书验证现在总是需要,因为我们依赖hosts文件
|
||||||
command.append('--check-certificate=false')
|
command.append('--check-certificate=false')
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ class IpOptimizer:
|
|||||||
# 正确的参数设置,根据cfst帮助文档
|
# 正确的参数设置,根据cfst帮助文档
|
||||||
command = [
|
command = [
|
||||||
cst_path,
|
cst_path,
|
||||||
"-n", "500", # 延迟测速线程数 (默认200)
|
"-n", "1000", # 延迟测速线程数 (默认200)
|
||||||
"-p", "1", # 显示结果数量 (默认10个)
|
"-p", "1", # 显示结果数量 (默认10个)
|
||||||
"-url", url, # 指定测速地址
|
"-url", url, # 指定测速地址
|
||||||
"-f", ip_txt_path, # IP文件
|
"-f", ip_txt_path, # IP文件
|
||||||
"-dd", # 禁用下载测速,按延迟排序
|
"-dd", # 禁用下载测速,按延迟排序
|
||||||
"-o","" # 不写入结果文件
|
"-o"," " # 不写入结果文件
|
||||||
]
|
]
|
||||||
|
|
||||||
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
||||||
@@ -145,6 +145,142 @@ class IpOptimizer:
|
|||||||
print(f"执行 CloudflareSpeedTest 时发生错误: {e}")
|
print(f"执行 CloudflareSpeedTest 时发生错误: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_optimal_ipv6(self, url: str) -> str | None:
|
||||||
|
"""
|
||||||
|
使用 CloudflareSpeedTest 工具获取给定 URL 的最优 Cloudflare IPv6 地址。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url: 需要进行优选的下载链接。
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
最优的 IPv6 地址字符串,如果找不到则返回 None。
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
cst_path = resource_path("cfst.exe")
|
||||||
|
if not os.path.exists(cst_path):
|
||||||
|
print(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 未在资源路径中找到。")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 正确的参数设置,根据cfst帮助文档
|
||||||
|
command = [
|
||||||
|
cst_path,
|
||||||
|
"-n", "1000", # 延迟测速线程数,IPv6测试线程稍少
|
||||||
|
"-p", "1", # 显示结果数量 (默认10个)
|
||||||
|
"-url", url, # 指定测速地址
|
||||||
|
"-f", ipv6_txt_path, # IPv6文件
|
||||||
|
"-dd", # 禁用下载测速,按延迟排序
|
||||||
|
"-o", " " # 不写入结果文件
|
||||||
|
]
|
||||||
|
|
||||||
|
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0
|
||||||
|
|
||||||
|
print("--- CloudflareSpeedTest IPv6 开始执行 ---")
|
||||||
|
|
||||||
|
self.process = subprocess.Popen(
|
||||||
|
command,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
text=True,
|
||||||
|
encoding='utf-8',
|
||||||
|
errors='replace',
|
||||||
|
creationflags=creation_flags,
|
||||||
|
bufsize=0
|
||||||
|
)
|
||||||
|
|
||||||
|
# 更新正则表达式以匹配cfst输出中的IPv6格式
|
||||||
|
# IPv6格式更加复杂,可能有多种表示形式
|
||||||
|
ipv6_pattern = re.compile(r'^([0-9a-fA-F:]+)\s+.*')
|
||||||
|
|
||||||
|
# 标记是否已经找到结果表头和完成标记
|
||||||
|
found_header = False
|
||||||
|
found_completion = False
|
||||||
|
|
||||||
|
stdout = self.process.stdout
|
||||||
|
if not stdout:
|
||||||
|
print("错误: 无法获取子进程的输出流。")
|
||||||
|
return None
|
||||||
|
|
||||||
|
optimal_ipv6 = None
|
||||||
|
timeout_counter = 0
|
||||||
|
max_timeout = 300 # 增加超时时间到5分钟
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if self.process.poll() is not None:
|
||||||
|
break
|
||||||
|
try:
|
||||||
|
ready = True
|
||||||
|
try:
|
||||||
|
line = stdout.readline()
|
||||||
|
except:
|
||||||
|
ready = False
|
||||||
|
|
||||||
|
if not ready or not line:
|
||||||
|
timeout_counter += 1
|
||||||
|
if timeout_counter > max_timeout:
|
||||||
|
print("超时: CloudflareSpeedTest IPv6 响应超时")
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
continue
|
||||||
|
|
||||||
|
timeout_counter = 0
|
||||||
|
|
||||||
|
cleaned_line = line.strip()
|
||||||
|
if cleaned_line:
|
||||||
|
print(cleaned_line)
|
||||||
|
|
||||||
|
# 检测结果表头
|
||||||
|
if "IP 地址" in cleaned_line and "平均延迟" in cleaned_line:
|
||||||
|
print("检测到IPv6结果表头,准备获取IPv6地址...")
|
||||||
|
found_header = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 检测完成标记
|
||||||
|
if "完整测速结果已写入" in cleaned_line or "按下 回车键 或 Ctrl+C 退出" in cleaned_line:
|
||||||
|
print("检测到IPv6测速完成信息")
|
||||||
|
found_completion = True
|
||||||
|
|
||||||
|
# 如果已经找到了IPv6,可以退出了
|
||||||
|
if optimal_ipv6:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 已找到表头后,尝试匹配IPv6地址行
|
||||||
|
if found_header:
|
||||||
|
match = ipv6_pattern.search(cleaned_line)
|
||||||
|
if match and not optimal_ipv6: # 只保存第一个匹配的IPv6(最优IPv6)
|
||||||
|
optimal_ipv6 = match.group(1)
|
||||||
|
print(f"找到最优 IPv6: {optimal_ipv6}")
|
||||||
|
# 找到最优IPv6后立即退出循环,不等待完成标记
|
||||||
|
break
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"读取输出时发生错误: {e}")
|
||||||
|
break
|
||||||
|
|
||||||
|
# 确保完全读取输出后再发送退出信号
|
||||||
|
if self.process and self.process.poll() is None:
|
||||||
|
try:
|
||||||
|
if self.process.stdin and not self.process.stdin.closed:
|
||||||
|
print("发送退出信号...")
|
||||||
|
self.process.stdin.write('\n')
|
||||||
|
self.process.stdin.flush()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
print("--- CloudflareSpeedTest IPv6 执行结束 ---")
|
||||||
|
return optimal_ipv6
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"执行 CloudflareSpeedTest IPv6 时发生错误: {e}")
|
||||||
|
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 进程...")
|
print("正在终止 CloudflareSpeedTest 进程...")
|
||||||
@@ -169,13 +305,17 @@ class IpOptimizerThread(QThread):
|
|||||||
"""用于在后台线程中运行IP优化的类"""
|
"""用于在后台线程中运行IP优化的类"""
|
||||||
finished = Signal(str)
|
finished = Signal(str)
|
||||||
|
|
||||||
def __init__(self, url, parent=None):
|
def __init__(self, url, parent=None, use_ipv6=False):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.url = url
|
self.url = url
|
||||||
self.optimizer = IpOptimizer()
|
self.optimizer = IpOptimizer()
|
||||||
|
self.use_ipv6 = use_ipv6
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
optimal_ip = self.optimizer.get_optimal_ip(self.url)
|
if self.use_ipv6:
|
||||||
|
optimal_ip = self.optimizer.get_optimal_ipv6(self.url)
|
||||||
|
else:
|
||||||
|
optimal_ip = self.optimizer.get_optimal_ip(self.url)
|
||||||
self.finished.emit(optimal_ip if optimal_ip else "")
|
self.finished.emit(optimal_ip if optimal_ip else "")
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user