Files
FRAISEMOE-Addons-Installer-…/source/core/cloudflare_optimizer.py

254 lines
10 KiB
Python
Raw Normal View History

import os
from urllib.parse import urlparse
from PySide6 import QtWidgets
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QIcon, QPixmap
from utils import msgbox_frame, resource_path
from workers import IpOptimizerThread
class CloudflareOptimizer:
"""Cloudflare IP优化器负责处理IP优化和Cloudflare加速相关功能"""
def __init__(self, main_window, hosts_manager):
"""初始化Cloudflare优化器
Args:
main_window: 主窗口实例用于访问UI和状态
hosts_manager: Hosts文件管理器实例
"""
self.main_window = main_window
self.hosts_manager = hosts_manager
self.optimized_ip = None
self.optimization_done = False # 标记是否已执行过优选
self.countdown_finished = False # 标记倒计时是否结束
self.optimizing_msg_box = None
self.optimization_cancelled = False
self.ip_optimizer_thread = None
def is_optimization_done(self):
"""检查是否已完成优化
Returns:
bool: 是否已完成优化
"""
return self.optimization_done
def is_countdown_finished(self):
"""检查倒计时是否已完成
Returns:
bool: 倒计时是否已完成
"""
return self.countdown_finished
def get_optimized_ip(self):
"""获取优选的IP地址
Returns:
str: 优选的IP地址如果未优选则为None
"""
return self.optimized_ip
def start_ip_optimization(self, url):
"""开始IP优化过程
Args:
url: 用于优化的URL
"""
# 创建取消状态标记
self.optimization_cancelled = False
self.countdown_finished = False
# 使用Cloudflare图标创建消息框
self.optimizing_msg_box = msgbox_frame(
f"通知 - {self.main_window.APP_NAME}",
"\n正在优选Cloudflare IP请稍候...\n\n这可能需要5-10分钟请耐心等待喵~"
)
# 设置Cloudflare图标
cf_icon_path = resource_path("IMG/ICO/cloudflare_logo_icon.ico")
if os.path.exists(cf_icon_path):
cf_pixmap = QPixmap(cf_icon_path)
if not cf_pixmap.isNull():
self.optimizing_msg_box.setWindowIcon(QIcon(cf_pixmap))
self.optimizing_msg_box.setIconPixmap(cf_pixmap.scaled(64, 64, Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation))
# 添加取消按钮
self.optimizing_msg_box.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Cancel)
self.optimizing_msg_box.buttonClicked.connect(self._on_optimization_dialog_clicked)
self.optimizing_msg_box.setWindowModality(Qt.WindowModality.ApplicationModal)
# 创建并启动优化线程
self.ip_optimizer_thread = IpOptimizerThread(url)
self.ip_optimizer_thread.finished.connect(self.on_optimization_finished)
self.ip_optimizer_thread.start()
# 显示消息框(非模态,不阻塞)
self.optimizing_msg_box.open()
def _on_optimization_dialog_clicked(self, button):
"""处理优化对话框按钮点击
Args:
button: 被点击的按钮
"""
if button.text() == "Cancel": # 如果是取消按钮
# 标记已取消
self.optimization_cancelled = True
# 停止优化线程
if hasattr(self, 'ip_optimizer_thread') and self.ip_optimizer_thread and self.ip_optimizer_thread.isRunning():
self.ip_optimizer_thread.stop()
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
# 显示取消消息
QtWidgets.QMessageBox.information(
self.main_window,
f"已取消 - {self.main_window.APP_NAME}",
"\n已取消IP优选和安装过程。\n"
)
def on_optimization_finished(self, ip):
"""IP优化完成后的处理
Args:
ip: 优选的IP地址如果失败则为空字符串
"""
# 如果已经取消,则不继续处理
if hasattr(self, 'optimization_cancelled') and self.optimization_cancelled:
return
self.optimized_ip = ip
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
# 显示优选结果
if not ip:
# 临时启用窗口以显示对话框
self.main_window.setEnabled(True)
msg_box = QtWidgets.QMessageBox(self.main_window)
msg_box.setWindowTitle(f"优选失败 - {self.main_window.APP_NAME}")
msg_box.setText("\n未能找到合适的Cloudflare IP将使用默认网络进行下载。\n\n10秒后自动继续...")
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Warning)
ok_button = msg_box.addButton("确定 (10)", QtWidgets.QMessageBox.ButtonRole.AcceptRole)
cancel_button = msg_box.addButton("取消安装", QtWidgets.QMessageBox.ButtonRole.RejectRole)
# 创建计时器实现倒计时
countdown = 10
timer = QTimer(self.main_window)
def update_countdown():
nonlocal countdown
countdown -= 1
ok_button.setText(f"确定 ({countdown})")
if countdown <= 0:
timer.stop()
if msg_box.isVisible():
msg_box.accept()
timer.timeout.connect(update_countdown)
timer.start(1000) # 每秒更新一次
# 显示对话框并等待用户响应
result = msg_box.exec()
# 停止计时器
timer.stop()
# 如果用户点击了取消安装
if msg_box.clickedButton() == cancel_button:
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
return False
# 用户点击了继续,重新禁用主窗口
self.main_window.setEnabled(False)
# 标记倒计时已完成
self.countdown_finished = True
return True
else:
# 应用优选IP到hosts文件
hostname = urlparse(self.main_window.current_url).hostname if hasattr(self.main_window, 'current_url') else None
if hostname:
# 先清理可能存在的旧记录
self.hosts_manager.clean_hostname_entries(hostname)
# 临时启用窗口以显示对话框
self.main_window.setEnabled(True)
if self.hosts_manager.apply_ip(hostname, ip):
msg_box = QtWidgets.QMessageBox(self.main_window)
msg_box.setWindowTitle(f"成功 - {self.main_window.APP_NAME}")
msg_box.setText(f"\n已将优选IP ({ip}) 应用到hosts文件。\n\n10秒后自动继续...")
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Information)
ok_button = msg_box.addButton("确定 (10)", QtWidgets.QMessageBox.ButtonRole.AcceptRole)
cancel_button = msg_box.addButton("取消安装", QtWidgets.QMessageBox.ButtonRole.RejectRole)
# 创建计时器实现倒计时
countdown = 10
timer = QTimer(self.main_window)
def update_countdown():
nonlocal countdown
countdown -= 1
ok_button.setText(f"确定 ({countdown})")
if countdown <= 0:
timer.stop()
if msg_box.isVisible():
msg_box.accept()
timer.timeout.connect(update_countdown)
timer.start(1000) # 每秒更新一次
# 显示对话框并等待用户响应
result = msg_box.exec()
# 停止计时器
timer.stop()
# 如果用户点击了取消安装
if msg_box.clickedButton() == cancel_button:
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
return False
else:
QtWidgets.QMessageBox.critical(
self.main_window,
f"错误 - {self.main_window.APP_NAME}",
"\n修改hosts文件失败请检查程序是否以管理员权限运行。\n"
)
# 恢复主窗口状态
self.main_window.ui.start_install_text.setText("开始安装")
return False
# 用户点击了继续,重新禁用主窗口
self.main_window.setEnabled(False)
# 标记倒计时已完成
self.countdown_finished = True
return True
def stop_optimization(self):
"""停止正在进行的IP优化"""
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.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