Spaces:
Paused
Paused
Upload 23 files
Browse files- app/sub_manager.py +35 -50
app/sub_manager.py
CHANGED
|
@@ -121,85 +121,69 @@ class SubscriptionManager:
|
|
| 121 |
|
| 122 |
# 确保数据目录存在
|
| 123 |
data_dir = os.path.dirname(self.config_path)
|
| 124 |
-
|
| 125 |
-
logger.info(f"创建数据目录: {data_dir}")
|
| 126 |
-
try:
|
| 127 |
-
os.makedirs(data_dir, exist_ok=True)
|
| 128 |
-
except Exception as e:
|
| 129 |
-
logger.error(f"创建数据目录失败: {str(e)}")
|
| 130 |
|
| 131 |
-
# 准备subconverter命令
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
cmd = [
|
| 133 |
self.subconverter_path,
|
| 134 |
-
"-
|
| 135 |
-
"-
|
|
|
|
|
|
|
| 136 |
"-o", self.config_path, # 输出文件
|
| 137 |
"-t", "clash" # 目标格式
|
| 138 |
-
#
|
|
|
|
|
|
|
| 139 |
]
|
| 140 |
|
| 141 |
logger.info(f"执行命令: {' '.join(cmd)}")
|
| 142 |
|
| 143 |
-
# 检查 subconverter 是否存在
|
| 144 |
if not os.path.exists(self.subconverter_path):
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
with open(input_file, "r", encoding="utf-8") as f:
|
| 149 |
-
content = f.read()
|
| 150 |
-
# 假定原始内容需要添加头部
|
| 151 |
-
final_content = self._add_clash_headers() + content
|
| 152 |
-
with open(self.config_path, "w", encoding="utf-8") as f:
|
| 153 |
-
f.write(final_content)
|
| 154 |
-
logger.warning("subconverter未找到,尝试使用原始订阅内容 + Clash头部信息写入配置文件")
|
| 155 |
-
except Exception as e:
|
| 156 |
-
logger.error(f"写入原始订阅内容时出错: {str(e)}")
|
| 157 |
-
raise RuntimeError(f"无法转换配置,且无法写入原始订阅: {str(e)}")
|
| 158 |
-
return # 即使尝试写入,也应返回,后续 patch 可能仍有问题
|
| 159 |
|
|
|
|
| 160 |
try:
|
| 161 |
# 执行subconverter
|
| 162 |
process = subprocess.Popen(
|
| 163 |
cmd,
|
| 164 |
stdout=subprocess.PIPE,
|
| 165 |
stderr=subprocess.PIPE,
|
| 166 |
-
universal_newlines=True
|
|
|
|
| 167 |
)
|
| 168 |
-
stdout, stderr = process.communicate(timeout=60)
|
| 169 |
|
| 170 |
# 记录完整的 subconverter 输出用于调试
|
| 171 |
logger.info(f"subconverter STDOUT:\n---\n{stdout}\n---")
|
| 172 |
if stderr:
|
| 173 |
logger.warning(f"subconverter STDERR:\n---\n{stderr}\n---")
|
| 174 |
|
|
|
|
| 175 |
if process.returncode != 0:
|
| 176 |
-
logger.error(f"subconverter执行失败,返回码: {process.returncode}.
|
| 177 |
-
#
|
| 178 |
-
|
| 179 |
-
with open(input_file, "r", encoding="utf-8") as f:
|
| 180 |
-
content = f.read()
|
| 181 |
-
# 检查是否需要添加 Clash 头部信息
|
| 182 |
-
if "proxies:" not in content:
|
| 183 |
-
logger.warning("subconverter失败,且原始内容不像Clash配置,添加基本头部")
|
| 184 |
-
content = self._add_clash_headers() + content
|
| 185 |
-
else:
|
| 186 |
-
logger.warning("subconverter失败,但原始内容看似Clash配置,直接使用")
|
| 187 |
-
|
| 188 |
-
with open(self.config_path, "w", encoding="utf-8") as f:
|
| 189 |
-
f.write(content)
|
| 190 |
-
logger.warning("subconverter转换失败,已尝试直接使用原始订阅内容写入配置文件")
|
| 191 |
-
except Exception as e:
|
| 192 |
-
logger.error(f"subconverter失败后,尝试使用原始订阅内容时出错: {str(e)}")
|
| 193 |
-
raise RuntimeError(f"subconverter转换失败,且无法回退到原始订阅: {str(e)}")
|
| 194 |
else:
|
| 195 |
-
|
|
|
|
| 196 |
# 验证输出文件是否存在且非空
|
| 197 |
if os.path.exists(self.config_path) and os.path.getsize(self.config_path) > 0:
|
| 198 |
logger.info(f"配置文件已生成,路径: {self.config_path},大小: {os.path.getsize(self.config_path)} 字节")
|
| 199 |
else:
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
|
|
|
| 203 |
|
| 204 |
except subprocess.TimeoutExpired:
|
| 205 |
logger.error(f"执行subconverter超时 (超过60秒)")
|
|
@@ -443,7 +427,8 @@ secret: ""
|
|
| 443 |
f.write(config_content)
|
| 444 |
logger.info("已修补配置文件并成功保存")
|
| 445 |
except Exception as write_err:
|
| 446 |
-
|
|
|
|
| 447 |
else:
|
| 448 |
logger.info("配置文件无需修补")
|
| 449 |
|
|
|
|
| 121 |
|
| 122 |
# 确保数据目录存在
|
| 123 |
data_dir = os.path.dirname(self.config_path)
|
| 124 |
+
os.makedirs(data_dir, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
+
# 准备subconverter命令 - 尝试使用 file:// URI
|
| 127 |
+
# 将 Windows 路径转换为 file:// URI (如果需要)
|
| 128 |
+
# Python on Linux should handle /path/to/file directly
|
| 129 |
+
input_uri = input_file
|
| 130 |
+
if os.name == 'nt': # 如果在 Windows 上运行 (理论上我们是在 Linux 容器)
|
| 131 |
+
input_uri = 'file:///' + input_file.replace('\\', '/')
|
| 132 |
+
|
| 133 |
cmd = [
|
| 134 |
self.subconverter_path,
|
| 135 |
+
#"-i", input_file, # 之前的尝试
|
| 136 |
+
#"-o", self.config_path, # 之前的尝试
|
| 137 |
+
"-g", # 明确表示生成模式
|
| 138 |
+
"--url", input_uri, # 使用文件 URI 作为输入
|
| 139 |
"-o", self.config_path, # 输出文件
|
| 140 |
"-t", "clash" # 目标格式
|
| 141 |
+
# 添加 --config 参数指向基础配置,可能有助于避免服务器模式
|
| 142 |
+
# 需要一个基础配置文件,例如 subconverter/base/clash.yaml
|
| 143 |
+
# "--config", os.path.join(os.path.dirname(self.subconverter_path), "subconverter/base/clash.yaml")
|
| 144 |
]
|
| 145 |
|
| 146 |
logger.info(f"执行命令: {' '.join(cmd)}")
|
| 147 |
|
| 148 |
+
# 检查 subconverter 是否存在 (之前的代码已修复)
|
| 149 |
if not os.path.exists(self.subconverter_path):
|
| 150 |
+
# ... (省略 subconverter 未找到的回退逻辑) ...
|
| 151 |
+
logger.error(f"subconverter未找到: {self.subconverter_path}. 无法转换配置。")
|
| 152 |
+
raise RuntimeError(f"无法转换配置 (subconverter未找到)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
|
| 154 |
+
# --- 正式执行 subconverter ---
|
| 155 |
try:
|
| 156 |
# 执行subconverter
|
| 157 |
process = subprocess.Popen(
|
| 158 |
cmd,
|
| 159 |
stdout=subprocess.PIPE,
|
| 160 |
stderr=subprocess.PIPE,
|
| 161 |
+
universal_newlines=True,
|
| 162 |
+
cwd=os.path.dirname(self.subconverter_path) # 尝试在subconverter目录下运行
|
| 163 |
)
|
| 164 |
+
stdout, stderr = process.communicate(timeout=60)
|
| 165 |
|
| 166 |
# 记录完整的 subconverter 输出用于调试
|
| 167 |
logger.info(f"subconverter STDOUT:\n---\n{stdout}\n---")
|
| 168 |
if stderr:
|
| 169 |
logger.warning(f"subconverter STDERR:\n---\n{stderr}\n---")
|
| 170 |
|
| 171 |
+
# 检查 subconverter 返回码
|
| 172 |
if process.returncode != 0:
|
| 173 |
+
logger.error(f"subconverter执行失败,返回码: {process.returncode}.")
|
| 174 |
+
# ... (省略 subconverter 失败的回退逻辑) ...
|
| 175 |
+
raise RuntimeError(f"subconverter转换失败(code {process.returncode})。 Subconverter STDERR: {stderr[:200]}...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
else:
|
| 177 |
+
# subconverter 返回码为 0,表示理论上成功
|
| 178 |
+
logger.info("subconverter成功执行 (返回码 0)")
|
| 179 |
# 验证输出文件是否存在且非空
|
| 180 |
if os.path.exists(self.config_path) and os.path.getsize(self.config_path) > 0:
|
| 181 |
logger.info(f"配置文件已生成,路径: {self.config_path},大小: {os.path.getsize(self.config_path)} 字节")
|
| 182 |
else:
|
| 183 |
+
logger.error(f"subconverter执行成功,但配置文件不存在或为空: {self.config_path}. 请检查subconverter日志了解详情。")
|
| 184 |
+
# 检查STDERR中是否有线索
|
| 185 |
+
error_detail = stderr if stderr else "(无错误输出)"
|
| 186 |
+
raise RuntimeError(f"subconverter执行成功但未生成有效配置文件。 Subconverter STDERR: {error_detail[:500]}...")
|
| 187 |
|
| 188 |
except subprocess.TimeoutExpired:
|
| 189 |
logger.error(f"执行subconverter超时 (超过60秒)")
|
|
|
|
| 427 |
f.write(config_content)
|
| 428 |
logger.info("已修补配置文件并成功保存")
|
| 429 |
except Exception as write_err:
|
| 430 |
+
logger.error(f"写回配置文件失败: {write_err}")
|
| 431 |
+
# 即使写回失败,也不要阻止程序继续,可能只是临时问题
|
| 432 |
else:
|
| 433 |
logger.info("配置文件无需修补")
|
| 434 |
|