feat(core): 初步添加IPv6支持和优化功能

- 在CloudflareOptimizer中添加IPv6优化功能,支持同时进行IPv4和IPv6的优选。
- 更新UIManager,增加IPv6支持选项,并实现用户切换功能。
- 在下载线程中检查IPv6支持状态,并根据设置决定是否禁用IPv6。
- 在IP优化器中实现获取最优IPv6地址的功能,优化测速参数设置。
- 改进用户提示信息,确保用户了解IPv6优选的时间和效果。
This commit is contained in:
欧阳淇淇
2025-08-02 01:49:08 +08:00
parent 6399382242
commit 291c471b9e
5 changed files with 391 additions and 41 deletions

View File

@@ -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):
"""检查是否已完成优化 """检查是否已完成优化
@@ -51,6 +53,14 @@ class CloudflareOptimizer:
""" """
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("开始安装")
@@ -113,8 +180,8 @@ class CloudflareOptimizer:
"\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 # 确保倒计时标志重置
@@ -133,14 +208,69 @@ class CloudflareOptimizer:
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()
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) 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,6 +390,11 @@ 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, 'ipv6_optimizer_thread') and self.ipv6_optimizer_thread and self.ipv6_optimizer_thread.isRunning():
self.ipv6_optimizer_thread.stop()
self.ipv6_optimizer_thread.wait()
if hasattr(self, 'optimizing_msg_box') and self.optimizing_msg_box: if hasattr(self, 'optimizing_msg_box') and self.optimizing_msg_box:
if self.optimizing_msg_box.isVisible(): if self.optimizing_msg_box.isVisible():
self.optimizing_msg_box.accept() self.optimizing_msg_box.accept()

View File

@@ -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

View File

@@ -178,6 +178,14 @@ class DownloadThread(QThread):
# 从下载管理器获取线程数设置 # 从下载管理器获取线程数设置
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([
'--dir', download_dir, '--dir', download_dir,
@@ -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')

View File

@@ -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,12 +305,16 @@ 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):
if self.use_ipv6:
optimal_ip = self.optimizer.get_optimal_ipv6(self.url)
else:
optimal_ip = self.optimizer.get_optimal_ip(self.url) 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 "")