mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
Update On Mon May 26 20:35:53 CEST 2025
This commit is contained in:
10
openclash/.github/workflows/compile_new_ipk.yml
vendored
10
openclash/.github/workflows/compile_new_ipk.yml
vendored
@@ -67,11 +67,15 @@ jobs:
|
||||
- name: Install OpenWrt SNAPSHPT SDK
|
||||
run: |
|
||||
cd ..
|
||||
curl -SLk --connect-timeout 30 --retry 2 "https://downloads.openwrt.org/snapshots/targets/x86/64/openwrt-sdk-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst" -o "./tmp/SNAPSDK.tar.zst"
|
||||
cd \tmp
|
||||
mkdir -p tmp
|
||||
BASE_URL="https://downloads.openwrt.org/snapshots/targets/x86/64/"
|
||||
SDK_NAME=$(curl -s $BASE_URL | grep -oE 'openwrt-sdk-x86-64[^"]+\.tar\.zst' | head -n 1)
|
||||
curl -SLk --connect-timeout 30 --retry 2 "$BASE_URL/$SDK_NAME" -o "./tmp/SNAPSDK.tar.zst"
|
||||
cd tmp
|
||||
zstd -d SNAPSDK.tar.zst
|
||||
tar xf SNAPSDK.tar
|
||||
mv "openwrt-sdk-x86-64_gcc-13.3.0_musl.Linux-x86_64" "SNAPSDK"
|
||||
SDK_DIR=$(tar tf SNAPSDK.tar | head -n 1 | cut -d/ -f1)
|
||||
mv "$SDK_DIR" "SNAPSDK"
|
||||
|
||||
- name: Copy OpenClash Source Codes
|
||||
run: |
|
||||
|
268
openclash/.github/workflows/update_third_party_resources.yml
vendored
Normal file
268
openclash/.github/workflows/update_third_party_resources.yml
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
name: Update Third-Party Resources
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 0 */3 * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-resources:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: dev
|
||||
|
||||
- name: Set up environment
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install curl wget unzip git jq coreutils
|
||||
|
||||
- name: Set file paths
|
||||
run: |
|
||||
echo "CHNR_PATH=luci-app-openclash/root/etc/openclash/china_ip_route.ipset" >> $GITHUB_ENV
|
||||
echo "CHNR6_PATH=luci-app-openclash/root/etc/openclash/china_ip6_route.ipset" >> $GITHUB_ENV
|
||||
echo "YACD_PATH=luci-app-openclash/root/usr/share/openclash/ui/yacd" >> $GITHUB_ENV
|
||||
echo "ZASHBOARD_PATH=luci-app-openclash/root/usr/share/openclash/ui/zashboard" >> $GITHUB_ENV
|
||||
echo "METACUBEXD_PATH=luci-app-openclash/root/usr/share/openclash/ui/metacubexd" >> $GITHUB_ENV
|
||||
echo "GEOIP_PATH=luci-app-openclash/root/etc/openclash/GeoIP.dat" >> $GITHUB_ENV
|
||||
echo "GEOSITE_PATH=luci-app-openclash/root/etc/openclash/GeoSite.dat" >> $GITHUB_ENV
|
||||
echo "COUNTRY_MMDB_PATH=luci-app-openclash/root/etc/openclash/Country.mmdb" >> $GITHUB_ENV
|
||||
|
||||
- name: Update China IP Route Files
|
||||
run: |
|
||||
mkdir -p tmp
|
||||
echo "Downloading China IP Route files..."
|
||||
|
||||
curl -sSL https://ispip.clang.cn/all_cn.txt -o tmp/china_ip_route.ipset
|
||||
|
||||
mkdir -p $(dirname $CHNR_PATH)
|
||||
|
||||
if [ -f "$CHNR_PATH" ]; then
|
||||
if ! cmp -s tmp/china_ip_route.ipset "$CHNR_PATH"; then
|
||||
echo "China IP Route list has been updated, replacing old version."
|
||||
cp tmp/china_ip_route.ipset "$CHNR_PATH"
|
||||
echo "CHNR_UPDATED=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo "China IP Route list is up to date."
|
||||
fi
|
||||
else
|
||||
echo "China IP Route list file doesn't exist, creating it."
|
||||
cp tmp/china_ip_route.ipset "$CHNR_PATH"
|
||||
echo "CHNR_UPDATED=1" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
curl -sSL https://ispip.clang.cn/all_cn_ipv6.txt -o tmp/china_ip6_route.ipset
|
||||
|
||||
mkdir -p $(dirname $CHNR6_PATH)
|
||||
|
||||
if [ -f "$CHNR6_PATH" ]; then
|
||||
if ! cmp -s tmp/china_ip6_route.ipset "$CHNR6_PATH"; then
|
||||
echo "China IP6 Route list has been updated, replacing old version."
|
||||
cp tmp/china_ip6_route.ipset "$CHNR6_PATH"
|
||||
echo "CHNR6_UPDATED=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo "China IP6 Route list is up to date."
|
||||
fi
|
||||
else
|
||||
echo "China IP6 Route list file doesn't exist, creating it."
|
||||
cp tmp/china_ip6_route.ipset "$CHNR6_PATH"
|
||||
echo "CHNR6_UPDATED=1" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Update MetaCubeXD UI
|
||||
run: |
|
||||
echo "Downloading latest MetaCubeXD UI from gh-pages branch..."
|
||||
mkdir -p tmp/metacubexd
|
||||
git clone --depth=1 -b gh-pages https://github.com/MetaCubeX/metacubexd.git tmp/metacubexd_clone
|
||||
|
||||
mkdir -p "$METACUBEXD_PATH"
|
||||
|
||||
if [ -d "$METACUBEXD_PATH" ]; then
|
||||
if ! diff -r tmp/metacubexd_clone "$METACUBEXD_PATH" > /dev/null 2>&1; then
|
||||
echo "MetaCubeXD UI has been updated, replacing old version."
|
||||
rm -rf "$METACUBEXD_PATH"/*
|
||||
cp -rf tmp/metacubexd_clone/* "$METACUBEXD_PATH"
|
||||
echo "METACUBEXD_UPDATED=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo "MetaCubeXD UI is up to date."
|
||||
fi
|
||||
else
|
||||
echo "MetaCubeXD UI directory doesn't exist, creating it."
|
||||
mkdir -p "$METACUBEXD_PATH"
|
||||
cp -rf tmp/metacubexd_clone/* "$METACUBEXD_PATH"
|
||||
echo "METACUBEXD_UPDATED=1" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
echo "MetaCubeXD UI update check completed."
|
||||
|
||||
- name: Update Yacd UI
|
||||
run: |
|
||||
echo "Downloading latest Yacd UI from MetaCubeX/metacubexd gh-pages branch..."
|
||||
mkdir -p tmp/yacd
|
||||
git clone --depth=1 -b gh-pages https://github.com/MetaCubeX/metacubexd.git tmp/yacd_clone
|
||||
|
||||
mkdir -p "$YACD_PATH"
|
||||
|
||||
if [ -d "$YACD_PATH" ]; then
|
||||
if ! diff -r tmp/yacd_clone "$YACD_PATH" > /dev/null 2>&1; then
|
||||
echo "Yacd UI has been updated, replacing old version."
|
||||
rm -rf "$YACD_PATH"/*
|
||||
cp -rf tmp/yacd_clone/* "$YACD_PATH"
|
||||
echo "YACD_UPDATED=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Yacd UI is up to date."
|
||||
fi
|
||||
else
|
||||
echo "Yacd UI directory doesn't exist, creating it."
|
||||
mkdir -p "$YACD_PATH"
|
||||
cp -rf tmp/yacd_clone/* "$YACD_PATH"
|
||||
echo "YACD_UPDATED=1" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
echo "Yacd UI update check completed."
|
||||
|
||||
- name: Update ZashBoard UI
|
||||
run: |
|
||||
echo "Downloading latest Clash Dashboard UI from gh-pages branch..."
|
||||
mkdir -p tmp/zashboard
|
||||
git clone --depth=1 -b gh-pages https://github.com/zzzgydi/clash-dashboard.git tmp/zashboard_clone
|
||||
|
||||
mkdir -p "$ZASHBOARD_PATH"
|
||||
|
||||
if [ -d "$ZASHBOARD_PATH" ]; then
|
||||
if ! diff -r tmp/zashboard_clone "$ZASHBOARD_PATH" > /dev/null 2>&1; then
|
||||
echo "ZashBoard UI has been updated, replacing old version."
|
||||
rm -rf "$ZASHBOARD_PATH"/*
|
||||
cp -rf tmp/zashboard_clone/* "$ZASHBOARD_PATH"
|
||||
echo "ZASHBOARD_UPDATED=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo "ZashBoard UI is up to date."
|
||||
fi
|
||||
else
|
||||
echo "ZashBoard UI directory doesn't exist, creating it."
|
||||
mkdir -p "$ZASHBOARD_PATH"
|
||||
cp -rf tmp/zashboard_clone/* "$ZASHBOARD_PATH"
|
||||
echo "ZASHBOARD_UPDATED=1" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
echo "ZashBoard UI update check completed."
|
||||
|
||||
- name: Update GeoIP and GeoSite files
|
||||
run: |
|
||||
RULES_RELEASE=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest | jq -r '.tag_name')
|
||||
echo "Latest v2ray-rules-dat version: $RULES_RELEASE"
|
||||
|
||||
curl -sSL "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${RULES_RELEASE}/geoip.dat" -o tmp/GeoIP.dat
|
||||
|
||||
mkdir -p $(dirname "$GEOIP_PATH")
|
||||
if [ -f "$GEOIP_PATH" ]; then
|
||||
if ! cmp -s tmp/GeoIP.dat "$GEOIP_PATH"; then
|
||||
echo "GeoIP.dat has been updated, replacing old version."
|
||||
cp tmp/GeoIP.dat "$GEOIP_PATH"
|
||||
echo "GEOIP_UPDATED=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo "GeoIP.dat is up to date."
|
||||
fi
|
||||
else
|
||||
echo "GeoIP.dat file doesn't exist, creating it."
|
||||
cp tmp/GeoIP.dat "$GEOIP_PATH"
|
||||
echo "GEOIP_UPDATED=1" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
curl -sSL "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${RULES_RELEASE}/geosite.dat" -o tmp/GeoSite.dat
|
||||
|
||||
mkdir -p $(dirname "$GEOSITE_PATH")
|
||||
if [ -f "$GEOSITE_PATH" ]; then
|
||||
if ! cmp -s tmp/GeoSite.dat "$GEOSITE_PATH"; then
|
||||
echo "GeoSite.dat has been updated, replacing old version."
|
||||
cp tmp/GeoSite.dat "$GEOSITE_PATH"
|
||||
echo "GEOSITE_UPDATED=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo "GeoSite.dat is up to date."
|
||||
fi
|
||||
else
|
||||
echo "GeoSite.dat file doesn't exist, creating it."
|
||||
cp tmp/GeoSite.dat "$GEOSITE_PATH"
|
||||
echo "GEOSITE_UPDATED=1" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Update Country.mmdb
|
||||
run: |
|
||||
curl -sSL "https://github.com/alecthw/mmdb_china_ip_list/releases/latest/download/Country-lite.mmdb" -o tmp/Country.mmdb
|
||||
|
||||
mkdir -p $(dirname "$COUNTRY_MMDB_PATH")
|
||||
if [ -f "$COUNTRY_MMDB_PATH" ]; then
|
||||
if ! cmp -s tmp/Country.mmdb "$COUNTRY_MMDB_PATH"; then
|
||||
echo "Country.mmdb has been updated, replacing old version."
|
||||
cp tmp/Country.mmdb "$COUNTRY_MMDB_PATH"
|
||||
echo "MMDB_UPDATED=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Country.mmdb is up to date."
|
||||
fi
|
||||
else
|
||||
echo "Country.mmdb file doesn't exist, creating it."
|
||||
cp tmp/Country.mmdb "$COUNTRY_MMDB_PATH"
|
||||
echo "MMDB_UPDATED=1" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git config user.name 'github-actions[bot]'
|
||||
git config user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
|
||||
UPDATED=0
|
||||
UPDATE_MSG="Chore: update resources:"
|
||||
|
||||
if [ "${CHNR_UPDATED}" = "1" ]; then
|
||||
UPDATE_MSG="${UPDATE_MSG} china_ip_route.ipset"
|
||||
UPDATED=1
|
||||
fi
|
||||
|
||||
if [ "${CHNR6_UPDATED}" = "1" ]; then
|
||||
UPDATE_MSG="${UPDATE_MSG} china_ip6_route.ipset"
|
||||
UPDATED=1
|
||||
fi
|
||||
|
||||
if [ "${GEOIP_UPDATED}" = "1" ]; then
|
||||
UPDATE_MSG="${UPDATE_MSG} GeoIP.dat"
|
||||
UPDATED=1
|
||||
fi
|
||||
|
||||
if [ "${GEOSITE_UPDATED}" = "1" ]; then
|
||||
UPDATE_MSG="${UPDATE_MSG} GeoSite.dat"
|
||||
UPDATED=1
|
||||
fi
|
||||
|
||||
if [ "${MMDB_UPDATED}" = "1" ]; then
|
||||
UPDATE_MSG="${UPDATE_MSG} Country.mmdb"
|
||||
UPDATED=1
|
||||
fi
|
||||
|
||||
if [ "${METACUBEXD_UPDATED}" = "1" ]; then
|
||||
UPDATE_MSG="${UPDATE_MSG} MetaCubeXD"
|
||||
UPDATED=1
|
||||
fi
|
||||
|
||||
if [ "${YACD_UPDATED}" = "1" ]; then
|
||||
UPDATE_MSG="${UPDATE_MSG} Yacd"
|
||||
UPDATED=1
|
||||
fi
|
||||
|
||||
if [ "${ZASHBOARD_UPDATED}" = "1" ]; then
|
||||
UPDATE_MSG="${UPDATE_MSG} Zashboard"
|
||||
UPDATED=1
|
||||
fi
|
||||
|
||||
if [ $UPDATED -eq 1 ]; then
|
||||
git add .
|
||||
git commit -m "${UPDATE_MSG}"
|
||||
git push
|
||||
echo "Changes committed and pushed to repository."
|
||||
else
|
||||
echo "No changes to commit."
|
||||
fi
|
||||
|
||||
rm -rf tmp
|
10
openclash/announcement
Normal file
10
openclash/announcement
Normal file
@@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"zh": "Smart 策略组内核现已支持 policy-priority 参数来自定义调整节点权重,请自行替换测试、使用。",
|
||||
"en": "The Smart policy group core now supports the policy-priority parameter to customize node weights. Please replace it for testing and use."
|
||||
},
|
||||
{
|
||||
"zh": "如在更新内核后出现【Parse config error: path is not subpath of home directory】的错误时请在最新版插件设置页面启用【跳过安全路径检查】选项。",
|
||||
"en": "If you get [Parse config error: path is not subpath of home directory] after updating the core, please enable [Skip Safe Path Check] option in the settings page of the latest dev version of the OpenClash."
|
||||
}
|
||||
]
|
@@ -1,7 +1,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-openclash
|
||||
PKG_VERSION:=0.46.079
|
||||
PKG_VERSION:=0.46.086
|
||||
PKG_MAINTAINER:=vernesong <https://github.com/vernesong/OpenClash>
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
@@ -147,6 +147,8 @@ define Package/$(PKG_NAME)/postrm
|
||||
rm -rf /tmp/dler* >/dev/null 2>&1
|
||||
rm -rf /tmp/etc/openclash >/dev/null 2>&1
|
||||
rm -rf /tmp/openclash_edit_file_name >/dev/null 2>&1
|
||||
rm -rf /tmp/openclash_announcement >/dev/null 2>&1
|
||||
rm -rf /usr/share/openclash/ui/xd >/dev/null 2>&1
|
||||
sed -i '/OpenClash Append/,/OpenClash Append End/d' "/usr/lib/lua/luci/model/network.lua" >/dev/null 2>&1
|
||||
sed -i '/.*kB maximum content size*/c\HTTP_MAX_CONTENT = 1024*100 -- 100 kB maximum content size' /usr/lib/lua/luci/http.lua >/dev/null 2>&1
|
||||
sed -i '/.*kB maximum content size*/c\export let HTTP_MAX_CONTENT = 1024*100; // 100 kB maximum content size' /usr/share/ucode/luci/http.uc >/dev/null 2>&1
|
||||
|
@@ -26,6 +26,7 @@ function index()
|
||||
entry({"admin", "services", "openclash", "lastversion"},call("action_lastversion"))
|
||||
entry({"admin", "services", "openclash", "save_corever_branch"},call("action_save_corever_branch"))
|
||||
entry({"admin", "services", "openclash", "update"},call("action_update"))
|
||||
entry({"admin", "services", "openclash", "get_last_version"},call("action_get_last_version"))
|
||||
entry({"admin", "services", "openclash", "update_info"},call("action_update_info"))
|
||||
entry({"admin", "services", "openclash", "update_ma"},call("action_update_ma"))
|
||||
entry({"admin", "services", "openclash", "opupdate"},call("action_opupdate"))
|
||||
@@ -73,6 +74,7 @@ function index()
|
||||
entry({"admin", "services", "openclash", "set_subinfo_url"}, call("set_subinfo_url"))
|
||||
entry({"admin", "services", "openclash", "check_core"}, call("action_check_core"))
|
||||
entry({"admin", "services", "openclash", "core_download"}, call("core_download"))
|
||||
entry({"admin", "services", "openclash", "announcement"}, call("action_announcement"))
|
||||
entry({"admin", "services", "openclash", "settings"},cbi("openclash/settings"),_("Plugin Settings"), 30).leaf = true
|
||||
entry({"admin", "services", "openclash", "config-overwrite"},cbi("openclash/config-overwrite"),_("Overwrite Settings"), 40).leaf = true
|
||||
entry({"admin", "services", "openclash", "servers"},cbi("openclash/servers"),_("Onekey Create"), 50).leaf = true
|
||||
@@ -216,9 +218,9 @@ local function coremodel()
|
||||
if opkg and opkg.info("libc") and opkg.info("libc")["libc"] then
|
||||
return opkg.info("libc")["libc"]["Architecture"]
|
||||
else
|
||||
if fs.access("/bin/opkg") then
|
||||
if pkg_type() == "opkg" then
|
||||
return luci.sys.exec("rm -f /var/lock/opkg.lock && opkg status libc 2>/dev/null |grep 'Architecture' |awk -F ': ' '{print $2}' 2>/dev/null")
|
||||
elseif fs.access("/usr/bin/apk") then
|
||||
else
|
||||
return luci.sys.exec("apk list libc 2>/dev/null |awk '{print $2}'")
|
||||
end
|
||||
end
|
||||
@@ -236,13 +238,23 @@ local function coremetacv()
|
||||
if not nixio.fs.access(meta_core_path) then
|
||||
return "0"
|
||||
else
|
||||
return luci.sys.exec(string.format("%s -v 2>/dev/null |awk -F ' ' '{print $3}' |head -1", meta_core_path))
|
||||
return luci.sys.exec(string.format("%s -v 2>/dev/null |awk -F ' ' '{print $3}' |head -1 |tr -d '\n'", meta_core_path))
|
||||
end
|
||||
end
|
||||
|
||||
local function corelv()
|
||||
luci.sys.call("bash /usr/share/openclash/clash_version.sh")
|
||||
local core_meta_lv = luci.sys.exec("sed -n 3p /tmp/clash_last_version 2>/dev/null")
|
||||
local status = process_status("/usr/share/openclash/clash_version.sh")
|
||||
local core_meta_lv = ""
|
||||
if not status then
|
||||
if fs.access("/tmp/clash_last_version") then
|
||||
core_meta_lv = luci.sys.exec("sed -n 3p /tmp/clash_last_version 2>/dev/null |tr -d '\n'")
|
||||
else
|
||||
action_get_last_version()
|
||||
core_meta_lv = "loading..."
|
||||
end
|
||||
else
|
||||
core_meta_lv = "loading..."
|
||||
end
|
||||
return core_meta_lv
|
||||
end
|
||||
|
||||
@@ -250,18 +262,28 @@ local function opcv()
|
||||
if opkg and opkg.info("luci-app-openclash") and opkg.info("luci-app-openclash")["luci-app-openclash"] then
|
||||
return "v" .. opkg.info("luci-app-openclash")["luci-app-openclash"]["Version"]
|
||||
else
|
||||
if fs.access("/bin/opkg") then
|
||||
return luci.sys.exec("rm -f /var/lock/opkg.lock && opkg status luci-app-openclash 2>/dev/null |grep 'Version' |awk -F 'Version: ' '{print \"v\"$2}'")
|
||||
elseif fs.access("/usr/bin/apk") then
|
||||
return "v" .. luci.sys.exec("apk list luci-app-openclash 2>/dev/null|grep 'installed' | grep -oE '[0-9]+(\\.[0-9]+)*' | head -1")
|
||||
if pkg_type() == "opkg" then
|
||||
return luci.sys.exec("rm -f /var/lock/opkg.lock && opkg status luci-app-openclash 2>/dev/null |grep 'Version' |awk -F 'Version: ' '{print \"v\"$2}' |tr -d '\n'")
|
||||
else
|
||||
return "v" .. luci.sys.exec("apk list luci-app-openclash 2>/dev/null|grep 'installed' | grep -oE '[0-9]+(\\.[0-9]+)*' | head -1 |tr -d '\n'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function oplv()
|
||||
local new = luci.sys.call(string.format("bash /usr/share/openclash/openclash_version.sh"))
|
||||
local oplv = luci.sys.exec("sed -n 1p /tmp/openclash_last_version 2>/dev/null")
|
||||
return oplv .. "," .. new
|
||||
local status = process_status("/usr/share/openclash/openclash_version.sh")
|
||||
local oplv = ""
|
||||
if not status then
|
||||
if fs.access("/tmp/openclash_last_version") then
|
||||
oplv = luci.sys.exec("sed -n 1p /tmp/openclash_last_version 2>/dev/null |tr -d '\n'")
|
||||
else
|
||||
action_get_last_version()
|
||||
oplv = "loading..."
|
||||
end
|
||||
else
|
||||
oplv = "loading..."
|
||||
end
|
||||
return oplv
|
||||
end
|
||||
|
||||
local function opup()
|
||||
@@ -680,38 +702,61 @@ function sub_info_get()
|
||||
if string.match(info, "expire=%d+") then
|
||||
day_expire = tonumber(string.sub(string.match(info, "expire=%d+"), 8, -1)) or nil
|
||||
end
|
||||
expire = os.date("%Y-%m-%d", day_expire) or "null"
|
||||
if day_expire and os.time() <= day_expire then
|
||||
|
||||
if day_expire and day_expire == 0 then
|
||||
expire = luci.i18n.translate("Long-term")
|
||||
elseif day_expire then
|
||||
expire = os.date("%Y-%m-%d", day_expire) or "null"
|
||||
else
|
||||
expire = "null"
|
||||
end
|
||||
|
||||
if day_expire and day_expire ~= 0 and os.time() <= day_expire then
|
||||
day_left = math.ceil((day_expire - os.time()) / (3600*24))
|
||||
if math.ceil(day_left / 365) > 50 then
|
||||
day_left = "∞"
|
||||
end
|
||||
elseif day_expire and day_expire == 0 then
|
||||
day_left = "∞"
|
||||
elseif day_expire == nil then
|
||||
day_left = "null"
|
||||
else
|
||||
day_left = 0
|
||||
end
|
||||
if used and total and used <= total then
|
||||
percent = string.format("%.1f",((total-used)/total)*100) or nil
|
||||
surplus = fs.filesize(total - used) or "null"
|
||||
|
||||
if used and total and used <= total and total > 0 then
|
||||
percent = string.format("%.1f",((total-used)/total)*100) or "100"
|
||||
surplus = fs.filesize(total - used)
|
||||
elseif used and total and used > total and total > 0 then
|
||||
percent = "0"
|
||||
surplus = "-"..fs.filesize(total - used)
|
||||
elseif used and total and used < total and total == 0.0 then
|
||||
percent = "0"
|
||||
surplus = fs.filesize(total - used)
|
||||
elseif used and total and used == total and total == 0.0 then
|
||||
percent = "0"
|
||||
surplus = "0.0 KB"
|
||||
elseif used and total and used > total and total == 0.0 then
|
||||
percent = "100"
|
||||
surplus = fs.filesize(total - used)
|
||||
elseif used == nil and total and total > 0.0 then
|
||||
percent = 100
|
||||
surplus = total
|
||||
elseif total and total == 0.0 then
|
||||
surplus = fs.filesize(total)
|
||||
elseif used == nil and total and total == 0.0 then
|
||||
percent = 100
|
||||
surplus = "∞"
|
||||
else
|
||||
percent = 0
|
||||
surplus = "null"
|
||||
end
|
||||
if total and total > 0.0 then
|
||||
total = fs.filesize(total) or "null"
|
||||
if total and total > 0 then
|
||||
total = fs.filesize(total)
|
||||
elseif total and total == 0.0 then
|
||||
total = "∞"
|
||||
else
|
||||
total = "null"
|
||||
end
|
||||
used = fs.filesize(used) or "null"
|
||||
used = fs.filesize(used)
|
||||
sub_info = "Successful"
|
||||
else
|
||||
sub_info = "No Sub Info Found"
|
||||
@@ -1093,6 +1138,15 @@ function action_start()
|
||||
})
|
||||
end
|
||||
|
||||
function action_get_last_version()
|
||||
luci.sys.call("bash /usr/share/openclash/clash_version.sh &")
|
||||
luci.sys.call("bash /usr/share/openclash/openclash_version.sh &")
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
status = "success"
|
||||
})
|
||||
end
|
||||
|
||||
function action_update()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
@@ -1177,81 +1231,87 @@ function action_download_rule()
|
||||
end
|
||||
|
||||
function action_refresh_log()
|
||||
luci.http.prepare_content("application/json")
|
||||
local logfile="/tmp/openclash.log"
|
||||
local file = io.open(logfile, "r+")
|
||||
local info, len, line, lens, cache, ex_match, line_trans
|
||||
local data = ""
|
||||
local limit = 1000
|
||||
local log_tb = {}
|
||||
local log_len = tonumber(luci.http.formvalue("log_len")) or 0
|
||||
if file == nil then
|
||||
return nil
|
||||
end
|
||||
file:seek("set")
|
||||
info = file:read("*all")
|
||||
info = info:reverse()
|
||||
file:close()
|
||||
cache, len = string.gsub(info, '[^\n]+', "")
|
||||
if len == log_len then return nil end
|
||||
if log_len == 0 then
|
||||
if len > limit then lens = limit else lens = len end
|
||||
else
|
||||
lens = len - log_len
|
||||
end
|
||||
string.gsub(info, '[^\n]+', function(w) table.insert(log_tb, w) end, lens)
|
||||
for i=1, lens do
|
||||
line = log_tb[i]:reverse()
|
||||
line_trans = line
|
||||
ex_match = false
|
||||
core_match = false
|
||||
time_format = false
|
||||
while true do
|
||||
ex_keys = {"UDP%-Receive%-Buffer%-Size", "^Sec%-Fetch%-Mode", "^User%-Agent", "^Access%-Control", "^Accept", "^Origin", "^Referer", "^Connection", "^Pragma", "^Cache-"}
|
||||
for key=1, #ex_keys do
|
||||
if string.find (line, ex_keys[key]) then
|
||||
ex_match = true
|
||||
break
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
local logfile = "/tmp/openclash.log"
|
||||
local log_len = tonumber(luci.http.formvalue("log_len")) or 0
|
||||
|
||||
if not fs.access(logfile) then
|
||||
luci.http.write_json({
|
||||
len = 0,
|
||||
update = false,
|
||||
core_log = "",
|
||||
oc_log = ""
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local total_lines = tonumber(luci.sys.exec("wc -l < " .. logfile)) or 0
|
||||
|
||||
if total_lines == log_len and log_len > 0 then
|
||||
luci.http.write_json({
|
||||
len = total_lines,
|
||||
update = false,
|
||||
core_log = "",
|
||||
oc_log = ""
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local exclude_pattern = "UDP%-Receive%-Buffer%-Size|^Sec%-Fetch%-Mode|^User%-Agent|^Access%-Control|^Accept|^Origin|^Referer|^Connection|^Pragma|^Cache%-"
|
||||
local core_pattern = " DBG | INF |level=| WRN | ERR | FTL "
|
||||
local limit = 1000
|
||||
local start_line = (log_len > 0 and total_lines > log_len) and (log_len + 1) or 1
|
||||
|
||||
local core_cmd = string.format(
|
||||
"tail -n +%d '%s' | grep -v -E '%s' | grep -E '%s' | tail -n %d",
|
||||
start_line, logfile, exclude_pattern, core_pattern, limit
|
||||
)
|
||||
local core_raw = luci.sys.exec(core_cmd)
|
||||
|
||||
local oc_cmd = string.format(
|
||||
"tail -n +%d '%s' | grep -v -E '%s' | grep -v -E '%s' | tail -n %d",
|
||||
start_line, logfile, exclude_pattern, core_pattern, limit
|
||||
)
|
||||
local oc_raw = luci.sys.exec(oc_cmd)
|
||||
|
||||
local core_log = ""
|
||||
if core_raw and core_raw ~= "" then
|
||||
local core_logs = {}
|
||||
for line in core_raw:gmatch("[^\n]+") do
|
||||
local line_trans = line
|
||||
if string.match(string.sub(line, 0, 8), "%d%d:%d%d:%d%d") then
|
||||
line_trans = '"'..os.date("%Y-%m-%d", os.time()).. " "..os.date("%H:%M:%S", tonumber(string.sub(line, 0, 8)))..'"'..string.sub(line, 9, -1)
|
||||
end
|
||||
if ex_match then break end
|
||||
|
||||
core_keys = {" DBG ", " INF ", "level=", " WRN ", " ERR ", " FTL "}
|
||||
for key=1, #core_keys do
|
||||
if string.find(string.sub(line, 0, 13), core_keys[key]) or (string.find(line, core_keys[key]) and core_keys[key] == "level=") then
|
||||
core_match = true
|
||||
if core_keys[key] ~= "level=" then
|
||||
time_format = true
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
if time_format then
|
||||
if string.match(string.sub(line, 0, 8), "%d%d:%d%d:%d%d") then
|
||||
line_trans = '"'..os.date("%Y-%m-%d %H:%M:%S", tonumber(string.sub(line, 0, 8)))..'"'..string.sub(line, 9, -1)
|
||||
end
|
||||
end
|
||||
if not core_match then
|
||||
if not string.find (line, "【") or not string.find (line, "】") then
|
||||
line_trans = trans_line_nolabel(line)
|
||||
else
|
||||
line_trans = trans_line(line)
|
||||
end
|
||||
end
|
||||
if data == "" then
|
||||
data = line_trans
|
||||
elseif log_len == 0 and i == limit then
|
||||
data = data .."\n" .. line_trans .. "\n..."
|
||||
else
|
||||
data = data .."\n" .. line_trans
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
luci.http.write_json({
|
||||
len = len,
|
||||
log = data;
|
||||
})
|
||||
table.insert(core_logs, line_trans)
|
||||
end
|
||||
if #core_logs > 0 then
|
||||
core_log = table.concat(core_logs, "\n")
|
||||
end
|
||||
end
|
||||
|
||||
local oc_log = ""
|
||||
if oc_raw and oc_raw ~= "" then
|
||||
local oc_logs = {}
|
||||
for line in oc_raw:gmatch("[^\n]+") do
|
||||
local line_trans
|
||||
if not string.find(line, "【") or not string.find(line, "】") then
|
||||
line_trans = trans_line_nolabel(line)
|
||||
else
|
||||
line_trans = trans_line(line)
|
||||
end
|
||||
table.insert(oc_logs, line_trans)
|
||||
end
|
||||
if #oc_logs > 0 then
|
||||
oc_log = table.concat(oc_logs, "\n")
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.write_json({
|
||||
len = total_lines,
|
||||
update = true,
|
||||
core_log = core_log,
|
||||
oc_log = oc_log
|
||||
})
|
||||
end
|
||||
|
||||
function action_del_log()
|
||||
@@ -1614,61 +1674,98 @@ function all_proxies_stream_test()
|
||||
end
|
||||
|
||||
function trans_line_nolabel(data)
|
||||
local line_trans = ""
|
||||
if string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
line_trans = string.sub(data, 0, 20)..luci.i18n.translate(string.sub(data, 21, -1))
|
||||
else
|
||||
line_trans = luci.i18n.translate(string.sub(data, 0, -1))
|
||||
end
|
||||
return line_trans
|
||||
if data == nil or data == "" then
|
||||
return ""
|
||||
end
|
||||
|
||||
local line_trans = ""
|
||||
if string.len(data) >= 19 and string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
line_trans = string.sub(data, 0, 20)..luci.i18n.translate(string.sub(data, 21, -1))
|
||||
else
|
||||
line_trans = luci.i18n.translate(data)
|
||||
end
|
||||
return line_trans
|
||||
end
|
||||
|
||||
function trans_line(data)
|
||||
local no_trans = {}
|
||||
local line_trans = ""
|
||||
local a = string.find (data, "【")
|
||||
local b = string.find (data, "】") + 2
|
||||
local c = 21
|
||||
local d = 0
|
||||
local v
|
||||
local x
|
||||
while true do
|
||||
table.insert(no_trans, a)
|
||||
table.insert(no_trans, b)
|
||||
if string.find (data, "【", b+1) and string.find (data, "】", b+1) then
|
||||
a = string.find (data, "【", b+1)
|
||||
b = string.find (data, "】", b+1) + 2
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
for k = 1, #no_trans, 2 do
|
||||
x = no_trans[k]
|
||||
v = no_trans[k+1]
|
||||
if x <= 21 or not string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
line_trans = line_trans .. luci.i18n.translate(string.sub(data, d, x - 1)) .. string.sub(data, x, v)
|
||||
d = v + 1
|
||||
elseif v <= string.len(data) then
|
||||
line_trans = line_trans .. luci.i18n.translate(string.sub(data, c, x - 1)) .. string.sub(data, x, v)
|
||||
end
|
||||
c = v + 1
|
||||
end
|
||||
if c > string.len(data) then
|
||||
if d == 0 then
|
||||
if string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
line_trans = string.sub(data, 0, 20) .. line_trans
|
||||
end
|
||||
end
|
||||
else
|
||||
if d == 0 then
|
||||
if string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
line_trans = string.sub(data, 0, 20) .. line_trans .. luci.i18n.translate(string.sub(data, c, -1))
|
||||
end
|
||||
else
|
||||
line_trans = line_trans .. luci.i18n.translate(string.sub(data, c, -1))
|
||||
end
|
||||
end
|
||||
return line_trans
|
||||
if data == nil or data == "" then
|
||||
return ""
|
||||
end
|
||||
|
||||
local no_trans = {}
|
||||
local line_trans = ""
|
||||
local a = string.find(data, "【")
|
||||
|
||||
if not a then
|
||||
if string.len(data) >= 19 and string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
return string.sub(data, 0, 20) .. luci.i18n.translate(string.sub(data, 21, -1))
|
||||
else
|
||||
return luci.i18n.translate(data)
|
||||
end
|
||||
end
|
||||
|
||||
local b_pos = string.find(data, "】")
|
||||
if not b_pos then
|
||||
return luci.i18n.translate(data)
|
||||
end
|
||||
|
||||
local b = b_pos + 2
|
||||
local c = 21
|
||||
local d = 0
|
||||
local v
|
||||
local x
|
||||
|
||||
while true do
|
||||
table.insert(no_trans, a)
|
||||
table.insert(no_trans, b)
|
||||
|
||||
local next_a = string.find(data, "【", b+1)
|
||||
local next_b = string.find(data, "】", b+1)
|
||||
|
||||
if next_a and next_b then
|
||||
a = next_a
|
||||
b = next_b + 2
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if #no_trans % 2 ~= 0 then
|
||||
table.remove(no_trans)
|
||||
end
|
||||
|
||||
for k = 1, #no_trans, 2 do
|
||||
x = no_trans[k]
|
||||
v = no_trans[k+1]
|
||||
|
||||
if x and v then
|
||||
if x <= 21 or not string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
line_trans = line_trans .. luci.i18n.translate(string.sub(data, d, x - 1)) .. string.sub(data, x, v)
|
||||
d = v + 1
|
||||
elseif v <= string.len(data) then
|
||||
line_trans = line_trans .. luci.i18n.translate(string.sub(data, c, x - 1)) .. string.sub(data, x, v)
|
||||
end
|
||||
c = v + 1
|
||||
end
|
||||
end
|
||||
|
||||
if c > string.len(data) then
|
||||
if d == 0 then
|
||||
if string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
line_trans = string.sub(data, 0, 20) .. line_trans
|
||||
end
|
||||
end
|
||||
else
|
||||
if d == 0 then
|
||||
if string.match(string.sub(data, 0, 19), "%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") then
|
||||
line_trans = string.sub(data, 0, 20) .. line_trans .. luci.i18n.translate(string.sub(data, c, -1))
|
||||
end
|
||||
else
|
||||
line_trans = line_trans .. luci.i18n.translate(string.sub(data, c, -1))
|
||||
end
|
||||
end
|
||||
|
||||
return line_trans
|
||||
end
|
||||
|
||||
function process_status(name)
|
||||
@@ -1679,3 +1776,17 @@ function process_status(name)
|
||||
return luci.sys.call(string.format("ps -w |grep '%s' |grep -v grep >/dev/null", name)) == 0
|
||||
end
|
||||
end
|
||||
|
||||
function action_announcement()
|
||||
if not fs.access("/tmp/openclash_announcement") or fs.readfile("/tmp/openclash_announcement") == "" or fs.mtime("/tmp/openclash_announcement") < (os.time() - 86400) then
|
||||
local HTTP_CODE = luci.sys.exec("curl -SsL -m 5 -w '%{http_code}' -o /tmp/openclash_announcement https://raw.githubusercontent.com/vernesong/OpenClash/dev/announcement 2>/dev/null")
|
||||
if HTTP_CODE ~= "200" then
|
||||
fs.unlink("/tmp/openclash_announcement")
|
||||
end
|
||||
end
|
||||
local info = luci.sys.exec("cat /tmp/openclash_announcement 2>/dev/null") or ""
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
content = info;
|
||||
})
|
||||
end
|
@@ -367,6 +367,21 @@ o:value("REJECT-DROP")
|
||||
o:value("PASS")
|
||||
o:value("GLOBAL")
|
||||
|
||||
o = s:option(ListValue, "TikTok", translate("TikTok"))
|
||||
o:depends("rule_name", "lhie1")
|
||||
o.rmempty = true
|
||||
for groupname in string.gmatch(groupnames, "([^'##\n']+)##") do
|
||||
if groupname ~= nil and groupname ~= "" then
|
||||
o:value(groupname)
|
||||
end
|
||||
end
|
||||
o:value("DIRECT")
|
||||
o:value("REJECT")
|
||||
o:value("REJECT-DROP")
|
||||
o:value("PASS")
|
||||
o:value("GLOBAL")
|
||||
|
||||
|
||||
o = s:option(ListValue, "miHoYo", translate("miHoYo"))
|
||||
o:depends("rule_name", "lhie1")
|
||||
o.rmempty = true
|
||||
|
@@ -14,12 +14,12 @@ m.pageaction = false
|
||||
m.description=translate("Attention:")..
|
||||
"<br/>"..translate("The game proxy is a test function and does not guarantee the availability of rules")..
|
||||
"<br/>"..translate("Preparation steps:")..
|
||||
"<br/>"..translate("1. In the <server and policy group management> page, create the policy group and node you are going to use, and apply the configuration (when adding nodes, you must select the policy group you want to join). Policy group type suggestion: fallback, game nodes must be support UDP and not a Vmess")..
|
||||
"<br/>"..translate("1. Check the policy group and node you are going to use, Policy group type suggestion: fallback, game nodes must be support UDP and not a Vmess")..
|
||||
"<br/>"..translate("2. Click the <manage third party game rules> or <manage third party rule set> button to enter the rule list and download the rules you want to use")..
|
||||
"<br/>"..translate("3. On this page, set the corresponding configuration file and policy group of the rule you have downloaded, and save the settings")..
|
||||
"<br/>"..translate("4. Install the TUN or Meta core")..
|
||||
"<br/>"..
|
||||
"<br/>"..translate("When setting this page, if the groups is empty, please go to the <server and group management> page to add")..
|
||||
"<br/>"..translate("When setting this page, if the groups is empty, please go to the <Onekey Create> page to add")..
|
||||
"<br/>"..
|
||||
"<br/>"..translate("Introduction to rule set usage: https://wiki.metacubex.one/config/rule-providers/content/")
|
||||
|
||||
|
@@ -143,9 +143,13 @@ o:value("hysteria2", translate("Hysteria2 ")..translate("(Only Meta Core)"))
|
||||
o:value("wireguard", translate("WireGuard")..translate("(Only Meta Core)"))
|
||||
o:value("tuic", translate("Tuic")..translate("(Only Meta Core)"))
|
||||
o:value("snell", translate("Snell"))
|
||||
o:value("mieru", translate("Mieru"))
|
||||
o:value("mieru", translate("Mieru")..translate("(Only Meta Core)"))
|
||||
o:value("anytls", translate("AnyTLS")..translate("(Only Meta Core)"))
|
||||
o:value("socks5", translate("Socks5"))
|
||||
o:value("http", translate("HTTP(S)"))
|
||||
o:value("direct", translate("DIRECT")..translate("(Only Meta Core)"))
|
||||
o:value("dns", translate("DNS")..translate("(Only Meta Core)"))
|
||||
o:value("ssh", translate("SSH")..translate("(Only Meta Core)"))
|
||||
|
||||
o.description = translate("Using incorrect encryption mothod may causes service fail to start")
|
||||
|
||||
@@ -156,11 +160,41 @@ o.default = "Server - "..sid
|
||||
o = s:option(Value, "server", translate("Server Address"))
|
||||
o.datatype = "host"
|
||||
o.rmempty = true
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "vmess")
|
||||
o:depends("type", "trojan")
|
||||
o:depends("type", "vless")
|
||||
o:depends("type", "hysteria")
|
||||
o:depends("type", "hysteria2")
|
||||
o:depends("type", "wireguard")
|
||||
o:depends("type", "tuic")
|
||||
o:depends("type", "mieru")
|
||||
o:depends("type", "anytls")
|
||||
o:depends("type", "snell")
|
||||
o:depends("type", "socks5")
|
||||
o:depends("type", "http")
|
||||
o:depends("type", "ssh")
|
||||
|
||||
o = s:option(Value, "port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
o.default = "443"
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "vmess")
|
||||
o:depends("type", "trojan")
|
||||
o:depends("type", "vless")
|
||||
o:depends("type", "hysteria")
|
||||
o:depends("type", "hysteria2")
|
||||
o:depends("type", "wireguard")
|
||||
o:depends("type", "tuic")
|
||||
o:depends("type", "mieru")
|
||||
o:depends("type", "anytls")
|
||||
o:depends("type", "snell")
|
||||
o:depends("type", "socks5")
|
||||
o:depends("type", "http")
|
||||
o:depends("type", "ssh")
|
||||
|
||||
o = s:option(Flag, "flag_port_hopping", translate("Enable Port Hopping"))
|
||||
o:depends("type", "hysteria")
|
||||
@@ -184,6 +218,7 @@ o:depends("type", "ssr")
|
||||
o:depends("type", "trojan")
|
||||
o:depends("type", "hysteria2")
|
||||
o:depends("type", "mieru")
|
||||
o:depends("type", "anytls")
|
||||
|
||||
-- [[ Mieru ]]--
|
||||
o = s:option(Value, "port_range", translate("Port Range"))
|
||||
@@ -415,6 +450,8 @@ o:depends("type", "socks5")
|
||||
o:depends("type", "trojan")
|
||||
o:depends({type = "snell", snell_version = "3"})
|
||||
o:depends("type", "wireguard")
|
||||
o:depends("type", "direct")
|
||||
o:depends("type", "anytls")
|
||||
|
||||
o = s:option(ListValue, "udp_over_tcp", translate("udp-over-tcp"))
|
||||
o.rmempty = true
|
||||
@@ -602,6 +639,7 @@ o:depends("type", "vless")
|
||||
o:depends("type", "hysteria")
|
||||
o:depends("type", "hysteria2")
|
||||
o:depends("type", "tuic")
|
||||
o:depends("type", "anytls")
|
||||
|
||||
-- [[ TLS ]]--
|
||||
o = s:option(ListValue, "tls", translate("TLS"))
|
||||
@@ -648,6 +686,7 @@ o:depends("type", "trojan")
|
||||
o:depends("type", "http")
|
||||
o:depends("type", "hysteria")
|
||||
o:depends("type", "hysteria2")
|
||||
o:depends("type", "anytls")
|
||||
|
||||
-- [[ headers ]]--
|
||||
o = s:option(DynamicList, "http_headers", translate("headers"))
|
||||
@@ -659,12 +698,30 @@ o:depends("type", "http")
|
||||
o = s:option(Value, "auth_name", translate("Auth Username"))
|
||||
o:depends("type", "socks5")
|
||||
o:depends("type", "http")
|
||||
o:depends("type", "ssh")
|
||||
o.rmempty = true
|
||||
|
||||
-- 验证密码
|
||||
o = s:option(Value, "auth_pass", translate("Auth Password"))
|
||||
o:depends("type", "socks5")
|
||||
o:depends("type", "http")
|
||||
o:depends("type", "ssh")
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "private_key", translate("private-key"))
|
||||
o:depends("type", "ssh")
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "private_key_passphrase", translate("private-key-passphrase"))
|
||||
o:depends("type", "ssh")
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(DynamicList, "host_key", translate("host-key"))
|
||||
o:depends("type", "ssh")
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(DynamicList, "host_key_algorithms", translate("host-key-algorithms"))
|
||||
o:depends("type", "ssh")
|
||||
o.rmempty = true
|
||||
|
||||
-- [[ alpn ]]--
|
||||
@@ -673,6 +730,7 @@ o.rmempty = true
|
||||
o:value("h2")
|
||||
o:value("http/1.1")
|
||||
o:depends("type", "trojan")
|
||||
o:depends("type", "anytls")
|
||||
|
||||
-- [[ alpn ]]--
|
||||
o = s:option(DynamicList, "hysteria_alpn", translate("alpn"))
|
||||
@@ -822,6 +880,22 @@ o:value("true")
|
||||
o:value("false")
|
||||
o:depends("type", "vmess")
|
||||
|
||||
-- [[ AnyTLS ]]--
|
||||
o = s:option(Value, "idle_session_check_interval", translate("idle-session-check-interval"))
|
||||
o.rmempty = true
|
||||
o.default = "30"
|
||||
o:depends("type", "anytls")
|
||||
|
||||
o = s:option(Value, "idle_session_timeout", translate("idle-session-timeout"))
|
||||
o.rmempty = true
|
||||
o.default = "30"
|
||||
o:depends("type", "anytls")
|
||||
|
||||
o = s:option(Value, "min_idle_session", translate("min-idle-session"))
|
||||
o.rmempty = true
|
||||
o.default = "0"
|
||||
o:depends("type", "anytls")
|
||||
|
||||
-- [[ Fast Open ]]--
|
||||
o = s:option(ListValue, "fast_open", translate("Fast Open"))
|
||||
o.rmempty = true
|
||||
@@ -879,6 +953,7 @@ o:depends({type = "vmess", obfs_vmess = "websocket"})
|
||||
o:depends({type = "vmess", obfs_vmess = "http"})
|
||||
o:depends({type = "vmess", obfs_vmess = "h2"})
|
||||
o:depends({type = "vmess", obfs_vmess = "grpc"})
|
||||
o:depends("type", "anytls")
|
||||
|
||||
-- [[ ip version ]]--
|
||||
o = s:option(ListValue, "ip_version", translate("IP Version")..translate("(Only Meta Core)"))
|
||||
@@ -889,6 +964,21 @@ o:value("ipv4-prefer")
|
||||
o:value("ipv6")
|
||||
o:value("ipv6-prefer")
|
||||
o.default = "ipv4-prefer"
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "vmess")
|
||||
o:depends("type", "trojan")
|
||||
o:depends("type", "vless")
|
||||
o:depends("type", "hysteria")
|
||||
o:depends("type", "hysteria2")
|
||||
o:depends("type", "wireguard")
|
||||
o:depends("type", "tuic")
|
||||
o:depends("type", "mieru")
|
||||
o:depends("type", "snell")
|
||||
o:depends("type", "socks5")
|
||||
o:depends("type", "http")
|
||||
o:depends("type", "ssh")
|
||||
o:depends("type", "direct")
|
||||
|
||||
-- [[ smux ]]--
|
||||
o = s:option(ListValue, "multiplex", translate("Multiplex")..translate("(Only Meta Core)"))
|
||||
@@ -952,11 +1042,41 @@ o:depends("multiplex", "true")
|
||||
o = s:option(Value, "interface_name", translate("interface-name"))
|
||||
o.rmempty = true
|
||||
o.placeholder = translate("eth0")
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "vmess")
|
||||
o:depends("type", "trojan")
|
||||
o:depends("type", "vless")
|
||||
o:depends("type", "hysteria")
|
||||
o:depends("type", "hysteria2")
|
||||
o:depends("type", "wireguard")
|
||||
o:depends("type", "tuic")
|
||||
o:depends("type", "mieru")
|
||||
o:depends("type", "snell")
|
||||
o:depends("type", "socks5")
|
||||
o:depends("type", "http")
|
||||
o:depends("type", "ssh")
|
||||
o:depends("type", "direct")
|
||||
|
||||
-- [[ routing-mark ]]--
|
||||
o = s:option(Value, "routing_mark", translate("routing-mark"))
|
||||
o.rmempty = true
|
||||
o.placeholder = translate("2333")
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "vmess")
|
||||
o:depends("type", "trojan")
|
||||
o:depends("type", "vless")
|
||||
o:depends("type", "hysteria")
|
||||
o:depends("type", "hysteria2")
|
||||
o:depends("type", "wireguard")
|
||||
o:depends("type", "tuic")
|
||||
o:depends("type", "mieru")
|
||||
o:depends("type", "snell")
|
||||
o:depends("type", "socks5")
|
||||
o:depends("type", "http")
|
||||
o:depends("type", "ssh")
|
||||
o:depends("type", "direct")
|
||||
|
||||
-- [[ other-setting ]]--
|
||||
o = s:option(Value, "other_parameters", translate("Other Parameters"))
|
||||
|
@@ -103,6 +103,10 @@ o = s:taboption("op_mode", Flag, "disable_quic_go_gso", translate("Disable quic-
|
||||
o.description = font_red..bold_on..translate("Suggestion: If Encountering Issues With QUIC UDP on The Linux Kernel Version Above 6.6, Please Try to Enable.")..bold_off..font_off
|
||||
o.default = 0
|
||||
|
||||
o = s:taboption("op_mode", Flag, "skip_safe_path_check", translate("Skip Safe Path Check"))
|
||||
o.description = font_red..bold_on..translate("Enable If You Want Using Files Not in /etc/openclash in You Config")..bold_off..font_off
|
||||
o.default = 0
|
||||
|
||||
o = s:taboption("op_mode", Flag, "small_flash_memory", translate("Small Flash Memory"))
|
||||
o.description = translate("Move Core And GEOIP Data File To /tmp/etc/openclash For Small Flash Memory Device")
|
||||
o.default = 0
|
||||
@@ -790,8 +794,7 @@ o.description = translate("Custom GeoIP MMDB URL, Click Button Below To Refresh
|
||||
o:value("https://testingcf.jsdelivr.net/gh/alecthw/mmdb_china_ip_list@release/lite/Country.mmdb", translate("Alecthw-lite-Version")..translate("(Default mmdb)"))
|
||||
o:value("https://testingcf.jsdelivr.net/gh/alecthw/mmdb_china_ip_list@release/Country.mmdb", translate("Alecthw-Version")..translate("(All Info mmdb)"))
|
||||
o:value("https://testingcf.jsdelivr.net/gh/Hackl0us/GeoIP2-CN@release/Country.mmdb", translate("Hackl0us-Version")..translate("(Only CN)"))
|
||||
o:value("https://geolite.clash.dev/Country.mmdb", translate("Geolite.clash.dev"))
|
||||
o.default = "http://www.ideame.top/mmdb/Country.mmdb"
|
||||
o.default = "https://testingcf.jsdelivr.net/gh/alecthw/mmdb_china_ip_list@release/lite/Country.mmdb"
|
||||
|
||||
o = s:taboption("geo_update", Button, translate("GEOIP Update"))
|
||||
o.title = translate("Update GeoIP MMDB")
|
||||
@@ -890,6 +893,49 @@ o.write = function()
|
||||
end
|
||||
o:depends("geosite_auto_update", "1")
|
||||
|
||||
o = s:taboption("geo_update", Flag, "geoasn_auto_update", font_red..bold_on..translate("Auto Update Geo ASN")..bold_off..font_off)
|
||||
o.default = 0
|
||||
|
||||
o = s:taboption("geo_update", ListValue, "geoasn_update_week_time", translate("Update Time (Every Week)"))
|
||||
o:value("*", translate("Every Day"))
|
||||
o:value("1", translate("Every Monday"))
|
||||
o:value("2", translate("Every Tuesday"))
|
||||
o:value("3", translate("Every Wednesday"))
|
||||
o:value("4", translate("Every Thursday"))
|
||||
o:value("5", translate("Every Friday"))
|
||||
o:value("6", translate("Every Saturday"))
|
||||
o:value("0", translate("Every Sunday"))
|
||||
o.default = "1"
|
||||
o:depends("geoasn_auto_update", "1")
|
||||
|
||||
o = s:taboption("geo_update", ListValue, "geoasn_update_day_time", translate("Update time (every day)"))
|
||||
for t = 0,23 do
|
||||
o:value(t, t..":00")
|
||||
end
|
||||
o.default = "0"
|
||||
o:depends("geoasn_auto_update", "1")
|
||||
|
||||
o = s:taboption("geo_update", Value, "geoasn_custom_url")
|
||||
o.title = translate("Custom GeoSite URL")
|
||||
o.rmempty = true
|
||||
o.description = translate("Custom Geo ASN Data URL, Click Button Below To Refresh After Edit")
|
||||
o:value("https://testingcf.jsdelivr.net/gh/xishang0128/geoip@release/GeoLite2-ASN.mmdb", translate("xishang0128-testingcf-jsdelivr-Version")..translate("(Default)"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/xishang0128/geoip@release/GeoLite2-ASN.mmdb", translate("xishang0128-fastly-jsdelivr-Version"))
|
||||
o.default = "https://testingcf.jsdelivr.net/gh/xishang0128/geoip@release/GeoLite2-ASN.mmdb"
|
||||
o:depends("geoasn_auto_update", "1")
|
||||
|
||||
o = s:taboption("geo_update", Button, translate("ASN Update"))
|
||||
o.title = translate("Update Geo ASN Database")
|
||||
o.inputtitle = translate("Check And Update")
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
m.uci:set("openclash", "config", "enable", 1)
|
||||
m.uci:commit("openclash")
|
||||
SYS.call("/usr/share/openclash/openclash_geoasn.sh >/dev/null 2>&1 &")
|
||||
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
||||
end
|
||||
o:depends("geoasn_auto_update", "1")
|
||||
|
||||
o = s:taboption("chnr_update", Flag, "chnr_auto_update", translate("Auto Update"))
|
||||
o.description = translate("Auto Update Chnroute Lists")
|
||||
o.default = 0
|
||||
@@ -917,8 +963,8 @@ o.rmempty = false
|
||||
o.description = translate("Custom Chnroute Lists URL, Click Button Below To Refresh After Edit")
|
||||
o:value("https://ispip.clang.cn/all_cn.txt", translate("Clang-CN")..translate("(Default)"))
|
||||
o:value("https://ispip.clang.cn/all_cn_cidr.txt", translate("Clang-CN-CIDR"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/Hackl0us/GeoIP2-CN@release/CN-ip-cidr.txt", translate("Hackl0us-CN-CIDR-fastly-jsdelivr")..translate("(Large Size)"))
|
||||
o:value("https://testingcf.jsdelivr.net/gh/Hackl0us/GeoIP2-CN@release/CN-ip-cidr.txt", translate("Hackl0us-CN-CIDR-testingcf-jsdelivr")..translate("(Large Size)"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/Hackl0us/GeoIP2-CN@release/CN-ip-cidr.txt", translate("Hackl0us-CN-CIDR-fastly-jsdelivr"))
|
||||
o:value("https://testingcf.jsdelivr.net/gh/Hackl0us/GeoIP2-CN@release/CN-ip-cidr.txt", translate("Hackl0us-CN-CIDR-testingcf-jsdelivr"))
|
||||
o.default = "https://ispip.clang.cn/all_cn.txt"
|
||||
|
||||
o = s:taboption("chnr_update", Value, "chnr6_custom_url")
|
||||
|
@@ -261,11 +261,14 @@ end
|
||||
function filesize(e)
|
||||
local t=0
|
||||
local a={' KB',' MB',' GB',' TB',' PB'}
|
||||
if e < 0 then
|
||||
e = -e
|
||||
end
|
||||
repeat
|
||||
e=e/1024
|
||||
t=t+1
|
||||
until(e<=1024)
|
||||
return string.format("%.1f",e)..a[t]
|
||||
return string.format("%.1f",e)..a[t] or "0.0 KB"
|
||||
end
|
||||
|
||||
function lanip()
|
||||
|
@@ -92,8 +92,8 @@ ul{
|
||||
<div id="tab" class="cbi-section">
|
||||
<div id="tab-header" class="cbi-tabmenu">
|
||||
<ul class="cbi-tabmenu">
|
||||
<li name="tab-header" class="cbi-tab"><a><%:OpenClash Log%></a></li>
|
||||
<li name="tab-header" class="cbi-tab-disabled"><a><%:Core Log%></a></li>
|
||||
<li name="tab-header" class="cbi-tab"><a href="#"><%:OpenClash Log%></a></li>
|
||||
<li name="tab-header" class="cbi-tab-disabled"><a href="#"><%:Core Log%></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="tab-content">
|
||||
@@ -144,6 +144,8 @@ var s;
|
||||
var log_len = 0;
|
||||
var lv = document.getElementById('cbid.openclash.config.clog');
|
||||
var cl = document.getElementById('core_log');
|
||||
var animatingOC = false;
|
||||
var animatingCore = false;
|
||||
|
||||
function get_log_level() {
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "log_level")%>', null, function(x, status) {
|
||||
@@ -220,76 +222,339 @@ function p(s) {
|
||||
return s < 10 ? '0' + s: s;
|
||||
};
|
||||
|
||||
function line_tolocal(str){
|
||||
var strt=new Array();
|
||||
var cstrt=new Array();
|
||||
var cn = 0;
|
||||
var sn = 0;
|
||||
str.trim().split('\n').forEach(function(v, i) {
|
||||
var regex = /(time=)"([^"]*)"/g;
|
||||
var res = regex.exec(v);
|
||||
if (res) {
|
||||
var dt = new Date(res[2]);
|
||||
}
|
||||
else {
|
||||
var dtt = new Date(v.substring(0,19));
|
||||
}
|
||||
if (dt && dt != "Invalid Date"){
|
||||
if (v.indexOf("level=") != -1) {
|
||||
var log_info = v.substring(res[2].length + 7);
|
||||
}
|
||||
else {
|
||||
var log_info = v.substring(res[2].length + 2);
|
||||
}
|
||||
cstrt[cn]=dt.getFullYear()+"-"+p(dt.getMonth()+1)+"-"+p(dt.getDate())+" "+p(dt.getHours())+":"+p(dt.getMinutes())+":"+p(dt.getSeconds())+log_info;
|
||||
cn = cn + 1;
|
||||
}
|
||||
else if (dtt && dtt != "Invalid Date" && v.substring(28,33).indexOf(" ERR ") == -1) {
|
||||
strt[sn]=v;
|
||||
sn = sn + 1;
|
||||
}
|
||||
else{
|
||||
cstrt[cn]=v;
|
||||
cn = cn + 1;
|
||||
}
|
||||
})
|
||||
return [strt,cstrt]
|
||||
function line_tolocal(str) {
|
||||
var trans_local = new Array();
|
||||
var local_count = 0;
|
||||
|
||||
|
||||
str.trim().split('\n').forEach(function(v, i) {
|
||||
var regex = /(time=)"([^"]*)"/g;
|
||||
var res = regex.exec(v);
|
||||
|
||||
try {
|
||||
if (res) {
|
||||
var dt = new Date(res[2]);
|
||||
|
||||
if (!isNaN(dt.getTime())) {
|
||||
if (v.indexOf("level=") != -1) {
|
||||
var log_info = v.substring(res[2].length + 7);
|
||||
} else {
|
||||
var log_info = v.substring(res[2].length + 2);
|
||||
}
|
||||
trans_local[local_count] = dt.getFullYear() + "-" + p(dt.getMonth() + 1) + "-" + p(dt.getDate()) + " " +
|
||||
p(dt.getHours()) + ":" + p(dt.getMinutes()) + ":" + p(dt.getSeconds()) + log_info;
|
||||
local_count++;
|
||||
} else {
|
||||
trans_local[local_count] = v;
|
||||
local_count++;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
var dtt = new Date(v.substring(0, 19));
|
||||
|
||||
if (!isNaN(dtt.getTime()) && v.substring(0, 19).match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)) {
|
||||
trans_local[local_count] = v;
|
||||
local_count++;
|
||||
} else {
|
||||
trans_local[local_count] = v;
|
||||
local_count++;
|
||||
}
|
||||
} catch (e) {
|
||||
trans_local[local_count] = v;
|
||||
local_count++;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
trans_local[local_count] = v;
|
||||
local_count++;
|
||||
}
|
||||
});
|
||||
|
||||
return trans_local;
|
||||
};
|
||||
|
||||
function smoothlyDisplayLogs(newLines, target, isEditor, currentContent, isActiveTab) {
|
||||
var scrollPosition = null;
|
||||
var isAtTop = false;
|
||||
var cursorPos = null;
|
||||
var selectionRange = null;
|
||||
|
||||
var isFirstLoad = !currentContent || currentContent.trim() === "";
|
||||
|
||||
if (isEditor && target) {
|
||||
scrollPosition = target.getScrollInfo();
|
||||
isAtTop = (scrollPosition.top < 20);
|
||||
|
||||
if (target.hasFocus()) {
|
||||
cursorPos = target.getCursor();
|
||||
|
||||
if (cursorPos.line === 0) {
|
||||
cursorPos = null;
|
||||
selectionRange = null;
|
||||
} else if (target.somethingSelected()) {
|
||||
selectionRange = {
|
||||
from: target.getCursor(true),
|
||||
to: target.getCursor(false)
|
||||
};
|
||||
} else {
|
||||
selectionRange = null;
|
||||
}
|
||||
} else {
|
||||
cursorPos = null;
|
||||
selectionRange = null;
|
||||
}
|
||||
} else if (!isEditor && target) {
|
||||
scrollPosition = target.scrollTop;
|
||||
isAtTop = (target.scrollTop < 20);
|
||||
}
|
||||
|
||||
if ((target === oc_editor && animatingOC) || (target === core_editor && animatingCore) || !isActiveTab) {
|
||||
var content = "";
|
||||
var lines = newLines.slice().reverse();
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
content += lines[i] + "\n";
|
||||
}
|
||||
content = content + (currentContent || "");
|
||||
|
||||
var allLines = content.split("\n");
|
||||
if (allLines.length > 2000) {
|
||||
allLines = allLines.slice(0, 1999);
|
||||
allLines.push("...");
|
||||
content = allLines.join("\n");
|
||||
}
|
||||
|
||||
if (isEditor) {
|
||||
var addedLines = lines.length;
|
||||
target.setValue(content);
|
||||
|
||||
if (!isAtTop && scrollPosition) {
|
||||
if (cursorPos) {
|
||||
cursorPos.line += addedLines;
|
||||
target.setCursor(cursorPos);
|
||||
|
||||
target.scrollIntoView({line: cursorPos.line, ch: cursorPos.ch}, 300);
|
||||
} else {
|
||||
target.scrollTo(scrollPosition.left, scrollPosition.top);
|
||||
}
|
||||
|
||||
if (selectionRange) {
|
||||
selectionRange.from.line += addedLines;
|
||||
selectionRange.to.line += addedLines;
|
||||
target.setSelection(selectionRange.from, selectionRange.to);
|
||||
|
||||
target.scrollIntoView({
|
||||
from: selectionRange.from,
|
||||
to: selectionRange.to
|
||||
}, 300);
|
||||
}
|
||||
} else if (isAtTop) {
|
||||
target.scrollTo(0, 0);
|
||||
if (isFirstLoad) {
|
||||
target.setCursor({line: 0, ch: 0});
|
||||
}
|
||||
}
|
||||
|
||||
target.refresh();
|
||||
} else {
|
||||
var oldScrollTop = scrollPosition;
|
||||
target.innerHTML = content;
|
||||
if (!isAtTop && oldScrollTop) {
|
||||
target.scrollTop = oldScrollTop;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (target === oc_editor || target === lv) {
|
||||
animatingOC = true;
|
||||
} else {
|
||||
animatingCore = true;
|
||||
}
|
||||
|
||||
var totalLines = newLines.length;
|
||||
var batchSize, interval;
|
||||
|
||||
if (totalLines <= 10) {
|
||||
batchSize = 1;
|
||||
interval = 90;
|
||||
} else if (totalLines <= 50) {
|
||||
batchSize = 3;
|
||||
interval = 60;
|
||||
} else if (totalLines <= 200) {
|
||||
batchSize = 8;
|
||||
interval = 35;
|
||||
} else if (totalLines <= 500) {
|
||||
batchSize = 15;
|
||||
interval = 25;
|
||||
} else if (totalLines <= 1000) {
|
||||
batchSize = 25;
|
||||
interval = 15;
|
||||
} else {
|
||||
batchSize = 40;
|
||||
interval = 10;
|
||||
}
|
||||
|
||||
var displayedContent = currentContent || "";
|
||||
var logLines = newLines.slice();
|
||||
var currentBatchCount = 0;
|
||||
var accumulatedContent = "";
|
||||
|
||||
function displayNextBatch() {
|
||||
if (currentBatchCount >= logLines.length) {
|
||||
if (target === oc_editor || target === lv) {
|
||||
animatingOC = false;
|
||||
} else {
|
||||
animatingCore = false;
|
||||
}
|
||||
|
||||
if (isEditor && !isAtTop && cursorPos) {
|
||||
cursorPos.line += logLines.length;
|
||||
target.setCursor(cursorPos);
|
||||
|
||||
if (selectionRange) {
|
||||
selectionRange.from.line += logLines.length;
|
||||
selectionRange.to.line += logLines.length;
|
||||
target.setSelection(selectionRange.from, selectionRange.to);
|
||||
|
||||
target.scrollIntoView({
|
||||
from: selectionRange.from,
|
||||
to: selectionRange.to
|
||||
}, 300);
|
||||
} else {
|
||||
target.scrollIntoView({line: cursorPos.line, ch: cursorPos.ch}, 300);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var nextBatchSize = Math.min(batchSize, logLines.length - currentBatchCount);
|
||||
|
||||
var batchLines = logLines.slice(currentBatchCount, currentBatchCount + nextBatchSize).reverse();
|
||||
currentBatchCount += nextBatchSize;
|
||||
|
||||
if (accumulatedContent) {
|
||||
accumulatedContent = batchLines.join("\n") + "\n" + accumulatedContent;
|
||||
} else {
|
||||
accumulatedContent = batchLines.join("\n");
|
||||
}
|
||||
|
||||
var content = accumulatedContent + (displayedContent ? "\n" + displayedContent : "");
|
||||
|
||||
var contentLines = content.split("\n");
|
||||
if (contentLines.length > 2000) {
|
||||
contentLines = contentLines.slice(0, 1999);
|
||||
contentLines.push("...");
|
||||
content = contentLines.join("\n");
|
||||
}
|
||||
|
||||
if (isEditor) {
|
||||
var currentScrollInfo = isAtTop ? null : target.getScrollInfo();
|
||||
target.setValue(content);
|
||||
|
||||
if (!isAtTop && currentScrollInfo) {
|
||||
target.scrollTo(currentScrollInfo.left, currentScrollInfo.top);
|
||||
}
|
||||
target.refresh();
|
||||
} else {
|
||||
var currentScrollTop = isAtTop ? null : target.scrollTop;
|
||||
target.innerHTML = content;
|
||||
if (!isAtTop && currentScrollTop !== null) {
|
||||
target.scrollTop = currentScrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentBatchCount < logLines.length) {
|
||||
setTimeout(displayNextBatch, interval);
|
||||
} else {
|
||||
if (target === oc_editor || target === lv) {
|
||||
animatingOC = false;
|
||||
} else {
|
||||
animatingCore = false;
|
||||
}
|
||||
|
||||
if (isEditor && !isAtTop && cursorPos) {
|
||||
cursorPos.line += logLines.length;
|
||||
target.setCursor(cursorPos);
|
||||
|
||||
if (selectionRange) {
|
||||
selectionRange.from.line += logLines.length;
|
||||
selectionRange.to.line += logLines.length;
|
||||
target.setSelection(selectionRange.from, selectionRange.to);
|
||||
|
||||
target.scrollIntoView({
|
||||
from: selectionRange.from,
|
||||
to: selectionRange.to
|
||||
}, 300);
|
||||
} else {
|
||||
target.scrollIntoView({line: cursorPos.line, ch: cursorPos.ch}, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
displayNextBatch();
|
||||
}
|
||||
|
||||
function poll_log(){
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "refresh_log")%>', {log_len: log_len},
|
||||
function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if (status && status.log != "" && lv && cl) {
|
||||
var log = line_tolocal(status.log);
|
||||
var lines = log[0];
|
||||
var clines = log[1];
|
||||
if (lines != "" || clines != "") {
|
||||
if (lines != "") {
|
||||
lv.innerHTML = lines.join('\n')+ (log_len != 0 ? '\n' : '') + lv.innerHTML;
|
||||
oc_editor.setValue(lv.value);
|
||||
oc_editor.refresh();
|
||||
}
|
||||
if (clines != "") {
|
||||
if (lines[0] != "..." && lines[lines.length-1] != "...") {
|
||||
cl.innerHTML = clines.join('\n') + (log_len != 0 ? '\n' : '') + cl.innerHTML;
|
||||
}
|
||||
else {
|
||||
cl.innerHTML = clines.join('\n') + (log_len != 0 ? '\n' : cl.innerHTML + '\n...');
|
||||
}
|
||||
core_editor.setValue(cl.value);
|
||||
core_editor.refresh();
|
||||
}
|
||||
log_len = status.len;
|
||||
//lv.innerHTML = x.responseText.split('\n').reverse().join('\n')+lv.innerHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
r=setTimeout("poll_log()",1000*2);
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "refresh_log")%>',
|
||||
{
|
||||
log_len: log_len
|
||||
},
|
||||
function(x, status) {
|
||||
if (x && x.status == 200) {
|
||||
if (status) {
|
||||
if (!status.update) {
|
||||
r = setTimeout("poll_log()", 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status.len) {
|
||||
log_len = status.len;
|
||||
}
|
||||
|
||||
var activeTabId = 0;
|
||||
var titles = document.getElementsByName('tab-header');
|
||||
for(var i=0; i<titles.length; i++){
|
||||
if(titles[i].className === 'cbi-tab') {
|
||||
activeTabId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (status.oc_log && status.oc_log !== "") {
|
||||
var oc_logs = line_tolocal(status.oc_log);
|
||||
|
||||
if (oc_logs && oc_logs.length > 0) {
|
||||
if (oc_editor) {
|
||||
var currentContent = oc_editor.getValue();
|
||||
smoothlyDisplayLogs(oc_logs, oc_editor, true, currentContent, activeTabId === 0);
|
||||
} else if (lv) {
|
||||
var currentContent = lv.innerHTML;
|
||||
smoothlyDisplayLogs(oc_logs, lv, false, currentContent, activeTabId === 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status.core_log && status.core_log !== "") {
|
||||
var core_logs = line_tolocal(status.core_log);
|
||||
|
||||
if (core_logs && core_logs.length > 0) {
|
||||
if (core_editor) {
|
||||
var currentCoreContent = core_editor.getValue();
|
||||
smoothlyDisplayLogs(core_logs, core_editor, true, currentCoreContent, activeTabId === 1);
|
||||
} else if (cl) {
|
||||
var currentCoreContent = cl.innerHTML;
|
||||
smoothlyDisplayLogs(core_logs, cl, false, currentCoreContent, activeTabId === 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r = setTimeout("poll_log()", 2000);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
window.onload = function(){
|
||||
var titles = document.getElementsByName('tab-header');
|
||||
var divs = document.getElementsByClassName('dom');
|
||||
@@ -297,22 +562,30 @@ window.onload = function(){
|
||||
for(var i=0; i<titles.length; i++){
|
||||
var li = titles[i];
|
||||
li.id = i;
|
||||
li.onclick = function(){
|
||||
for(var j=0; j<titles.length; j++){
|
||||
titles[j].className = 'cbi-tab-disabled';
|
||||
divs[j].style.display = 'none';
|
||||
}
|
||||
this.className = 'cbi-tab';
|
||||
divs[this.id].style.display = 'block';
|
||||
}
|
||||
li.onTouchStart = function(){
|
||||
for(var j=0; j<titles.length; j++){
|
||||
titles[j].className = 'cbi-tab-disabled';
|
||||
divs[j].style.display = 'none';
|
||||
}
|
||||
this.className = 'cbi-tab';
|
||||
divs[this.id].style.display = 'block';
|
||||
function handleTabSwitch(tab) {
|
||||
return function(e) {
|
||||
for(var j=0; j<titles.length; j++){
|
||||
titles[j].className = 'cbi-tab-disabled';
|
||||
divs[j].style.display = 'none';
|
||||
}
|
||||
tab.className = 'cbi-tab';
|
||||
divs[tab.id].style.display = 'block';
|
||||
|
||||
if(tab.id == 0 && typeof oc_editor !== 'undefined') {
|
||||
setTimeout(function(){
|
||||
oc_editor.refresh();
|
||||
}, 10);
|
||||
} else if(tab.id == 1 && typeof core_editor !== 'undefined') {
|
||||
setTimeout(function(){
|
||||
core_editor.refresh();
|
||||
}, 10);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 正确绑定事件
|
||||
li.onclick = handleTabSwitch(li);
|
||||
li.ontouchstart = handleTabSwitch(li);
|
||||
}
|
||||
get_log_level();
|
||||
poll_log();
|
||||
|
@@ -32,6 +32,53 @@
|
||||
.radio-button input[type="radio"]:checked+label {
|
||||
background-color: #1080c1;
|
||||
}
|
||||
|
||||
.announcement-banner {
|
||||
display: none;
|
||||
background-color: #1080c1;
|
||||
color: white;
|
||||
padding: 8px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 24px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.announcement-content {
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
padding-right: 50px;
|
||||
left: 30px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#megaphone {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) scaleX(-1);
|
||||
z-index: 2;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
.megaphone-container {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 30px;
|
||||
background-color: #1080c1;
|
||||
z-index: 2;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<%
|
||||
@@ -41,8 +88,12 @@
|
||||
%>
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td colspan="4" width="100%">
|
||||
<div id="announcement-banner" class="announcement-banner">
|
||||
<div class="megaphone-container"></div>
|
||||
<img id="megaphone" src="/luci-static/resources/openclash/img/megaphone-simple.svg?<%=random%>" loading="lazy" alt="megaphone" width="15px" height="15px">
|
||||
<div id="announcement-content" class="announcement-content"></div>
|
||||
</div>
|
||||
<p style="margin: 10px 0; text-align: center">
|
||||
<img id="_logo" src="/luci-static/resources/openclash/img/logo.png?<%=random%>" loading="lazy" width="150px" height="150px" onload="return logo_check(this,this.src,'https://raw.githubusercontent.com/vernesong/OpenClash/<%=RELEASE_BRANCH%>/img/meta.png')" onerror="return logo_error(this,'/luci-static/resources/openclash/img/logo.png?<%=random%>')" title="Hello, World!" alt="OpenClash" onclick="return homepage()" />
|
||||
</p>
|
||||
@@ -450,6 +501,105 @@
|
||||
clashversion_check();
|
||||
check_core();
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var userLang = navigator.language || navigator.userLanguage;
|
||||
var isChineseUser = userLang.indexOf('zh') === 0;
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "announcement")%>', null, function(x, status) {
|
||||
if (x && x.status == 200) {
|
||||
var banner = document.getElementById('announcement-banner');
|
||||
var content = document.getElementById('announcement-content');
|
||||
var announcements = [];
|
||||
|
||||
if (status.content) {
|
||||
try {
|
||||
var contentData = status.content;
|
||||
if (typeof contentData === 'string') {
|
||||
contentData = JSON.parse(contentData);
|
||||
}
|
||||
|
||||
if (Array.isArray(contentData)) {
|
||||
if (contentData.length > 0 && (contentData[0].zh || contentData[0].en)) {
|
||||
contentData.forEach(function(item) {
|
||||
if (isChineseUser && item.zh) {
|
||||
announcements.push(item.zh);
|
||||
} else if (item.en) {
|
||||
announcements.push(item.en);
|
||||
} else if (item.zh) {
|
||||
announcements.push(item.zh);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
announcements = contentData;
|
||||
}
|
||||
} else if (typeof contentData === 'string' && contentData.trim() !== '') {
|
||||
announcements = [contentData];
|
||||
}
|
||||
} catch (e) {
|
||||
if (typeof status.content === 'string' && status.content.trim() !== '') {
|
||||
announcements = [status.content];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (announcements.length === 0) {
|
||||
banner.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
banner.style.display = 'block';
|
||||
var currentIndex = 0;
|
||||
|
||||
content.textContent = announcements[currentIndex];
|
||||
|
||||
var isPaused = false;
|
||||
|
||||
banner.addEventListener('mouseenter', function() {
|
||||
isPaused = true;
|
||||
});
|
||||
|
||||
banner.addEventListener('mouseleave', function() {
|
||||
isPaused = false;
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
var bannerWidth = banner.offsetWidth;
|
||||
var contentWidth = content.offsetWidth;
|
||||
content.style.left = bannerWidth + 'px';
|
||||
|
||||
var speed = 3;
|
||||
var position = bannerWidth;
|
||||
var pauseCounter = 0;
|
||||
var pauseDuration = 20;
|
||||
|
||||
function moveText() {
|
||||
if (!isPaused) {
|
||||
if (position < -contentWidth && pauseCounter >= pauseDuration) {
|
||||
currentIndex = (currentIndex + 1) % announcements.length;
|
||||
content.textContent = announcements[currentIndex];
|
||||
contentWidth = content.offsetWidth;
|
||||
position = bannerWidth;
|
||||
pauseCounter = 0;
|
||||
}
|
||||
else if (position < -contentWidth) {
|
||||
pauseCounter++;
|
||||
}
|
||||
else {
|
||||
position -= speed;
|
||||
}
|
||||
|
||||
content.style.left = position + 'px';
|
||||
}
|
||||
|
||||
requestAnimationFrame(moveText);
|
||||
}
|
||||
|
||||
moveText();
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function get_rule_mode() {
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "rule_mode")%>', null, function(x, status) {
|
||||
if (x && x.status == 200 && status.mode != "") {
|
||||
|
@@ -24,37 +24,73 @@
|
||||
}
|
||||
|
||||
.sub_setting{
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
margin: 0 auto;
|
||||
opacity: 1;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
margin: 0 auto;
|
||||
opacity: 1;
|
||||
vertical-align: middle;
|
||||
line-height: 0; /* 消除行高影响 */
|
||||
}
|
||||
|
||||
.sub_div{
|
||||
white-space: nowrap;
|
||||
.sub_setting img {
|
||||
vertical-align: middle; /* 确保图标垂直居中 */
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* 日间模式样式 */
|
||||
.text_show{
|
||||
color: #000000;
|
||||
text-shadow:
|
||||
-0.7px -0.7px 0 #ffffff,
|
||||
0.7px -0.7px 0 #ffffff,
|
||||
-0.7px 0.7px 0 #ffffff,
|
||||
0.7px 0.7px 0 #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
:root[data-darkmode="true"] {
|
||||
.progress_bar_bg {
|
||||
border: 1px solid #999999;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
#icon_wrench {
|
||||
-webkit-filter: invert(1);
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
#icon_arrow {
|
||||
-webkit-filter: invert(1);
|
||||
filter: invert(1);
|
||||
}
|
||||
.progress_bar_high {
|
||||
background-color: #9edd9e;
|
||||
}
|
||||
|
||||
.progress_bar_medium {
|
||||
background-color: #ffc99f;
|
||||
}
|
||||
|
||||
.progress_bar_low {
|
||||
background-color: #ffb9b9;
|
||||
}
|
||||
|
||||
/* 夜间模式样式 */
|
||||
:root[data-darkmode="true"] {
|
||||
#icon_wrench {
|
||||
-webkit-filter: invert(1);
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
#icon_arrow {
|
||||
-webkit-filter: invert(1);
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
.text_show{
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.progress_bar_bg {
|
||||
border: 1px solid #666666;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
.progress_bar_high {
|
||||
background-color: #5da05d;
|
||||
}
|
||||
|
||||
.progress_bar_medium {
|
||||
background-color: #cc8550;
|
||||
}
|
||||
|
||||
.progress_bar_low {
|
||||
background-color: #cc6262;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -105,10 +141,14 @@ if (isDarkBackground(document.body)) {
|
||||
|
||||
function progressbar_<%=idname%>(v, m, pc, np, f, t, tr) {
|
||||
return String.format(
|
||||
'<div style="width:250px; max-width:500px; position:relative; border:1px solid #999999; border-radius: 6px">' +
|
||||
(pc >= 50 ? '<div style="background-color:#9edd9e; width:%d%%; height:36px; border-radius: 6px">' : (pc < 50 && pc >= 20 ? '<div style="background-color:#ffc99f; width:%d%%; height:35px">' : '<div style="background-color:#ffb9b9; width:%d%%; height:35px">')) +
|
||||
'<div style="position:absolute; left:0;' + (tr == "null" ? 'top:12px;' : 'top:0;') + 'text-align:center; width:100%%">' +
|
||||
'<small class="text_show">%s '+ (f ? f : '/') +' %s ' + (np ? "" : '(%s%%)') + (tr == "null" ? '<div style="visibility: hidden;">' : '<div style="visibility: visible;">') + '%s (<%:Remaining%> %s <%:days%>)</small>' +
|
||||
'<div class="progress_bar_bg" style="width:250px; max-width:500px; position:relative; border-radius: 6px">' +
|
||||
(pc >= 50 ? '<div class="progress_bar_high" style="width:%d%%; height:36px; border-radius: 6px">' :
|
||||
(pc < 50 && pc >= 20 ? '<div class="progress_bar_medium" style="width:%d%%; height:36px; border-radius: 6px">' :
|
||||
'<div class="progress_bar_low" style="width:%d%%; height:36px; border-radius: 6px">')) +
|
||||
'<div style="position:absolute; left:0;' + (tr == "null" ? 'top:12px;' : 'top:0px;') + 'text-align:center; width:100%%">' +
|
||||
'<small class="text_show">%s '+ (f ? f : '/') +' %s ' + (np ? "" : '(%s%%)') +
|
||||
(tr == "null" ? '<div style="visibility: hidden;">' : '<div style="visibility: visible;">') +
|
||||
'%s (<%:Remaining%> %s <%:days%>)</small>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>', pc, v, m, pc, t, tr
|
||||
|
@@ -186,6 +186,9 @@
|
||||
release_branch.value = "master";
|
||||
}
|
||||
});
|
||||
|
||||
XHR.poll(300, '<%=luci.dispatcher.build_url("admin", "services", "openclash", "get_last_version")%>', null, function(x, status) {
|
||||
});
|
||||
|
||||
XHR.poll(3, '<%=luci.dispatcher.build_url("admin", "services", "openclash", "update")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
@@ -206,28 +209,38 @@
|
||||
core_meta_cv.innerHTML = "<b style=color:red><%:Unknown%></b>";
|
||||
}
|
||||
var coremetalvis = status.corelv;
|
||||
if (coremetalvis != status.coremetacv && coremetalvis != "" && coremetalvis != "\n") {
|
||||
if (coremetalvis != status.coremetacv && coremetalvis != "" && coremetalvis != "loading...") {
|
||||
core_meta_lv.innerHTML = "<b style=color:green>"+coremetalvis+"<%:<New>%></b>";
|
||||
}
|
||||
else if (coremetalvis != "" && coremetalvis == status.coremetacv && coremetalvis != "\n") {
|
||||
else if (coremetalvis != "" && coremetalvis == status.coremetacv && coremetalvis != "loading...") {
|
||||
core_meta_lv.innerHTML = "<b style=color:green>"+coremetalvis+"</b>";
|
||||
}
|
||||
else if (coremetalvis == "loading...") {
|
||||
core_meta_lv.innerHTML = "<b style=color:green><%:Getting Last Version...%></b>";
|
||||
}
|
||||
else {
|
||||
core_meta_lv.innerHTML = "<b style=color:red><%:Unknown%></b>";
|
||||
}
|
||||
var oplv = status.oplv;
|
||||
var arr_op = oplv.split(",");
|
||||
var oplvis = arr_op[0];
|
||||
var new_op = arr_op[1];
|
||||
op_cv.innerHTML = status.opcv ? "<b style=color:green>"+status.opcv+"</b>" : "<b style=color:red><%:Unknown%></b>";
|
||||
if ( new_op == "2" && oplvis != "" && oplvis != "\n") {
|
||||
op_lv.innerHTML = "<b style=color:green>"+oplvis+"<%:<New>%></b>";
|
||||
if (oplv != "" && oplv != "loading..." && status.opcv) {
|
||||
var oplvck = oplv.match(/\d+(\.\d+)+/)[0].replace(/\./g, "")
|
||||
var opcvck = status.opcv.match(/\d+(\.\d+)+/)[0].replace(/\./g, "")
|
||||
if (oplvck > opcvck) {
|
||||
op_lv.innerHTML = "<b style=color:green>"+oplv+"<%:<New>%></b>";
|
||||
}
|
||||
else {
|
||||
op_lv.innerHTML = "<b style=color:green>"+oplv+"</b>";
|
||||
}
|
||||
}
|
||||
else if (oplvis != "" && oplvis != "\n") {
|
||||
op_lv.innerHTML = "<b style=color:green>"+oplvis+"</b>";
|
||||
else if (oplv != "" && oplv != "loading...") {
|
||||
op_lv.innerHTML = "<b style=color:green>"+oplv+"</b>";
|
||||
}
|
||||
else if (oplv == "loading...") {
|
||||
op_lv.innerHTML = "<b style=color:green><%:Getting Last Version...%></b>";
|
||||
}
|
||||
else {
|
||||
op_lv.innerHTML = "<b style=color:red><%:Unknown%></b>";
|
||||
op_lv.innerHTML = "<b style=color:red><%:Unknown%></b>";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -449,6 +449,12 @@ msgstr "自动更新 GeoSite 数据库"
|
||||
msgid "Update GeoSite Database"
|
||||
msgstr "更新 GeoSite 数据库"
|
||||
|
||||
msgid "Auto Update Geo ASN"
|
||||
msgstr "自动更新 Geo ASN 数据库"
|
||||
|
||||
msgid "Update Geo ASN Database"
|
||||
msgstr "更新 Geo ASN 数据库"
|
||||
|
||||
msgid "Auto Update Chnroute Lists"
|
||||
msgstr "自动更新大陆白名单"
|
||||
|
||||
@@ -602,6 +608,9 @@ msgstr "查询更新失败"
|
||||
msgid "<New>"
|
||||
msgstr "<可更新>"
|
||||
|
||||
msgid "Getting Last Version..."
|
||||
msgstr "最新版本获取中..."
|
||||
|
||||
msgid "Update Core File"
|
||||
msgstr "更新内核"
|
||||
|
||||
@@ -1500,6 +1509,9 @@ msgstr "自定义 GeoIP MMDB 数据库的更新来源,编辑后点击下方按
|
||||
msgid "Custom GeoSite Data URL, Click Button Below To Refresh After Edit"
|
||||
msgstr "自定义 GeoSite 数据库的更新来源,编辑后点击下方按钮生效"
|
||||
|
||||
msgid "Custom Geo ASN Data URL, Click Button Below To Refresh After Edit"
|
||||
msgstr "自定义 Geo ASN 数据库的更新来源,编辑后点击下方按钮生效"
|
||||
|
||||
msgid "Custom Chnroute Lists URL, Click Button Below To Refresh After Edit"
|
||||
msgstr "自定义大陆 IP 段的更新来源,编辑后点击下方按钮生效"
|
||||
|
||||
@@ -1518,9 +1530,6 @@ msgstr "(全部国家且且包含官方全部信息数据)"
|
||||
msgid "(Only CN)"
|
||||
msgstr "(仅中国数据)"
|
||||
|
||||
msgid "(Large Size)"
|
||||
msgstr "(18MB大文件,请确保足够的剩余空间)"
|
||||
|
||||
msgid "Other Rules Edit"
|
||||
msgstr "设置第三方规则"
|
||||
|
||||
@@ -1857,6 +1866,24 @@ msgstr "GEOIP 数据库版本没有更新,停止继续操作..."
|
||||
msgid "Geoip Database Update Error, Please Try Again Later..."
|
||||
msgstr "GEOIP 数据库下载失败,请检查网络或稍后再试..."
|
||||
|
||||
msgid "Start Downloading Geo ASN Database..."
|
||||
msgstr "开始下载 GEO ASN 数据库..."
|
||||
|
||||
msgid "Geo ASN Database Download Success, Check Updated..."
|
||||
msgstr "GEO ASN 数据库下载成功,检查数据库版本是否更新..."
|
||||
|
||||
msgid "Geo ASN Database Has Been Updated, Starting To Replace The Old Version..."
|
||||
msgstr "GEO ASN 数据库版本有更新,开始替换数据库版本..."
|
||||
|
||||
msgid "Geo ASN Database Update Successful!"
|
||||
msgstr "GEO ASN 数据库更新成功!"
|
||||
|
||||
msgid "Updated Geo ASN Database No Change, Do Nothing..."
|
||||
msgstr "GEO ASN 数据库版本没有更新,停止继续操作..."
|
||||
|
||||
msgid "Geo ASN Database Update Error, Please Try Again Later..."
|
||||
msgstr "GEO ASN 数据库下载失败,请检查网络或稍后再试..."
|
||||
|
||||
msgid "Start Getting"
|
||||
msgstr "开始获取"
|
||||
|
||||
@@ -2079,8 +2106,8 @@ msgstr "游戏代理为测试功能,不保证规则可用性"
|
||||
msgid "Preparation steps:"
|
||||
msgstr "准备步骤:"
|
||||
|
||||
msgid "1. In the <server and policy group management> page, create the policy group and node you are going to use, and apply the configuration (when adding nodes, you must select the policy group you want to join). Policy group type suggestion: fallback, game nodes must be support UDP and not a Vmess"
|
||||
msgstr "1、在《服务器与策略组管理》页面创建您准备使用的策略组和节点,并应用配置(节点添加时必须选择要加入的策略组),策略组类型建议: FallBack,游戏节点必须支持 UDP 且不是 Vmess 节点"
|
||||
msgid "1. Check the policy group and node you are going to use, Policy group type suggestion: fallback, game nodes must be support UDP and not a Vmess"
|
||||
msgstr "1、检查您准备使用的策略组和节点,策略组类型建议: FallBack,游戏节点必须支持 UDP 且不是 Vmess 节点"
|
||||
|
||||
msgid "2. Click the <manage third party game rules> or <manage third party rule set> button to enter the rule list and download the rules you want to use"
|
||||
msgstr "2、点击《管理第三方游戏规则》或者《管理第三方规则集》按钮进入规则列表下载您要使用的规则"
|
||||
@@ -2091,8 +2118,8 @@ msgstr "3、在此页面设置您已下载的规则的对应配置文件、策
|
||||
msgid "4. Install the TUN or Meta core"
|
||||
msgstr "4、安装 TUN 或者 Meta 内核"
|
||||
|
||||
msgid "When setting this page, if the groups is empty, please go to the <server and group management> page to add"
|
||||
msgstr "本页设置时如策略组为空,请先到《服务器与策略组管理》页面进行添加"
|
||||
msgid "When setting this page, if the groups is empty, please go to the <Onekey Create> page to add"
|
||||
msgstr "本页设置时如策略组为空,请先到《一键生成》页面进行添加"
|
||||
|
||||
msgid "Introduction to rule set usage: https://wiki.metacubex.one/config/rule-providers/content/"
|
||||
msgstr "规则集使用介绍:https://wiki.metacubex.one/config/rule-providers/content/"
|
||||
@@ -3478,4 +3505,10 @@ msgid "Disable quic-go GSO Support"
|
||||
msgstr "禁用 quic-go GSO 支持"
|
||||
|
||||
msgid "Suggestion: If Encountering Issues With QUIC UDP on The Linux Kernel Version Above 6.6, Please Try to Enable."
|
||||
msgstr "建议: 如果固件 Linux 核心版本在 6.6 以上时遇到 quic-go 的 UDP 连接问题,请尝试启用。"
|
||||
msgstr "建议: 如果固件 Linux 核心版本在 6.6 以上时遇到 quic-go 的 UDP 连接问题,请尝试启用。"
|
||||
|
||||
msgid "Skip Safe Path Check"
|
||||
msgstr "跳过安全路径检查"
|
||||
|
||||
msgid "Enable If You Want Using Files Not in /etc/openclash in You Config"
|
||||
msgstr "如果您希望在配置中使用不在 /etc/openclash 中的文件,请启用该选项"
|
@@ -62,6 +62,7 @@ config openclash 'config'
|
||||
option geo_custom_url 'https://testingcf.jsdelivr.net/gh/alecthw/mmdb_china_ip_list@release/lite/Country.mmdb'
|
||||
option geosite_custom_url 'https://testingcf.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat'
|
||||
option geoip_custom_url 'https://testingcf.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geoip.dat'
|
||||
option geoasn_custom_url 'https://testingcf.jsdelivr.net/gh/xishang0128/geoip@release/GeoLite2-ASN.mmdb'
|
||||
option chnr_custom_url 'https://ispip.clang.cn/all_cn.txt'
|
||||
option chnr6_custom_url 'https://ispip.clang.cn/all_cn_ipv6.txt'
|
||||
|
||||
|
@@ -648,11 +648,13 @@ start_run_core()
|
||||
chown root:root /etc/openclash/core/* 2>/dev/null
|
||||
kill_clash
|
||||
procd_open_instance "openclash"
|
||||
procd_set_param env SKIP_SAFE_PATH_CHECK="$skip_safe_path_check"
|
||||
procd_append_param env SAFE_PATHS=/usr/share/openclash:/etc/ssl
|
||||
procd_set_param command /bin/sh -c "$CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1"
|
||||
procd_set_param user "root"
|
||||
procd_set_param group "nogroup"
|
||||
procd_set_param limits nproc="unlimited" as="unlimited" memlock="unlimited" nofile="1000000 1000000"
|
||||
procd_set_param respawn 3600 3 10
|
||||
procd_set_param respawn 300 5 3
|
||||
procd_set_param stderr 1
|
||||
procd_set_param no_new_privs 1
|
||||
procd_close_instance
|
||||
@@ -793,7 +795,6 @@ check_core_status()
|
||||
done >/dev/null 2>&1
|
||||
if [ -z "$(echo ${lan_ip} | grep -Eo ${reg4})" ]; then
|
||||
LOG_OUT "Error: LAN IP Address Get Error, Please Check The LAN Interface Setting or Choose the Correct Interface in the Setting!"
|
||||
sleep 10
|
||||
fi
|
||||
if [ "$CORE_HTTP_CODE" != "200" ]; then
|
||||
LOG_OUT "Error: Core Status Abnormal, Please Check The Log Infos!"
|
||||
@@ -1978,7 +1979,7 @@ if [ -n "$FW4" ]; then
|
||||
rule="ip6 daddr != @china_ip6_route"
|
||||
fi
|
||||
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip6 daddr != @china_ip6_route_pass"
|
||||
nft 'add rule inet fw4 openclash_mangle_output_v6 $rule counter return'
|
||||
nft "add rule inet fw4 openclash_mangle_output_v6 $rule counter return"
|
||||
fi
|
||||
|
||||
if ([ "$ipv6_mode" -eq 1 ] && [ "$enable_v6_udp_proxy" -eq 1 ]) || [ "$ipv6_mode" -eq 3 ]; then
|
||||
@@ -2963,6 +2964,7 @@ get_config()
|
||||
custom_fakeip_filter_mode=$(uci -q get openclash.config.custom_fakeip_filter_mode || echo "blacklist")
|
||||
iptables_compat=$(iptables -m owner -h 2>/dev/null | grep "owner match options" || command -v fw4 || echo 0)
|
||||
disable_quic_go_gso=$(uci -q get openclash.config.disable_quic_go_gso || echo 0)
|
||||
skip_safe_path_check=$(uci -q get openclash.config.skip_safe_path_check || echo 0)
|
||||
[ -z "$dns_port" ] && dns_port=7874 && uci -q set openclash.config.dns_port=7874
|
||||
uci -q commit openclash
|
||||
}
|
||||
@@ -3057,7 +3059,6 @@ stop_service()
|
||||
|
||||
LOG_OUT "Step 6: Delete OpenClash Residue File..."
|
||||
if [ "$enable" != "1" ]; then
|
||||
|
||||
rm -rf /tmp/clash_last_version >/dev/null 2>&1
|
||||
rm -rf /tmp/Proxy_Group >/dev/null 2>&1
|
||||
rm -rf /tmp/rules_name >/dev/null 2>&1
|
||||
@@ -3067,6 +3068,7 @@ stop_service()
|
||||
rm -rf /tmp/openclash.change >/dev/null 2>&1
|
||||
rm -rf /tmp/openclash_debug.log >/dev/null 2>&1
|
||||
rm -rf /tmp/openclash_edit_file_name >/dev/null 2>&1
|
||||
rm -rf /tmp/openclash_announcement >/dev/null 2>&1
|
||||
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf >/dev/null 2>&1
|
||||
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf >/dev/null 2>&1
|
||||
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_custom_domain.conf >/dev/null 2>&1
|
||||
|
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
. /usr/share/openclash/openclash_ps.sh
|
||||
. /usr/share/openclash/log.sh
|
||||
. /usr/share/openclash/openclash_curl.sh
|
||||
|
||||
set_lock() {
|
||||
exec 874>"/tmp/lock/openclash_geoasn.lock" 2>/dev/null
|
||||
flock -x 874 2>/dev/null
|
||||
}
|
||||
|
||||
del_lock() {
|
||||
flock -u 874 2>/dev/null
|
||||
rm -rf "/tmp/lock/openclash_geoasn.lock" 2>/dev/null
|
||||
}
|
||||
|
||||
set_lock
|
||||
|
||||
small_flash_memory=$(uci get openclash.config.small_flash_memory 2>/dev/null)
|
||||
GEOASN_CUSTOM_URL=$(uci get openclash.config.geoasn_custom_url 2>/dev/null)
|
||||
github_address_mod=$(uci -q get openclash.config.github_address_mod || echo 0)
|
||||
restart=0
|
||||
|
||||
if [ "$small_flash_memory" != "1" ]; then
|
||||
geoasn_path="/etc/openclash/ASN.mmdb"
|
||||
mkdir -p /etc/openclash
|
||||
else
|
||||
geoasn_path="/tmp/etc/openclash/ASN.mmdb"
|
||||
mkdir -p /tmp/etc/openclash
|
||||
fi
|
||||
LOG_OUT "Start Downloading Geo ASN Database..."
|
||||
if [ -z "$GEOASN_CUSTOM_URL" ]; then
|
||||
if [ "$github_address_mod" != "0" ]; then
|
||||
if [ "$github_address_mod" == "https://cdn.jsdelivr.net/" ] || [ "$github_address_mod" == "https://fastly.jsdelivr.net/" ] || [ "$github_address_mod" == "https://testingcf.jsdelivr.net/" ]; then
|
||||
DOWNLOAD_URL="${github_address_mod}gh/xishang0128/geoip@release/GeoLite2-ASN.mmdb"
|
||||
else
|
||||
DOWNLOAD_URL="${github_address_mod}https://github.com/xishang0128/geoip/releases/latest/download/GeoLite2-ASN.mmdb"
|
||||
fi
|
||||
else
|
||||
DOWNLOAD_URL="https://github.com/xishang0128/geoip/releases/latest/download/GeoLite2-ASN.mmdb"
|
||||
fi
|
||||
else
|
||||
DOWNLOAD_URL=$GEOASN_CUSTOM_URL
|
||||
fi
|
||||
DOWNLOAD_FILE_CURL "$DOWNLOAD_URL" "/tmp/GeoLite2-ASN.mmdb"
|
||||
if [ "$?" -eq 0 ] && [ -s "/tmp/GeoLite2-ASN.mmdb" ]; then
|
||||
LOG_OUT "Geo ASN Database Download Success, Check Updated..."
|
||||
cmp -s /tmp/GeoLite2-ASN.mmdb "$geoasn_path"
|
||||
if [ "$?" -ne "0" ]; then
|
||||
LOG_OUT "Geo ASN Database Has Been Updated, Starting To Replace The Old Version..."
|
||||
rm -rf "/etc/openclash/GeoLite2-ASN.mmdb"
|
||||
mv /tmp/GeoLite2-ASN.mmdb "$geoasn_path" >/dev/null 2>&1
|
||||
LOG_OUT "Geo ASN Database Update Successful!"
|
||||
restart=1
|
||||
else
|
||||
LOG_OUT "Updated Geo ASN Database No Change, Do Nothing..."
|
||||
fi
|
||||
else
|
||||
LOG_OUT "Geo ASN Database Update Error, Please Try Again Later..."
|
||||
fi
|
||||
|
||||
if [ "$restart" -eq 1 ] && [ "$(unify_ps_prevent)" -eq 0 ]; then
|
||||
/etc/init.d/openclash restart >/dev/null 2>&1 &
|
||||
elif [ "$restart" -eq 0 ] && [ "$(unify_ps_prevent)" -eq 0 ] && [ "$(uci -q get openclash.config.restart)" -eq 1 ]; then
|
||||
/etc/init.d/openclash restart >/dev/null 2>&1 &
|
||||
uci -q set openclash.config.restart=0
|
||||
uci -q commit openclash
|
||||
elif [ "$restart" -eq 1 ] && [ "$(unify_ps_prevent)" -eq 0 ]; then
|
||||
uci -q set openclash.config.restart=1
|
||||
uci -q commit openclash
|
||||
fi
|
||||
|
||||
rm -rf /tmp/GeoLite2-ASN.mmdb >/dev/null 2>&1
|
||||
SLOG_CLEAN
|
||||
del_lock
|
@@ -21,7 +21,7 @@ local unlock_cache_file = "/etc/openclash/history/streaming_unlock_cache"
|
||||
local unlock_cache = FS.readfile(unlock_cache_file)
|
||||
local unlock_cache_info = {}
|
||||
if unlock_cache then
|
||||
unlock_cache_info = JSON.parse(unlock_cache)
|
||||
unlock_cache_info = JSON.parse(unlock_cache) or {}
|
||||
end
|
||||
local self_status = SYS.exec(string.format('ps -w |grep -v grep |grep -c "openclash_streaming_unlock.lua %s"', type))
|
||||
local select_logic = UCI:get("openclash", "config", "stream_auto_select_logic") or "urltest"
|
||||
@@ -146,18 +146,17 @@ function unlock_auto_select()
|
||||
table.insert(tested_proxy, now_name)
|
||||
group_match = true
|
||||
--test now proxy
|
||||
region, old_region = proxy_unlock_test()
|
||||
region = proxy_unlock_test()
|
||||
if table_include(groups, now_name) then
|
||||
now = os.date("%Y-%m-%d %H:%M:%S").." "..type.." "..gorup_i18.."【"..group_show.."】"
|
||||
else
|
||||
now = os.date("%Y-%m-%d %H:%M:%S").." "..type.." "..gorup_i18.."【"..group_show.." ➟ "..now_name.."】"
|
||||
end
|
||||
if status ~= 2 and status ~= 4 then
|
||||
os.execute("sleep 3")
|
||||
region, old_region = proxy_unlock_test()
|
||||
region = proxy_unlock_test()
|
||||
end
|
||||
if status == 2 or status == 4 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
table.insert(full_support_list, {value.now, value.now, get_group_now(info, value.now), region})
|
||||
print(now..full_support.."【"..region.."】")
|
||||
write_cache(type, get_group_now(info, value.now), region)
|
||||
@@ -169,7 +168,7 @@ function unlock_auto_select()
|
||||
if not all_test and #nodes_filter(now_name, info) ~= 0 then
|
||||
if status == 4 then
|
||||
status = 2
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
end
|
||||
@@ -181,7 +180,7 @@ function unlock_auto_select()
|
||||
status = 0
|
||||
end
|
||||
elseif status == 3 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
table.insert(other_region_unlock, {value.now, value.now, get_group_now(info, value.now), region})
|
||||
write_cache(type, get_group_now(info, value.now), region)
|
||||
else
|
||||
@@ -189,13 +188,13 @@ function unlock_auto_select()
|
||||
write_cache(type, get_group_now(info, value.now))
|
||||
end
|
||||
if not all_test then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
print(now..full_support.."【"..region.."】"..other_region_unlock_test_start)
|
||||
else
|
||||
print(now..full_support_no_area..other_region_unlock_test_start)
|
||||
end
|
||||
else
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
print(now..full_support.."【"..region.."】"..other_region_unlock_test)
|
||||
else
|
||||
print(now..full_support_no_area..other_region_unlock_test)
|
||||
@@ -298,9 +297,9 @@ function unlock_auto_select()
|
||||
break
|
||||
else
|
||||
SYS.exec(string.format("curl -sL -m 5 --retry 2 -w %%{http_code} -o /dev/null -H 'Authorization: Bearer %s' -H 'Content-Type:application/json' -X PUT -d '{\"name\":\"%s\"}' http://%s:%s/proxies/%s", passwd, proxy, ip, port, urlencode(group_name)))
|
||||
region, old_region = proxy_unlock_test()
|
||||
region = proxy_unlock_test()
|
||||
if status == 2 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
table.insert(full_support_list, {value.all[i], group_name, proxy, region})
|
||||
if not all_test then
|
||||
print(now..full_support.."【"..region.."】")
|
||||
@@ -320,7 +319,7 @@ function unlock_auto_select()
|
||||
write_cache(type, proxy)
|
||||
end
|
||||
elseif status == 3 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
table.insert(other_region_unlock, {value.all[i], group_name, proxy, region})
|
||||
print(now..full_support.."【"..region.."】"..other_region_unlock_test)
|
||||
write_cache(type, proxy, region)
|
||||
@@ -330,7 +329,7 @@ function unlock_auto_select()
|
||||
write_cache(type, proxy)
|
||||
end
|
||||
elseif status == 4 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
table.insert(no_old_region_unlock, {value.all[i], group_name, proxy, region})
|
||||
print(now..full_support.."【"..region.."】"..no_old_region_unlock_old_region.."【"..old_region.."】")
|
||||
write_cache(type, proxy, region)
|
||||
@@ -371,14 +370,14 @@ function unlock_auto_select()
|
||||
else
|
||||
table.insert(tested_proxy, now_name)
|
||||
end
|
||||
region, old_region = proxy_unlock_test()
|
||||
region = proxy_unlock_test()
|
||||
if table_include(groups, now_name) then
|
||||
now = os.date("%Y-%m-%d %H:%M:%S").." "..type.." "..gorup_i18.."【"..group_show.."】"
|
||||
else
|
||||
now = os.date("%Y-%m-%d %H:%M:%S").." "..type.." "..gorup_i18.."【"..group_show.." ➟ "..now_name.."】"
|
||||
end
|
||||
if status == 2 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
table.insert(full_support_list, {value.all[i], group_name, value.all[i], region})
|
||||
if not all_test then
|
||||
print(now..full_support.."【"..region.."】")
|
||||
@@ -398,7 +397,7 @@ function unlock_auto_select()
|
||||
write_cache(type, value.all[i])
|
||||
end
|
||||
elseif status == 3 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
table.insert(other_region_unlock, {value.all[i], group_name, value.all[i], region})
|
||||
print(now..full_support.."【"..region.."】"..other_region_unlock_no_select)
|
||||
write_cache(type, value.all[i], region)
|
||||
@@ -408,7 +407,7 @@ function unlock_auto_select()
|
||||
write_cache(type, value.all[i])
|
||||
end
|
||||
elseif status == 4 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
table.insert(no_old_region_unlock, {value.all[i], group_name, value.all[i], region})
|
||||
print(now..full_support.."【"..region.."】"..no_old_region_unlock_old_region.."【"..old_region.."】"..no_old_region_unlock_old_region_no_select)
|
||||
write_cache(type, value.all[i], region)
|
||||
@@ -504,9 +503,9 @@ function unlock_auto_select()
|
||||
end
|
||||
end
|
||||
elseif #nodes_filter(get_group_now(info, value.name), info) ~= 0 then
|
||||
region, old_region = proxy_unlock_test()
|
||||
region = proxy_unlock_test()
|
||||
if status == 2 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
if not all_test then
|
||||
print(now..full_support.."【"..region.."】")
|
||||
end
|
||||
@@ -521,13 +520,13 @@ function unlock_auto_select()
|
||||
break
|
||||
end
|
||||
elseif status == 3 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
print(now..full_support.."【"..region.."】"..other_region_unlock_no_select)
|
||||
else
|
||||
print(now..full_support_no_area..other_region_unlock_no_select)
|
||||
end
|
||||
elseif status == 4 then
|
||||
if region and region ~= "" then
|
||||
if region ~= "" then
|
||||
print(now..full_support.."【"..region.."】"..no_old_region_unlock_old_region.."【"..old_region.."】"..no_old_region_unlock_old_region_no_select)
|
||||
else
|
||||
print(now..full_support_no_area..no_old_region_unlock_no_select)
|
||||
@@ -570,11 +569,8 @@ function get_old_region(stream_type)
|
||||
if not stream_type then
|
||||
stream_type = type
|
||||
end
|
||||
for k, v in pairs(unlock_cache_info) do
|
||||
if v[1] == stream_type and v[2] == "old_region" and v[3] then
|
||||
old_region = v[3]
|
||||
break
|
||||
end
|
||||
if unlock_cache_info[stream_type] and unlock_cache_info[stream_type]["old_region"] then
|
||||
return unlock_cache_info[stream_type]["old_region"]
|
||||
end
|
||||
return old_region
|
||||
end
|
||||
@@ -584,32 +580,25 @@ function get_old_regex(stream_type)
|
||||
if not stream_type then
|
||||
stream_type = type
|
||||
end
|
||||
for k, v in pairs(unlock_cache_info) do
|
||||
if v[1] == stream_type and v[2] == "old_regex" and v[3] then
|
||||
old_regex = v[3]
|
||||
break
|
||||
end
|
||||
if unlock_cache_info[stream_type] and unlock_cache_info[stream_type]["old_regex"] then
|
||||
return unlock_cache_info[stream_type]["old_regex"]
|
||||
end
|
||||
return old_regex
|
||||
end
|
||||
|
||||
function write_cache(stream_type, node, region)
|
||||
if not region then
|
||||
region = ""
|
||||
end
|
||||
if not table_include(unlock_cache_info, {stream_type, node, region}) then
|
||||
if table_include(unlock_cache_info, {stream_type, node, "cache"}) then
|
||||
delete_cache(stream_type, node)
|
||||
end
|
||||
table.insert(unlock_cache_info, {stream_type, node, region})
|
||||
function write_cache(stream_type, node, value)
|
||||
if not value then
|
||||
value = ""
|
||||
end
|
||||
if not unlock_cache_info[stream_type] then unlock_cache_info[stream_type] = {} end
|
||||
if unlock_cache_info[stream_type][node] ~= value then
|
||||
unlock_cache_info[stream_type][node] = value
|
||||
end
|
||||
end
|
||||
|
||||
function delete_cache(stream_type, node)
|
||||
for k, v in pairs(unlock_cache_info) do
|
||||
if v[1] == stream_type and v[2] == node then
|
||||
table.remove(unlock_cache_info, k)
|
||||
end
|
||||
if unlock_cache_info[stream_type] and unlock_cache_info[stream_type][node] then
|
||||
unlock_cache_info[stream_type][node] = nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -708,11 +697,8 @@ function table_sort_by_cache(t)
|
||||
local tab = {}
|
||||
local tab_b = {}
|
||||
local old_region = get_old_region()
|
||||
if old_region == "" then
|
||||
old_region = "cache"
|
||||
end
|
||||
for n = 1, #(t) do
|
||||
if table_include(unlock_cache_info, {type, t[n], old_region}) then
|
||||
if unlock_cache_info and unlock_cache_info[type] and unlock_cache_info[type][t[n]] and unlock_cache_info[type][t[n]] == old_region then
|
||||
table.insert(tab, t[n])
|
||||
else
|
||||
table.insert(tab_b, t[n])
|
||||
@@ -735,9 +721,12 @@ function table_include(table, value)
|
||||
if table_eq(v, value) then
|
||||
return true
|
||||
else
|
||||
if v[1] == value[1] and v[2] == value[2] and value[3] == "cache" then
|
||||
return true
|
||||
for i = 1, #(v) do
|
||||
if v[i] ~= value[i] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
else
|
||||
if v == value then
|
||||
@@ -863,33 +852,33 @@ function nodes_filter(t, info)
|
||||
end
|
||||
|
||||
function proxy_unlock_test()
|
||||
local region, old_region
|
||||
local region = ""
|
||||
if type == "Netflix" then
|
||||
region, old_region = netflix_unlock_test()
|
||||
region = netflix_unlock_test()
|
||||
elseif type == "Disney Plus" then
|
||||
region, old_region = disney_unlock_test()
|
||||
region = disney_unlock_test()
|
||||
elseif type == "HBO Max" then
|
||||
region, old_region = hbo_max_unlock_test()
|
||||
region = hbo_max_unlock_test()
|
||||
elseif type == "YouTube Premium" then
|
||||
region, old_region = ytb_unlock_test()
|
||||
region = ytb_unlock_test()
|
||||
elseif type == "TVB Anywhere+" then
|
||||
region, old_region = tvb_anywhere_unlock_test()
|
||||
region = tvb_anywhere_unlock_test()
|
||||
elseif type == "Amazon Prime Video" then
|
||||
region, old_region = prime_video_unlock_test()
|
||||
region = prime_video_unlock_test()
|
||||
elseif type == "DAZN" then
|
||||
region, old_region = dazn_unlock_test()
|
||||
region = dazn_unlock_test()
|
||||
elseif type == "Paramount Plus" then
|
||||
region, old_region = paramount_plus_unlock_test()
|
||||
region = paramount_plus_unlock_test()
|
||||
elseif type == "Discovery Plus" then
|
||||
region, old_region = discovery_plus_unlock_test()
|
||||
region = discovery_plus_unlock_test()
|
||||
elseif type == "Bilibili" then
|
||||
region, old_region = bilibili_unlock_test()
|
||||
region = bilibili_unlock_test()
|
||||
elseif type == "Google" then
|
||||
region, old_region = google_not_cn_test()
|
||||
region = google_not_cn_test()
|
||||
elseif type == "OpenAI" then
|
||||
region, old_region = openai_unlock_test()
|
||||
region = openai_unlock_test()
|
||||
end
|
||||
return region, old_region
|
||||
return region
|
||||
end
|
||||
|
||||
function auto_get_policy_group(passwd, ip, port)
|
||||
@@ -1113,7 +1102,7 @@ function netflix_unlock_test()
|
||||
local headers = "User-Agent: "..UA
|
||||
local info = SYS.exec(string.format('curl -sLI --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 -o /dev/null -w %%{json} -H "Content-Type: application/json" -H "host: www.netflix.com" -H "accept-language: en-US,en;q=0.9" -H "sec-ch-ua: Google Chrome;v=125, Chromium;v=125, Not.A/Brand;v=24" -H "sec-ch-ua-mobile: ?0" -H "sec-ch-ua-platform: Windows" -H "sec-fetch-site: none" -H "sec-fetch-mode: navigate" -H "sec-fetch-user: ?1" -H "sec-fetch-dest: document" -H "%s" -XGET %s', headers, url))
|
||||
local result = {}
|
||||
local region
|
||||
local region = ""
|
||||
local old_region = get_old_region()
|
||||
local old_regex = get_old_regex()
|
||||
local regex = UCI:get("openclash", "config", "stream_auto_select_region_key_netflix") or ""
|
||||
@@ -1124,9 +1113,8 @@ function netflix_unlock_test()
|
||||
if info.http_code == 200 then
|
||||
status = 2
|
||||
string.gsub(info.url_effective, '[^/]+', function(w) table.insert(result, w) end)
|
||||
region = string.upper(string.match(result[3], "^%a+"))
|
||||
if region == "TITLE" then region = "US" end
|
||||
if region then
|
||||
if string.match(result[3], "^%a+") then
|
||||
region = string.upper(string.match(result[3], "^%a+"))
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
elseif old_regex ~= regex and not all_test then
|
||||
@@ -1134,19 +1122,18 @@ function netflix_unlock_test()
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
end
|
||||
return region, old_region
|
||||
elseif info.http_code == 404 or info.http_code == 403 then
|
||||
status = 1
|
||||
end
|
||||
end
|
||||
return
|
||||
return region
|
||||
end
|
||||
|
||||
function disney_unlock_test()
|
||||
@@ -1157,7 +1144,8 @@ function disney_unlock_test()
|
||||
local headers = '-H "Accept-Language: en" -H "Content-Type: application/json" -H "authorization: ZGlzbmV5JmJyb3dzZXImMS4wLjA.Cu56AgSfBTDag5NiRA81oLHkDZfu5L3CKadnefEAY84"'
|
||||
local auth = '-H "authorization: Bearer ZGlzbmV5JmJyb3dzZXImMS4wLjA.Cu56AgSfBTDag5NiRA81oLHkDZfu5L3CKadnefEAY84"'
|
||||
local body = '{"query":"mutation registerDevice($input: RegisterDeviceInput!) { registerDevice(registerDevice: $input) { grant { grantType assertion } } }","variables":{"input":{"deviceFamily":"browser","applicationRuntime":"chrome","deviceProfile":"windows","deviceLanguage":"en","attributes":{"osDeviceIds":[],"manufacturer":"microsoft","model":null,"operatingSystem":"windows","operatingSystemVersion":"10.0","browserName":"chrome","browserVersion":"96.0.4606"}}}}'
|
||||
local region, assertion, data, preassertion, disneycookie, tokencontent
|
||||
local region = ""
|
||||
local assertion, data, preassertion, disneycookie, tokencontent
|
||||
local regex = UCI:get("openclash", "config", "stream_auto_select_region_key_disney") or ""
|
||||
local old_region = get_old_region()
|
||||
local old_regex = get_old_regex()
|
||||
@@ -1168,7 +1156,7 @@ function disney_unlock_test()
|
||||
assertion = JSON.parse(preassertion).assertion
|
||||
end
|
||||
|
||||
if not assertion then return end
|
||||
if not assertion then return region end
|
||||
|
||||
disneycookie = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&latitude=0&longitude=0&platform=browser&subject_token="..assertion.."&subject_token_type=urn%3Abamtech%3Aparams%3Aoauth%3Atoken-type%3Adevice"
|
||||
tokencontent = SYS.exec(string.format("curl -sL --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 %s -H 'User-Agent: %s' -d '%s' -XPOST %s", auth, UA, disneycookie, url2))
|
||||
@@ -1176,7 +1164,7 @@ function disney_unlock_test()
|
||||
if tokencontent and JSON.parse(tokencontent) then
|
||||
if JSON.parse(tokencontent).error_description then
|
||||
status = 1
|
||||
return
|
||||
return region
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1184,8 +1172,8 @@ function disney_unlock_test()
|
||||
|
||||
if data and JSON.parse(data) then
|
||||
status = 1
|
||||
if JSON.parse(data).extensions and JSON.parse(data).extensions.sdk and JSON.parse(data).extensions.sdk.session then
|
||||
region = JSON.parse(data).extensions.sdk.session.location.countryCode or ""
|
||||
if JSON.parse(data).extensions and JSON.parse(data).extensions.sdk and JSON.parse(data).extensions.sdk.session and JSON.parse(data).extensions.sdk.session.location.countryCode then
|
||||
region = JSON.parse(data).extensions.sdk.session.location.countryCode
|
||||
inSupportedLocation = JSON.parse(data).extensions.sdk.session.inSupportedLocation or ""
|
||||
if region == "JP" then
|
||||
status = 2
|
||||
@@ -1202,47 +1190,48 @@ function disney_unlock_test()
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
return region, old_region
|
||||
return region
|
||||
end
|
||||
|
||||
if region and region ~= "" and inSupportedLocation then
|
||||
if region ~= "" and inSupportedLocation then
|
||||
status = 2
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
elseif old_region ~= "" and not datamatch(region, old_region) and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
return region, old_region
|
||||
return region
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
return region
|
||||
end
|
||||
|
||||
function hbo_max_unlock_test()
|
||||
status = 0
|
||||
local url = "https://www.max.com/"
|
||||
local data = SYS.exec(string.format("curl -sL --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 -w '_TAG_%%{http_code}_TAG_' -H 'Content-Type: application/json' -H 'User-Agent: %s' %s", UA, url))
|
||||
local result = {}
|
||||
local region = ""
|
||||
local outofregion
|
||||
local old_region = get_old_region()
|
||||
local old_regex = get_old_regex()
|
||||
local regex = UCI:get("openclash", "config", "stream_auto_select_region_key_hbo_max") or ""
|
||||
if data and tonumber(string.sub(string.match(data, "_TAG_%d+_TAG_"), 6, 8)) == 200 then
|
||||
status = 1
|
||||
for i in string.gmatch(data, "\"url\":\"/%a+/%a+\"") do
|
||||
table.insert(result, string.sub(string.match(i, "/%a+/"), 2, -2))
|
||||
if string.match(data, "\"isUserOutOfRegion\":%a+") then
|
||||
outofregion = string.lower(string.sub(string.match(data, "\"isUserOutOfRegion\":%a+"), 21, -1))
|
||||
end
|
||||
region = string.sub(string.match(data, "\"countryCode\":\"%a+\""), 16, -2)
|
||||
if region and table_include(result, region) then
|
||||
if string.match(data, "\"userCountry\":\"%a+\"") then
|
||||
region = string.upper(string.sub(string.match(data, "\"userCountry\":\"%a+\""), 16, -2))
|
||||
end
|
||||
if region ~= "" and outofregion == "false" then
|
||||
status = 2
|
||||
region = string.upper(region)
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
elseif old_regex ~= regex and not all_test then
|
||||
@@ -1250,16 +1239,15 @@ function hbo_max_unlock_test()
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
return region, old_region
|
||||
end
|
||||
end
|
||||
return
|
||||
return region
|
||||
end
|
||||
|
||||
function ytb_unlock_test()
|
||||
@@ -1274,15 +1262,15 @@ function ytb_unlock_test()
|
||||
if data and tonumber(string.sub(string.match(data, "_TAG_%d+_TAG_"), 6, 8)) == 200 then
|
||||
status = 1
|
||||
if string.find(data,"www%.google%.cn") or string.find(data, "is not available in your country") then
|
||||
return
|
||||
return region
|
||||
end
|
||||
region = string.sub(string.match(data, "\"GL\":\"%a+\""), 7, -2)
|
||||
if region then
|
||||
if string.match(data, "\"GL\":\"%a+\"") then
|
||||
region = string.sub(string.match(data, "\"GL\":\"%a+\""), 7, -2)
|
||||
status = 2
|
||||
else
|
||||
he_data = SYS.exec(string.format("curl -sIL --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 -H 'Accept-Language: en' -H 'Content-Type: application/json' -H 'User-Agent: %s' %s", UA, url))
|
||||
region = string.sub(string.match(he_data, "gl=%a+"), 4, -1)
|
||||
if region then
|
||||
if string.match(he_data, "gl=%a+") then
|
||||
region = string.sub(string.match(he_data, "gl=%a+"), 4, -1)
|
||||
status = 2
|
||||
else
|
||||
region = "US"
|
||||
@@ -1302,7 +1290,7 @@ function ytb_unlock_test()
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
end
|
||||
return region, old_region
|
||||
return region
|
||||
end
|
||||
|
||||
function tvb_anywhere_unlock_test()
|
||||
@@ -1321,7 +1309,7 @@ function tvb_anywhere_unlock_test()
|
||||
if data.country then
|
||||
region = string.upper(data.country)
|
||||
end
|
||||
if region then
|
||||
if region ~= "" then
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
elseif old_regex ~= regex and not all_test then
|
||||
@@ -1329,7 +1317,7 @@ function tvb_anywhere_unlock_test()
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
@@ -1338,21 +1326,21 @@ function tvb_anywhere_unlock_test()
|
||||
end
|
||||
end
|
||||
end
|
||||
return region, old_region
|
||||
return region
|
||||
end
|
||||
|
||||
function prime_video_unlock_test()
|
||||
status = 0
|
||||
local url = "https://www.primevideo.com"
|
||||
local region
|
||||
local region = ""
|
||||
local old_region = get_old_region()
|
||||
local old_regex = get_old_regex()
|
||||
local regex = UCI:get("openclash", "config", "stream_auto_select_region_key_prime_video") or ""
|
||||
local data = SYS.exec(string.format("curl -sL --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 -w '_TAG_%%{http_code}_TAG_' -H 'Accept-Language: en' -H 'Content-Type: application/json' -H 'User-Agent: %s' %s", UA, url))
|
||||
if data and tonumber(string.sub(string.match(data, "_TAG_%d+_TAG_"), 6, 8)) == 200 then
|
||||
status = 1
|
||||
region = string.sub(string.match(data, "\"currentTerritory\":\"%a+\""), 21, -2)
|
||||
if region then
|
||||
if string.match(data, "\"currentTerritory\":\"%a+\"") then
|
||||
region = string.sub(string.match(data, "\"currentTerritory\":\"%a+\""), 21, -2)
|
||||
status = 2
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
@@ -1361,22 +1349,21 @@ function prime_video_unlock_test()
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
return region, old_region
|
||||
end
|
||||
end
|
||||
return
|
||||
return region
|
||||
end
|
||||
|
||||
function dazn_unlock_test()
|
||||
status = 0
|
||||
local url = "https://startup.core.indazn.com/misl/v5/Startup"
|
||||
local region
|
||||
local region = ""
|
||||
local old_region = get_old_region()
|
||||
local old_regex = get_old_regex()
|
||||
local regex = UCI:get("openclash", "config", "stream_auto_select_region_key_dazn") or ""
|
||||
@@ -1389,7 +1376,7 @@ function dazn_unlock_test()
|
||||
if data.Region.GeolocatedCountry then
|
||||
region = string.upper(data.Region.GeolocatedCountry)
|
||||
end
|
||||
if region then
|
||||
if region ~= "" then
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
elseif old_regex ~= regex and not all_test then
|
||||
@@ -1397,7 +1384,7 @@ function dazn_unlock_test()
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
@@ -1406,47 +1393,49 @@ function dazn_unlock_test()
|
||||
end
|
||||
end
|
||||
end
|
||||
return region, old_region
|
||||
return region
|
||||
end
|
||||
|
||||
function paramount_plus_unlock_test()
|
||||
status = 0
|
||||
local url = "https://www.paramountplus.com/"
|
||||
local region
|
||||
local region = ""
|
||||
local old_region = get_old_region()
|
||||
local old_regex = get_old_regex()
|
||||
local regex = UCI:get("openclash", "config", "stream_auto_select_region_key_paramount_plus") or ""
|
||||
local data = SYS.exec(string.format("curl -sL --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 -w '_TAG_%%{http_code}_TAG_%%{url_effective}_TAGS_' -H 'Accept-Language: en' -H 'Content-Type: application/json' -H 'User-Agent: %s' %s", UA, url))
|
||||
if data and tonumber(string.sub(string.match(data, "_TAG_%d+_TAG_"), 6, 8)) == 200 then
|
||||
status = 1
|
||||
if not string.find(string.match(data, "_TAG_[^\n]+_TAGS_"), "intl") then
|
||||
status = 2
|
||||
region = string.upper(string.sub(string.match(data, "\"siteEdition\":\"%a+|%a+\""), 19, -2)) or string.upper(string.sub(string.match(data, "property: '%a+'"), 12, -2))
|
||||
if region then
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
elseif old_regex ~= regex and not all_test then
|
||||
status = 2
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
if string.match(data, "_TAG_[^\n]+_TAGS_") then
|
||||
if not string.find(string.match(data, "_TAG_[^\n]+_TAGS_"), "intl") then
|
||||
status = 2
|
||||
if string.match(data, "\"siteEdition\":\"%a+|%a+\"") or string.match(data, "property: '%a+'") then
|
||||
region = string.upper(string.sub(string.match(data, "\"siteEdition\":\"%a+|%a+\""), 19, -2)) or string.upper(string.sub(string.match(data, "property: '%a+'"), 12, -2))
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
elseif old_regex ~= regex and not all_test then
|
||||
status = 2
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
return region, old_region
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return region
|
||||
end
|
||||
|
||||
function discovery_plus_unlock_test()
|
||||
status = 0
|
||||
local url = "https://us1-prod-direct.discoveryplus.com/token?deviceId=d1a4a5d25212400d1e6985984604d740&realm=go&shortlived=true"
|
||||
local url1 = "https://us1-prod-direct.discoveryplus.com/users/me"
|
||||
local region
|
||||
local region = ""
|
||||
local old_region = get_old_region()
|
||||
local old_regex = get_old_regex()
|
||||
local regex = UCI:get("openclash", "config", "stream_auto_select_region_key_discovery_plus") or ""
|
||||
@@ -1456,9 +1445,10 @@ function discovery_plus_unlock_test()
|
||||
token = JSON.parse(token).data.attributes.token
|
||||
local cookie = string.format("-b \"_gcl_au=1.1.858579665.1632206782; _rdt_uuid=1632206782474.6a9ad4f2-8ef7-4a49-9d60-e071bce45e88; _scid=d154b864-8b7e-4f46-90e0-8b56cff67d05; _pin_unauth=dWlkPU1qWTRNR1ZoTlRBdE1tSXdNaTAwTW1Nd0xUbGxORFV0WWpZMU0yVXdPV1l6WldFeQ; _sctr=1|1632153600000; aam_fw=aam%%3D9354365%%3Baam%%3D9040990; aam_uuid=24382050115125439381416006538140778858; st=%s; gi_ls=0; _uetvid=a25161a01aa711ec92d47775379d5e4d; AMCV_BC501253513148ED0A490D45%%40AdobeOrg=-1124106680%%7CMCIDTS%%7C18894%%7CMCMID%%7C24223296309793747161435877577673078228%%7CMCAAMLH-1633011393%%7C9%%7CMCAAMB-1633011393%%7CRKhpRz8krg2tLO6pguXWp5olkAcUniQYPHaMWWgdJ3xzPWQmdj0y%%7CMCOPTOUT-1632413793s%%7CNONE%%7CvVersion%%7C5.2.0; ass=19ef15da-95d6-4b1d-8fa2-e9e099c9cc38.1632408400.1632406594\"", token)
|
||||
local data = SYS.exec(string.format("curl -sL --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 -H 'Accept-Language: en' -H 'Content-Type: application/json' -H 'User-Agent: %s' %s %s", UA, cookie, url1))
|
||||
if data and JSON.parse(data) and JSON.parse(data).data and JSON.parse(data).data.attributes and JSON.parse(data).data.attributes.currentLocationSovereignTerritory then
|
||||
region = string.upper(JSON.parse(data).data.attributes.currentLocationTerritory) or string.upper(JSON.parse(data).data.attributes.currentLocationSovereignTerritory)
|
||||
if region then
|
||||
if data and JSON.parse(data) and JSON.parse(data).data and JSON.parse(data).data.attributes and (JSON.parse(data).data.attributes.currentLocationSovereignTerritory or JSON.parse(data).data.attributes.currentLocationTerritory) then
|
||||
region = JSON.parse(data).data.attributes.currentLocationTerritory or JSON.parse(data).data.attributes.currentLocationSovereignTerritory
|
||||
if region ~= "" then
|
||||
region = string.upper(region)
|
||||
status = 2
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
@@ -1467,22 +1457,23 @@ function discovery_plus_unlock_test()
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
return region, old_region
|
||||
end
|
||||
end
|
||||
end
|
||||
return region
|
||||
end
|
||||
|
||||
function bilibili_unlock_test()
|
||||
status = 0
|
||||
local randsession = SYS.exec("cat /dev/urandom 2>/dev/null | head -n 32 | md5sum | head -c 32")
|
||||
local region, httpcode, data, url
|
||||
local region = ""
|
||||
local httpcode, data, url
|
||||
local regex = UCI:get("openclash", "config", "stream_auto_select_region_key_bilibili") or "CN"
|
||||
local old_region = get_old_region()
|
||||
if regex == "HK/MO/TW" then
|
||||
@@ -1491,7 +1482,7 @@ function bilibili_unlock_test()
|
||||
elseif regex == "TW" then
|
||||
url = string.format("https://api.bilibili.com/pgc/player/web/playurl?avid=50762638&cid=100279344&qn=0&type=&otype=json&ep_id=268176&fourk=1&fnver=0&fnval=16&session=%s&module=bangumi", randsession)
|
||||
region = "TW"
|
||||
elseif regex == "CN" then
|
||||
else
|
||||
url = string.format("https://api.bilibili.com/pgc/player/web/playurl?avid=82846771&qn=0&type=&otype=json&ep_id=307247&fourk=1&fnver=0&fnval=16&session=%s&module=bangumi", randsession)
|
||||
region = "CN"
|
||||
end
|
||||
@@ -1505,22 +1496,22 @@ function bilibili_unlock_test()
|
||||
if old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
write_cache(type, "old_regex", regex)
|
||||
end
|
||||
return region, old_region
|
||||
end
|
||||
end
|
||||
end
|
||||
return region
|
||||
end
|
||||
|
||||
function google_not_cn_test()
|
||||
status = 0
|
||||
local url = "https://timeline.google.com"
|
||||
local region
|
||||
local region = ""
|
||||
local httpcode = SYS.exec(string.format("curl -sL --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 -o /dev/null -w %%{http_code} -H 'Accept-Language: en' -H 'Content-Type: application/json' -H 'User-Agent: %s' '%s'", UA, url))
|
||||
if httpcode then
|
||||
if tonumber(httpcode) == 200 then
|
||||
@@ -1533,8 +1524,8 @@ function google_not_cn_test()
|
||||
region = "CN"
|
||||
status = 1
|
||||
end
|
||||
return region
|
||||
end
|
||||
return region
|
||||
end
|
||||
|
||||
function openai_unlock_test()
|
||||
@@ -1558,8 +1549,6 @@ function openai_unlock_test()
|
||||
region_data = SYS.exec(string.format("curl -sL --connect-timeout 5 -m 5 --speed-time 5 --speed-limit 1 --retry 2 -H 'Accept-Language: en' -H 'Content-Type: application/json' -H 'User-Agent: %s' '%s'", UA, region_url))
|
||||
if region_data and string.match(region_data, "loc=%a+") then
|
||||
region = string.upper(string.sub(string.match(region_data, "loc=%a+"), 5, -1))
|
||||
end
|
||||
if region then
|
||||
if not datamatch(region, regex) then
|
||||
status = 3
|
||||
elseif old_regex ~= regex and not all_test then
|
||||
@@ -1567,7 +1556,7 @@ function openai_unlock_test()
|
||||
elseif old_region ~= "" and region ~= old_region and not all_test then
|
||||
status = 4
|
||||
end
|
||||
if status == 2 and not all_test and region ~= "" and region ~= old_region then
|
||||
if status == 2 and not all_test and region ~= old_region then
|
||||
write_cache(type, "old_region", region)
|
||||
end
|
||||
if status == 2 and not all_test and regex ~= old_regex then
|
||||
@@ -1575,8 +1564,8 @@ function openai_unlock_test()
|
||||
end
|
||||
end
|
||||
end
|
||||
return region, old_region
|
||||
end
|
||||
return region
|
||||
end
|
||||
|
||||
function network_test()
|
||||
|
@@ -45,19 +45,7 @@ if [ "$TIME" != "$CHTIME" ]; then
|
||||
OP_LV=$(sed -n 1p $DOWNLOAD_FILE 2>/dev/null |awk -F 'v' '{print $2}' |awk -F '.' '{print $2$3}' 2>/dev/null)
|
||||
if [ "$(expr "$OP_CV" \>= "$OP_LV")" = "1" ]; then
|
||||
sed -i '/^https:/,$d' $DOWNLOAD_FILE
|
||||
elif [ "$(expr "$OP_LV" \> "$OP_CV")" = "1" ] && [ -n "$OP_LV" ]; then
|
||||
del_lock
|
||||
exit 2
|
||||
else
|
||||
del_lock
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
elif [ "$(expr "$OP_LV" \> "$OP_CV")" = "1" ] && [ -n "$OP_LV" ]; then
|
||||
del_lock
|
||||
exit 2
|
||||
else
|
||||
del_lock
|
||||
exit 0
|
||||
fi 2>/dev/null
|
||||
fi
|
||||
del_lock
|
@@ -54,6 +54,7 @@ Discord语音,Discord-All.rules
|
||||
饥荒-steam,Don't-Starve-steam.rules,Dont-Starve-steam.rules
|
||||
刀塔霸业,Dota-Underlords.rules
|
||||
DOTA2-日服,Dota2-jp.rules
|
||||
精英-危险,Elite-Dangerous.rules
|
||||
逃离塔科夫,Escape-from-Tarkov.rules
|
||||
欧卡2所有分区-UU,Euro-Truck-Simulator-2.rules
|
||||
Eve-online欧服,Eve-online.rules
|
||||
@@ -68,6 +69,7 @@ FIFA20,FIFA20.rules
|
||||
极限竞速地平线4,Forza-Horizon-4.rules
|
||||
极限竞速地平线5,Forza-Horizon-5.rules
|
||||
极限竞速7,Forza-Motorsport-7.rules
|
||||
侠盗猎车手5,GTA-V.rules
|
||||
基佬大乱斗Gang Beasts,Gang-Beasts.rules
|
||||
原神-港澳台服,GenshinImpact.exe_SSTAP.rules
|
||||
鹅鸭杀,Goose-Goose-Duck-HK.rules
|
||||
@@ -97,6 +99,7 @@ Kurtzpel,Kurtzpel.rules
|
||||
冒险岛,Maplestory-us.rules
|
||||
心灵终结,MentalOmega.rules
|
||||
微软模拟飞行年度版,Microsoft-Flight-Simulator-Game-Of-The-Year-Edition.rules
|
||||
微软模拟飞行,Microsoft-Flight-Simulator.rules
|
||||
巨硬商店,Microsoft-Srote.rules
|
||||
我的世界-地下城,Minecraft-Dungeons.rules
|
||||
传奇4-亚服,MIR4-asia.rules
|
||||
@@ -109,6 +112,7 @@ NBA2K20,NBA2K20.rules
|
||||
仁王,NIOH.rules
|
||||
橘子客户端-UU,Origin.rules
|
||||
Osu!,Osu!.rules
|
||||
守望先锋2,Overwatch-2-Asia-Singapore.rules
|
||||
守望先锋-亚服,Overwatch-Asia.rules
|
||||
守望先锋-美服,Overwatch-US.rules
|
||||
流亡黯道-国际服,Path Of Exile.rules
|
||||
@@ -119,6 +123,7 @@ Osu!,Osu!.rules
|
||||
实况足球-2018,Pro-Evolution-Soccer-2018.rules
|
||||
实况足球-2019,Pro-Evolution-Soccer-2019.rules
|
||||
绝地求生亚服&东南亚服,PUBG-Asia&-Southeast-Asia.rules
|
||||
绝地求生亚服,PUBG-Asis.rules
|
||||
绝地求生国际服,PUBG-INT.rules
|
||||
绝地求生韩服,PUBG-kakao.rules
|
||||
绝地求生低配版-Garena,PUBGLite-Garena.rules
|
||||
|
@@ -3,7 +3,7 @@ rules:
|
||||
- RULE-SET,HTTPDNS,HTTPDNS
|
||||
- RULE-SET,Special,DIRECT
|
||||
- RULE-SET,Netflix,Netflix
|
||||
- RULE-SET,Disney Plus,Disney
|
||||
- RULE-SET,Disney Plus,Disney Plus
|
||||
- RULE-SET,YouTube,YouTube
|
||||
- RULE-SET,Max,Max
|
||||
- RULE-SET,Spotify,Spotify
|
||||
@@ -17,6 +17,7 @@ rules:
|
||||
- RULE-SET,Youku,CN Mainland TV
|
||||
- RULE-SET,Abema TV,Asian TV
|
||||
- RULE-SET,Bahamut,Asian TV
|
||||
- RULE-SET,DMM,Asian TV
|
||||
- RULE-SET,Fox+,Asian TV
|
||||
- RULE-SET,Hulu Japan,Asian TV
|
||||
- RULE-SET,Japonx,Asian TV
|
||||
@@ -40,10 +41,6 @@ rules:
|
||||
- RULE-SET,PBS,Global TV
|
||||
- RULE-SET,Pornhub,Global TV
|
||||
- RULE-SET,Soundcloud,Global TV
|
||||
- RULE-SET,Apple Music,Apple TV
|
||||
- RULE-SET,Apple News,Apple TV
|
||||
- RULE-SET,Apple TV,Apple TV
|
||||
- RULE-SET,Apple,Apple
|
||||
- RULE-SET,Telegram,Telegram
|
||||
- RULE-SET,Crypto,Crypto
|
||||
- RULE-SET,Discord,Discord
|
||||
@@ -54,6 +51,11 @@ rules:
|
||||
- RULE-SET,Scholar,Scholar
|
||||
- RULE-SET,Speedtest,Speedtest
|
||||
- RULE-SET,Steam,Steam
|
||||
- RULE-SET,TikTok,TikTok
|
||||
- RULE-SET,Apple Music,Apple TV
|
||||
- RULE-SET,Apple News,Apple TV
|
||||
- RULE-SET,Apple TV,Apple TV
|
||||
- RULE-SET,Apple,Apple
|
||||
- RULE-SET,miHoYo,miHoYo
|
||||
- RULE-SET,PROXY,Proxy
|
||||
- RULE-SET,Domestic,Domestic
|
||||
@@ -242,6 +244,12 @@ rule-providers:
|
||||
url: https://testingcf.jsdelivr.net/gh/dler-io/Rules@main/Clash/Provider/Media/Disney%20Plus.yaml
|
||||
path: "./Rules/Media/Disney_Plus"
|
||||
interval: 86400
|
||||
DMM:
|
||||
type: http
|
||||
behavior: classical
|
||||
url: https://testingcf.jsdelivr.net/gh/dler-io/Rules@main/Clash/Provider/Media/DMM.yaml
|
||||
path: "./Rules/Media/DMM"
|
||||
interval: 86400
|
||||
encoreTVB:
|
||||
type: http
|
||||
behavior: classical
|
||||
@@ -374,6 +382,12 @@ rule-providers:
|
||||
url: https://testingcf.jsdelivr.net/gh/dler-io/Rules@main/Clash/Provider/Steam.yaml
|
||||
path: "./Rules/Steam"
|
||||
interval: 86400
|
||||
TikTok:
|
||||
type: http
|
||||
behavior: classical
|
||||
url: https://testingcf.jsdelivr.net/gh/dler-io/Rules@main/Clash/Provider/TikTok.yaml
|
||||
path: "./Rules/TikTok"
|
||||
interval: 86400
|
||||
Speedtest:
|
||||
type: http
|
||||
behavior: classical
|
||||
|
@@ -345,8 +345,14 @@ threads << Thread.new {
|
||||
Value['secret']='$2';
|
||||
Value['bind-address']='*';
|
||||
Value['external-ui']='/usr/share/openclash/ui';
|
||||
Value['keep-alive-interval']=15;
|
||||
Value['keep-alive-idle']=600;
|
||||
Value['external-ui-name']='metacubexd';
|
||||
if Value.key?('external-ui-url') then
|
||||
Value.delete('external-ui-url');
|
||||
end;
|
||||
if not Value.key?('keep-alive-interval') and not Value.key?('keep-alive-idle') then
|
||||
Value['keep-alive-interval']=15;
|
||||
Value['keep-alive-idle']=600;
|
||||
end;
|
||||
if $6 == 1 then
|
||||
Value['ipv6']=true;
|
||||
else
|
||||
@@ -467,6 +473,9 @@ threads << Thread.new {
|
||||
if Value.key?('auto-redir') then
|
||||
Value.delete('auto-redir');
|
||||
end;
|
||||
if Value.key?('geo-auto-update') then
|
||||
Value['geo-auto-update']=false;
|
||||
end;
|
||||
rescue Exception => e
|
||||
YAML.LOG('Error: Set General Failed,【' + e.message + '】');
|
||||
end;
|
||||
|
@@ -222,6 +222,20 @@ ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
|
||||
uci_commands << uci_set + 'policy_filter=\"' + x['filter'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads_g << Thread.new {
|
||||
#interface-name
|
||||
if x.key?('interface-name') then
|
||||
uci_commands << uci_set + 'interface_name=\"' + x['interface-name'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads_g << Thread.new {
|
||||
#routing-mark
|
||||
if x.key?('routing-mark') then
|
||||
uci_commands << uci_set + 'routing_mark=\"' + x['routing-mark'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads_g << Thread.new {
|
||||
#other_group
|
||||
|
@@ -47,7 +47,7 @@ cfg_groups_set()
|
||||
sed -i "s/new_servers_group \'${convert_old_name_cfg}\'/new_servers_group \'${convert_name}\'/g" $CFG_FILE 2>/dev/null
|
||||
sed -i "s/relay_groups \'${convert_old_name_cfg}\'/relay_groups \'${convert_name}\'/g" $CFG_FILE 2>/dev/null
|
||||
#第三方规则处理
|
||||
OTHER_RULE_NAMES=("GlobalTV" "AsianTV" "MainlandTV" "Proxy" "Youtube" "Bilibili" "Bahamut" "HBOMax" "Pornhub" "Apple" "GoogleFCM" "Scholar" "Microsoft" "Netflix" "Disney" "Spotify" "Steam" "Speedtest" "Telegram" "PayPal" "Netease_Music" "AdBlock" "Domestic" "Others" "miHoYo" "AI_Suite" "AppleTV" "Crypto" "Discord" "HTTPDNS")
|
||||
OTHER_RULE_NAMES=("GlobalTV" "AsianTV" "MainlandTV" "Proxy" "Youtube" "Bilibili" "Bahamut" "HBOMax" "Pornhub" "Apple" "GoogleFCM" "Scholar" "Microsoft" "Netflix" "Disney Plus" "Spotify" "Steam" "TikTok" "Speedtest" "Telegram" "PayPal" "Netease_Music" "AdBlock" "Domestic" "Others" "miHoYo" "AI_Suite" "AppleTV" "Crypto" "Discord" "HTTPDNS")
|
||||
for i in ${OTHER_RULE_NAMES[@]}; do
|
||||
sed -i "s/option ${i} \'${convert_old_name_cfg}\'/option ${i} \'${convert_name}\'/g" $CFG_FILE 2>/dev/null
|
||||
done 2>/dev/null
|
||||
|
@@ -350,6 +350,12 @@ yml_groups_set()
|
||||
[ -n "$policy_filter" ] && {
|
||||
echo " filter: \"$policy_filter\"" >>$GROUP_FILE
|
||||
}
|
||||
[ -n "$interface_name" ] && {
|
||||
echo " interface-name: \"$interface_name\"" >>$GROUP_FILE
|
||||
}
|
||||
[ -n "$routing_mark" ] && {
|
||||
echo " routing-mark: \"$routing_mark\"" >>$GROUP_FILE
|
||||
}
|
||||
}
|
||||
|
||||
create_config=$(uci -q get openclash.config.create_config)
|
||||
|
@@ -730,7 +730,7 @@ ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
|
||||
};
|
||||
end;
|
||||
|
||||
#Mieru
|
||||
#Mieru
|
||||
if x['type'] == 'mieru' then
|
||||
threads << Thread.new{
|
||||
#port-range
|
||||
@@ -761,6 +761,68 @@ ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
|
||||
};
|
||||
end;
|
||||
|
||||
#AnyTLS
|
||||
if x['type'] == 'anytls' then
|
||||
threads << Thread.new{
|
||||
if x.key?('password') then
|
||||
uci_commands << uci_set + 'password=\"' + x['password'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
#idle-session-check-interval
|
||||
if x.key?('idle-session-check-interval') then
|
||||
uci_commands << uci_set + 'idle_session_check_interval=\"' + x['idle-session-check-interval'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
#idle-session-timeout
|
||||
if x.key?('idle-session-timeout') then
|
||||
uci_commands << uci_set + 'idle_session_timeout=\"' + x['idle-session-timeout'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
#min-idle-session
|
||||
if x.key?('min-idle-session') then
|
||||
uci_commands << uci_set + 'min_idle_session=\"' + x['min-idle-session'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
#alpn
|
||||
if x.key?('alpn') then
|
||||
alpn = uci_del + 'alpn >/dev/null 2>&1'
|
||||
system(alpn)
|
||||
x['alpn'].each{
|
||||
|x|
|
||||
uci_commands << uci_add + 'alpn=\"' + x.to_s + '\"'
|
||||
}
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
#sni
|
||||
if x.key?('sni') then
|
||||
uci_commands << uci_set + 'sni=\"' + x['sni'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
#skip-cert-verify
|
||||
if x.key?('skip-cert-verify') then
|
||||
uci_commands << uci_set + 'skip_cert_verify=\"' + x['skip-cert-verify'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
#client_fingerprint
|
||||
if x.key?('client-fingerprint') then
|
||||
uci_commands << uci_set + 'client_fingerprint=\"' + x['client-fingerprint'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
end;
|
||||
|
||||
#Tuic
|
||||
if x['type'] == 'tuic' then
|
||||
threads << Thread.new{
|
||||
@@ -1266,6 +1328,56 @@ ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
|
||||
};
|
||||
end;
|
||||
|
||||
if x['type'] == 'ssh' then
|
||||
threads << Thread.new{
|
||||
if x.key?('username') then
|
||||
uci_commands << uci_set + 'auth_name=\"' + x['username'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
if x.key?('password') then
|
||||
uci_commands << uci_set + 'auth_pass=\"' + x['password'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
if x.key?('private-key') then
|
||||
uci_commands << uci_set + 'private_key=\"' + x['private-key'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
if x.key?('private-key-passphrase') then
|
||||
uci_commands << uci_set + 'private_key_passphrase=\"' + x['private-key-passphrase'].to_s + '\"'
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
#host-key-algorithms
|
||||
if x.key?('host-key-algorithms') then
|
||||
host_key_algorithms = uci_del + 'host_key_algorithms >/dev/null 2>&1'
|
||||
system(host_key_algorithms)
|
||||
x['host-key-algorithms'].each{
|
||||
|x|
|
||||
uci_commands << uci_add + 'host_key_algorithms=\"' + x.to_s + '\"'
|
||||
}
|
||||
end
|
||||
};
|
||||
|
||||
threads << Thread.new{
|
||||
#host-key
|
||||
if x.key?('host-key') then
|
||||
host_key = uci_del + 'host_key >/dev/null 2>&1'
|
||||
system(host_key)
|
||||
x['host-key'].each{
|
||||
|x|
|
||||
uci_commands << uci_add + 'host_key=\"' + x.to_s + '\"'
|
||||
}
|
||||
end
|
||||
};
|
||||
end;
|
||||
|
||||
if x['type'] == 'socks5' or x['type'] == 'http' then
|
||||
threads << Thread.new{
|
||||
if x.key?('username') then
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -335,10 +335,11 @@ yml_other_set()
|
||||
.gsub(/,[\s]?Apple TV$/, ',$AppleTV#delete_')
|
||||
.gsub(/,[\s]?Scholar$/, ',$Scholar#delete_')
|
||||
.gsub(/,[\s]?Netflix$/, ',$Netflix#delete_')
|
||||
.gsub(/,[\s]?Disney$/, ',$Disney#delete_')
|
||||
.gsub(/,[\s]?Disney Plus$/, ',$Disney#delete_')
|
||||
.gsub(/,[\s]?Spotify$/, ',$Spotify#delete_')
|
||||
.gsub(/,[\s]?AI Suite$/, ',$AI_Suite#delete_')
|
||||
.gsub(/,[\s]?Steam$/, ',$Steam#delete_')
|
||||
.gsub(/,[\s]?TikTok$/, ',$TikTok#delete_')
|
||||
.gsub(/,[\s]?miHoYo$/, ',$miHoYo#delete_')
|
||||
.gsub(/,[\s]?AdBlock$/, ',$AdBlock#delete_')
|
||||
.gsub(/,[\s]?HTTPDNS$/, ',$HTTPDNS#delete_')
|
||||
@@ -435,7 +436,7 @@ yml_other_set()
|
||||
end;
|
||||
end;
|
||||
Value['rules'].to_a.collect!{|x|x.to_s
|
||||
.gsub(/GEOIP,([^,]+),([^,]+)(,.*)?/, 'GEOIP,\1,DIRECT\3')
|
||||
.gsub(/GEOIP,([A-Z]{2}),([^,]+)(,.*)?/, 'GEOIP,\1,DIRECT\3')
|
||||
.gsub(/(^MATCH.*|^FINAL.*)/, 'MATCH,DIRECT')};
|
||||
end;
|
||||
rescue Exception => e
|
||||
@@ -952,6 +953,7 @@ yml_other_rules_get()
|
||||
config_get "Disney" "$section" "Disney" ""
|
||||
config_get "Spotify" "$section" "Spotify" ""
|
||||
config_get "Steam" "$section" "Steam" ""
|
||||
config_get "TikTok" "$section" "TikTok" "$GlobalTV"
|
||||
config_get "AdBlock" "$section" "AdBlock" ""
|
||||
config_get "HTTPDNS" "$section" "HTTPDNS" "REJECT"
|
||||
config_get "Netease_Music" "$section" "Netease_Music" ""
|
||||
@@ -1004,6 +1006,7 @@ if [ "$1" != "0" ]; then
|
||||
|| [ -z "$(grep -F "$AI_Suite" /tmp/Proxy_Group)" ]\
|
||||
|| [ -z "$(grep -F "$Spotify" /tmp/Proxy_Group)" ]\
|
||||
|| [ -z "$(grep -F "$Steam" /tmp/Proxy_Group)" ]\
|
||||
|| [ -z "$(grep -F "$TikTok" /tmp/Proxy_Group)" ]\
|
||||
|| [ -z "$(grep -F "$miHoYo" /tmp/Proxy_Group)" ]\
|
||||
|| [ -z "$(grep -F "$AdBlock" /tmp/Proxy_Group)" ]\
|
||||
|| [ -z "$(grep -F "$HTTPDNS" /tmp/Proxy_Group)" ]\
|
||||
|
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M228.54,86.66l-176.06-54A16,16,0,0,0,32,48V192a16,16,0,0,0,16,16,16,16,0,0,0,4.52-.65L136,181.73V192a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16v-29.9l28.54-8.75A16.09,16.09,0,0,0,240,138V102A16.09,16.09,0,0,0,228.54,86.66ZM136,165,48,192V48l88,27Zm48,27H152V176.82L184,167Zm40-54-.11,0L152,160.08V79.92l71.89,22,.11,0v36Z"></path></svg>
|
After Width: | Height: | Size: 441 B |
Reference in New Issue
Block a user