From d2fbff17bfb1f9fbaed41c8c384be27b326276bc Mon Sep 17 00:00:00 2001 From: Andrey Petelin Date: Fri, 9 Jan 2026 23:32:58 +0500 Subject: [PATCH] feat: add selector proxy type support --- .../resources/view/podkop/section.js | 31 ++++++++++++-- podkop/files/usr/bin/podkop | 40 ++++++++++++++++--- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js index 0529ac5..95a5b1d 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js @@ -23,8 +23,9 @@ function createSectionContent(section) { _("Select how to configure the proxy"), ); o.value("url", _("Connection URL")); - o.value("outbound", _("Outbound Config")); + o.value("selector", _("Selector")); o.value("urltest", _("URLTest")); + o.value("outbound", _("Outbound Config")); o.default = "url"; o.depends("connection_type", "proxy"); @@ -32,7 +33,7 @@ function createSectionContent(section) { form.TextValue, "proxy_string", _("Proxy Configuration URL"), - "", + _("vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links") ); o.depends("proxy_config_type", "url"); o.rows = 5; @@ -42,7 +43,6 @@ function createSectionContent(section) { o.textarea = true; o.rmempty = false; o.sectionDescriptions = new Map(); - o.placeholder = "vless://uuid@server:port?type=tcp&security=tls#main"; o.validate = function (section_id, value) { // Optional if (!value || value.length === 0) { @@ -81,13 +81,36 @@ function createSectionContent(section) { return validation.message; }; + o = section.option( + form.DynamicList, + "selector_proxy_links", + _("Selector Proxy Links"), + _("vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links") + ); + o.depends("proxy_config_type", "selector"); + o.rmempty = false; + o.validate = function (section_id, value) { + // Optional + if (!value || value.length === 0) { + return true; + } + + const validation = main.validateProxyUrl(value); + + if (validation.valid) { + return true; + } + + return validation.message; + }; + o = section.option( form.DynamicList, "urltest_proxy_links", _("URLTest Proxy Links"), + _("vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links") ); o.depends("proxy_config_type", "urltest"); - o.placeholder = "vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links"; o.rmempty = false; o.validate = function (section_id, value) { // Optional diff --git a/podkop/files/usr/bin/podkop b/podkop/files/usr/bin/podkop index bcf243b..d467d68 100755 --- a/podkop/files/usr/bin/podkop +++ b/podkop/files/usr/bin/podkop @@ -78,7 +78,7 @@ check_requirements() { if has_outbound_section; then log "Outbound section found" "debug" else - log "Outbound section not found. Please check your configuration file (missing proxy_string, interface, outbound_json, or urltest_proxy_links). Aborted." "error" + log "Outbound section not found. Please check your configuration file (missing proxy_string, selector_proxy_links, urltest_proxy_links, outbound_json, or interface). Aborted." "error" exit 1 fi } @@ -88,12 +88,13 @@ _check_outbound_section() { local proxy_string interface outbound_json urltest_proxy_links config_get proxy_string "$section" "proxy_string" - config_get interface "$section" "interface" - config_get outbound_json "$section" "outbound_json" + config_get selector_proxy_links "$section" "selector_proxy_links" config_get urltest_proxy_links "$section" "urltest_proxy_links" + config_get outbound_json "$section" "outbound_json" + config_get interface "$section" "interface" - if [ -n "$proxy_string" ] || [ -n "$interface" ] || - [ -n "$outbound_json" ] || [ -n "$urltest_proxy_links" ]; then + if [ -n "$proxy_string" ] || [ -n "$selector_proxy_links" ] || [ -n "$urltest_proxy_links" ] || + [ -n "$outbound_json" ] || [ -n "$interface" ]; then section_exists=0 fi } @@ -645,6 +646,35 @@ configure_outbound_handler() { config_get json_outbound "$section" "outbound_json" config=$(sing_box_cf_add_json_outbound "$config" "$section" "$json_outbound") ;; + selector) + log "Detected proxy configuration type: selector" "debug" + local selector_proxy_links udp_over_tcp i outbound_tags outbound_tag default_outbound + config_get selector_proxy_links "$section" "selector_proxy_links" + config_get udp_over_tcp "$section" "enable_udp_over_tcp" + + if [ -z "$selector_proxy_links" ]; then + log "URLTest proxy links is not set. Aborted." "fatal" + exit 1 + fi + + i=1 + for link in $selector_proxy_links; do + config="$(sing_box_cf_add_proxy_outbound "$config" "$section-$i" "$link" "$udp_over_tcp")" + outbound_tag="$(get_outbound_tag_by_section "$section-$i")" + if [ -z "$outbound_tags" ]; then + outbound_tags="$outbound_tag" + default_outbound="$outbound_tag" + else + outbound_tags="$outbound_tags,$outbound_tag" + fi + i=$((i + 1)) + done + + selector_tag="$(get_outbound_tag_by_section "$section")" + selector_outbounds="$(comma_string_to_json_array "$outbound_tags")" + config="$(sing_box_cm_add_selector_outbound "$config" "$selector_tag" "$selector_outbounds" \ + "$default_outbound")" + ;; urltest) log "Detected proxy configuration type: urltest" "debug" local urltest_proxy_links udp_over_tcp i urltest_tag selector_tag outbound_tag outbound_tags \