mirror of
https://github.com/asdlokj1qpi233/subconverter.git
synced 2026-11-01 17:25:02 +00:00
Bug fixes
Fix compatibility issue for some ShadowsocksD subscription. Fix some cross-platform configuration file reader bugs. Add upload to Gist function. Add append MANAGED-CONFIG to Surge configuration function. Clean up codes.
This commit is contained in:
11 files changed
+351
-274
No files matched your search
@@ -0,0 +1,3 @@
|
||||
[common]
|
||||
;uncomment the following line and enter your token to enable upload function
|
||||
;token = your_personal_token_here
|
||||
+1
-1
@@ -129,7 +129,7 @@ public:
|
||||
string_multimap itemGroup, existItemGroup;
|
||||
std::stringstream strStrm;
|
||||
unsigned int lineSize = 0;
|
||||
char delimiter = count(content.begin(), content.end(), '\n') <= 1 ? '\r' : '\n';
|
||||
char delimiter = count(content.begin(), content.end(), '\n') < 1 ? '\r' : '\n';
|
||||
|
||||
EraseAll(); //first erase all data
|
||||
if(do_utf8_to_gbk && is_str_utf8(content))
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
//common settings
|
||||
string_array def_exclude_remarks, def_include_remarks, rulesets;
|
||||
std::vector<ruleset_content> ruleset_content_array;
|
||||
std::string listen_address = "127.0.0.1", default_url;
|
||||
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, update_ruleset_on_request = false, overwrite_original_rules = true;
|
||||
bool api_mode = true, write_managed_config = true, update_ruleset_on_request = false, overwrite_original_rules = true;
|
||||
extern std::string custom_group;
|
||||
|
||||
//safety lock for multi-thread
|
||||
@@ -40,24 +40,24 @@ std::string surge_rule_base;
|
||||
|
||||
void setcd(char *argv[])
|
||||
{
|
||||
#ifndef _WIN32
|
||||
std::string path, prgpath;
|
||||
char szTmp[1024];
|
||||
prgpath.assign(argv[0]);
|
||||
if(prgpath[0] == '/')
|
||||
{
|
||||
path = prgpath.substr(0, prgpath.rfind("/") + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
getcwd(szTmp, 1023);
|
||||
path.append(szTmp);
|
||||
path.append("/");
|
||||
path.append(argv[0]);
|
||||
path = path.substr(0, path.rfind("/") + 1);
|
||||
}
|
||||
#ifndef _WIN32
|
||||
std::string path, prgpath;
|
||||
char szTmp[1024];
|
||||
prgpath.assign(argv[0]);
|
||||
if(prgpath[0] == '/')
|
||||
{
|
||||
path = prgpath.substr(0, prgpath.rfind("/") + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
getcwd(szTmp, 1023);
|
||||
path.append(szTmp);
|
||||
path.append("/");
|
||||
path.append(argv[0]);
|
||||
path = path.substr(0, path.rfind("/") + 1);
|
||||
}
|
||||
chdir(path.data());
|
||||
#endif // _WIN32
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
std::string refreshRulesets()
|
||||
@@ -101,6 +101,8 @@ std::string refreshRulesets()
|
||||
}
|
||||
if(rc.rule_content.size())
|
||||
ruleset_content_array.emplace_back(rc);
|
||||
else
|
||||
std::cerr<<"Warning: No data was fetched from this link. Skipping..."<<std::endl;
|
||||
}
|
||||
|
||||
return "done";
|
||||
@@ -136,6 +138,12 @@ void readConf()
|
||||
if(ini.ItemPrefixExist("rename_node"))
|
||||
ini.GetAll("rename_node", renames);
|
||||
|
||||
ini.EnterSection("managed_config");
|
||||
if(ini.ItemExist("write_managed_config"))
|
||||
write_managed_config = ini.GetBool("write_managed_config");
|
||||
if(ini.ItemExist("managed_config_prefix"))
|
||||
managed_config_prefix = ini.Get("managed_config_prefix");
|
||||
|
||||
ini.EnterSection("emojis");
|
||||
if(ini.ItemExist("add_emoji"))
|
||||
add_emoji = ini.GetBool("add_emoji");
|
||||
@@ -180,6 +188,122 @@ void readConf()
|
||||
std::cerr<<"Read preference settings completed."<<std::endl;
|
||||
}
|
||||
|
||||
std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string target = getUrlArg(argument, "target"), url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex"));
|
||||
std::string group = UrlDecode(getUrlArg(argument, "group")), upload = getUrlArg(argument, "upload"), version = getUrlArg(argument, "ver");
|
||||
std::string base_content, output_content;
|
||||
if(!url.size())
|
||||
url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_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);
|
||||
groupID++;
|
||||
}
|
||||
if(!target.size())
|
||||
return std::string();
|
||||
|
||||
std::cerr<<"Generate target: ";
|
||||
if(target == "clash" || target == "clashr")
|
||||
{
|
||||
std::cerr<<"Clash"<<((target == "clashr") ? "R" : "")<<std::endl;
|
||||
if(fileExist(clash_rule_base))
|
||||
base_content = fileGet(clash_rule_base, false);
|
||||
else
|
||||
base_content = webGet(clash_rule_base, getSystemProxy());
|
||||
|
||||
if(update_ruleset_on_request)
|
||||
refreshRulesets();
|
||||
output_content = netchToClash(nodes, base_content, ruleset_content_array, clash_extra_group, target == "clashr");
|
||||
if(upload == "true")
|
||||
uploadGist("clash", output_content, false);
|
||||
return output_content;
|
||||
}
|
||||
else if(target == "surge")
|
||||
{
|
||||
std::cerr<<"Surge "<<version<<std::endl;
|
||||
int surge_ver = version.size() ? stoi(version) : 3;
|
||||
if(fileExist(surge_rule_base))
|
||||
base_content = fileGet(surge_rule_base, false);
|
||||
else
|
||||
base_content = webGet(surge_rule_base, getSystemProxy());
|
||||
|
||||
output_content = netchToSurge(nodes, base_content, rulesets, clash_extra_group, surge_ver);
|
||||
if(upload == "true")
|
||||
uploadGist("surge" + version, output_content, true);
|
||||
|
||||
if(write_managed_config && managed_config_prefix.size())
|
||||
output_content = "#!MANAGED-CONFIG " + managed_config_prefix + "/sub?" + argument + "\n\n" + output_content;
|
||||
return output_content;
|
||||
}
|
||||
else if(target == "ss")
|
||||
{
|
||||
std::cerr<<"SS"<<std::endl;
|
||||
output_content = netchToSS(nodes);
|
||||
if(upload == "true")
|
||||
uploadGist("ss", output_content, false);
|
||||
return output_content;
|
||||
}
|
||||
else if(target == "ssr")
|
||||
{
|
||||
std::cerr<<"SSR"<<std::endl;
|
||||
output_content = netchToSSR(nodes);
|
||||
if(upload == "true")
|
||||
uploadGist("ssr", output_content, false);
|
||||
return output_content;
|
||||
}
|
||||
else if(target == "v2ray")
|
||||
{
|
||||
std::cerr<<"v2rayN"<<std::endl;
|
||||
output_content = netchToVMess(nodes);
|
||||
if(upload == "true")
|
||||
uploadGist("v2ray", output_content, false);
|
||||
return output_content;
|
||||
}
|
||||
else if(target == "quan")
|
||||
{
|
||||
std::cerr<<"Quantumult"<<std::endl;
|
||||
output_content = netchToQuan(nodes);
|
||||
if(upload == "true")
|
||||
uploadGist("quan", output_content, false);
|
||||
return output_content;
|
||||
}
|
||||
else if(target == "quanx")
|
||||
{
|
||||
std::cerr<<"Quantumult X"<<std::endl;
|
||||
output_content = netchToQuanX(nodes);
|
||||
if(upload == "true")
|
||||
uploadGist("quanx", output_content, false);
|
||||
return output_content;
|
||||
}
|
||||
else if(target == "ssd")
|
||||
{
|
||||
std::cerr<<"SSD"<<std::endl;
|
||||
output_content = netchToSSD(nodes, group);
|
||||
if(upload == "true")
|
||||
uploadGist("ssd", output_content, false);
|
||||
return output_content;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr<<"Unspecified"<<std::endl;
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -208,243 +332,51 @@ int main(int argc, char *argv[])
|
||||
return "done";
|
||||
});
|
||||
|
||||
append_response("GET", "/sub", "text/plain;charset=utf-8", subconverter);
|
||||
|
||||
append_response("GET", "/clash", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string clash_base_content;
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex")), group = UrlDecode(getUrlArg(argument, "group"));
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
if(group.size()) custom_group = group;
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: Clash"<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
if(fileExist(clash_rule_base))
|
||||
clash_base_content = fileGet(clash_rule_base, false);
|
||||
else
|
||||
clash_base_content = webGet(clash_rule_base, getSystemProxy());
|
||||
|
||||
if(update_ruleset_on_request)
|
||||
refreshRulesets();
|
||||
return netchToClash(nodes, clash_base_content, ruleset_content_array, clash_extra_group, false);
|
||||
return subconverter(argument + "&target=clash", postdata);
|
||||
});
|
||||
|
||||
append_response("GET", "/clashr", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string clash_base_content;
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex")), group = UrlDecode(getUrlArg(argument, "group"));
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
if(group.size()) custom_group = group;
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: ClashR"<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
if(fileExist(clash_rule_base))
|
||||
clash_base_content = fileGet(clash_rule_base, false);
|
||||
else
|
||||
clash_base_content = webGet(clash_rule_base, getSystemProxy());
|
||||
|
||||
if(update_ruleset_on_request)
|
||||
refreshRulesets();
|
||||
return netchToClash(nodes, clash_base_content, ruleset_content_array, clash_extra_group, true);
|
||||
return subconverter(argument + "&target=clashr", postdata);
|
||||
});
|
||||
|
||||
append_response("GET", "/surge", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string surge_base_content;
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex")), group = UrlDecode(getUrlArg(argument, "group")), version = getUrlArg(argument, "ver");
|
||||
int surge_ver = version.size() ? stoi(version) : 3;
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
if(group.size()) custom_group = group;
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: Surge "<<surge_ver<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
if(fileExist(surge_rule_base))
|
||||
surge_base_content = fileGet(surge_rule_base, false);
|
||||
else
|
||||
surge_base_content = webGet(surge_rule_base, getSystemProxy());
|
||||
|
||||
return netchToSurge(nodes, surge_base_content, rulesets, clash_extra_group, surge_ver);
|
||||
return subconverter(argument + "&target=surge", postdata);
|
||||
});
|
||||
|
||||
append_response("GET", "/ss", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex"));
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: SIP002"<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
|
||||
return netchToSS(nodes);
|
||||
return subconverter(argument + "&target=ss", postdata);
|
||||
});
|
||||
|
||||
append_response("GET", "/ssr", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex"));
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: SSR"<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
|
||||
return netchToSSR(nodes);
|
||||
return subconverter(argument + "&target=ssr", postdata);
|
||||
});
|
||||
|
||||
append_response("GET", "/v2rayn", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
append_response("GET", "/v2ray", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex"));
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: VMess"<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
|
||||
return netchToVMess(nodes);
|
||||
return subconverter(argument + "&target=v2ray", postdata);
|
||||
});
|
||||
|
||||
append_response("GET", "/v2rayq", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
append_response("GET", "/quan", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex"));
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: VMess"<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
|
||||
return netchToQuan(nodes);
|
||||
return subconverter(argument + "&target=quan", postdata);
|
||||
});
|
||||
|
||||
append_response("GET", "/quanx", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex"));
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: Quantumult X"<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
|
||||
return netchToQuanX(nodes);
|
||||
return subconverter(argument + "&target=quanx", postdata);
|
||||
});
|
||||
|
||||
append_response("GET", "/ssd", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
if(!api_mode)
|
||||
readConf();
|
||||
std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex")), group = UrlDecode(getUrlArg(argument, "group"));
|
||||
if(!url.size()) url = default_url;
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
if(include.size())
|
||||
{
|
||||
eraseElements(def_include_remarks);
|
||||
def_include_remarks.emplace_back(include);
|
||||
}
|
||||
for(std::string &x : urls)
|
||||
{
|
||||
std::cerr<<"Fetching node data from url '"<<x<<"'. Generate target: SSD"<<std::endl;
|
||||
addNodes(x, nodes, groupID);
|
||||
groupID++;
|
||||
}
|
||||
|
||||
return netchToSSD(nodes, group);
|
||||
return subconverter(argument + "&target=ssd", postdata);
|
||||
});
|
||||
|
||||
if(!api_mode)
|
||||
|
||||
@@ -478,7 +478,7 @@ std::string urlsafe_base64_decode(std::string encoded_string)
|
||||
|
||||
std::string urlsafe_base64_encode(std::string string_to_encode)
|
||||
{
|
||||
return replace_all_distinct(replace_all_distinct(base64_encode(string_to_encode), "+", "-"), "/", "_");
|
||||
return replace_all_distinct(replace_all_distinct(replace_all_distinct(base64_encode(string_to_encode), "+", "-"), "/", "_"), "=", "");
|
||||
}
|
||||
|
||||
std::string getMD5(std::string data)
|
||||
|
||||
@@ -72,6 +72,13 @@ surge_rule_base=surge.conf
|
||||
; times RE
|
||||
rename_node=\(?((x|X)?(\d+)(\.?\d+)?)((\s?倍率?)|(x|X))\)?@$1x
|
||||
|
||||
[managed_config]
|
||||
;Append a '#!MANAGED-CONFIG' info to Surge configurations
|
||||
write_managed_config=false
|
||||
|
||||
;Address prefix for MANAGED-CONFIG info, without the trailing "/".
|
||||
managed_config_prefix=http://127.0.0.1:25500
|
||||
|
||||
[emojis]
|
||||
add_emoji=true
|
||||
remove_old_emoji=true
|
||||
|
||||
+14
-9
@@ -390,19 +390,24 @@ void explodeSSD(std::string link, bool libev, std::string custom_port, int local
|
||||
jsondata.Parse(link.c_str());
|
||||
if(!jsondata.HasMember("servers"))
|
||||
return;
|
||||
GetMember(jsondata, "airport", group);
|
||||
for(unsigned int i = 0; i < jsondata["servers"].Size(); i++)
|
||||
{
|
||||
jsondata["airport"] >> group;
|
||||
jsondata["servers"][i]["remarks"] >> remarks;
|
||||
jsondata["port"] >> port;
|
||||
jsondata["encryption"] >> method;
|
||||
jsondata["password"] >> password;
|
||||
//get default info
|
||||
GetMember(jsondata, "port", port);
|
||||
GetMember(jsondata, "encryption", method);
|
||||
GetMember(jsondata, "password", password);
|
||||
GetMember(jsondata, "plugin", plugin);
|
||||
GetMember(jsondata, "plugin_options", pluginopts);
|
||||
|
||||
//get server-specific info
|
||||
jsondata["servers"][i]["server"] >> server;
|
||||
GetMember(jsondata["servers"][i], "remarks", remarks);
|
||||
GetMember(jsondata["servers"][i], "port", port);
|
||||
GetMember(jsondata["servers"][i], "encryption", method);
|
||||
GetMember(jsondata["servers"][i], "password", password);
|
||||
GetMember(jsondata["servers"][i], "plugin", plugin);
|
||||
GetMember(jsondata["servers"][i], "plugin_options", pluginopts);
|
||||
GetMember(jsondata["servers"][i], "encryption", method);
|
||||
GetMember(jsondata["servers"][i], "port", port);
|
||||
GetMember(jsondata["servers"][i], "password", password);
|
||||
|
||||
if(custom_port != "")
|
||||
port = custom_port;
|
||||
@@ -1550,7 +1555,7 @@ void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom
|
||||
sub = urlsafe_base64_decode(sub);
|
||||
strstream << sub;
|
||||
unsigned int index = nodes.size();
|
||||
char delimiter = split(sub, "\n").size() <= 1 ? split(sub, "\r").size() <= 1 ? ' ' : '\r' : '\n';
|
||||
char delimiter = split(sub, "\n").size() < 1 ? split(sub, "\r").size() < 1 ? ' ' : '\r' : '\n';
|
||||
while(getline(strstream, strLink, delimiter))
|
||||
{
|
||||
explode(strLink, sslibev, ssrlibev, custom_port, local_port, node);
|
||||
|
||||
+131
-13
@@ -2,7 +2,6 @@
|
||||
#include "speedtestutil.h"
|
||||
#include "ini_reader.h"
|
||||
#include "rapidjson_extra.h"
|
||||
#include "yamlcpp_extra.h"
|
||||
#include "webget.h"
|
||||
#include "subexport.h"
|
||||
#include "printout.h"
|
||||
@@ -245,7 +244,7 @@ void rulesetToClash(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset
|
||||
allRules.emplace_back(retrived_rules.substr(2) + "," + rule_group);
|
||||
continue;
|
||||
}
|
||||
char delimiter = count(retrived_rules.begin(), retrived_rules.end(), '\n') <= 1 ? '\r' : '\n';
|
||||
char delimiter = count(retrived_rules.begin(), retrived_rules.end(), '\n') < 1 ? '\r' : '\n';
|
||||
|
||||
strStrm.clear();
|
||||
strStrm<<retrived_rules;
|
||||
@@ -305,7 +304,7 @@ void rulesetToSurge(INIReader &base_rule, string_array &ruleset_array, int surge
|
||||
if(api_mode)
|
||||
continue;
|
||||
retrived_rules = fileGet(rule_path, false);
|
||||
char delimiter = count(retrived_rules.begin(), retrived_rules.end(), '\n') <= 1 ? '\r' : '\n';
|
||||
char delimiter = count(retrived_rules.begin(), retrived_rules.end(), '\n') < 1 ? '\r' : '\n';
|
||||
|
||||
strStrm.clear();
|
||||
strStrm<<retrived_rules;
|
||||
@@ -527,7 +526,7 @@ std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &baseConf, st
|
||||
|
||||
singlegroup["name"] = vArray[0];
|
||||
singlegroup["type"] = vArray[1];
|
||||
singlegroup["proxies"] = vectorToNode(filtered_nodelist);
|
||||
singlegroup["proxies"] = filtered_nodelist;
|
||||
|
||||
for(unsigned int i = 0; i < original_groups.size(); i++)
|
||||
{
|
||||
@@ -828,7 +827,9 @@ std::string netchToVMess(std::vector<nodeInfo> &nodes)
|
||||
std::string netchToQuan(std::vector<nodeInfo> &nodes)
|
||||
{
|
||||
rapidjson::Document json;
|
||||
std::string remark, hostname, port, method;
|
||||
std::string remark, hostname, port, method, password;
|
||||
std::string plugin, pluginopts;
|
||||
std::string protocol, protoparam, obfs, obfsparam;
|
||||
std::string id, aid, transproto, faketype, host, path, quicsecure, quicsecret;
|
||||
std::string proxyStr, allLinks;
|
||||
bool tlssecure;
|
||||
@@ -839,17 +840,19 @@ std::string netchToQuan(std::vector<nodeInfo> &nodes)
|
||||
hostname = GetMember(json, "Hostname");
|
||||
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
|
||||
method = GetMember(json, "EncryptMethod");
|
||||
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") == "true";
|
||||
password = GetMember(json, "Password");
|
||||
|
||||
switch(x.linkType)
|
||||
{
|
||||
case 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") == "true";
|
||||
|
||||
if(method == "auto")
|
||||
method = "chacha20-ietf-poly1305";
|
||||
proxyStr = remark + " = vmess, " + hostname + ", " + port + ", " + method + ", \"" + id + "\", group=" + x.group;
|
||||
@@ -857,11 +860,32 @@ std::string netchToQuan(std::vector<nodeInfo> &nodes)
|
||||
proxyStr += ", obfs=ws, obfs-path=" + path + ", obfs-header=\"Host: " + host + "\"";
|
||||
if(tlssecure)
|
||||
proxyStr += ", over-tls=true, tls-host=" + host;
|
||||
proxyStr = "vmess://" + urlsafe_base64_encode(proxyStr);
|
||||
break;
|
||||
case SPEEDTEST_MESSAGE_FOUNDSSR:
|
||||
protocol = GetMember(json, "Protocol");
|
||||
protoparam = GetMember(json, "ProtocolParam");
|
||||
obfs = GetMember(json, "OBFS");
|
||||
obfsparam = GetMember(json, "OBFSParam");
|
||||
|
||||
proxyStr = "ssr://" + urlsafe_base64_encode(hostname + ":" + port + ":" + protocol + ":" + method + ":" + obfs + ":" + urlsafe_base64_encode(password) \
|
||||
+ "/?group=" + urlsafe_base64_encode(x.group) + "&remarks=" + urlsafe_base64_encode(remark) \
|
||||
+ "&obfsparam=" + urlsafe_base64_encode(obfsparam) + "&protoparam=" + urlsafe_base64_encode(protoparam));
|
||||
break;
|
||||
case SPEEDTEST_MESSAGE_FOUNDSS:
|
||||
plugin = GetMember(json, "Plugin");
|
||||
pluginopts = GetMember(json, "PluginOption");
|
||||
proxyStr = "ss://" + urlsafe_base64_encode(method + ":" + password + "@" + hostname + ":" + port);
|
||||
if(plugin.size() & pluginopts.size())
|
||||
{
|
||||
proxyStr += "/?plugin=" + UrlEncode(plugin + ";" +pluginopts);
|
||||
}
|
||||
proxyStr += "&group=" + urlsafe_base64_encode(x.group) + "#" + UrlEncode(remark);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
allLinks += "vmess://" + urlsafe_base64_encode(proxyStr) + "\n";
|
||||
allLinks += proxyStr + "\n";
|
||||
}
|
||||
|
||||
return allLinks;
|
||||
@@ -992,3 +1016,97 @@ std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group)
|
||||
writer.EndObject();
|
||||
return "ssd://" + base64_encode(sb.GetString());
|
||||
}
|
||||
|
||||
std::string buildGistData(std::string name, std::string content)
|
||||
{
|
||||
rapidjson::StringBuffer sb;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
|
||||
writer.StartObject();
|
||||
writer.Key("description");
|
||||
writer.String("subconverter");
|
||||
writer.Key("public");
|
||||
writer.Bool(false);
|
||||
writer.Key("files");
|
||||
writer.StartObject();
|
||||
writer.Key(name.data());
|
||||
writer.StartObject();
|
||||
writer.Key("content");
|
||||
writer.String(content.data());
|
||||
writer.EndObject();
|
||||
writer.EndObject();
|
||||
writer.EndObject();
|
||||
return sb.GetString();
|
||||
}
|
||||
|
||||
int uploadGist(std::string path, std::string content, bool writeManageURL)
|
||||
{
|
||||
INIReader ini;
|
||||
rapidjson::Document json;
|
||||
std::string token, id, username, retData, url;
|
||||
int retVal = 0;
|
||||
|
||||
if(!fileExist("gistconf.ini"))
|
||||
{
|
||||
std::cerr<<"gistconf.ini not found. Skipping...\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
ini.ParseFile("gistconf.ini");
|
||||
if(ini.EnterSection("common") == 0)
|
||||
{
|
||||
token = ini.Get("token");
|
||||
if(!token.size())
|
||||
{
|
||||
std::cerr<<"No token is provided. Skipping...\n";
|
||||
return -1;
|
||||
}
|
||||
id = ini.Get("id");
|
||||
username = ini.Get("username");
|
||||
if(!id.size())
|
||||
{
|
||||
std::cerr<<"No gist id is provided. Creating new gist...\n";
|
||||
retVal = curlPost("https://api.github.com/gists", buildGistData(path, content), "", token, &retData);
|
||||
if(retVal != 201)
|
||||
{
|
||||
std::cerr<<"Create new Gist failed! Return data:\n"<<retData<<"\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
url = ini.Get(path, "url");
|
||||
if(!url.size())
|
||||
url = "https://gist.githubusercontent.com/" + username + "/" + id + "/raw/" + path;
|
||||
std::cerr<<"Gist id provided. Modifying gist...\n";
|
||||
if(writeManageURL)
|
||||
content = "#!MANAGED-CONFIG "+ url + "\n" + content;
|
||||
retVal = curlPatch("https://api.github.com/gists/" + id, buildGistData(path, content), "", token, &retData);
|
||||
if(retVal != 200)
|
||||
{
|
||||
std::cerr<<"Modify gist failed! Return data:\n"<<retData<<"\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
json.Parse(retData.data());
|
||||
GetMember(json, "id", id);
|
||||
if(json.HasMember("owner"))
|
||||
GetMember(json["owner"], "login", username);
|
||||
std::cerr<<"Writing to Gist success!\nPath: "<<path<<"\nRaw URL: "<<url<<"\nGist owner: "<<username<<"\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr<<"gistconf.ini has incorrect format. Skipping...\n";
|
||||
return -1;
|
||||
}
|
||||
ini.EraseSection();
|
||||
ini.Set("token", token);
|
||||
ini.Set("id", id);
|
||||
ini.Set("username", username);
|
||||
|
||||
ini.SetCurrentSection(path);
|
||||
ini.EraseSection();
|
||||
ini.Set("url", url);
|
||||
|
||||
ini.ToFile("gistconf.ini");
|
||||
return 0;
|
||||
}
|
||||
@@ -18,5 +18,7 @@ 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 buildGistData(std::string name, std::string content);
|
||||
int uploadGist(std::string path, std::string content, bool writeManageURL);
|
||||
|
||||
#endif // SUBEXPORT_H_INCLUDED
|
||||
+34
-11
@@ -31,7 +31,7 @@ std::string curlGet(std::string url, std::string proxy)
|
||||
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 10L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 15L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, user_agent_str.data());
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data);
|
||||
@@ -56,32 +56,42 @@ std::string webGet(std::string url, std::string proxy)
|
||||
return curlGet(url, proxy);
|
||||
}
|
||||
|
||||
long curlPost(std::string url, std::string data, std::string proxy)
|
||||
int curlPost(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData)
|
||||
{
|
||||
CURL *curl_handle;
|
||||
double retVal = 0.0;
|
||||
struct curl_slist *list = NULL;
|
||||
int retVal = 0;
|
||||
|
||||
CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl_handle = curl_easy_init();
|
||||
list = curl_slist_append(list, "Content-Type: application/json;charset='utf-8'");
|
||||
if(auth_token.size())
|
||||
list = curl_slist_append(list, std::string("Authorization: token " + auth_token).data());
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, url.data());
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HEADER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.data());
|
||||
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, data.size());
|
||||
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 10L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 15L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, retData);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, user_agent_str.data());
|
||||
if(proxy != "")
|
||||
curl_easy_setopt(curl_handle, CURLOPT_PROXY, proxy.data());
|
||||
|
||||
res = curl_easy_perform(curl_handle);
|
||||
curl_slist_free_all(list);
|
||||
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
res = curl_easy_getinfo(curl_handle, CURLINFO_SPEED_UPLOAD, &retVal);
|
||||
res = curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CODE, &retVal);
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl_handle);
|
||||
@@ -89,30 +99,43 @@ long curlPost(std::string url, std::string data, std::string proxy)
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int curlPatch(std::string url, std::string data, std::string proxy)
|
||||
int curlPatch(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData)
|
||||
{
|
||||
CURL *curl_handle;
|
||||
int retVal = 0;
|
||||
struct curl_slist *list = NULL;
|
||||
|
||||
CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl_handle = curl_easy_init();
|
||||
|
||||
list = curl_slist_append(list, "Content-Type: application/json;charset='utf-8'");
|
||||
if(auth_token.size())
|
||||
list = curl_slist_append(list, std::string("Authorization: token " + auth_token).data());
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, url.data());
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HEADER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "PATCH");
|
||||
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.data());
|
||||
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, data.size());
|
||||
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 10L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 15L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, retData);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, user_agent_str.data());
|
||||
if(proxy != "")
|
||||
curl_easy_setopt(curl_handle, CURLOPT_PROXY, proxy.data());
|
||||
|
||||
res = curl_easy_perform(curl_handle);
|
||||
if(res != CURLE_OK)
|
||||
retVal = -1;
|
||||
curl_slist_free_all(list);
|
||||
if(res == CURLE_OK)
|
||||
{
|
||||
res = curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CODE, &retVal);
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl_handle);
|
||||
curl_global_cleanup();
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
std::string webGet(std::string url, std::string proxy = "");
|
||||
std::string httpGet(std::string host, std::string addr, std::string uri);
|
||||
std::string httpsGet(std::string host, std::string addr, std::string uri);
|
||||
long curlPost(std::string url, std::string data, std::string proxy);
|
||||
int curlPost(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData);
|
||||
int curlPatch(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData);
|
||||
std::string buildSocks5ProxyString(std::string addr, int port, std::string username, std::string password);
|
||||
|
||||
#endif // WEBGET_H_INCLUDED
|
||||
@@ -1,14 +0,0 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
YAML::Node vectorToNode(string_array data)
|
||||
{
|
||||
YAML::Node node;
|
||||
for(std::string &x : data)
|
||||
node.push_back(x);
|
||||
return node;
|
||||
}
|
||||
Reference in new issue
Block a user