🎄 Sync 2026-09-29 23:49:35

This commit is contained in:
github-actions[bot] committed 2026-09-29 23:49:35 +08:00
1 parent 2c45fa21e0
commit a633bba059
4 files changed
-480

No files matched your search

-85
View File
@@ -1,85 +0,0 @@
#!/bin/sh
set -eu
ROOT_DIR="$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)"
OUT_DIR="${ROOT_DIR}/clashoo/files/usr/share/clashoo/nftables"
TMP_DIR="$(mktemp -d)"
V2DAT_BIN="${V2DAT_BIN:-}"
GEOIP_DAT_URL="${GEOIP_DAT_URL:-https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat}"
V2DAT_PKG="${V2DAT_PKG:-github.com/kenzok8/v2dat}"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT INT TERM
ensure_v2dat() {
if [ -n "$V2DAT_BIN" ] && [ -x "$V2DAT_BIN" ]; then
return 0
fi
if command -v v2dat >/dev/null 2>&1; then
V2DAT_BIN="$(command -v v2dat)"
return 0
fi
export GOBIN="${TMP_DIR}/bin"
mkdir -p "$GOBIN"
go install "${V2DAT_PKG}@latest"
V2DAT_BIN="${GOBIN}/v2dat"
}
render_nft_set() {
local family="$1"
local input_file="$2"
local output_file="$3"
local set_name="$4"
awk -v set_name="$set_name" -v set_type="$family" '
BEGIN {
print "set " set_name " {"
print "\ttype " set_type ";"
print "\tflags interval;"
print "\tauto-merge;"
print "\telements = {"
first = 1
}
!/^[[:space:]]*$/ && !/^[[:space:]]*#/ {
gsub(/^[[:space:]]+|[[:space:]]+$/, "", $0)
if ($0 == "")
next
if (!first)
print ","
printf "\t\t%s", $0
first = 0
}
END {
if (!first)
print ""
print "\t}"
print "}"
}
' "$input_file" > "$output_file"
}
mkdir -p "$OUT_DIR" "${TMP_DIR}/out"
ensure_v2dat
curl -fsSL "$GEOIP_DAT_URL" -o "${TMP_DIR}/geoip.dat"
"$V2DAT_BIN" unpack geoip -o "${TMP_DIR}/out" -f cn "${TMP_DIR}/geoip.dat"
CN_TXT="$(find "${TMP_DIR}/out" -type f -name '*_cn.txt' | head -1)"
[ -n "${CN_TXT}" ] && [ -f "${CN_TXT}" ] || {
echo "failed to unpack CN CIDRs from geoip.dat" >&2
exit 1
}
awk 'index($0, ":") == 0 { print }' "${CN_TXT}" > "${TMP_DIR}/cn_ipv4.txt"
awk 'index($0, ":") != 0 { print }' "${CN_TXT}" > "${TMP_DIR}/cn_ipv6.txt"
render_nft_set ipv4_addr "${TMP_DIR}/cn_ipv4.txt" "${OUT_DIR}/geoip_cn.nft" clashoo_china
render_nft_set ipv6_addr "${TMP_DIR}/cn_ipv6.txt" "${OUT_DIR}/geoip6_cn.nft" clashoo_china6
echo "generated:"
echo " ${OUT_DIR}/geoip_cn.nft"
echo " ${OUT_DIR}/geoip6_cn.nft"
-57
View File
@@ -1,57 +0,0 @@
#!/bin/sh
set -eu
ROOT_DIR="$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)"
RULESET_DIR="${ROOT_DIR}/clashoo/files/usr/share/clashoo/ruleset"
TMP_DIR="$(mktemp -d)"
GEOSITE_BASE="${GEOSITE_BASE:-https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite}"
GEOIP_BASE="${GEOIP_BASE:-https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geoip}"
# mihomo .mrs lives on the meta branch (binary, not .srs)
META_GEOSITE_BASE="${META_GEOSITE_BASE:-https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite}"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT INT TERM
fetch_ruleset() {
tag="$1"
base="$2"
remote_name="${3:-$tag}"
url="${base}/${remote_name}.srs"
tmp_file="${TMP_DIR}/${tag}.srs"
out_file="${RULESET_DIR}/${tag}.srs"
echo "fetch ${tag}.srs"
curl -fsSL --retry 3 --retry-delay 2 "$url" -o "$tmp_file"
[ -s "$tmp_file" ] || {
echo "empty ruleset: $url" >&2
exit 1
}
mv "$tmp_file" "$out_file"
}
mkdir -p "$RULESET_DIR"
rm -f "${RULESET_DIR}"/*.srs
# Minimal built-in set:
# - geolocation-!cn: required by fake-ip DNS and broad non-CN routing.
# - geosite-cn: local alias for subscription tags geolocation-cn/cn.
# - cn-ip/private-ip: keep China/private IP direct without remote downloads.
fetch_ruleset "geolocation-!cn" "$GEOSITE_BASE"
fetch_ruleset "geosite-cn" "$GEOSITE_BASE" geolocation-cn
fetch_ruleset "private-ip" "$GEOIP_BASE" private
fetch_ruleset "cn-ip" "$GEOIP_BASE" cn
# mihomo cn.mrs replaces geosite:cn in fake-ip-filter so the core skips geosite.dat
echo "fetch cn.mrs"
curl -fsSL --retry 3 --retry-delay 2 "${META_GEOSITE_BASE}/cn.mrs" -o "${TMP_DIR}/cn.mrs"
[ -s "${TMP_DIR}/cn.mrs" ] || {
echo "empty ruleset: ${META_GEOSITE_BASE}/cn.mrs" >&2
exit 1
}
mv "${TMP_DIR}/cn.mrs" "${RULESET_DIR}/cn.mrs"
echo "generated sing-box rule sets in ${RULESET_DIR}"
-281
View File
@@ -1,281 +0,0 @@
#!/bin/sh
set -eu
FEED_BASE_URL="https://down.dllkids.xyz/openwrt-feed/clashoo"
GITHUB_API_URL="https://api.github.com/repos/kenzok8/openwrt-clashoo/releases/latest"
GITHUB_PROXY_PREFIX="${GITHUB_PROXY_PREFIX:-https://ghfast.top/}"
TMP_DIR="/tmp/clashoo-install"
fetch_text() {
url="$1"
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$url"
return $?
fi
if command -v wget >/dev/null 2>&1; then
wget -qO- "$url"
return $?
fi
return 127
}
download_file() {
url="$1"
out="$2"
if command -v curl >/dev/null 2>&1; then
curl -fL "$url" -o "$out"
return $?
fi
wget -qO "$out" "$url"
}
download_url() {
url="$1"
case "$url" in
https://github.com/*)
printf '%s%s\n' "$GITHUB_PROXY_PREFIX" "$url"
;;
*)
printf '%s\n' "$url"
;;
esac
}
detect_manager() {
if command -v opkg >/dev/null 2>&1; then
echo opkg
return
fi
if command -v apk >/dev/null 2>&1; then
echo apk
return
fi
echo "unsupported"
}
detect_arch() {
pm="$1"
if [ "$pm" = "opkg" ]; then
opkg print-architecture | awk '/^arch / {print $2}' | tail -n 1
return
fi
# apk --print-arch 只回 CPU family(如 aarch64),丢掉 subtarget 后缀;
# feed/release 产物用完整 target arch(aarch64_cortex-a53),优先读 DISTRIB_ARCH
distrib_arch="$(sed -n "s/^DISTRIB_ARCH=['\"]\([^'\"]*\)['\"].*/\1/p" /etc/openwrt_release 2>/dev/null | head -n 1)"
if [ -n "$distrib_arch" ]; then
printf '%s\n' "$distrib_arch"
else
apk --print-arch
fi
}
detect_sdk() {
if [ ! -r /etc/openwrt_release ]; then
return 1
fi
release="$(sed -n "s/^DISTRIB_RELEASE=['\"]\\([^'\"]*\\)['\"]$/\\1/p" /etc/openwrt_release | head -n 1)"
[ -n "$release" ] || return 1
sdk="$(printf '%s\n' "$release" | grep -Eo '[0-9]+\.[0-9]+' | head -n 1)"
[ -n "$sdk" ] || return 1
printf '%s\n' "$sdk"
}
find_feed_filename() {
package_name="$1"
packages_text="$2"
printf '%s\n' "$packages_text" | awk -v pkg="$package_name" '
$0 == "Package: " pkg {
in_pkg = 1
next
}
in_pkg && /^Filename: / {
sub(/^Filename: /, "")
print
exit
}
in_pkg && /^$/ {
in_pkg = 0
}
'
}
find_manifest_value() {
key="$1"
manifest_text="$2"
printf '%s\n' "$manifest_text" | sed -n "s/^${key}=//p" | head -n 1
}
append_unique_word() {
value="$1"
list="$2"
[ -n "$value" ] || {
printf '%s\n' "$list"
return
}
case " $list " in
*" $value "*) ;;
*) list="${list}${list:+ }${value}" ;;
esac
printf '%s\n' "$list"
}
build_sdk_candidates() {
pm="$1"
candidates=""
detected_sdk="$(detect_sdk || true)"
candidates="$(append_unique_word "$detected_sdk" "$candidates")"
if [ "$pm" = "opkg" ]; then
for sdk in 24.10 23.05 22.03 21.02; do
candidates="$(append_unique_word "$sdk" "$candidates")"
done
else
for sdk in 25.12 24.10; do
candidates="$(append_unique_word "$sdk" "$candidates")"
done
fi
printf '%s\n' "$candidates"
}
# Feed 结构:<base>/<sdk>/<arch>/<files> —— 与 dllkids setup.sh 对齐,不嵌 feedname 子目录
feed_base_for() {
printf '%s/%s/%s' "$FEED_BASE_URL" "$1" "$2"
}
load_manifest_urls() {
sdk="$1"
arch="$2"
base="$(feed_base_for "$sdk" "$arch")"
manifest_url="${base}/manifest-clashoo.txt"
manifest_text="$(fetch_text "$manifest_url" || true)"
[ -n "$manifest_text" ] || return 1
core_file="$(find_manifest_value "core" "$manifest_text")"
luci_file="$(find_manifest_value "luci" "$manifest_text")"
i18n_file="$(find_manifest_value "i18n" "$manifest_text")"
[ -n "$core_file" ] || return 1
[ -n "$luci_file" ] || return 1
CORE_URL="${base}/${core_file}"
LUCI_URL="${base}/${luci_file}"
I18N_URL=""
[ -n "$i18n_file" ] && I18N_URL="${base}/${i18n_file}"
return 0
}
load_opkg_feed_urls() {
sdk="$1"
arch="$2"
base="$(feed_base_for "$sdk" "$arch")"
packages_url="${base}/Packages.gz"
packages_text="$(fetch_text "$packages_url" || true)"
if ! printf '%s' "$packages_text" | grep -q '^Package: '; then
return 1
fi
core_file="$(find_feed_filename "clashoo" "$packages_text")"
luci_file="$(find_feed_filename "luci-app-clashoo" "$packages_text")"
i18n_file="$(find_feed_filename "luci-i18n-clashoo-zh-cn" "$packages_text")"
[ -n "$core_file" ] || return 1
[ -n "$luci_file" ] || return 1
CORE_URL="${base}/${core_file}"
LUCI_URL="${base}/${luci_file}"
I18N_URL=""
[ -n "$i18n_file" ] && I18N_URL="${base}/${i18n_file}"
return 0
}
load_github_urls() {
arch="$1"
ext="$2"
payload="$(fetch_text "$GITHUB_API_URL" || true)"
[ -n "$payload" ] || return 1
urls="$(printf '%s\n' "$payload" | sed -n 's/.*"browser_download_url":[[:space:]]*"\([^"]*\)".*/\1/p')"
[ -n "$urls" ] || return 1
if [ "$ext" = "apk" ]; then
CORE_URL="$(printf '%s\n' "$urls" | grep -E '/clashoo-[^-]+.*-r[0-9]+-'"$arch"'\.apk$' | head -n 1)"
LUCI_URL="$(printf '%s\n' "$urls" | grep -E '/luci-app-clashoo-[^-]+.*-r[0-9]+-('"$arch"'|all)\.apk$' | head -n 1)"
I18N_URL="$(printf '%s\n' "$urls" | grep -E '/luci-i18n-clashoo-zh-cn-[^-]+.*-r[0-9]+-('"$arch"'|all)\.apk$' | head -n 1)"
else
CORE_URL="$(printf '%s\n' "$urls" | grep -E '/clashoo_.*_'"$arch"'\.ipk$' | head -n 1)"
LUCI_URL="$(printf '%s\n' "$urls" | grep -E '/luci-app-clashoo_.*_all\.ipk$' | head -n 1)"
I18N_URL="$(printf '%s\n' "$urls" | grep -E '/luci-i18n-clashoo-zh-cn_.*_all\.ipk$' | head -n 1)"
fi
[ -n "$CORE_URL" ] || return 1
[ -n "$LUCI_URL" ] || return 1
return 0
}
PM="$(detect_manager)"
if [ "$PM" = "unsupported" ]; then
echo "No supported package manager found (opkg/apk)."
exit 1
fi
ARCH="$(detect_arch "$PM")"
[ -n "$ARCH" ] || { echo "Cannot detect architecture"; exit 1; }
SDK_CANDIDATES="$(build_sdk_candidates "$PM")"
EXT="ipk"
[ "$PM" = "apk" ] && EXT="apk"
CORE_URL=""
LUCI_URL=""
I18N_URL=""
if [ -n "$SDK_CANDIDATES" ]; then
for SDK in $SDK_CANDIDATES; do
if load_manifest_urls "$SDK" "$ARCH"; then
echo "Using R2 feed manifest: ${SDK}/${ARCH}"
break
fi
if [ "$PM" = "opkg" ] && load_opkg_feed_urls "$SDK" "$ARCH"; then
echo "Using R2 feed: ${SDK}/${ARCH}"
break
fi
done
fi
if [ -z "$CORE_URL" ] || [ -z "$LUCI_URL" ]; then
if load_github_urls "$ARCH" "$EXT"; then
echo "Using GitHub latest release"
else
echo "Cannot find required packages for arch: $ARCH"
echo "Detected package manager: $PM"
echo "Tried SDKs: $SDK_CANDIDATES"
exit 1
fi
fi
rm -rf "$TMP_DIR"
mkdir -p "$TMP_DIR"
echo "Downloading packages..."
download_file "$(download_url "$CORE_URL")" "$TMP_DIR/core.${EXT}"
download_file "$(download_url "$LUCI_URL")" "$TMP_DIR/luci.${EXT}"
if [ -n "$I18N_URL" ]; then
download_file "$(download_url "$I18N_URL")" "$TMP_DIR/i18n.${EXT}"
fi
echo "Installing packages with $PM..."
if [ "$PM" = "opkg" ]; then
# Refresh package lists so deps (yq, coreutils-nohup, kmod-*) resolve on fresh systems
opkg update || echo "Warning: opkg update failed, dependency resolution may break"
opkg install "$TMP_DIR/core.${EXT}" "$TMP_DIR/luci.${EXT}" ${I18N_URL:+"$TMP_DIR/i18n.${EXT}"}
else
apk update || echo "Warning: apk update failed, dependency resolution may break"
apk add --allow-untrusted "$TMP_DIR/core.${EXT}" "$TMP_DIR/luci.${EXT}" ${I18N_URL:+"$TMP_DIR/i18n.${EXT}"}
fi
echo "Install complete."
-57
View File
@@ -1,57 +0,0 @@
#!/bin/sh
set -eu
echo "Stopping clashoo service..."
/etc/init.d/clashoo stop >/dev/null 2>&1 || true
/etc/init.d/clashoo disable >/dev/null 2>&1 || true
core_still_installed() {
if command -v apk >/dev/null 2>&1; then
apk list -I 2>/dev/null | grep -q "^clashoo-[0-9]"
elif command -v opkg >/dev/null 2>&1; then
opkg list-installed 2>/dev/null | grep -q "^clashoo "
else
return 1
fi
}
if command -v opkg >/dev/null 2>&1; then
echo "Removing packages with opkg..."
opkg remove luci-i18n-clashoo-zh-cn luci-app-clashoo clashoo >/dev/null 2>&1 || true
elif command -v apk >/dev/null 2>&1; then
echo "Removing packages with apk..."
apk del luci-i18n-clashoo-zh-cn luci-app-clashoo clashoo >/dev/null 2>&1 || true
else
echo "No supported package manager found (opkg/apk), skip package removal."
fi
# Always safe: purely runtime/temp files, never owned by the package manager.
echo "Cleaning runtime temp files..."
rm -rf /tmp/clashoo /tmp/clashoo-install /tmp/clashoo_* /tmp/luci* 2>/dev/null || true
# CRITICAL: only delete package-owned files (config / init.d / dirs) when the
# core package was actually removed. If it's still installed - e.g. nikki, which
# depends on the clashoo-provided `mihomo`, blocks `apk del clashoo` - deleting
# these behind the package manager's back corrupts apk's state: the db keeps
# owning files that no longer exist, so a later same-version reinstall only
# writes `.apk-new` and never restores them, leaving the UI broken
# ("kernel not installed" / start stuck). Leave them in place instead.
if core_still_installed; then
echo "WARNING: 'clashoo' is still installed because other packages depend on it"
echo " (e.g. nikki depends on the clashoo-provided 'mihomo')."
echo " Kept /etc/config/clashoo, /etc/init.d/clashoo and /etc/clashoo intact"
echo " to avoid corrupting package state. Remove nikki first for a full"
echo " uninstall, or just reinstall clashoo to refresh it."
else
echo "Cleaning package files..."
rm -rf /etc/clashoo /usr/share/clashoo /usr/share/clashbackup 2>/dev/null || true
rm -f /etc/init.d/clashoo /etc/config/clashoo 2>/dev/null || true
fi
/etc/init.d/rpcd restart >/dev/null 2>&1 || true
/etc/init.d/uhttpd restart >/dev/null 2>&1 || true
/etc/init.d/dnsmasq restart >/dev/null 2>&1 || true
/etc/init.d/firewall restart >/dev/null 2>&1 || true
echo "Uninstall & reset complete."