mirror of
https://github.com/hyb-oyqq/FRAISEMOE-Addons-Installer-NEXT.git
synced 2025-12-16 11:50:29 +00:00
feat(core): 增强hosts管理功能和自动还原设置
- 添加对hosts文件优选IP记录的检查,避免重复优选。 - 添加禁用自动还原hosts的选项,允许用户自定义设置。 - 更新HostsManager以支持自动还原状态的设置和检查,优化hosts文件的管理逻辑。
This commit is contained in:
@@ -28,6 +28,7 @@ class CloudflareOptimizer:
|
||||
self.optimization_cancelled = False
|
||||
self.ip_optimizer_thread = None
|
||||
self.ipv6_optimizer_thread = None
|
||||
self.has_optimized_in_session = False # 本次启动是否已执行过优选
|
||||
|
||||
def is_optimization_done(self):
|
||||
"""检查是否已完成优化
|
||||
@@ -67,6 +68,39 @@ class CloudflareOptimizer:
|
||||
Args:
|
||||
url: 用于优化的URL
|
||||
"""
|
||||
# 解析域名
|
||||
hostname = urlparse(url).hostname
|
||||
|
||||
# 检查hosts文件中是否已有该域名的IP记录
|
||||
existing_ips = self.hosts_manager.get_hostname_entries(hostname) if hostname else []
|
||||
|
||||
# 判断是否继续优选的逻辑
|
||||
if existing_ips and self.has_optimized_in_session:
|
||||
# 如果本次会话中已执行过优选且hosts中存在记录,则跳过优选过程
|
||||
print(f"发现hosts文件中已有域名 {hostname} 的优选IP记录且本次会话已优选过,跳过优选过程")
|
||||
|
||||
# 设置标记为已优选完成
|
||||
self.optimization_done = True
|
||||
self.countdown_finished = True
|
||||
|
||||
# 尝试获取现有的IPv4和IPv6地址
|
||||
ipv4_entries = [ip for ip in existing_ips if ':' not in ip] # IPv4地址不含冒号
|
||||
ipv6_entries = [ip for ip in existing_ips if ':' in ip] # IPv6地址包含冒号
|
||||
|
||||
if ipv4_entries:
|
||||
self.optimized_ip = ipv4_entries[0]
|
||||
if ipv6_entries:
|
||||
self.optimized_ipv6 = ipv6_entries[0]
|
||||
|
||||
print(f"使用已存在的优选IP - IPv4: {self.optimized_ip}, IPv6: {self.optimized_ipv6}")
|
||||
return True
|
||||
else:
|
||||
# 如果本次会话尚未优选过,或hosts中没有记录,则显示优选窗口
|
||||
if existing_ips:
|
||||
print(f"发现hosts文件中已有域名 {hostname} 的优选IP记录,但本次会话尚未优选过")
|
||||
# 清理已有的hosts记录,准备重新优选
|
||||
self.hosts_manager.clean_hostname_entries(hostname)
|
||||
|
||||
# 创建取消状态标记
|
||||
self.optimization_cancelled = False
|
||||
self.countdown_finished = False
|
||||
@@ -332,6 +366,15 @@ class CloudflareOptimizer:
|
||||
if ipv6_success:
|
||||
success = self.hosts_manager.apply_ip(hostname, self.optimized_ipv6, clean=False) or success
|
||||
|
||||
# 记录此次优选操作对hosts文件进行了更新
|
||||
if hasattr(self.main_window, 'config'):
|
||||
self.main_window.config['last_hosts_optimized_hostname'] = hostname
|
||||
from utils import save_config
|
||||
save_config(self.main_window.config)
|
||||
|
||||
# 记录本次会话已执行过优选
|
||||
self.has_optimized_in_session = True
|
||||
|
||||
if success:
|
||||
msg_box = QtWidgets.QMessageBox(self.main_window)
|
||||
msg_box.setWindowTitle(f"成功 - {self.main_window.APP_NAME}")
|
||||
|
||||
@@ -406,6 +406,38 @@ class DownloadManager:
|
||||
|
||||
def _show_cloudflare_option(self):
|
||||
"""显示Cloudflare加速选择对话框"""
|
||||
# 首先检查队列中第一个URL的域名是否已在hosts中有优选IP
|
||||
if self.download_queue:
|
||||
first_url = self.download_queue[0][0]
|
||||
hostname = urlparse(first_url).hostname
|
||||
|
||||
# 检查hosts文件中是否已有该域名的IP记录
|
||||
if hostname:
|
||||
existing_ips = self.cloudflare_optimizer.hosts_manager.get_hostname_entries(hostname)
|
||||
|
||||
if existing_ips:
|
||||
print(f"发现hosts文件中已有域名 {hostname} 的优选IP记录,跳过询问直接使用")
|
||||
|
||||
# 设置标记为已优选完成
|
||||
self.cloudflare_optimizer.optimization_done = True
|
||||
self.cloudflare_optimizer.countdown_finished = True
|
||||
|
||||
# 尝试获取现有的IPv4和IPv6地址
|
||||
ipv4_entries = [ip for ip in existing_ips if ':' not in ip]
|
||||
ipv6_entries = [ip for ip in existing_ips if ':' in ip]
|
||||
|
||||
if ipv4_entries:
|
||||
self.cloudflare_optimizer.optimized_ip = ipv4_entries[0]
|
||||
if ipv6_entries:
|
||||
self.cloudflare_optimizer.optimized_ipv6 = ipv6_entries[0]
|
||||
|
||||
# 保存当前URL供CloudflareOptimizer使用
|
||||
self.main_window.current_url = first_url
|
||||
|
||||
# 直接开始下载,跳过询问
|
||||
self.next_download_task()
|
||||
return
|
||||
|
||||
# 临时启用窗口以显示对话框
|
||||
self.main_window.setEnabled(True)
|
||||
|
||||
|
||||
@@ -341,12 +341,26 @@ class UIManager:
|
||||
self.clean_hosts_action.setFont(menu_font)
|
||||
self.clean_hosts_action.triggered.connect(self.clean_hosts_entries)
|
||||
|
||||
# 添加禁用自动还原hosts的选项
|
||||
self.disable_auto_restore_action = QAction("禁用关闭/重启自动还原hosts", self.main_window, checkable=True)
|
||||
self.disable_auto_restore_action.setFont(menu_font)
|
||||
|
||||
# 从配置中读取当前状态
|
||||
config = getattr(self.main_window, 'config', {})
|
||||
disable_auto_restore = False
|
||||
if isinstance(config, dict):
|
||||
disable_auto_restore = config.get("disable_auto_restore_hosts", False)
|
||||
|
||||
self.disable_auto_restore_action.setChecked(disable_auto_restore)
|
||||
self.disable_auto_restore_action.triggered.connect(self.toggle_disable_auto_restore_hosts)
|
||||
|
||||
# 添加打开hosts文件选项
|
||||
self.open_hosts_action = QAction("打开hosts文件", self.main_window)
|
||||
self.open_hosts_action.setFont(menu_font)
|
||||
self.open_hosts_action.triggered.connect(self.open_hosts_file)
|
||||
|
||||
# 添加到hosts子菜单
|
||||
self.hosts_submenu.addAction(self.disable_auto_restore_action)
|
||||
self.hosts_submenu.addAction(self.restore_hosts_action)
|
||||
self.hosts_submenu.addAction(self.clean_hosts_action)
|
||||
self.hosts_submenu.addAction(self.open_hosts_action)
|
||||
@@ -645,6 +659,54 @@ class UIManager:
|
||||
msg_box = self._create_message_box("错误", f"\n打开hosts文件时发生错误:\n\n{str(e)}\n")
|
||||
msg_box.exec()
|
||||
|
||||
def toggle_disable_auto_restore_hosts(self, checked):
|
||||
"""切换禁用自动还原hosts的状态
|
||||
|
||||
Args:
|
||||
checked: 是否禁用自动还原
|
||||
"""
|
||||
if hasattr(self.main_window, 'download_manager') and hasattr(self.main_window.download_manager, 'hosts_manager'):
|
||||
try:
|
||||
# 调用HostsManager的方法设置自动还原标志
|
||||
result = self.main_window.download_manager.hosts_manager.set_auto_restore_disabled(checked)
|
||||
|
||||
if result:
|
||||
# 同时更新内部配置,确保立即生效
|
||||
if hasattr(self.main_window, 'config'):
|
||||
self.main_window.config['disable_auto_restore_hosts'] = checked
|
||||
|
||||
# 显示成功提示
|
||||
status = "禁用" if checked else "启用"
|
||||
msg_box = self._create_message_box(
|
||||
"设置已更新",
|
||||
f"\n已{status}关闭/重启时自动还原hosts。\n\n{'hosts将被保留' if checked else 'hosts将在关闭时自动还原'}。\n"
|
||||
)
|
||||
msg_box.exec()
|
||||
else:
|
||||
# 如果设置失败,恢复复选框状态
|
||||
self.disable_auto_restore_action.setChecked(not checked)
|
||||
msg_box = self._create_message_box(
|
||||
"设置失败",
|
||||
"\n更新设置时发生错误,请稍后再试。\n"
|
||||
)
|
||||
msg_box.exec()
|
||||
except Exception as e:
|
||||
# 如果发生异常,恢复复选框状态
|
||||
self.disable_auto_restore_action.setChecked(not checked)
|
||||
msg_box = self._create_message_box(
|
||||
"错误",
|
||||
f"\n更新设置时发生异常:\n\n{str(e)}\n"
|
||||
)
|
||||
msg_box.exec()
|
||||
else:
|
||||
# 如果hosts管理器不可用,恢复复选框状态
|
||||
self.disable_auto_restore_action.setChecked(not checked)
|
||||
msg_box = self._create_message_box(
|
||||
"错误",
|
||||
"\nhosts管理器不可用,无法更新设置。\n"
|
||||
)
|
||||
msg_box.exec()
|
||||
|
||||
def show_about_dialog(self):
|
||||
"""显示关于对话框"""
|
||||
about_text = f"""
|
||||
|
||||
@@ -3,7 +3,7 @@ import base64
|
||||
|
||||
# 配置信息
|
||||
app_data = {
|
||||
"APP_VERSION": "1.3.1",
|
||||
"APP_VERSION": "1.3.2",
|
||||
"APP_NAME": "FRAISEMOE Addons Installer NEXT",
|
||||
"TEMP": "TEMP",
|
||||
"CACHE": "FRAISEMOE",
|
||||
|
||||
@@ -456,10 +456,10 @@ class MainWindow(QMainWindow):
|
||||
event.ignore()
|
||||
return
|
||||
|
||||
# 恢复hosts文件
|
||||
# 恢复hosts文件(如果未禁用自动还原)
|
||||
self.download_manager.hosts_manager.restore()
|
||||
|
||||
# 额外检查并清理hosts文件中的残留记录
|
||||
# 额外检查并清理hosts文件中的残留记录(如果未禁用自动还原)
|
||||
self.download_manager.hosts_manager.check_and_clean_all_entries()
|
||||
|
||||
# 停止日志记录
|
||||
|
||||
@@ -273,7 +273,53 @@ class HostsManager:
|
||||
self.original_content = None
|
||||
self.modified = False
|
||||
self.modified_hostnames = set() # 跟踪被修改的主机名
|
||||
self.auto_restore_disabled = False # 是否禁用自动还原hosts
|
||||
|
||||
def get_hostname_entries(self, hostname):
|
||||
"""获取hosts文件中指定域名的所有IP记录
|
||||
|
||||
Args:
|
||||
hostname: 要查询的域名
|
||||
|
||||
Returns:
|
||||
list: 域名对应的IP地址列表,如果未找到则返回空列表
|
||||
"""
|
||||
try:
|
||||
# 如果original_content为空,先读取hosts文件
|
||||
if not self.original_content:
|
||||
try:
|
||||
with open(self.hosts_path, 'r', encoding='utf-8') as f:
|
||||
self.original_content = f.read()
|
||||
except Exception as e:
|
||||
print(f"读取hosts文件失败: {e}")
|
||||
return []
|
||||
|
||||
# 解析hosts文件中的每一行
|
||||
ip_addresses = []
|
||||
lines = self.original_content.splitlines()
|
||||
|
||||
for line in lines:
|
||||
# 跳过注释和空行
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
|
||||
# 分割行内容获取IP和域名
|
||||
parts = line.split()
|
||||
if len(parts) >= 2: # 至少包含IP和一个域名
|
||||
ip = parts[0]
|
||||
domains = parts[1:]
|
||||
|
||||
# 如果当前行包含目标域名
|
||||
if hostname in domains:
|
||||
ip_addresses.append(ip)
|
||||
|
||||
return ip_addresses
|
||||
|
||||
except Exception as e:
|
||||
print(f"获取hosts记录失败: {e}")
|
||||
return []
|
||||
|
||||
def backup(self):
|
||||
if not AdminPrivileges().is_admin():
|
||||
print("需要管理员权限来备份hosts文件。")
|
||||
@@ -373,12 +419,58 @@ class HostsManager:
|
||||
msg_box.exec()
|
||||
return False
|
||||
|
||||
def set_auto_restore_disabled(self, disabled):
|
||||
"""设置是否禁用自动还原hosts
|
||||
|
||||
Args:
|
||||
disabled: 是否禁用自动还原hosts
|
||||
|
||||
Returns:
|
||||
bool: 操作是否成功
|
||||
"""
|
||||
try:
|
||||
# 更新状态
|
||||
self.auto_restore_disabled = disabled
|
||||
|
||||
# 从配置文件读取当前配置
|
||||
from utils import load_config, save_config
|
||||
config = load_config()
|
||||
|
||||
# 更新配置
|
||||
config['disable_auto_restore_hosts'] = disabled
|
||||
|
||||
# 保存配置
|
||||
save_config(config)
|
||||
|
||||
print(f"已{'禁用' if disabled else '启用'}自动还原hosts")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"设置自动还原hosts状态失败: {e}")
|
||||
return False
|
||||
|
||||
def is_auto_restore_disabled(self):
|
||||
"""检查是否禁用了自动还原hosts
|
||||
|
||||
Returns:
|
||||
bool: 是否禁用自动还原hosts
|
||||
"""
|
||||
from utils import load_config
|
||||
config = load_config()
|
||||
auto_restore_disabled = config.get('disable_auto_restore_hosts', False)
|
||||
self.auto_restore_disabled = auto_restore_disabled
|
||||
return auto_restore_disabled
|
||||
|
||||
def check_and_clean_all_entries(self):
|
||||
"""检查并清理所有由本应用程序添加的hosts记录
|
||||
|
||||
Returns:
|
||||
bool: 清理是否成功
|
||||
"""
|
||||
# 如果禁用了自动还原,则不执行清理操作
|
||||
if self.is_auto_restore_disabled():
|
||||
print("已禁用自动还原hosts,跳过清理操作")
|
||||
return True
|
||||
|
||||
if not AdminPrivileges().is_admin():
|
||||
print("需要管理员权限来检查和清理hosts文件。")
|
||||
return False
|
||||
@@ -423,6 +515,11 @@ class HostsManager:
|
||||
return False
|
||||
|
||||
def restore(self):
|
||||
# 如果禁用了自动还原,则不执行还原操作
|
||||
if self.is_auto_restore_disabled():
|
||||
print("已禁用自动还原hosts,跳过还原操作")
|
||||
return True
|
||||
|
||||
if not self.modified:
|
||||
if os.path.exists(self.backup_path):
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user