mirror of
https://github.com/asdlokj1qpi233/subconverter.git
synced 2026-11-03 02:02:24 +00:00
Breaking changes
Fix broken /sub2clashr and /surge2clash interface. Add template support for base configurations. Add support for exporting HTTP/Socks 5 nodes to Quantumult configurations. Add support for VMess HTTP nodes in Clash configurations. Optimize codes.
This commit is contained in:
11 files changed
+27151
-57
No files matched your search
@@ -0,0 +1,207 @@
|
||||
{% if request.target == "clash" or request.target == "clashr" %}
|
||||
|
||||
port: {{ global.clash.http_port }}
|
||||
socks-port: {{ global.clash.socks_port }}
|
||||
allow-lan: {{ global.clash.allow_lan }}
|
||||
mode: Rule
|
||||
log-level: {{ global.clash.log_level }}
|
||||
external-controller: :9090
|
||||
{% if exists("request.clash.dns") %}
|
||||
{% if request.clash.dns == "1" %}
|
||||
dns:
|
||||
enabled: true
|
||||
listen: 1053
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if local.clash.new_field_name == "true" %}
|
||||
proxies: ~
|
||||
proxy-groups: ~
|
||||
rules: ~
|
||||
{% else %}
|
||||
Proxy: ~
|
||||
Proxy Group: ~
|
||||
Rule: ~
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% if request.target == "surge" %}
|
||||
|
||||
[General]
|
||||
loglevel = notify
|
||||
bypass-system = true
|
||||
skip-proxy = 127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,100.64.0.0/10,localhost,*.local,e.crashlytics.com,captive.apple.com,::ffff:0:0:0:0/1,::ffff:128:0:0:0/1
|
||||
#DNS设置或根据自己网络情况进行相应设置
|
||||
bypass-tun = 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12
|
||||
dns-server = 119.29.29.29,223.5.5.5
|
||||
|
||||
[Script]
|
||||
http-request https?:\/\/.*\.iqiyi\.com\/.*authcookie= script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/iQIYI-DailyBonus/iQIYI_GetCookie.js
|
||||
|
||||
{% endif %}
|
||||
{% if request.target == "loon" %}
|
||||
|
||||
[General]
|
||||
skip-proxy = 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,localhost,*.local,e.crashlynatics.com
|
||||
bypass-tun = 10.0.0.0/8,100.64.0.0/10,127.0.0.0/8,169.254.0.0/16,172.16.0.0/12,192.0.0.0/24,192.0.2.0/24,192.88.99.0/24,192.168.0.0/16,198.18.0.0/15,198.51.100.0/24,203.0.113.0/24,224.0.0.0/4,255.255.255.255/32
|
||||
dns-server = system,119.29.29.29,223.5.5.5
|
||||
allow-udp-proxy = false
|
||||
host = 127.0.0.1
|
||||
|
||||
[Proxy]
|
||||
|
||||
[Remote Proxy]
|
||||
|
||||
[Proxy Group]
|
||||
|
||||
[Rule]
|
||||
|
||||
[Remote Rule]
|
||||
|
||||
[URL Rewrite]
|
||||
enable = true
|
||||
^https?:\/\/(www.)?(g|google)\.cn https://www.google.com 302
|
||||
|
||||
[Remote Rewrite]
|
||||
https://raw.githubusercontent.com/Loon0x00/LoonExampleConfig/master/Rewrite/AutoRewrite_Example.list,auto
|
||||
|
||||
[MITM]
|
||||
hostname = *.example.com,*.sample.com
|
||||
enable = true
|
||||
skip-server-cert-verify = true
|
||||
#ca-p12 =
|
||||
#ca-passphrase =
|
||||
|
||||
{% endif %}
|
||||
{% if request.target == "quan" %}
|
||||
|
||||
[SERVER]
|
||||
|
||||
[SOURCE]
|
||||
|
||||
[BACKUP-SERVER]
|
||||
|
||||
[SUSPEND-SSID]
|
||||
|
||||
[POLICY]
|
||||
|
||||
[DNS]
|
||||
1.1.1.1
|
||||
|
||||
[REWRITE]
|
||||
|
||||
[URL-REJECTION]
|
||||
|
||||
[TCP]
|
||||
|
||||
[GLOBAL]
|
||||
|
||||
[HOST]
|
||||
|
||||
[STATE]
|
||||
STATE,AUTO
|
||||
|
||||
[MITM]
|
||||
|
||||
{% endif %}
|
||||
{% if request.target == "quanx" %}
|
||||
|
||||
[general]
|
||||
excluded_routes=192.168.0.0/16, 172.16.0.0/12, 100.64.0.0/10, 10.0.0.0/8
|
||||
geo_location_checker=http://ip-api.com/json/?lang=zh-CN, https://github.com/KOP-XIAO/QuantumultX/raw/master/Scripts/IP_API.js
|
||||
network_check_url=http://www.baidu.com/
|
||||
server_check_url=http://www.gstatic.com/generate_204
|
||||
|
||||
[dns]
|
||||
server=119.29.29.29
|
||||
server=223.5.5.5
|
||||
server=1.0.0.1
|
||||
server=8.8.8.8
|
||||
|
||||
[policy]
|
||||
static=♻️ 自动选择, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Auto.png
|
||||
static=🔰 节点选择, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Proxy.png
|
||||
static=🌍 国外媒体, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/GlobalMedia.png
|
||||
static=🌏 国内媒体, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/DomesticMedia.png
|
||||
static=Ⓜ️ 微软服务, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Microsoft.png
|
||||
static=📲 电报信息, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Telegram.png
|
||||
static=🍎 苹果服务, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Apple.png
|
||||
static=🎯 全球直连, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Direct.png
|
||||
static=🛑 全球拦截, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Advertising.png
|
||||
static=🐟 漏网之鱼, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Final.png
|
||||
|
||||
[server_remote]
|
||||
|
||||
[filter_remote]
|
||||
|
||||
[rewrite_remote]
|
||||
|
||||
[server_local]
|
||||
|
||||
[filter_local]
|
||||
|
||||
[rewrite_local]
|
||||
|
||||
[mitm]
|
||||
|
||||
{% endif %}
|
||||
{% if request.target == "mellow" %}
|
||||
|
||||
[Endpoint]
|
||||
DIRECT, builtin, freedom, domainStrategy=UseIP
|
||||
REJECT, builtin, blackhole
|
||||
Dns-Out, builtin, dns
|
||||
|
||||
[Routing]
|
||||
domainStrategy = IPIfNonMatch
|
||||
|
||||
[Dns]
|
||||
hijack = Dns-Out
|
||||
clientIp = 114.114.114.114
|
||||
|
||||
[DnsServer]
|
||||
localhost
|
||||
223.5.5.5
|
||||
8.8.8.8, 53, Remote
|
||||
8.8.4.4
|
||||
|
||||
[DnsRule]
|
||||
DOMAIN-KEYWORD, geosite:geolocation-!cn, Remote
|
||||
DOMAIN-SUFFIX, google.com, Remote
|
||||
|
||||
[DnsHost]
|
||||
doubleclick.net = 127.0.0.1
|
||||
|
||||
[Log]
|
||||
loglevel = warning
|
||||
|
||||
{% endif %}
|
||||
{% if request.target == "surfboard" %}
|
||||
|
||||
[General]
|
||||
loglevel = notify
|
||||
interface = 127.0.0.1
|
||||
skip-proxy = 127.0.0.1, 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 100.64.0.0/10, localhost, *.local
|
||||
ipv6 = false
|
||||
dns-server = system, 223.5.5.5
|
||||
exclude-simple-hostnames = true
|
||||
enhanced-mode-by-rule = true
|
||||
{% endif %}
|
||||
{% if request.target == "sssub" %}
|
||||
{
|
||||
"route": "bypass-lan-china",
|
||||
"remote_dns": "dns.google",
|
||||
"ipv6": false,
|
||||
"metered": false,
|
||||
"proxy_apps": {
|
||||
"enabled": false,
|
||||
"bypass": true,
|
||||
"android_list": [
|
||||
"com.eg.android.AlipayGphone",
|
||||
"com.wudaokou.hippo",
|
||||
"com.zhihu.android"
|
||||
]
|
||||
},
|
||||
"udpdns": false
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
@@ -55,3 +55,7 @@ clash_rule_base=base/forcerule.yml
|
||||
;Options for filtering nodes
|
||||
;include_remarks=
|
||||
;exclude_remarks=
|
||||
|
||||
;[template]
|
||||
;;variables in the local scope
|
||||
;clash.dns.port=5353
|
||||
@@ -23,3 +23,5 @@ custom:
|
||||
|
||||
# include_remarks: []
|
||||
# exclude_remarks: []
|
||||
# template_args:
|
||||
# - {key: clash.dns.port, value: 5353}
|
||||
+16
-8
@@ -5,14 +5,14 @@ common:
|
||||
insert_url: []
|
||||
exclude_remarks: ["(到期|剩余流量|时间|官网|产品)"]
|
||||
include_remarks: []
|
||||
clash_rule_base: base/simple_base.yml
|
||||
surge_rule_base: base/surge.conf
|
||||
surfboard_rule_base: base/surfboard.conf
|
||||
mellow_rule_base: base/mellow.conf
|
||||
quan_rule_base: base/quan.conf
|
||||
quanx_rule_base: base/quanx.conf
|
||||
loon_rule_base: base/loon.conf
|
||||
sssub_rule_base: base/shadowsocks_base.json
|
||||
clash_rule_base: base/all_base.tpl
|
||||
surge_rule_base: base/all_base.tpl
|
||||
surfboard_rule_base: base/all_base.tpl
|
||||
mellow_rule_base: base/all_base.tpl
|
||||
quan_rule_base: base/all_base.tpl
|
||||
quanx_rule_base: base/all_base.tpl
|
||||
loon_rule_base: base/all_base.tpl
|
||||
sssub_rule_base: base/all_base.tpl
|
||||
proxy_config: SYSTEM
|
||||
proxy_ruleset: SYSTEM
|
||||
proxy_subscription: NONE
|
||||
@@ -79,6 +79,14 @@ proxy_group:
|
||||
# - {name: ssid group, type: ssid, rule: ["default_group", "celluar=group0,ssid1=group1,ssid2=group2"]}
|
||||
- {import: snippets/groups.txt}
|
||||
|
||||
template:
|
||||
template_path: "template"
|
||||
globals:
|
||||
- {key: clash.http_port, value: 7890}
|
||||
- {key: clash.socks_port, value: 7891}
|
||||
- {key: clash.allow_lan, value: true}
|
||||
- {key: clash.log_level, value: info}
|
||||
|
||||
server:
|
||||
listen: 0.0.0.0
|
||||
port: 25500
|
||||
|
||||
+15
-8
@@ -19,28 +19,28 @@ exclude_remarks=(到期|剩余流量|时间|官网|产品)
|
||||
;include_remarks=V3.*港
|
||||
|
||||
;Clash config base used by the generator, supports local files/URL
|
||||
clash_rule_base=base/simple_base.yml
|
||||
clash_rule_base=base/all_base.tpl
|
||||
|
||||
;Surge config base used by the generator, supports local files/URL
|
||||
surge_rule_base=base/surge.conf
|
||||
surge_rule_base=base/all_base.tpl
|
||||
|
||||
;Surfboard config base used by the generator, supports local files/URL
|
||||
surfboard_rule_base=base/surfboard.conf
|
||||
surfboard_rule_base=base/all_base.tpl
|
||||
|
||||
;Mellow config base used by the generator, supports local files/URL
|
||||
mellow_rule_base=base/mellow.conf
|
||||
mellow_rule_base=base/all_base.tpl
|
||||
|
||||
;Quantumult config base used by the generator, supports local files/URL
|
||||
quan_rule_base=base/quan.conf
|
||||
quan_rule_base=base/all_base.tpl
|
||||
|
||||
;Quantumult X config base used by the generator, supports local files/URL
|
||||
quanx_rule_base=base/quanx.conf
|
||||
quanx_rule_base=base/all_base.tpl
|
||||
|
||||
;Loon config base used by the generator, supports local files/URL
|
||||
loon_rule_base=base/loon.conf
|
||||
loon_rule_base=base/all_base.tpl
|
||||
|
||||
;Shadowsocks Android config base used by the generator, supports local files/URL
|
||||
sssub_rule_base=base/shadowsocks_base.json
|
||||
sssub_rule_base=base/all_base.tpl
|
||||
|
||||
;Proxy used to download configs, 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://)
|
||||
@@ -164,6 +164,13 @@ surge_ruleset=!!import:snippets/rulesets.txt
|
||||
;for Surge rulesets
|
||||
custom_proxy_group=!!import:snippets/groups.txt
|
||||
|
||||
[template]
|
||||
template_path=template
|
||||
clash.http_port=7890
|
||||
clash.socks_port=7891
|
||||
clash.allow_lan=true
|
||||
clash.log_level=info
|
||||
|
||||
[server]
|
||||
;Address to bind on for Web Server
|
||||
listen=0.0.0.0
|
||||
|
||||
+3705
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+182
-40
@@ -16,6 +16,7 @@
|
||||
#include "multithread.h"
|
||||
#include "logger.h"
|
||||
#include "string_hash.h"
|
||||
#include "templates.h"
|
||||
|
||||
//common settings
|
||||
std::string pref_path = "pref.ini";
|
||||
@@ -29,6 +30,10 @@ std::string access_token;
|
||||
extern std::string custom_group;
|
||||
extern int global_log_level;
|
||||
|
||||
//global variables for template
|
||||
std::string template_path;
|
||||
string_map global_vars;
|
||||
|
||||
//generator settings
|
||||
bool generator_mode = false;
|
||||
std::string gen_profile;
|
||||
@@ -513,6 +518,22 @@ void readYAMLConf(YAML::Node &node)
|
||||
if(node["proxy_group"].IsDefined() && node["proxy_group"]["custom_proxy_group"].IsDefined())
|
||||
readGroup(node["proxy_group"]["custom_proxy_group"], clash_extra_group, false);
|
||||
|
||||
if(node["template"].IsDefined())
|
||||
{
|
||||
node["template"]["template_path"] >> template_path;
|
||||
if(node["template"]["globals"].IsSequence())
|
||||
{
|
||||
eraseElements(global_vars);
|
||||
std::string key, value;
|
||||
for(size_t i = 0; i < node["template"]["globals"].size(); i++)
|
||||
{
|
||||
node["template"]["globals"][i]["key"] >> key;
|
||||
node["template"]["globals"][i]["value"] >> value;
|
||||
global_vars[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(node["server"].IsDefined())
|
||||
{
|
||||
node["server"]["listen"] >> listen_address;
|
||||
@@ -715,6 +736,18 @@ void readConf()
|
||||
importItems(clash_extra_group, false);
|
||||
}
|
||||
|
||||
ini.EnterSection("template");
|
||||
ini.GetIfExist("template_path", template_path);
|
||||
string_multimap tempmap;
|
||||
ini.GetItems(tempmap);
|
||||
eraseElements(global_vars);
|
||||
for(auto &x : tempmap)
|
||||
{
|
||||
if(x.first == "template_path")
|
||||
continue;
|
||||
global_vars[x.first] = x.second;
|
||||
}
|
||||
|
||||
ini.EnterSection("server");
|
||||
ini.GetIfExist("listen", listen_address);
|
||||
ini.GetIntIfExist("port", listen_port);
|
||||
@@ -788,6 +821,7 @@ struct ExternalConfig
|
||||
string_array emoji;
|
||||
string_array include;
|
||||
string_array exclude;
|
||||
string_map template_args;
|
||||
bool overwrite_original_rules = false;
|
||||
bool enable_rule_generator = true;
|
||||
};
|
||||
@@ -822,6 +856,17 @@ int loadExternalYAML(YAML::Node &node, ExternalConfig &ext)
|
||||
section["include_remarks"] >> ext.include;
|
||||
section["exclude_remarks"] >> ext.exclude;
|
||||
|
||||
if(node["template_args"].IsSequence())
|
||||
{
|
||||
std::string key, value;
|
||||
for(size_t i = 0; i < node["template_args"].size(); i++)
|
||||
{
|
||||
node["template_args"][i]["key"] >> key;
|
||||
node["template_args"][i]["value"] >> value;
|
||||
ext.template_args[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -891,6 +936,15 @@ int loadExternalConfig(std::string &path, ExternalConfig &ext)
|
||||
if(ini.ItemPrefixExist("exclude_remarks"))
|
||||
ini.GetAll("exclude_remarks", ext.exclude);
|
||||
|
||||
if(ini.SectionExist("template"))
|
||||
{
|
||||
ini.EnterSection("template");
|
||||
string_multimap tempmap;
|
||||
ini.GetItems(tempmap);
|
||||
for(auto &x : tempmap)
|
||||
ext.template_args[x.first] = x.second;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -962,6 +1016,23 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
return "Invalid request!";
|
||||
}
|
||||
|
||||
//load request arguments as template variables
|
||||
string_array req_args = split(argument, "&");
|
||||
string_size pos;
|
||||
string_map req_arg_map;
|
||||
for(std::string &x : req_args)
|
||||
{
|
||||
pos = x.find("=");
|
||||
if(pos == x.npos)
|
||||
continue;
|
||||
req_arg_map[x.substr(0, pos)] = x.substr(pos + 1);
|
||||
}
|
||||
|
||||
//save template variables
|
||||
template_args tpl_args;
|
||||
tpl_args.global_vars = global_vars;
|
||||
tpl_args.request_params = req_arg_map;
|
||||
|
||||
//check if we need to read configuration
|
||||
if((!api_mode || cfw_child_process) && !generator_mode)
|
||||
readConf();
|
||||
@@ -1034,6 +1105,8 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
ext.rename_array = extconf.rename;
|
||||
if(extconf.emoji.size())
|
||||
ext.emoji_array = extconf.emoji;
|
||||
if(extconf.template_args.size())
|
||||
tpl_args.local_vars = extconf.template_args;
|
||||
ext.enable_rule_generator = extconf.enable_rule_generator;
|
||||
//load custom group
|
||||
if(extconf.custom_proxy_group.size())
|
||||
@@ -1153,6 +1226,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
case "clash"_hash: case "clashr"_hash:
|
||||
//std::cerr<<"Clash"<<((target == "clashr") ? "R" : "")<<std::endl;
|
||||
writeLog(0, target == "clashr" ? "Generate target: ClashR" : "Generate target: Clash", LOG_LEVEL_INFO);
|
||||
tpl_args.local_vars["clash.new_field_name"] = ext.clash_new_field_name ? "true" : "false";
|
||||
if(ext.nodelist)
|
||||
{
|
||||
YAML::Node yamlnode;
|
||||
@@ -1161,7 +1235,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
}
|
||||
else if(ruleset_updated || update_ruleset_on_request || ext_clash_base != clash_rule_base || !enable_base_gen)
|
||||
{
|
||||
base_content = fetchFile(ext_clash_base, proxy, cache_config);
|
||||
if(render_template(fetchFile(ext_clash_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(ext_clash_base, proxy, cache_config);
|
||||
output_content = netchToClash(nodes, base_content, rca, extra_group, target == "clashr", ext);
|
||||
}
|
||||
else
|
||||
@@ -1188,7 +1267,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
}
|
||||
else
|
||||
{
|
||||
base_content = fetchFile(ext_surge_base, proxy, cache_config);
|
||||
if(render_template(fetchFile(ext_surge_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(ext_surge_base, proxy, cache_config);
|
||||
output_content = netchToSurge(nodes, base_content, rca, extra_group, surge_ver, ext);
|
||||
|
||||
if(upload == "true")
|
||||
@@ -1203,7 +1287,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
//std::cerr<<"Surfboard"<<std::endl;
|
||||
writeLog(0, "Generate target: Surfboard", LOG_LEVEL_INFO);
|
||||
|
||||
base_content = fetchFile(ext_surfboard_base, proxy, cache_config);
|
||||
if(render_template(fetchFile(ext_surfboard_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(ext_surfboard_base, proxy, cache_config);
|
||||
output_content = netchToSurge(nodes, base_content, rca, extra_group, -3, ext);
|
||||
if(upload == "true")
|
||||
uploadGist("surfboard", upload_path, output_content, true);
|
||||
@@ -1218,7 +1307,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
// mellow base generator removed for now
|
||||
//if(ruleset_updated || update_ruleset_on_request || ext_mellow_base != mellow_rule_base || !enable_base_gen)
|
||||
{
|
||||
base_content = fetchFile(ext_mellow_base, proxy, cache_config);
|
||||
if(render_template(fetchFile(ext_mellow_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(ext_mellow_base, proxy, cache_config);
|
||||
output_content = netchToMellow(nodes, base_content, rca, extra_group, ext);
|
||||
}
|
||||
/*
|
||||
@@ -1245,7 +1339,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
//std::cerr<<"SS Subscription"<<std::endl;
|
||||
writeLog(0, "Generate target: SS Subscription", LOG_LEVEL_INFO);
|
||||
|
||||
base_content = fetchFile(ext_sssub_base, proxy, cache_config);
|
||||
if(render_template(fetchFile(ext_sssub_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(ext_sssub_base, proxy, cache_config);
|
||||
output_content = netchToSSSub(base_content, nodes, ext);
|
||||
if(upload == "true")
|
||||
uploadGist("sssub", upload_path, output_content, false);
|
||||
@@ -1268,7 +1367,14 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
//std::cerr<<"Quantumult"<<std::endl;
|
||||
writeLog(0, "Generate target: Quantumult", LOG_LEVEL_INFO);
|
||||
if(!ext.nodelist)
|
||||
base_content = fetchFile(ext_quan_base, proxy, cache_config);
|
||||
{
|
||||
if(render_template(fetchFile(ext_quan_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(ext_quan_base, proxy, cache_config);
|
||||
}
|
||||
|
||||
output_content = netchToQuan(nodes, base_content, rca, extra_group, ext);
|
||||
|
||||
@@ -1279,7 +1385,15 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
//std::cerr<<"Quantumult X"<<std::endl;
|
||||
writeLog(0, "Generate target: Quantumult X", LOG_LEVEL_INFO);
|
||||
if(!ext.nodelist)
|
||||
base_content = fetchFile(ext_quanx_base, proxy, cache_config);
|
||||
{
|
||||
if(render_template(fetchFile(ext_quanx_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(ext_quanx_base, proxy, cache_config);
|
||||
}
|
||||
|
||||
|
||||
output_content = netchToQuanX(nodes, base_content, rca, extra_group, ext);
|
||||
|
||||
@@ -1290,7 +1404,14 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
//std::cerr<<"Loon"<<std::endl;
|
||||
writeLog(0, "Generate target: Loon", LOG_LEVEL_INFO);
|
||||
if(!ext.nodelist)
|
||||
base_content = fetchFile(ext_loon_base, proxy, cache_config);
|
||||
{
|
||||
if(render_template(fetchFile(ext_loon_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(ext_loon_base, proxy, cache_config);
|
||||
}
|
||||
|
||||
output_content = netchToLoon(nodes, base_content, rca, extra_group, ext);
|
||||
|
||||
@@ -1385,17 +1506,35 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
|
||||
return "No nodes were found!";
|
||||
}
|
||||
|
||||
std::cerr<<"Generate target: ClashR\n";
|
||||
writeLog(0, "Generate target: ClashR", LOG_LEVEL_INFO);
|
||||
|
||||
YAML::Node yamlnode = safe_get_clash_base();
|
||||
netchToClash(nodes, yamlnode, extra_group, true, ext);
|
||||
return YAML::Dump(yamlnode);
|
||||
template_args tpl_args;
|
||||
tpl_args.global_vars = global_vars;
|
||||
tpl_args.local_vars["clash.new_field_name"] = clash_use_new_field_name ? "true" : "false";
|
||||
tpl_args.request_params["target"] = "clashr";
|
||||
tpl_args.request_params["url"] = url;
|
||||
|
||||
if(!enable_base_gen)
|
||||
{
|
||||
if(render_template(fetchFile(clash_rule_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(clash_rule_base, proxy, cache_config);
|
||||
return netchToClash(nodes, base_content, rca, extra_group, true, ext);
|
||||
}
|
||||
else
|
||||
{
|
||||
YAML::Node yamlnode = safe_get_clash_base();
|
||||
netchToClash(nodes, yamlnode, extra_group, true, ext);
|
||||
return YAML::Dump(yamlnode);
|
||||
}
|
||||
}
|
||||
|
||||
std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
|
||||
{
|
||||
INIReader ini;
|
||||
YAML::Node clash = safe_get_clash_base();
|
||||
string_array dummy_str_array;
|
||||
std::vector<nodeInfo> nodes;
|
||||
std::string base_content, url = argument.size() <= 5 ? "" : argument.substr(5), dummy;
|
||||
@@ -1417,6 +1556,28 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
|
||||
}
|
||||
|
||||
std::string proxy = parseProxy(proxy_config);
|
||||
YAML::Node clash;
|
||||
template_args tpl_args;
|
||||
tpl_args.global_vars = global_vars;
|
||||
tpl_args.local_vars["clash.new_field_name"] = clash_use_new_field_name ? "true" : "false";
|
||||
tpl_args.request_params["target"] = "clash";
|
||||
tpl_args.request_params["url"] = url;
|
||||
|
||||
if(!enable_base_gen)
|
||||
{
|
||||
if(render_template(fetchFile(clash_rule_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
|
||||
{
|
||||
*status_code = 400;
|
||||
return base_content;
|
||||
}
|
||||
//base_content = fetchFile(clash_rule_base, proxy, cache_config);
|
||||
clash = YAML::Load(base_content);
|
||||
}
|
||||
else
|
||||
{
|
||||
clash = safe_get_clash_base();
|
||||
}
|
||||
|
||||
base_content = fetchFile(url, proxy, cache_config);
|
||||
|
||||
if(ini.Parse(base_content) != INIREADER_EXCEPTION_NONE)
|
||||
@@ -1436,8 +1597,6 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
proxy = parseProxy(proxy_subscription);
|
||||
|
||||
//scan groups first, get potential policy-path
|
||||
string_multimap section;
|
||||
ini.GetItems("Proxy Group", section);
|
||||
@@ -1472,12 +1631,15 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
|
||||
clash[proxygroup_name].push_back(singlegroup);
|
||||
}
|
||||
|
||||
proxy = parseProxy(proxy_subscription);
|
||||
eraseElements(dummy_str_array);
|
||||
|
||||
std::string subInfo;
|
||||
for(std::string &x : links)
|
||||
{
|
||||
//std::cerr<<"Fetching node data from url '"<<x<<"'."<<std::endl;
|
||||
writeLog(0, "Fetching node data from url '" + x + "'.", LOG_LEVEL_INFO);
|
||||
if(addNodes(x, nodes, 0, proxy, dummy_str_array, dummy_str_array, dummy_str_array, dummy_str_array, subInfo, false) == -1)
|
||||
if(addNodes(x, nodes, 0, proxy, dummy_str_array, dummy_str_array, dummy_str_array, dummy_str_array, subInfo, !api_mode) == -1)
|
||||
{
|
||||
*status_code = 400;
|
||||
return std::string("The following link doesn't contain any valid node info: " + x);
|
||||
@@ -1703,9 +1865,9 @@ std::string getRewriteRemote(RESPONSE_CALLBACK_ARGS)
|
||||
|
||||
static inline std::string intToStream(unsigned long long stream)
|
||||
{
|
||||
char chrs[16] = {};
|
||||
char chrs[16] = {}, units[6] = {' ', 'K', 'M', 'G', 'T', 'P'};
|
||||
double streamval = stream;
|
||||
int level = 0;
|
||||
unsigned int level = 0;
|
||||
while(streamval > 1024.0)
|
||||
{
|
||||
if(level >= 5)
|
||||
@@ -1713,27 +1875,7 @@ static inline std::string intToStream(unsigned long long stream)
|
||||
level++;
|
||||
streamval /= 1024.0;
|
||||
}
|
||||
switch(level)
|
||||
{
|
||||
case 3:
|
||||
snprintf(chrs, 15, "%.2f GB", streamval);
|
||||
break;
|
||||
case 4:
|
||||
snprintf(chrs, 15, "%.2f TB", streamval);
|
||||
break;
|
||||
case 5:
|
||||
snprintf(chrs, 15, "%.2f PB", streamval);
|
||||
break;
|
||||
case 2:
|
||||
snprintf(chrs, 15, "%.2f MB", streamval);
|
||||
break;
|
||||
case 1:
|
||||
snprintf(chrs, 15, "%.2f KB", streamval);
|
||||
break;
|
||||
case 0:
|
||||
snprintf(chrs, 15, "%.2f B", streamval);
|
||||
break;
|
||||
}
|
||||
snprintf(chrs, 15, "%.2f %cB", streamval, units[level]);
|
||||
return std::string(chrs);
|
||||
}
|
||||
|
||||
@@ -1813,7 +1955,7 @@ int simpleGenerator()
|
||||
string_multimap allItems;
|
||||
std::string dummy_str;
|
||||
std::string proxy = parseProxy(proxy_subscription);
|
||||
std::map<std::string, std::string> headers;
|
||||
string_map headers;
|
||||
int ret_code = 200;
|
||||
for(std::string &x : sections)
|
||||
{
|
||||
|
||||
+56
-1
@@ -855,6 +855,13 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
|
||||
if(edge.size())
|
||||
singleproxy["ws-headers"]["Edge"] = edge;
|
||||
break;
|
||||
case "http"_hash:
|
||||
singleproxy["network"] = transproto;
|
||||
singleproxy["http-opts"]["method"] = "GET";
|
||||
singleproxy["http-opts"]["path"].push_back(path);
|
||||
singleproxy["http-opts"]["headers"]["Host"].push_back(host);
|
||||
if(edge.size())
|
||||
singleproxy["http-opts"]["headers"]["Edge"].push_back(edge);
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@@ -1591,7 +1598,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
|
||||
{
|
||||
rapidjson::Document json;
|
||||
std::string type;
|
||||
std::string remark, hostname, port, method, password;
|
||||
std::string remark, hostname, port, method, username, password;
|
||||
std::string plugin, pluginopts;
|
||||
std::string protocol, protoparam, obfs, obfsparam;
|
||||
std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret;
|
||||
@@ -1644,6 +1651,8 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
|
||||
proxyStr += "[Rr][Nn]Edge: " + edge;
|
||||
proxyStr += "\"";
|
||||
}
|
||||
if(ext.skip_cert_verify)
|
||||
proxyStr += ", certificate=0";
|
||||
|
||||
if(ext.nodelist)
|
||||
proxyStr = "vmess://" + urlsafe_base64_encode(proxyStr);
|
||||
@@ -1691,6 +1700,52 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPEEDTEST_MESSAGE_FOUNDHTTP:
|
||||
username = GetMember(json, "Username");
|
||||
host = GetMember(json, "Host");
|
||||
tlssecure = GetMember(json, "TLSSecure") == "true";
|
||||
|
||||
proxyStr = remark + " = http, upstream-proxy-address=" + hostname + ", upstream-proxy-port=" + port + ", group=" + x.group;
|
||||
if(username.size() && password.size())
|
||||
proxyStr += ", upstream-proxy-auth=true, upstream-proxy-username=" + username + ", upstream-proxy-password=" + password;
|
||||
else
|
||||
proxyStr += ", upstream-proxy-auth=false";
|
||||
|
||||
if(tlssecure)
|
||||
{
|
||||
proxyStr += ", over-tls=true";
|
||||
if(host.size())
|
||||
proxyStr += ", tls-host=" + host;
|
||||
}
|
||||
if(ext.skip_cert_verify)
|
||||
proxyStr += ", certificate=0";
|
||||
|
||||
if(ext.nodelist)
|
||||
proxyStr = "http://" + urlsafe_base64_encode(proxyStr);
|
||||
break;
|
||||
case SPEEDTEST_MESSAGE_FOUNDSOCKS:
|
||||
username = GetMember(json, "Username");
|
||||
host = GetMember(json, "Host");
|
||||
tlssecure = GetMember(json, "TLSSecure") == "true";
|
||||
|
||||
proxyStr = remark + " = socks, upstream-proxy-address=" + hostname + ", upstream-proxy-port=" + port + ", group=" + x.group;
|
||||
if(username.size() && password.size())
|
||||
proxyStr += ", upstream-proxy-auth=true, upstream-proxy-username=" + username + ", upstream-proxy-password=" + password;
|
||||
else
|
||||
proxyStr += ", upstream-proxy-auth=false";
|
||||
|
||||
if(tlssecure)
|
||||
{
|
||||
proxyStr += ", over-tls=true";
|
||||
if(host.size())
|
||||
proxyStr += ", tls-host=" + host;
|
||||
}
|
||||
if(ext.skip_cert_verify)
|
||||
proxyStr += ", certificate=0";
|
||||
|
||||
if(ext.nodelist)
|
||||
proxyStr = "socks://" + urlsafe_base64_encode(proxyStr);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <inja.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "templates.h"
|
||||
#include "logger.h"
|
||||
#include "misc.h"
|
||||
|
||||
static inline void parse_json_pointer(nlohmann::json &json, const std::string &path, const std::string &value)
|
||||
{
|
||||
std::string pointer = "/" + replace_all_distinct(path, ".", "/");
|
||||
json[nlohmann::json::json_pointer(pointer)] = value;
|
||||
}
|
||||
|
||||
int render_template(const std::string &content, const template_args &vars, std::string &output, const std::string &include_scope)
|
||||
{
|
||||
nlohmann::json data;
|
||||
for(auto &x : vars.global_vars)
|
||||
parse_json_pointer(data["global"], x.first, x.second);
|
||||
for(auto &x : vars.request_params)
|
||||
parse_json_pointer(data["request"], x.first, x.second);
|
||||
for(auto &x : vars.local_vars)
|
||||
parse_json_pointer(data["local"], x.first, x.second);
|
||||
|
||||
inja::LexerConfig m_lexer_config;
|
||||
inja::FunctionStorage m_callbacks;
|
||||
inja::TemplateStorage m_included_templates;
|
||||
inja::ParserConfig m_parser_config;
|
||||
|
||||
m_lexer_config.trim_blocks = true;
|
||||
m_lexer_config.lstrip_blocks = true;
|
||||
m_callbacks.add_callback("UrlDecode", 1, [](inja::Arguments &args)
|
||||
{
|
||||
std::string data = args.at(0)->get<std::string>();
|
||||
return UrlDecode(data);
|
||||
});
|
||||
m_callbacks.add_callback("trim_of", 2, [](inja::Arguments &args)
|
||||
{
|
||||
std::string data = args.at(0)->get<std::string>(), target = args.at(1)->get<std::string>();
|
||||
if(target.empty())
|
||||
return data;
|
||||
return trim_of(data, target[0]);
|
||||
});
|
||||
m_callbacks.add_callback("trim", 1, [](inja::Arguments &args)
|
||||
{
|
||||
std::string data = args.at(0)->get<std::string>();
|
||||
return trim(data);
|
||||
});
|
||||
|
||||
inja::Parser parser(m_parser_config, m_lexer_config, m_included_templates);
|
||||
parser.include_scope_limit = true;
|
||||
parser.include_scope = include_scope;
|
||||
inja::Renderer renderer(m_included_templates, m_callbacks);
|
||||
|
||||
try
|
||||
{
|
||||
std::stringstream out;
|
||||
renderer.render_to(out, parser.parse(content), data);
|
||||
output = out.str();
|
||||
return 0;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
output = "Template render failed! Reason: " + std::string(e.what());
|
||||
writeLog(0, output, LOG_LEVEL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef TEMPLATES_H_INCLUDED
|
||||
#define TEMPLATES_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
typedef std::map<std::string, std::string> string_map;
|
||||
|
||||
struct template_args
|
||||
{
|
||||
string_map global_vars;
|
||||
string_map request_params;
|
||||
string_map local_vars;
|
||||
};
|
||||
|
||||
int render_template(const std::string &content, const template_args &vars, std::string &output, const std::string &include_scope = "template");
|
||||
|
||||
#endif // TEMPLATES_H_INCLUDED
|
||||
Reference in new issue
Block a user