Enhancements

Add exprtimental support for generating Mellow configuration.
Add proxy customization for downloading rulesets and subscriptions.
Add more customizations in manage URL arguments.
Optimize codes.
INIReader: Fix line break remove not working.
This commit is contained in:
Tindy X
2019-11-21 01:20:22 +08:00
parent a68363e108
commit 6d646c650e
9 changed files with 410 additions and 50 deletions

View File

@@ -146,7 +146,7 @@ public:
continue;
if(strLine[lineSize - 1] == '\r') //remove line break
{
strLine.replace(lineSize - 1, 0, "");
strLine = strLine.substr(0, lineSize - 1);
lineSize--;
}
if(strLine.find("=") != strLine.npos) //is an item
@@ -354,7 +354,7 @@ public:
/**
* @brief Retrieve all items in the given section.
*/
int GetItems(std::string section, std::multimap<std::string, std::string> &data)
int GetItems(std::string section, string_multimap &data)
{
if(!parsed || !SectionExist(section))
return -1;

View File

@@ -1,8 +1,13 @@
#include <string>
#include <iostream>
#include "logger.h"
extern bool print_debug_info;
void writeLog(int type, std::string content)
{
//placeholder
if(print_debug_info)
std::cerr<<"[DEBUG] "<<content<<"\n";
}

100
main.cpp
View File

@@ -21,6 +21,7 @@ std::vector<ruleset_content> ruleset_content_array;
std::string listen_address = "127.0.0.1", default_url, managed_config_prefix;
int listen_port = 25500, max_pending_connections = 10, max_concurrent_threads = 4;
bool api_mode = true, write_managed_config = false, update_ruleset_on_request = false, overwrite_original_rules = true;
bool print_debug_info = false;
extern std::string custom_group;
//safety lock for multi-thread
@@ -29,14 +30,12 @@ std::mutex on_configuring;
//preferences
string_array renames, emojis;
bool add_emoji = false, remove_old_emoji = false;
bool add_emoji = false, remove_old_emoji = false, append_proxy_type = true;
std::string proxy_ruleset, proxy_subscription;
//clash custom
std::string clash_rule_base;
string_array clash_extra_group;
//surge custom
std::string surge_rule_base, surfboard_rule_base;
std::string surge_rule_base, surfboard_rule_base, mellow_rule_base;
void setcd(char *argv[])
{
@@ -65,8 +64,17 @@ std::string refreshRulesets()
guarded_mutex guard(on_configuring);
eraseElements(ruleset_content_array);
string_array vArray;
std::string rule_group, rule_url, proxy = getSystemProxy();
std::string rule_group, rule_url;
ruleset_content rc;
std::string proxy;
if(proxy_ruleset == "SYSTEM")
proxy = getSystemProxy();
else if(proxy_ruleset == "NONE")
proxy = "";
else
proxy = proxy_ruleset;
for(std::string &x : rulesets)
{
/*
@@ -137,6 +145,14 @@ void readConf()
surge_rule_base = ini.Get("surge_rule_base");
if(ini.ItemExist("surfboard_rule_base"))
surfboard_rule_base = ini.Get("surfboard_rule_base");
if(ini.ItemExist("mellow_rule_base"))
mellow_rule_base = ini.Get("mellow_rule_base");
if(ini.ItemExist("append_proxy_type"))
append_proxy_type = ini.GetBool("append_proxy_type");
if(ini.ItemExist("proxy_ruleset"))
proxy_ruleset = ini.Get("proxy_ruleset");
if(ini.ItemExist("proxy_subscription"))
proxy_subscription = ini.Get("proxy_subscription");
if(ini.ItemPrefixExist("rename_node"))
ini.GetAll("rename_node", renames);
@@ -181,6 +197,8 @@ void readConf()
listen_port = ini.GetInt("port");
ini.EnterSection("advanced");
if(ini.ItemExist("print_debug_info"))
print_debug_info = ini.GetBool("print_debug_info");
if(ini.ItemExist("max_pending_connections"))
max_pending_connections = ini.GetInt("max_pending_connections");
if(ini.ItemExist("max_concurrent_threads"))
@@ -192,9 +210,34 @@ void readConf()
std::string subconverter(RESPONSE_CALLBACK_ARGS)
{
std::string target = getUrlArg(argument, "target"), url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex"));
std::string target = getUrlArg(argument, "target"), url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex")), emoji = getUrlArg(argument, "emoji");
std::string group = UrlDecode(getUrlArg(argument, "group")), upload = getUrlArg(argument, "upload"), upload_path = getUrlArg(argument, "upload_path"), version = getUrlArg(argument, "ver");
std::string append_type = getUrlArg(argument, "append_type");
std::string base_content, output_content;
extra_settings ext;
if(emoji == "true")
{
ext.add_emoji = ext.remove_emoji = true;
}
else
{
ext.add_emoji = add_emoji;
ext.remove_emoji = remove_old_emoji;
}
if(append_type.size())
ext.append_proxy_type = append_type == "true";
else
ext.append_proxy_type = append_proxy_type;
std::string proxy;
if(proxy_subscription == "SYSTEM")
proxy = getSystemProxy();
else if(proxy_subscription == "NONE")
proxy = "";
else
proxy = proxy_subscription;
if(!url.size())
url = default_url;
if(!url.size() || !target.size())
@@ -207,15 +250,15 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
int groupID = 0;
if(include.size())
{
eraseElements(def_include_remarks);
def_include_remarks.emplace_back(include);
eraseElements(ext.include_remarks);
ext.include_remarks.emplace_back(include);
}
if(group.size())
custom_group = group;
for(std::string &x : urls)
{
std::cerr<<"Fetching node data from url '"<<x<<"'."<<std::endl;
addNodes(x, nodes, groupID);
addNodes(x, nodes, groupID, proxy);
groupID++;
}
if(!nodes.size())
@@ -232,7 +275,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
if(update_ruleset_on_request)
refreshRulesets();
output_content = netchToClash(nodes, base_content, ruleset_content_array, clash_extra_group, target == "clashr");
output_content = netchToClash(nodes, base_content, ruleset_content_array, clash_extra_group, target == "clashr", ext);
if(upload == "true")
uploadGist("clash", upload_path, output_content, false);
return output_content;
@@ -246,7 +289,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
base_content = webGet(surge_rule_base, getSystemProxy());
output_content = netchToSurge(nodes, base_content, ruleset_content_array, clash_extra_group, surge_ver);
output_content = netchToSurge(nodes, base_content, ruleset_content_array, clash_extra_group, surge_ver, ext);
if(upload == "true")
uploadGist("surge" + version, upload_path, output_content, true);
@@ -262,7 +305,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
base_content = webGet(surfboard_rule_base, getSystemProxy());
output_content = netchToSurge(nodes, base_content, ruleset_content_array, clash_extra_group, 2);
output_content = netchToSurge(nodes, base_content, ruleset_content_array, clash_extra_group, 2, ext);
if(upload == "true")
uploadGist("surfboard", upload_path, output_content, true);
@@ -270,10 +313,24 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
output_content = "#!MANAGED-CONFIG " + managed_config_prefix + "/sub?" + argument + "\n\n" + output_content;
return output_content;
}
else if(target == "mellow")
{
std::cerr<<"Mellow"<<std::endl;
if(fileExist(mellow_rule_base))
base_content = fileGet(mellow_rule_base, false);
else
base_content = webGet(mellow_rule_base, getSystemProxy());
output_content = netchToMellow(nodes, base_content, ruleset_content_array, clash_extra_group, ext);
if(upload == "true")
uploadGist("mellow", upload_path, output_content, true);
return output_content;
}
else if(target == "ss")
{
std::cerr<<"SS"<<std::endl;
output_content = netchToSS(nodes);
output_content = netchToSS(nodes, ext);
if(upload == "true")
uploadGist("ss", upload_path, output_content, false);
return output_content;
@@ -281,7 +338,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else if(target == "ssr")
{
std::cerr<<"SSR"<<std::endl;
output_content = netchToSSR(nodes);
output_content = netchToSSR(nodes, ext);
if(upload == "true")
uploadGist("ssr", upload_path, output_content, false);
return output_content;
@@ -289,7 +346,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else if(target == "v2ray")
{
std::cerr<<"v2rayN"<<std::endl;
output_content = netchToVMess(nodes);
output_content = netchToVMess(nodes, ext);
if(upload == "true")
uploadGist("v2ray", upload_path, output_content, false);
return output_content;
@@ -297,7 +354,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else if(target == "quan")
{
std::cerr<<"Quantumult"<<std::endl;
output_content = netchToQuan(nodes);
output_content = netchToQuan(nodes, ext);
if(upload == "true")
uploadGist("quan", upload_path, output_content, false);
return output_content;
@@ -305,7 +362,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else if(target == "quanx")
{
std::cerr<<"Quantumult X"<<std::endl;
output_content = netchToQuanX(nodes);
output_content = netchToQuanX(nodes, ext);
if(upload == "true")
uploadGist("quanx", upload_path, output_content, false);
return output_content;
@@ -313,7 +370,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else if(target == "ssd")
{
std::cerr<<"SSD"<<std::endl;
output_content = netchToSSD(nodes, group);
output_content = netchToSSD(nodes, group, ext);
if(upload == "true")
uploadGist("ssd", upload_path, output_content, false);
return output_content;
@@ -377,6 +434,11 @@ int main(int argc, char *argv[])
return subconverter(argument + "&target=surfboard", postdata);
});
append_response("GET", "/mellow", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string
{
return subconverter(argument + "&target=mellow", postdata);
});
append_response("GET", "/ss", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
{
return subconverter(argument + "&target=ss", postdata);

27
mellow.conf Normal file
View File

@@ -0,0 +1,27 @@
[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

View File

@@ -21,7 +21,7 @@ void copyNodes(std::vector<nodeInfo> *source, std::vector<nodeInfo> *dest)
}
}
void addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID)
void addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy)
{
int linkType = -1;
std::vector<nodeInfo> nodes;
@@ -51,7 +51,8 @@ void addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID)
writeLog(LOG_TYPE_INFO, "Downloading subscription data...");
if(strFind(link, "surge:///install-config")) //surge config link
link = UrlDecode(getUrlArg(link, "url"));
strSub = webGet(link);
strSub = webGet(link, proxy);
/*
if(strSub.size() == 0)
{
//try to get it again with system proxy
@@ -64,6 +65,7 @@ void addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID)
else
writeLog(LOG_TYPE_WARN, "No system proxy is set. Skipping.");
}
*/
if(strSub.size())
{
writeLog(LOG_TYPE_INFO, "Parsing subscription data...");

View File

@@ -6,6 +6,6 @@
#include "nodeinfo.h"
void addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID);
void addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy = "");
#endif // NODEMANIP_H_INCLUDED

View File

@@ -21,6 +21,17 @@ surge_rule_base=surge.conf
;Surfboard config base used by the generator, supports local files/URL
surfboard_rule_base=surfboard.conf
;Mellow config base used by the generator, supports local files/URL
mellow_rule_base=mellow.conf
;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_ruleset=SYSTEM
proxy_subscription=NONE
;Append a proxy type string ([SS] [SSR] [VMess]) to node remark.
append_proxy_type=false
;Rename remarks with the following patterns. Supports regular expression.
;Format: Search_Pattern@Replace_Pattern
;rename_node=IPLC@专线
@@ -217,5 +228,6 @@ listen=0.0.0.0
port=25500
[advanced]
print_debug_info=false
max_pending_connections=10240
max_concurrent_threads=4

View File

@@ -332,7 +332,7 @@ void rulesetToSurge(INIReader &base_rule, std::vector<ruleset_content> &ruleset_
}
}
std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, bool clashR)
std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, bool clashR, extra_settings &ext)
{
YAML::Node yamlnode, proxies, singleproxy, singlegroup, original_groups;
rapidjson::Document json;
@@ -359,7 +359,16 @@ std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, s
singleproxy.reset();
json.Parse(x.proxyStr.data());
type = GetMember(json, "Type");
remark = x.remarks = addEmoji("[" + type + "]" + trim(removeEmoji(nodeRename(x.remarks))));
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks;
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
remark = x.remarks = x.remarks + "$";
hostname = GetMember(json, "Hostname");
@@ -530,7 +539,7 @@ std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, s
return to_string(yamlnode);
}
std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, int surge_ver)
std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, int surge_ver, extra_settings &ext)
{
rapidjson::Document json;
INIReader ini;
@@ -554,7 +563,16 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
{
json.Parse(x.proxyStr.data());
type = GetMember(json, "Type");
remark = x.remarks = addEmoji("[" + type + "]" + trim(removeEmoji(nodeRename(x.remarks))));
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks;
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
remark = x.remarks = x.remarks + "$";
hostname = GetMember(json, "Hostname");
@@ -681,8 +699,8 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
filtered_nodelist.emplace_back("DIRECT");
proxy = vArray[1];
for(std::string &x : filtered_nodelist)
proxy += "," + x;
for(std::string &y : filtered_nodelist)
proxy += "," + y;
if(vArray[1] == "url-test" || vArray[1] == "fallback" || vArray[1] == "load-balance")
proxy += ",url=" + url;
@@ -694,17 +712,25 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
return ini.ToString();
}
std::string netchToSS(std::vector<nodeInfo> &nodes)
std::string netchToSS(std::vector<nodeInfo> &nodes, extra_settings &ext)
{
rapidjson::Document json;
std::string remark, hostname, port, password, method;
std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam;
std::string proxyStr, allLinks;
for(nodeInfo &x : nodes)
{
json.Parse(x.proxyStr.data());
remark = x.remarks = addEmoji(trim(removeEmoji(nodeRename(x.remarks))));
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
password = GetMember(json, "Password");
@@ -739,7 +765,7 @@ std::string netchToSS(std::vector<nodeInfo> &nodes)
return base64_encode(allLinks);
}
std::string netchToSSR(std::vector<nodeInfo> &nodes)
std::string netchToSSR(std::vector<nodeInfo> &nodes, extra_settings &ext)
{
rapidjson::Document json;
std::string remark, hostname, port, password, method;
@@ -748,7 +774,14 @@ std::string netchToSSR(std::vector<nodeInfo> &nodes)
for(nodeInfo &x : nodes)
{
json.Parse(x.proxyStr.data());
remark = x.remarks = addEmoji(trim(removeEmoji(nodeRename(x.remarks))));
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
password = GetMember(json, "Password");
@@ -779,7 +812,7 @@ std::string netchToSSR(std::vector<nodeInfo> &nodes)
return base64_encode(allLinks);
}
std::string netchToVMess(std::vector<nodeInfo> &nodes)
std::string netchToVMess(std::vector<nodeInfo> &nodes, extra_settings &ext)
{
rapidjson::Document json;
std::string remark, hostname, port, method;
@@ -789,7 +822,14 @@ std::string netchToVMess(std::vector<nodeInfo> &nodes)
for(nodeInfo &x : nodes)
{
json.Parse(x.proxyStr.data());
remark = x.remarks = addEmoji(trim(removeEmoji(nodeRename(x.remarks))));
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
method = GetMember(json, "EncryptMethod");
@@ -815,9 +855,10 @@ std::string netchToVMess(std::vector<nodeInfo> &nodes)
return base64_encode(allLinks);
}
std::string netchToQuan(std::vector<nodeInfo> &nodes)
std::string netchToQuan(std::vector<nodeInfo> &nodes, extra_settings &ext)
{
rapidjson::Document json;
std::string type;
std::string remark, hostname, port, method, password;
std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam;
@@ -827,7 +868,17 @@ std::string netchToQuan(std::vector<nodeInfo> &nodes)
for(nodeInfo &x : nodes)
{
json.Parse(x.proxyStr.data());
remark = x.remarks = addEmoji(trim(removeEmoji(nodeRename(x.remarks))));
type = GetMember(json, "Type");
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks;
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
method = GetMember(json, "EncryptMethod");
@@ -882,9 +933,10 @@ std::string netchToQuan(std::vector<nodeInfo> &nodes)
return allLinks;
}
std::string netchToQuanX(std::vector<nodeInfo> &nodes)
std::string netchToQuanX(std::vector<nodeInfo> &nodes, extra_settings &ext)
{
rapidjson::Document json;
std::string type;
std::string remark, hostname, port, method;
std::string password, plugin, pluginopts;
std::string id, aid, transproto, host, path;
@@ -893,7 +945,17 @@ std::string netchToQuanX(std::vector<nodeInfo> &nodes)
for(nodeInfo &x : nodes)
{
json.Parse(x.proxyStr.data());
remark = x.remarks = addEmoji(trim(removeEmoji(nodeRename(x.remarks))));
type = GetMember(json, "Type");
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks;
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
method = GetMember(json, "EncryptMethod");
@@ -942,7 +1004,7 @@ std::string netchToQuanX(std::vector<nodeInfo> &nodes)
return allLinks;
}
std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group)
std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, extra_settings &ext)
{
rapidjson::Document json;
rapidjson::StringBuffer sb;
@@ -970,7 +1032,14 @@ std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group)
for(nodeInfo &x : nodes)
{
json.Parse(x.proxyStr.data());
remark = x.remarks = addEmoji(trim(removeEmoji(nodeRename(x.remarks))));
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = (unsigned short)stoi(GetMember(json, "Port"));
password = GetMember(json, "Password");
@@ -1036,6 +1105,179 @@ std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group)
return "ssd://" + base64_encode(sb.GetString());
}
std::string netchToMellow(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext)
{
rapidjson::Document json;
INIReader ini;
std::string proxy;
std::string type, remark, hostname, port, username, password, method;
std::string plugin, pluginopts;
std::string id, aid, transproto, faketype, host, path, quicsecure, quicsecret, tlssecure;
std::string url, group;
std::vector<nodeInfo> nodelist;
string_array vArray, remarks_list, filtered_nodelist;
ini.store_any_line = true;
if(ini.Parse(base_conf) != 0)
return std::string();
ini.SetCurrentSection("Endpoint");
for(nodeInfo &x : nodes)
{
json.Parse(x.proxyStr.data());
type = GetMember(json, "Type");
x.remarks = nodeRename(x.remarks);
if(ext.remove_emoji)
x.remarks = trim(removeEmoji(x.remarks));
if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks;
if(ext.add_emoji)
x.remarks = addEmoji(x.remarks);
remark = x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
remark = x.remarks = x.remarks + "$";
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
username = GetMember(json, "Username");
password = GetMember(json, "Password");
method = GetMember(json, "EncryptMethod");
if(x.linkType == SPEEDTEST_MESSAGE_FOUNDSS && GetMember(json, "Plugin") == "")
{
proxy = remark + ", ss, ss://" + urlsafe_base64_encode(method + ":" + password) + "@" + hostname + ":" + port;
}
else if(x.linkType == SPEEDTEST_MESSAGE_FOUNDVMESS)
{
id = GetMember(json, "UserID");
aid = GetMember(json, "AlterID");
transproto = GetMember(json, "TransferProtocol");
host = GetMember(json, "Host");
path = GetMember(json, "Path");
faketype = GetMember(json, "FakeType");
tlssecure = GetMember(json, "TLSSecure");
proxy = remark + ", vmess1, vmess1://" + id + "@" + hostname + ":" + port;
if(path.size())
proxy += path;
proxy += "?network=" + transproto;
if(transproto == "ws")
{
proxy += "&ws.host=" + UrlEncode(host);
}
proxy += "&tls=" + tlssecure;
}
else if(x.linkType == SPEEDTEST_MESSAGE_FOUNDSOCKS)
{
proxy = remark + ", builtin, socks, address=" + hostname + ", port=" + port + ", user=" + username + ", pass=" + password;
}
else if(type == "HTTP")
{
proxy = remark + ", builtin, http, address=" + hostname + ", port=" + port + ", user=" + username + ", pass=" + password;
}
else
continue;
ini.Set("{NONAME}", proxy);
remarks_list.emplace_back(remark);
nodelist.emplace_back(x);
}
ini.SetCurrentSection("EndpointGroup");
for(std::string &x : extra_proxy_group)
{
eraseElements(filtered_nodelist);
unsigned int rules_upper_bound = 0;
url = "";
proxy = "";
vArray = split(x, "`");
if(vArray.size() < 3)
continue;
if(vArray[1] == "select")
{
rules_upper_bound = vArray.size();
}
else if(vArray[1] == "url-test" || vArray[1] == "fallback" || vArray[1] == "load-balance")
{
if(vArray.size() < 5)
continue;
rules_upper_bound = vArray.size() - 2;
url = vArray[vArray.size() - 2];
}
else
continue;
for(unsigned int i = 2; i < rules_upper_bound; i++)
{
if(vArray[i].find("[]") == 0)
{
filtered_nodelist.emplace_back(vArray[i].substr(2));
}
else if(vArray[i].find("!!GROUP=") == 0)
{
group = vArray[i].substr(8);
for(nodeInfo &y : nodelist)
{
if(regFind(y.group, group) && std::find(filtered_nodelist.begin(), filtered_nodelist.end(), y.remarks) == filtered_nodelist.end())
filtered_nodelist.emplace_back(y.remarks);
}
}
else if(vArray[i].find("!!GROUPID=") == 0)
{
group = vArray[i].substr(10);
for(nodeInfo &y : nodelist)
{
if(y.groupID == stoi(group) && std::find(filtered_nodelist.begin(), filtered_nodelist.end(), y.remarks) == filtered_nodelist.end())
filtered_nodelist.emplace_back(y.remarks);
}
}
else
{
for(nodeInfo &y : nodelist)
{
if(regFind(y.remarks, vArray[i]) && std::find(filtered_nodelist.begin(), filtered_nodelist.end(), y.remarks) == filtered_nodelist.end())
filtered_nodelist.emplace_back(y.remarks);
}
}
}
if(!filtered_nodelist.size())
filtered_nodelist.emplace_back("DIRECT");
//don't process these for now
/*
proxy = vArray[1];
for(std::string &x : filtered_nodelist)
proxy += "," + x;
if(vArray[1] == "url-test" || vArray[1] == "fallback" || vArray[1] == "load-balance")
proxy += ",url=" + url;
*/
proxy = vArray[0] + ", ";
for(std::string &y : filtered_nodelist)
proxy += "\"" + y + "\":";
proxy = proxy.substr(0, proxy.size() - 1);
proxy += ", latency, interval=300, timeout=6"; //use hard-coded values for now
ini.Set("{NONAME}", proxy); //insert order
}
rulesetToSurge(ini, ruleset_content_array, 2);
string_multimap rules;
ini.GetItems("Rules", rules);
ini.EraseSection("Rules");
ini.SetCurrentSection("RoutingRule");
for(auto &x : rules)
ini.Set("{NONAME}", x.second);
return ini.ToString();
}
std::string buildGistData(std::string name, std::string content)
{
rapidjson::StringBuffer sb;
@@ -1121,6 +1363,7 @@ int uploadGist(std::string name, std::string path, std::string content, bool wri
GetMember(json, "id", id);
if(json.HasMember("owner"))
GetMember(json["owner"], "login", username);
url = "https://gist.githubusercontent.com/" + username + "/" + id + "/raw/" + path;
std::cerr<<"Writing to Gist success!\nGenerator: "<<name<<"\nPath: "<<path<<"\nRaw URL: "<<url<<"\nGist owner: "<<username<<"\n";
ini.EraseSection();

View File

@@ -10,15 +10,24 @@ struct ruleset_content
std::string rule_content;
};
struct extra_settings
{
bool add_emoji = false;
bool remove_emoji = false;
bool append_proxy_type = true;
string_array include_remarks;
};
std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, bool clashR);
std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, int surge_ver);
std::string netchToSS(std::vector<nodeInfo> &nodes);
std::string netchToSSR(std::vector<nodeInfo> &nodes);
std::string netchToVMess(std::vector<nodeInfo> &nodes);
std::string netchToQuanX(std::vector<nodeInfo> &nodes);
std::string netchToQuan(std::vector<nodeInfo> &nodes);
std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group);
std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, bool clashR, extra_settings &ext);
std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, int surge_ver, extra_settings &ext);
std::string netchToMellow(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext);
std::string netchToSS(std::vector<nodeInfo> &nodes, extra_settings &ext);
std::string netchToSSR(std::vector<nodeInfo> &nodes, extra_settings &ext);
std::string netchToVMess(std::vector<nodeInfo> &nodes, extra_settings &ext);
std::string netchToQuanX(std::vector<nodeInfo> &nodes, extra_settings &ext);
std::string netchToQuan(std::vector<nodeInfo> &nodes, extra_settings &ext);
std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, extra_settings &ext);
std::string buildGistData(std::string name, std::string content);
int uploadGist(std::string name, std::string path, std::string content, bool writeManageURL);