feat(webapp): add modern WebApp UI with tabs, presets and history
- Add tabbed interface (Basic/Advanced/History) - Add quick action buttons for common formats - Add preset system (Clash/Surge/QuanX/Sing-box/Node list) - Add form persistence with localStorage - Add conversion history with restore functionality - Add URL format validation - Add result statistics (size/lines/time) - Add toast notifications - Add light/dark theme support - Add i18n (Chinese/English auto-detect) - Add responsive mobile layout - Update CMakeLists.txt and main.cpp routing
This commit is contained in:
@@ -76,6 +76,7 @@ ADD_EXECUTABLE(${BUILD_TARGET_NAME}
|
|||||||
src/handler/dashboard_page.cpp
|
src/handler/dashboard_page.cpp
|
||||||
src/handler/inspect_page.cpp
|
src/handler/inspect_page.cpp
|
||||||
src/handler/interfaces.cpp
|
src/handler/interfaces.cpp
|
||||||
|
src/handler/webapp_page.cpp
|
||||||
src/handler/multithread.cpp
|
src/handler/multithread.cpp
|
||||||
src/handler/statistics.cpp
|
src/handler/statistics.cpp
|
||||||
src/handler/upload.cpp
|
src/handler/upload.cpp
|
||||||
|
|||||||
394
base/pref.toml
Normal file
394
base/pref.toml
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
version = 1
|
||||||
|
[common]
|
||||||
|
# API mode is hardcoded to true for security - cannot be configured
|
||||||
|
# Token authentication is disabled - users must provide url parameter
|
||||||
|
|
||||||
|
|
||||||
|
# Default URLs, used when no URL is provided in request, use "|" to separate multiple subscription links, supports local files/URL
|
||||||
|
default_url = []
|
||||||
|
|
||||||
|
# Insert subscription links to requests. Can be used to add node(s) to all exported subscriptions.
|
||||||
|
enable_insert = true
|
||||||
|
# URLs to insert before subscription links, can be used to add node(s) to all exported subscriptions, supports local files/URL
|
||||||
|
insert_url = [""]
|
||||||
|
# Prepend inserted URLs to subscription links. Nodes in insert_url will be added to groups first with non-group-specific match pattern.
|
||||||
|
prepend_insert_url = true
|
||||||
|
|
||||||
|
# Exclude nodes which remarks match the following patterns. Supports regular expression.
|
||||||
|
exclude_remarks = ["(到期|剩余流量|时间|官网|产品)"]
|
||||||
|
|
||||||
|
# Only include nodes which remarks match the following patterns. Supports regular expression.
|
||||||
|
#include_remarks = ["V3.*港"]
|
||||||
|
|
||||||
|
# Enable script support for filtering nodes
|
||||||
|
enable_filter = false
|
||||||
|
# Script used for filtering nodes. Supports inline script and script path. A "filter" function with 1 argument which is a node should be defined in the script.
|
||||||
|
# Example: Inline script: set value to content of script.
|
||||||
|
# Script path: set value to "path:/path/to/script.js".
|
||||||
|
#filter_script = '''
|
||||||
|
#function filter(node) {
|
||||||
|
# const info = JSON.parse(node.ProxyInfo);
|
||||||
|
# if(info.EncryptMethod.includes('chacha20'))
|
||||||
|
# return true;
|
||||||
|
# return false;
|
||||||
|
#}
|
||||||
|
#'''
|
||||||
|
|
||||||
|
default_external_config = "https://testingcf.jsdelivr.net/gh/Aethersailor/Custom_OpenClash_Rules@refs/heads/main/cfg/Custom_Clash.ini"
|
||||||
|
|
||||||
|
# The file scope limit of the 'rule_base' options in external configs.
|
||||||
|
base_path = "base"
|
||||||
|
|
||||||
|
# Clash config base used by the generator, supports local files/URL
|
||||||
|
clash_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Surge config base used by the generator, supports local files/URL
|
||||||
|
surge_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Surfboard config base used by the generator, supports local files/URL
|
||||||
|
surfboard_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Mellow config base used by the generator, supports local files/URL
|
||||||
|
mellow_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Quantumult config base used by the generator, supports local files/URL
|
||||||
|
quan_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Quantumult X config base used by the generator, supports local files/URL
|
||||||
|
quanx_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Loon config base used by the generator, supports local files/URL
|
||||||
|
loon_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Shadowsocks Android config base used by the generator, supports local files/URL
|
||||||
|
sssub_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# sing-box config base used by the generator, supports local files/URL
|
||||||
|
singbox_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Proxy used to download rulesets or subscriptions, set to NONE or empty to disable it, set to SYSTEM to use system proxy.
|
||||||
|
# Accept cURL-supported proxies (http:// https:// socks4a:// socks5://)
|
||||||
|
|
||||||
|
proxy_config = "SYSTEM"
|
||||||
|
proxy_ruleset = "SYSTEM"
|
||||||
|
proxy_subscription = "NONE"
|
||||||
|
|
||||||
|
# Append a proxy type string ([SS] [SSR] [VMess]) to node remark.
|
||||||
|
append_proxy_type = false
|
||||||
|
|
||||||
|
# When requesting /sub, reload this config file first.
|
||||||
|
reload_conf_on_request = false
|
||||||
|
|
||||||
|
[[userinfo.stream_rule]]
|
||||||
|
# Rules to extract stream data from node
|
||||||
|
# Format: full_match_regex|new_format_regex
|
||||||
|
# where new_format_regex should be like "total=$1&left=$2&used=$3"
|
||||||
|
match = '^剩余流量:(.*?)\|总流量:(.*)$'
|
||||||
|
replace = 'total=$2&left=$1'
|
||||||
|
|
||||||
|
[[userinfo.stream_rule]]
|
||||||
|
match = '^剩余流量:(.*?) (.*)$'
|
||||||
|
replace = 'total=$1&left=$2'
|
||||||
|
|
||||||
|
[[userinfo.stream_rule]]
|
||||||
|
match = '^Bandwidth: (.*?)/(.*)$'
|
||||||
|
replace = 'used=$1&total=$2'
|
||||||
|
|
||||||
|
[[userinfo.stream_rule]]
|
||||||
|
match = '^.*剩余(.*?)(?:\s*?)@(?:.*)$'
|
||||||
|
replace = 'total=$1'
|
||||||
|
|
||||||
|
[[userinfo.time_rule]]
|
||||||
|
# Rules to extract expire time data from node
|
||||||
|
# Format: full_match_regex|new_format_regex
|
||||||
|
# where new_format_regex should follow this example: yyyy:mm:dd:hh:mm:ss
|
||||||
|
match = '^过期时间:(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$'
|
||||||
|
replace = '$1:$2:$3:$4:$5:$6'
|
||||||
|
|
||||||
|
[[userinfo.time_rule]]
|
||||||
|
match = '^到期时间:(\d+)-(\d+)-(\d+)$'
|
||||||
|
replace = '$1:$2:$3:0:0:0'
|
||||||
|
|
||||||
|
[[userinfo.time_rule]]
|
||||||
|
match = '^Smart Access expire: (\d+)/(\d+)/(\d+)$'
|
||||||
|
replace = '$1:$2:$3:0:0:0'
|
||||||
|
|
||||||
|
[node_pref]
|
||||||
|
#udp_flag = false
|
||||||
|
#tcp_fast_open_flag = false
|
||||||
|
#skip_cert_verify_flag = false
|
||||||
|
#tls13_flag = false
|
||||||
|
|
||||||
|
sort_flag = false
|
||||||
|
# Script used for sorting nodes. A "compare" function with 2 arguments which are the 2 nodes to be compared should be defined in the script. Supports inline script and script path.
|
||||||
|
# Examples can be seen at the filter_script option in [common] section.
|
||||||
|
#sort_script = '''
|
||||||
|
#function compare(node_a, node_b) {
|
||||||
|
# return info_a.Remark > info_b.Remark;
|
||||||
|
#}
|
||||||
|
#'''
|
||||||
|
|
||||||
|
filter_deprecated_nodes = false
|
||||||
|
append_sub_userinfo = true
|
||||||
|
clash_use_new_field_name = true
|
||||||
|
|
||||||
|
# Generate style of the proxies and proxy groups section of Clash subscriptions.
|
||||||
|
# Supported styles: block, flow, compact
|
||||||
|
# Block: - name: name1 Flow: - {name: name1, key: value} Compact: [{name: name1, key: value},{name: name2, key: value}]
|
||||||
|
# key: value - {name: name2, key: value}
|
||||||
|
# - name: name2
|
||||||
|
# key: value
|
||||||
|
clash_proxies_style = "flow"
|
||||||
|
clash_proxy_groups_style = "flow"
|
||||||
|
|
||||||
|
# add Clash mode to sing-box rules, and add a GLOBAL group to end of outbounds
|
||||||
|
singbox_add_clash_modes = true
|
||||||
|
|
||||||
|
[[node_pref.rename_node]]
|
||||||
|
match = '\(?((x|X)?(\d+)(\.?\d+)?)((\s?倍率?)|(x|X))\)?'
|
||||||
|
replace = "$1x"
|
||||||
|
|
||||||
|
[managed_config]
|
||||||
|
# Append a '#!MANAGED-CONFIG' info to Surge configurations
|
||||||
|
write_managed_config = true
|
||||||
|
|
||||||
|
# Address prefix for MANAGED-CONFIG info, without the trailing "/".
|
||||||
|
managed_config_prefix = "http://127.0.0.1:25500"
|
||||||
|
|
||||||
|
# Managed config update interval in seconds, determine how long the config will be updated.
|
||||||
|
config_update_interval = 86400
|
||||||
|
|
||||||
|
# If config_update_strict is set to true, Surge will require a force update after the interval.
|
||||||
|
config_update_strict = false
|
||||||
|
|
||||||
|
# Device ID to be written to rewrite scripts for some version of Quantumult X
|
||||||
|
quanx_device_id = ""
|
||||||
|
|
||||||
|
[surge_external_proxy]
|
||||||
|
#surge_ssr_path = "/usr/bin/ssr-local"
|
||||||
|
resolve_hostname = true
|
||||||
|
|
||||||
|
[security]
|
||||||
|
# Security profile:
|
||||||
|
# lan - default, legacy behavior for private/LAN deployments. Local, private
|
||||||
|
# and fake-ip resources are allowed.
|
||||||
|
# public - for Internet-facing deployments. Only untrusted request-controlled
|
||||||
|
# fetches are restricted; built-in local templates and trusted config
|
||||||
|
# files continue to work.
|
||||||
|
# strict - same public fetch restrictions, and public upload cannot be enabled.
|
||||||
|
# Environment override: SUBCONVERTER_SECURITY_PROFILE=lan|public|strict
|
||||||
|
profile = "lan"
|
||||||
|
# Only used by public profile. lan keeps legacy upload behavior; strict always
|
||||||
|
# disables public upload.
|
||||||
|
# Environment override: SUBCONVERTER_ALLOW_PUBLIC_UPLOAD=true|false
|
||||||
|
allow_public_upload = false
|
||||||
|
|
||||||
|
[statistics]
|
||||||
|
# Opt-in runtime statistics and /dashboard. Missing or false keeps it disabled
|
||||||
|
# and avoids registering the dashboard or statistics-enabled request handler.
|
||||||
|
enabled = false
|
||||||
|
# Put this directory on a Docker volume if statistics should survive restarts.
|
||||||
|
data_dir = "stats"
|
||||||
|
# Minimum seconds between persistence writes.
|
||||||
|
flush_interval = 5
|
||||||
|
|
||||||
|
[statistics.geo]
|
||||||
|
# header uses country-only headers such as CF-IPCountry and never stores IPs.
|
||||||
|
# none records all countries as unknown.
|
||||||
|
provider = "header"
|
||||||
|
country_headers = ["CF-IPCountry", "X-Geo-Country", "X-Vercel-IP-Country", "CloudFront-Viewer-Country"]
|
||||||
|
|
||||||
|
[statistics.dashboard_auth]
|
||||||
|
# Optional Basic authentication for /dashboard and /dashboard/data.
|
||||||
|
# Only applies when statistics.enabled is true.
|
||||||
|
# Missing or false keeps the dashboard password disabled.
|
||||||
|
enabled = false
|
||||||
|
username = ""
|
||||||
|
password = ""
|
||||||
|
# Failed login attempts allowed within window_seconds before lock_seconds applies.
|
||||||
|
max_failures = 5
|
||||||
|
window_seconds = 300
|
||||||
|
lock_seconds = 900
|
||||||
|
|
||||||
|
[emojis]
|
||||||
|
add_emoji = false
|
||||||
|
remove_old_emoji = true
|
||||||
|
|
||||||
|
[[emojis.emoji]]
|
||||||
|
#match = '(流量|时间|应急)'
|
||||||
|
#emoji = '🏳️🌈'
|
||||||
|
import = "snippets/emoji.toml"
|
||||||
|
|
||||||
|
# [[custom_groups]]
|
||||||
|
# name = "Auto"
|
||||||
|
# type = "url-test"
|
||||||
|
# rule = [".*"]
|
||||||
|
# url = "http://www.gstatic.com/generate_204"
|
||||||
|
# interval = 300
|
||||||
|
# tolerance = 150
|
||||||
|
# lazy = true
|
||||||
|
|
||||||
|
# [[custom_groups]]
|
||||||
|
# name = "Proxy"
|
||||||
|
# type = "select"
|
||||||
|
# rule = [".*", "[]DIRECT"]
|
||||||
|
# disable_udp = false
|
||||||
|
|
||||||
|
# [[custom_groups]]
|
||||||
|
# name = "LoadBalance"
|
||||||
|
# type = "load-balance"
|
||||||
|
# rule = [".*", "[]Proxy", "[]DIRECT"]
|
||||||
|
# interval = 100
|
||||||
|
# strategy = "consistent-hashing"
|
||||||
|
# url = "http://www.gstatic.com/generate_204"
|
||||||
|
|
||||||
|
[[custom_groups]]
|
||||||
|
import = "snippets/groups.toml"
|
||||||
|
|
||||||
|
[ruleset]
|
||||||
|
# Enable generating rules with rulesets
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Overwrite the existing rules in rule_base
|
||||||
|
overwrite_original_rules = false
|
||||||
|
|
||||||
|
# Perform a ruleset update on request
|
||||||
|
update_ruleset_on_request = false
|
||||||
|
|
||||||
|
# [[rulesets]]
|
||||||
|
# group = "Proxy"
|
||||||
|
# ruleset = "https://raw.githubusercontent.com/DivineEngine/Profiles/master/Surge/Ruleset/Unbreak.list"
|
||||||
|
# type = "surge-ruleset"
|
||||||
|
# interval = 86400
|
||||||
|
|
||||||
|
[[rulesets]]
|
||||||
|
import = "snippets/rulesets.toml"
|
||||||
|
|
||||||
|
[template]
|
||||||
|
template_path = ""
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.http_port"
|
||||||
|
value = "7890"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.socks_port"
|
||||||
|
value = "7891"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.allow_lan"
|
||||||
|
value = "true"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.log_level"
|
||||||
|
value = "info"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.external_controller"
|
||||||
|
value = "127.0.0.1:9090"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "singbox.allow_lan"
|
||||||
|
value = "true"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "singbox.mixed_port"
|
||||||
|
value = "2080"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/clash"
|
||||||
|
target = "/sub?target=clash"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/clashr"
|
||||||
|
target = "/sub?target=clashr"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/surge"
|
||||||
|
target = "/sub?target=surge"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/quan"
|
||||||
|
target = "/sub?target=quan"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/quanx"
|
||||||
|
target = "/sub?target=quanx"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/mellow"
|
||||||
|
target = "/sub?target=mellow"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/surfboard"
|
||||||
|
target = "/sub?target=surfboard"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/loon"
|
||||||
|
target = "/sub?target=loon"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/singbox"
|
||||||
|
target = "/sub?target=singbox"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/ss"
|
||||||
|
target = "/sub?target=ss"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/ssd"
|
||||||
|
target = "/sub?target=ssd"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/sssub"
|
||||||
|
target = "/sub?target=sssub"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/ssr"
|
||||||
|
target = "/sub?target=ssr"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/v2ray"
|
||||||
|
target = "/sub?target=v2ray"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/trojan"
|
||||||
|
target = "/sub?target=trojan"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/test"
|
||||||
|
target = "/render?path=templates/test.tpl"
|
||||||
|
|
||||||
|
#[[tasks]]
|
||||||
|
#name = "tick"
|
||||||
|
#cronexp = "0/10 * * * * ?"
|
||||||
|
#path = "tick.js"
|
||||||
|
#timeout = 3
|
||||||
|
|
||||||
|
[server]
|
||||||
|
listen = "0.0.0.0"
|
||||||
|
port = 25500
|
||||||
|
serve_file_root = "web"
|
||||||
|
|
||||||
|
[advanced]
|
||||||
|
log_level = "info"
|
||||||
|
print_debug_info = false
|
||||||
|
max_pending_connections = 10240
|
||||||
|
max_concurrent_threads = 16
|
||||||
|
# Maximum HTTP worker threads during bursts. Requests above this limit remain
|
||||||
|
# queued instead of being rejected.
|
||||||
|
max_server_threads = 128
|
||||||
|
max_allowed_rulesets = 64
|
||||||
|
max_allowed_rules = 0
|
||||||
|
max_allowed_download_size = 0
|
||||||
|
enable_cache = true
|
||||||
|
cache_subscription = 60
|
||||||
|
cache_config = 300
|
||||||
|
cache_ruleset = 21600
|
||||||
|
script_clean_context = true
|
||||||
|
async_fetch_ruleset = true
|
||||||
|
skip_failed_links = true
|
||||||
|
enable_request_coalescing = true
|
||||||
|
coalesce_retry_on_5xx = true
|
||||||
|
# 0 disables completed response caching. If enabled, values above 5 seconds are clamped to 5.
|
||||||
|
response_cache_ttl = 0
|
||||||
@@ -87,7 +87,13 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// ConvertSubscription converts V2Ray subscription links to mihomo proxy configs
|
||||||
|
//
|
||||||
extern char* ConvertSubscription(char* data);
|
extern char* ConvertSubscription(char* data);
|
||||||
|
|
||||||
|
// FreeString frees memory allocated by Go (must be called from C++ after using the result)
|
||||||
|
//
|
||||||
extern void FreeString(char* s);
|
extern void FreeString(char* s);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
394
pref.toml
Normal file
394
pref.toml
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
version = 1
|
||||||
|
[common]
|
||||||
|
# API mode is hardcoded to true for security - cannot be configured
|
||||||
|
# Token authentication is disabled - users must provide url parameter
|
||||||
|
|
||||||
|
|
||||||
|
# Default URLs, used when no URL is provided in request, use "|" to separate multiple subscription links, supports local files/URL
|
||||||
|
default_url = []
|
||||||
|
|
||||||
|
# Insert subscription links to requests. Can be used to add node(s) to all exported subscriptions.
|
||||||
|
enable_insert = true
|
||||||
|
# URLs to insert before subscription links, can be used to add node(s) to all exported subscriptions, supports local files/URL
|
||||||
|
insert_url = [""]
|
||||||
|
# Prepend inserted URLs to subscription links. Nodes in insert_url will be added to groups first with non-group-specific match pattern.
|
||||||
|
prepend_insert_url = true
|
||||||
|
|
||||||
|
# Exclude nodes which remarks match the following patterns. Supports regular expression.
|
||||||
|
exclude_remarks = ["(到期|剩余流量|时间|官网|产品)"]
|
||||||
|
|
||||||
|
# Only include nodes which remarks match the following patterns. Supports regular expression.
|
||||||
|
#include_remarks = ["V3.*港"]
|
||||||
|
|
||||||
|
# Enable script support for filtering nodes
|
||||||
|
enable_filter = false
|
||||||
|
# Script used for filtering nodes. Supports inline script and script path. A "filter" function with 1 argument which is a node should be defined in the script.
|
||||||
|
# Example: Inline script: set value to content of script.
|
||||||
|
# Script path: set value to "path:/path/to/script.js".
|
||||||
|
#filter_script = '''
|
||||||
|
#function filter(node) {
|
||||||
|
# const info = JSON.parse(node.ProxyInfo);
|
||||||
|
# if(info.EncryptMethod.includes('chacha20'))
|
||||||
|
# return true;
|
||||||
|
# return false;
|
||||||
|
#}
|
||||||
|
#'''
|
||||||
|
|
||||||
|
default_external_config = "https://testingcf.jsdelivr.net/gh/Aethersailor/Custom_OpenClash_Rules@refs/heads/main/cfg/Custom_Clash.ini"
|
||||||
|
|
||||||
|
# The file scope limit of the 'rule_base' options in external configs.
|
||||||
|
base_path = "base"
|
||||||
|
|
||||||
|
# Clash config base used by the generator, supports local files/URL
|
||||||
|
clash_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Surge config base used by the generator, supports local files/URL
|
||||||
|
surge_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Surfboard config base used by the generator, supports local files/URL
|
||||||
|
surfboard_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Mellow config base used by the generator, supports local files/URL
|
||||||
|
mellow_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Quantumult config base used by the generator, supports local files/URL
|
||||||
|
quan_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Quantumult X config base used by the generator, supports local files/URL
|
||||||
|
quanx_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Loon config base used by the generator, supports local files/URL
|
||||||
|
loon_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Shadowsocks Android config base used by the generator, supports local files/URL
|
||||||
|
sssub_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# sing-box config base used by the generator, supports local files/URL
|
||||||
|
singbox_rule_base = "base/all_base.tpl"
|
||||||
|
|
||||||
|
# Proxy used to download rulesets or subscriptions, set to NONE or empty to disable it, set to SYSTEM to use system proxy.
|
||||||
|
# Accept cURL-supported proxies (http:// https:// socks4a:// socks5://)
|
||||||
|
|
||||||
|
proxy_config = "SYSTEM"
|
||||||
|
proxy_ruleset = "SYSTEM"
|
||||||
|
proxy_subscription = "NONE"
|
||||||
|
|
||||||
|
# Append a proxy type string ([SS] [SSR] [VMess]) to node remark.
|
||||||
|
append_proxy_type = false
|
||||||
|
|
||||||
|
# When requesting /sub, reload this config file first.
|
||||||
|
reload_conf_on_request = false
|
||||||
|
|
||||||
|
[[userinfo.stream_rule]]
|
||||||
|
# Rules to extract stream data from node
|
||||||
|
# Format: full_match_regex|new_format_regex
|
||||||
|
# where new_format_regex should be like "total=$1&left=$2&used=$3"
|
||||||
|
match = '^剩余流量:(.*?)\|总流量:(.*)$'
|
||||||
|
replace = 'total=$2&left=$1'
|
||||||
|
|
||||||
|
[[userinfo.stream_rule]]
|
||||||
|
match = '^剩余流量:(.*?) (.*)$'
|
||||||
|
replace = 'total=$1&left=$2'
|
||||||
|
|
||||||
|
[[userinfo.stream_rule]]
|
||||||
|
match = '^Bandwidth: (.*?)/(.*)$'
|
||||||
|
replace = 'used=$1&total=$2'
|
||||||
|
|
||||||
|
[[userinfo.stream_rule]]
|
||||||
|
match = '^.*剩余(.*?)(?:\s*?)@(?:.*)$'
|
||||||
|
replace = 'total=$1'
|
||||||
|
|
||||||
|
[[userinfo.time_rule]]
|
||||||
|
# Rules to extract expire time data from node
|
||||||
|
# Format: full_match_regex|new_format_regex
|
||||||
|
# where new_format_regex should follow this example: yyyy:mm:dd:hh:mm:ss
|
||||||
|
match = '^过期时间:(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$'
|
||||||
|
replace = '$1:$2:$3:$4:$5:$6'
|
||||||
|
|
||||||
|
[[userinfo.time_rule]]
|
||||||
|
match = '^到期时间:(\d+)-(\d+)-(\d+)$'
|
||||||
|
replace = '$1:$2:$3:0:0:0'
|
||||||
|
|
||||||
|
[[userinfo.time_rule]]
|
||||||
|
match = '^Smart Access expire: (\d+)/(\d+)/(\d+)$'
|
||||||
|
replace = '$1:$2:$3:0:0:0'
|
||||||
|
|
||||||
|
[node_pref]
|
||||||
|
#udp_flag = false
|
||||||
|
#tcp_fast_open_flag = false
|
||||||
|
#skip_cert_verify_flag = false
|
||||||
|
#tls13_flag = false
|
||||||
|
|
||||||
|
sort_flag = false
|
||||||
|
# Script used for sorting nodes. A "compare" function with 2 arguments which are the 2 nodes to be compared should be defined in the script. Supports inline script and script path.
|
||||||
|
# Examples can be seen at the filter_script option in [common] section.
|
||||||
|
#sort_script = '''
|
||||||
|
#function compare(node_a, node_b) {
|
||||||
|
# return info_a.Remark > info_b.Remark;
|
||||||
|
#}
|
||||||
|
#'''
|
||||||
|
|
||||||
|
filter_deprecated_nodes = false
|
||||||
|
append_sub_userinfo = true
|
||||||
|
clash_use_new_field_name = true
|
||||||
|
|
||||||
|
# Generate style of the proxies and proxy groups section of Clash subscriptions.
|
||||||
|
# Supported styles: block, flow, compact
|
||||||
|
# Block: - name: name1 Flow: - {name: name1, key: value} Compact: [{name: name1, key: value},{name: name2, key: value}]
|
||||||
|
# key: value - {name: name2, key: value}
|
||||||
|
# - name: name2
|
||||||
|
# key: value
|
||||||
|
clash_proxies_style = "flow"
|
||||||
|
clash_proxy_groups_style = "flow"
|
||||||
|
|
||||||
|
# add Clash mode to sing-box rules, and add a GLOBAL group to end of outbounds
|
||||||
|
singbox_add_clash_modes = true
|
||||||
|
|
||||||
|
[[node_pref.rename_node]]
|
||||||
|
match = '\(?((x|X)?(\d+)(\.?\d+)?)((\s?倍率?)|(x|X))\)?'
|
||||||
|
replace = "$1x"
|
||||||
|
|
||||||
|
[managed_config]
|
||||||
|
# Append a '#!MANAGED-CONFIG' info to Surge configurations
|
||||||
|
write_managed_config = true
|
||||||
|
|
||||||
|
# Address prefix for MANAGED-CONFIG info, without the trailing "/".
|
||||||
|
managed_config_prefix = "http://127.0.0.1:25500"
|
||||||
|
|
||||||
|
# Managed config update interval in seconds, determine how long the config will be updated.
|
||||||
|
config_update_interval = 86400
|
||||||
|
|
||||||
|
# If config_update_strict is set to true, Surge will require a force update after the interval.
|
||||||
|
config_update_strict = false
|
||||||
|
|
||||||
|
# Device ID to be written to rewrite scripts for some version of Quantumult X
|
||||||
|
quanx_device_id = ""
|
||||||
|
|
||||||
|
[surge_external_proxy]
|
||||||
|
#surge_ssr_path = "/usr/bin/ssr-local"
|
||||||
|
resolve_hostname = true
|
||||||
|
|
||||||
|
[security]
|
||||||
|
# Security profile:
|
||||||
|
# lan - default, legacy behavior for private/LAN deployments. Local, private
|
||||||
|
# and fake-ip resources are allowed.
|
||||||
|
# public - for Internet-facing deployments. Only untrusted request-controlled
|
||||||
|
# fetches are restricted; built-in local templates and trusted config
|
||||||
|
# files continue to work.
|
||||||
|
# strict - same public fetch restrictions, and public upload cannot be enabled.
|
||||||
|
# Environment override: SUBCONVERTER_SECURITY_PROFILE=lan|public|strict
|
||||||
|
profile = "lan"
|
||||||
|
# Only used by public profile. lan keeps legacy upload behavior; strict always
|
||||||
|
# disables public upload.
|
||||||
|
# Environment override: SUBCONVERTER_ALLOW_PUBLIC_UPLOAD=true|false
|
||||||
|
allow_public_upload = false
|
||||||
|
|
||||||
|
[statistics]
|
||||||
|
# Opt-in runtime statistics and /dashboard. Missing or false keeps it disabled
|
||||||
|
# and avoids registering the dashboard or statistics-enabled request handler.
|
||||||
|
enabled = false
|
||||||
|
# Put this directory on a Docker volume if statistics should survive restarts.
|
||||||
|
data_dir = "stats"
|
||||||
|
# Minimum seconds between persistence writes.
|
||||||
|
flush_interval = 5
|
||||||
|
|
||||||
|
[statistics.geo]
|
||||||
|
# header uses country-only headers such as CF-IPCountry and never stores IPs.
|
||||||
|
# none records all countries as unknown.
|
||||||
|
provider = "header"
|
||||||
|
country_headers = ["CF-IPCountry", "X-Geo-Country", "X-Vercel-IP-Country", "CloudFront-Viewer-Country"]
|
||||||
|
|
||||||
|
[statistics.dashboard_auth]
|
||||||
|
# Optional Basic authentication for /dashboard and /dashboard/data.
|
||||||
|
# Only applies when statistics.enabled is true.
|
||||||
|
# Missing or false keeps the dashboard password disabled.
|
||||||
|
enabled = false
|
||||||
|
username = ""
|
||||||
|
password = ""
|
||||||
|
# Failed login attempts allowed within window_seconds before lock_seconds applies.
|
||||||
|
max_failures = 5
|
||||||
|
window_seconds = 300
|
||||||
|
lock_seconds = 900
|
||||||
|
|
||||||
|
[emojis]
|
||||||
|
add_emoji = false
|
||||||
|
remove_old_emoji = true
|
||||||
|
|
||||||
|
[[emojis.emoji]]
|
||||||
|
#match = '(流量|时间|应急)'
|
||||||
|
#emoji = '🏳️🌈'
|
||||||
|
import = "snippets/emoji.toml"
|
||||||
|
|
||||||
|
# [[custom_groups]]
|
||||||
|
# name = "Auto"
|
||||||
|
# type = "url-test"
|
||||||
|
# rule = [".*"]
|
||||||
|
# url = "http://www.gstatic.com/generate_204"
|
||||||
|
# interval = 300
|
||||||
|
# tolerance = 150
|
||||||
|
# lazy = true
|
||||||
|
|
||||||
|
# [[custom_groups]]
|
||||||
|
# name = "Proxy"
|
||||||
|
# type = "select"
|
||||||
|
# rule = [".*", "[]DIRECT"]
|
||||||
|
# disable_udp = false
|
||||||
|
|
||||||
|
# [[custom_groups]]
|
||||||
|
# name = "LoadBalance"
|
||||||
|
# type = "load-balance"
|
||||||
|
# rule = [".*", "[]Proxy", "[]DIRECT"]
|
||||||
|
# interval = 100
|
||||||
|
# strategy = "consistent-hashing"
|
||||||
|
# url = "http://www.gstatic.com/generate_204"
|
||||||
|
|
||||||
|
[[custom_groups]]
|
||||||
|
import = "snippets/groups.toml"
|
||||||
|
|
||||||
|
[ruleset]
|
||||||
|
# Enable generating rules with rulesets
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Overwrite the existing rules in rule_base
|
||||||
|
overwrite_original_rules = false
|
||||||
|
|
||||||
|
# Perform a ruleset update on request
|
||||||
|
update_ruleset_on_request = false
|
||||||
|
|
||||||
|
# [[rulesets]]
|
||||||
|
# group = "Proxy"
|
||||||
|
# ruleset = "https://raw.githubusercontent.com/DivineEngine/Profiles/master/Surge/Ruleset/Unbreak.list"
|
||||||
|
# type = "surge-ruleset"
|
||||||
|
# interval = 86400
|
||||||
|
|
||||||
|
[[rulesets]]
|
||||||
|
import = "snippets/rulesets.toml"
|
||||||
|
|
||||||
|
[template]
|
||||||
|
template_path = ""
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.http_port"
|
||||||
|
value = "7890"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.socks_port"
|
||||||
|
value = "7891"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.allow_lan"
|
||||||
|
value = "true"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.log_level"
|
||||||
|
value = "info"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "clash.external_controller"
|
||||||
|
value = "127.0.0.1:9090"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "singbox.allow_lan"
|
||||||
|
value = "true"
|
||||||
|
|
||||||
|
[[template.globals]]
|
||||||
|
key = "singbox.mixed_port"
|
||||||
|
value = "2080"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/clash"
|
||||||
|
target = "/sub?target=clash"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/clashr"
|
||||||
|
target = "/sub?target=clashr"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/surge"
|
||||||
|
target = "/sub?target=surge"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/quan"
|
||||||
|
target = "/sub?target=quan"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/quanx"
|
||||||
|
target = "/sub?target=quanx"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/mellow"
|
||||||
|
target = "/sub?target=mellow"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/surfboard"
|
||||||
|
target = "/sub?target=surfboard"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/loon"
|
||||||
|
target = "/sub?target=loon"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/singbox"
|
||||||
|
target = "/sub?target=singbox"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/ss"
|
||||||
|
target = "/sub?target=ss"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/ssd"
|
||||||
|
target = "/sub?target=ssd"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/sssub"
|
||||||
|
target = "/sub?target=sssub"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/ssr"
|
||||||
|
target = "/sub?target=ssr"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/v2ray"
|
||||||
|
target = "/sub?target=v2ray"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/trojan"
|
||||||
|
target = "/sub?target=trojan"
|
||||||
|
|
||||||
|
[[aliases]]
|
||||||
|
uri = "/test"
|
||||||
|
target = "/render?path=templates/test.tpl"
|
||||||
|
|
||||||
|
#[[tasks]]
|
||||||
|
#name = "tick"
|
||||||
|
#cronexp = "0/10 * * * * ?"
|
||||||
|
#path = "tick.js"
|
||||||
|
#timeout = 3
|
||||||
|
|
||||||
|
[server]
|
||||||
|
listen = "0.0.0.0"
|
||||||
|
port = 25500
|
||||||
|
serve_file_root = "web"
|
||||||
|
|
||||||
|
[advanced]
|
||||||
|
log_level = "info"
|
||||||
|
print_debug_info = false
|
||||||
|
max_pending_connections = 10240
|
||||||
|
max_concurrent_threads = 16
|
||||||
|
# Maximum HTTP worker threads during bursts. Requests above this limit remain
|
||||||
|
# queued instead of being rejected.
|
||||||
|
max_server_threads = 128
|
||||||
|
max_allowed_rulesets = 64
|
||||||
|
max_allowed_rules = 0
|
||||||
|
max_allowed_download_size = 0
|
||||||
|
enable_cache = true
|
||||||
|
cache_subscription = 60
|
||||||
|
cache_config = 300
|
||||||
|
cache_ruleset = 21600
|
||||||
|
script_clean_context = true
|
||||||
|
async_fetch_ruleset = true
|
||||||
|
skip_failed_links = true
|
||||||
|
enable_request_coalescing = true
|
||||||
|
coalesce_retry_on_5xx = true
|
||||||
|
# 0 disables completed response caching. If enabled, values above 5 seconds are clamped to 5.
|
||||||
|
response_cache_ttl = 0
|
||||||
1029
src/handler/webapp_page.cpp
Normal file
1029
src/handler/webapp_page.cpp
Normal file
File diff suppressed because it is too large
Load Diff
14
src/handler/webapp_page.h
Normal file
14
src/handler/webapp_page.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef WEBAPP_PAGE_H_INCLUDED
|
||||||
|
#define WEBAPP_PAGE_H_INCLUDED
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "server/webserver.h"
|
||||||
|
|
||||||
|
namespace webapp_page {
|
||||||
|
|
||||||
|
std::string page(Request &, Response &response);
|
||||||
|
|
||||||
|
} // namespace webapp_page
|
||||||
|
|
||||||
|
#endif // WEBAPP_PAGE_H_INCLUDED
|
||||||
10
src/main.cpp
10
src/main.cpp
@@ -15,6 +15,7 @@
|
|||||||
#include "handler/statistics.h"
|
#include "handler/statistics.h"
|
||||||
#include "handler/version_page.h"
|
#include "handler/version_page.h"
|
||||||
#include "handler/webget.h"
|
#include "handler/webget.h"
|
||||||
|
#include "handler/webapp_page.h"
|
||||||
#include "script/cron.h"
|
#include "script/cron.h"
|
||||||
#include "server/socket.h"
|
#include "server/socket.h"
|
||||||
#include "server/webserver.h"
|
#include "server/webserver.h"
|
||||||
@@ -184,13 +185,8 @@ int main(int argc, char *argv[]) {
|
|||||||
if (global.generatorMode)
|
if (global.generatorMode)
|
||||||
return simpleGenerator();
|
return simpleGenerator();
|
||||||
|
|
||||||
/*
|
webServer.append_response("GET", "/", "text/html; charset=utf-8",
|
||||||
webServer.append_response("GET", "/", "text/plain", [](RESPONSE_CALLBACK_ARGS)
|
webapp_page::page);
|
||||||
-> std::string
|
|
||||||
{
|
|
||||||
return "SubConverter-Extended " VERSION " backend\n";
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
webServer.append_response("GET", "/version/favicon-dark.svg",
|
webServer.append_response("GET", "/version/favicon-dark.svg",
|
||||||
"image/svg+xml; charset=utf-8",
|
"image/svg+xml; charset=utf-8",
|
||||||
|
|||||||
Reference in New Issue
Block a user