Revert "clash_profile_conversion.sh resolve_subconverter.sh"

This reverts commit 1cb8091c70.
This commit is contained in:
wnlen
2026-01-16 15:52:05 +08:00
parent 1cb8091c70
commit 9dcc0a85e5
2 changed files with 125 additions and 146 deletions

View File

@ -1,85 +1,42 @@
#!/usr/bin/env bash #!/bin/bash
set -euo pipefail
# 作用: # 加载clash配置文件内容
# - 将订阅内容转换成 Clash Meta / Mihomo 可用的完整 YAML 配置 raw_content=$(cat ${Server_Dir}/temp/clash.yaml)
# - 默认使用 subconverter HTTP /sub 接口(最稳)
# - 失败则跳过,不影响主流程
#
# 输入/输出约定:
# - IN_FILE原订阅默认 temp/clash.yaml
# - OUT_FILE转换后的配置默认 temp/clash_config.yaml
#
# 设计原则:
# - 绝不 exit 1失败只 warn 并 exit 0
# - 已是完整 Clash 配置则直接 copy
# - 没有 CLASH_URL原始订阅 URL则不转换subconverter 最稳是 url=...
Server_Dir="${Server_Dir:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}" # 判断订阅内容是否符合clash配置文件标准
Temp_Dir="${Temp_Dir:-$Server_Dir/temp}" #if echo "$raw_content" | jq 'has("proxies") and has("proxy-groups") and has("rules")' 2>/dev/null; then
if echo "$raw_content" | awk '/^proxies:/{p=1} /^proxy-groups:/{g=1} /^rules:/{r=1} p&&g&&r{exit} END{if(p&&g&&r) exit 0; else exit 1}'; then
echo "订阅内容符合clash标准"
echo "$raw_content" > ${Server_Dir}/temp/clash_config.yaml
else
# 判断订阅内容是否为base64编码
if echo "$raw_content" | base64 -d &>/dev/null; then
# 订阅内容为base64编码进行解码
decoded_content=$(echo "$raw_content" | base64 -d)
mkdir -p "$Temp_Dir" # 判断解码后的内容是否符合clash配置文件标准
#if echo "$decoded_content" | jq 'has("proxies") and has("proxy-groups") and has("rules")' 2>/dev/null; then
IN_FILE="${IN_FILE:-$Temp_Dir/clash.yaml}" if echo "$decoded_content" | awk '/^proxies:/{p=1} /^proxy-groups:/{g=1} /^rules:/{r=1} p&&g&&r{exit} END{if(p&&g&&r) exit 0; else exit 1}'; then
OUT_FILE="${OUT_FILE:-$Temp_Dir/clash_config.yaml}" echo "解码后的内容符合clash标准"
echo "$decoded_content" > ${Server_Dir}/temp/clash_config.yaml
# “更先进”的默认Clash Meta / Mihomo else
SUB_TARGET="${SUB_TARGET:-clashmeta}" # 推荐 clashmeta兼容面最广 echo "解码后的内容不符合clash标准尝试将其转换为标准格式"
SUB_UDP="${SUB_UDP:-true}" if [ -z "$SUBCONVERTER_BIN" ]; then
SUB_EMOJI="${SUB_EMOJI:-true}" echo "subconverter 未配置,无法执行转换"
SUB_SORT="${SUB_SORT:-true}" exit 1
fi
# 订阅原始 URL你 .env 里 export CLASH_URL=... "${SUBCONVERTER_BIN}" -g &>> ${Server_Dir}/logs/subconverter.log
SUB_URL="${CLASH_URL:-}" converted_file=${Server_Dir}/temp/clash_config.yaml
# 判断转换后的内容是否符合clash配置文件标准
# 0) 输入不存在就跳过 if awk '/^proxies:/{p=1} /^proxy-groups:/{g=1} /^rules:/{r=1} p&&g&&r{exit} END{if(p&&g&&r) exit 0; else exit 1}' $converted_file; then
if [ ! -s "$IN_FILE" ]; then echo "配置文件已成功转换成clash标准格式"
echo "[WARN] no input file: $IN_FILE" else
exit 0 echo "配置文件转换标准格式失败"
exit 1
fi
fi
else
echo "订阅内容不符合clash标准无法转换为配置文件"
exit 1
fi
fi fi
# 1) 如果看起来已经是完整 Clash 配置,就直接用,不转换
# (包含 proxies / proxy-providers / rules / port 等任一关键词即可认为是完整配置)
if grep -qE '^(proxies:|proxy-providers:|mixed-port:|port:|rules:|dns:)' "$IN_FILE"; then
cp -f "$IN_FILE" "$OUT_FILE"
echo "[OK] input already looks like a Clash config -> $OUT_FILE"
exit 0
fi
# 2) subconverter 不可用就跳过
if [ "${SUBCONVERTER_READY:-false}" != "true" ] || [ -z "${SUBCONVERTER_URL:-}" ]; then
echo "[WARN] subconverter not ready, skip conversion"
exit 0
fi
# 3) 没有原始 URL 就不转subconverter 最稳是 url=... 拉取)
if [ -z "${SUB_URL:-}" ]; then
echo "[WARN] CLASH_URL empty, cannot convert via /sub?url=..., skip"
exit 0
fi
TMP_OUT="$Temp_Dir/.clash_config.converted.yaml"
rm -f "$TMP_OUT" 2>/dev/null || true
# 4) 拼接 /sub 参数(尽量通用)
CONVERT_URL="${SUBCONVERTER_URL}/sub?target=${SUB_TARGET}&url=${SUB_URL}"
if [ "$SUB_UDP" = "true" ]; then CONVERT_URL="${CONVERT_URL}&udp=true"; fi
if [ "$SUB_EMOJI" = "true" ]; then CONVERT_URL="${CONVERT_URL}&emoji=true"; fi
if [ "$SUB_SORT" = "true" ]; then CONVERT_URL="${CONVERT_URL}&sort=true"; fi
# 5) 执行转换(失败则回退)
set +e
curl -fsSL --connect-timeout 3 -m 25 "$CONVERT_URL" -o "$TMP_OUT"
rc=$?
set -e
if [ "$rc" -ne 0 ] || [ ! -s "$TMP_OUT" ]; then
echo "[WARN] convert failed (rc=$rc), keep original"
rm -f "$TMP_OUT" 2>/dev/null || true
exit 0
fi
mv -f "$TMP_OUT" "$OUT_FILE"
echo "[OK] converted via subconverter -> $OUT_FILE (target=${SUB_TARGET})"
true

View File

@ -1,78 +1,100 @@
#!/usr/bin/env bash #!/bin/bash
set -euo pipefail
# 作用: Subconverter_Bin=""
# - 检测 tools/subconverter/subconverter 是否存在
# -(可选)以 daemon 模式启动本地 subconverterHTTP 服务)
# - 导出统一变量给后续脚本使用:
# SUBCONVERTER_BIN / SUBCONVERTER_READY / SUBCONVERTER_URL
#
# 设计原则:
# - 永不 exit 1不可用就 Ready=false主流程继续
# - 不阻塞 start.sh快速启动不等待健康检查
Server_Dir="${Server_Dir:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
Temp_Dir="${Temp_Dir:-$Server_Dir/temp}"
mkdir -p "$Temp_Dir"
Subconverter_Bin="$Server_Dir/tools/subconverter/subconverter"
Subconverter_Ready=false Subconverter_Ready=false
# 配置项(可放 .env Subconverter_Dir="${Server_Dir}/tools/subconverter"
SUBCONVERTER_MODE="${SUBCONVERTER_MODE:-daemon}" # daemon | off Default_Bin="${Subconverter_Dir}/subconverter"
SUBCONVERTER_HOST="${SUBCONVERTER_HOST:-127.0.0.1}"
SUBCONVERTER_PORT="${SUBCONVERTER_PORT:-25500}"
SUBCONVERTER_URL="${SUBCONVERTER_URL:-http://${SUBCONVERTER_HOST}:${SUBCONVERTER_PORT}}"
# pref.ini不存在就从示例生成 resolve_subconverter_arch() {
SUBCONVERTER_PREF="${SUBCONVERTER_PREF:-$Server_Dir/tools/subconverter/pref.ini}" local raw_arch="$1"
PREF_EXAMPLE_INI="$Server_Dir/tools/subconverter/pref.example.ini" case "$raw_arch" in
x86_64|amd64)
echo "linux-amd64"
;;
aarch64|arm64)
echo "linux-arm64"
;;
armv7*|armv7l)
echo "linux-armv7"
;;
*)
echo ""
;;
esac
}
PID_FILE="$Temp_Dir/subconverter.pid" try_subconverter_bin() {
local candidate="$1"
if [ -n "$candidate" ] && [ -x "$candidate" ]; then
Subconverter_Bin="$candidate"
Subconverter_Ready=true
return 0
fi
return 1
}
# 1) 二进制存在性 # ------------------------------------------------------------
if [ -x "$Subconverter_Bin" ]; then # FIX: SUBCONVERTER_PATH may be unbound when parent shell uses `set -u`
Subconverter_Ready=true # Use ${SUBCONVERTER_PATH:-} to avoid "unbound variable"
# ------------------------------------------------------------
SUBCONVERTER_PATH_SAFE="${SUBCONVERTER_PATH:-}"
if [ -n "$SUBCONVERTER_PATH_SAFE" ]; then
try_subconverter_bin "$SUBCONVERTER_PATH_SAFE" && return 0
else else
Subconverter_Ready=false try_subconverter_bin "$Default_Bin" && return 0
fi fi
# 2) pref.ini 生成(仅当准备启用 daemon Detected_Arch="${CpuArch:-$(uname -m 2>/dev/null)}"
if [ "$Subconverter_Ready" = "true" ] && [ "$SUBCONVERTER_MODE" = "daemon" ]; then Resolved_Arch="$(resolve_subconverter_arch "$Detected_Arch")"
if [ ! -f "$SUBCONVERTER_PREF" ] && [ -f "$PREF_EXAMPLE_INI" ]; then
cp -f "$PREF_EXAMPLE_INI" "$SUBCONVERTER_PREF" if [ -n "$Resolved_Arch" ]; then
fi try_subconverter_bin "${Subconverter_Dir}/subconverter-${Resolved_Arch}" && return 0
try_subconverter_bin "${Subconverter_Dir}/bin/subconverter-${Resolved_Arch}" && return 0
try_subconverter_bin "${Subconverter_Dir}/${Resolved_Arch}/subconverter" && return 0
fi fi
# 3) daemon 启动(只在需要时) Default_Template="https://github.com/tindy2013/subconverter/releases/latest/download/subconverter_{arch}.tar.gz"
if [ "$Subconverter_Ready" = "true" ] && [ "$SUBCONVERTER_MODE" = "daemon" ]; then Auto_Download="${SUBCONVERTER_AUTO_DOWNLOAD:-auto}"
# pid 存活则认为已启动
if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE" 2>/dev/null)" 2>/dev/null; then if [ "$Auto_Download" != "false" ] && [ -n "$Resolved_Arch" ]; then
: Download_Template="${SUBCONVERTER_DOWNLOAD_URL_TEMPLATE:-$Default_Template}"
else if [ -z "$Download_Template" ]; then
# 端口已监听则不重复起(可能是之前启动的) echo -e "\033[33m[WARN] 未设置 SUBCONVERTER_DOWNLOAD_URL_TEMPLATE跳过 subconverter 自动下载\033[0m"
if command -v ss >/dev/null 2>&1 && ss -lnt | awk '{print $4}' | grep -q ":${SUBCONVERTER_PORT}\$"; then return 0
: fi
else
( Download_Url="${Download_Template//\{arch\}/${Resolved_Arch}}"
cd "$Server_Dir/tools/subconverter"
# 注意subconverter 读取 base/rules/snippets 等目录,必须在其目录下启动更稳 # Ensure temp dirs exist
nohup "$Subconverter_Bin" -f "$SUBCONVERTER_PREF" >/dev/null 2>&1 & mkdir -p "${Server_Dir}/temp" "${Subconverter_Dir}"
echo $! > "$PID_FILE"
) Download_Archive="${Server_Dir}/temp/subconverter-${Resolved_Arch}.tar.gz"
# 给一点点启动时间(不要长等,避免阻塞) Extract_Dir="${Server_Dir}/temp/subconverter-${Resolved_Arch}"
sleep 0.2 mkdir -p "${Extract_Dir}"
fi
fi if command -v curl >/dev/null 2>&1; then
curl -L -sS -o "${Download_Archive}" "${Download_Url}"
elif command -v wget >/dev/null 2>&1; then
wget -q -O "${Download_Archive}" "${Download_Url}"
else
echo -e "\033[33m[WARN] 未找到 curl 或 wget无法自动下载 subconverter\033[0m"
return 0
fi
# Only extract if archive exists and is non-empty
if [ -s "${Download_Archive}" ]; then
tar -xzf "${Download_Archive}" -C "${Extract_Dir}" 2>/dev/null
Downloaded_Bin="$(find "${Extract_Dir}" -maxdepth 3 -type f -name "subconverter" -print -quit)"
if [ -n "${Downloaded_Bin}" ]; then
mv "${Downloaded_Bin}" "${Subconverter_Dir}/subconverter-${Resolved_Arch}"
chmod +x "${Subconverter_Dir}/subconverter-${Resolved_Arch}"
try_subconverter_bin "${Subconverter_Dir}/subconverter-${Resolved_Arch}" && return 0
fi
fi
echo -e "\033[33m[WARN] subconverter 自动下载失败,跳过订阅转换\033[0m"
fi fi
# 4) 统一导出(给后续脚本用) return 0
export Subconverter_Bin
export Subconverter_Ready
export SUBCONVERTER_BIN="$Subconverter_Bin"
export SUBCONVERTER_READY="$Subconverter_Ready"
export SUBCONVERTER_URL
# 永不失败
true