Enhancements

Fix not correctly handle SOCKS5 nodes in Clash subscriptions.
Add specifying filter script from URL arguments.
Add support for using matchers in include/exclude options.
Rename default configuration files for easier upgrade.
This commit is contained in:
Tindy X 2020-11-08 18:34:26 +08:00
parent 069d1c00f6
commit 74d865ceb0
No known key found for this signature in database
GPG Key ID: C6AD413169968D58
5 changed files with 43 additions and 14 deletions

View File

@ -1362,7 +1362,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
std::string argIncludeRemark = UrlDecode(getUrlArg(argument, "include")), argExcludeRemark = UrlDecode(getUrlArg(argument, "exclude")); std::string argIncludeRemark = UrlDecode(getUrlArg(argument, "include")), argExcludeRemark = UrlDecode(getUrlArg(argument, "exclude"));
std::string argCustomGroups = urlsafe_base64_decode(getUrlArg(argument, "groups")), argCustomRulesets = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), argExternalConfig = UrlDecode(getUrlArg(argument, "config")); std::string argCustomGroups = urlsafe_base64_decode(getUrlArg(argument, "groups")), argCustomRulesets = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), argExternalConfig = UrlDecode(getUrlArg(argument, "config"));
std::string argDeviceID = getUrlArg(argument, "dev_id"), argFilename = getUrlArg(argument, "filename"), argUpdateInterval = getUrlArg(argument, "interval"), argUpdateStrict = getUrlArg(argument, "strict"); std::string argDeviceID = getUrlArg(argument, "dev_id"), argFilename = getUrlArg(argument, "filename"), argUpdateInterval = getUrlArg(argument, "interval"), argUpdateStrict = getUrlArg(argument, "strict");
std::string argRenames = UrlDecode(getUrlArg(argument, "rename")); std::string argRenames = UrlDecode(getUrlArg(argument, "rename")), argFilterScript = UrlDecode(getUrlArg(argument, "filter_script"));
/// switches with default value /// switches with default value
tribool argUpload = getUrlArg(argument, "upload"), argEmoji = getUrlArg(argument, "emoji"), argAddEmoji = getUrlArg(argument, "add_emoji"), argRemoveEmoji = getUrlArg(argument, "remove_emoji"); tribool argUpload = getUrlArg(argument, "upload"), argEmoji = getUrlArg(argument, "emoji"), argAddEmoji = getUrlArg(argument, "add_emoji"), argRemoveEmoji = getUrlArg(argument, "remove_emoji");
@ -1611,15 +1611,18 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
std::move(insert_nodes.begin(), insert_nodes.end(), std::back_inserter(nodes)); std::move(insert_nodes.begin(), insert_nodes.end(), std::back_inserter(nodes));
} }
//run filter script //run filter script
if(gFilterScript.size()) std::string filterScript = gFilterScript;
if(authorized && !argFilterScript.empty())
filterScript = argFilterScript;
if(filterScript.size())
{ {
if(startsWith(gFilterScript, "path:")) if(startsWith(filterScript, "path:"))
gFilterScript = fileGet(gFilterScript.substr(5), false); filterScript = fileGet(filterScript.substr(5), false);
duk_context *ctx = duktape_init(); duk_context *ctx = duktape_init();
if(ctx) if(ctx)
{ {
defer(duk_destroy_heap(ctx);) defer(duk_destroy_heap(ctx);)
if(duktape_peval(ctx, gFilterScript) == 0) if(duktape_peval(ctx, filterScript) == 0)
{ {
auto filter = [&](const nodeInfo &x) auto filter = [&](const nodeInfo &x)
{ {

View File

@ -105,6 +105,16 @@ int main(int argc, char *argv[])
#endif // _DEBUG #endif // _DEBUG
if(fileExist("pref.yml")) if(fileExist("pref.yml"))
gPrefPath = "pref.yml"; gPrefPath = "pref.yml";
else if(!fileExist("pref.ini"))
{
if(fileExist("pref.example.yml"))
{
fileCopy("pref.example.yml", "pref.yml");
gPrefPath = "pref.yml";
}
else if(fileExist("pref.example.ini"))
fileCopy("pref.example.ini", "pref.ini");
}
chkArg(argc, argv); chkArg(argc, argv);
setcd(gPrefPath); //then switch to pref directory setcd(gPrefPath); //then switch to pref directory
writeLog(0, "SubConverter " VERSION " starting up..", LOG_LEVEL_INFO); writeLog(0, "SubConverter " VERSION " starting up..", LOG_LEVEL_INFO);

View File

@ -1068,7 +1068,7 @@ void explodeClash(Node yamlnode, const std::string &custom_port, std::vector<nod
node.linkType = SPEEDTEST_MESSAGE_FOUNDSS; node.linkType = SPEEDTEST_MESSAGE_FOUNDSS;
node.proxyStr = ssConstruct(group, ps, server, port, password, cipher, plugin, pluginopts, ss_libev, udp, tfo, scv); node.proxyStr = ssConstruct(group, ps, server, port, password, cipher, plugin, pluginopts, ss_libev, udp, tfo, scv);
break; break;
case "socks"_hash: case "socks5"_hash:
group = SOCKS_DEFAULT_GROUP; group = SOCKS_DEFAULT_GROUP;
singleproxy["username"] >>= user; singleproxy["username"] >>= user;
@ -1912,22 +1912,38 @@ void explodeNetchConf(std::string netch, bool ss_libev, bool ssr_libev, const st
} }
} }
bool applyMatcher(const std::string &rule, std::string &real_rule, const nodeInfo &node);
bool chkIgnore(const nodeInfo &node, string_array &exclude_remarks, string_array &include_remarks) bool chkIgnore(const nodeInfo &node, string_array &exclude_remarks, string_array &include_remarks)
{ {
bool excluded = false, included = false; bool excluded = false, included = false;
//std::string remarks = UTF8ToACP(node.remarks); //std::string remarks = UTF8ToACP(node.remarks);
std::string remarks = node.remarks; //std::string remarks = node.remarks;
//writeLog(LOG_TYPE_INFO, "Comparing exclude remarks..."); //writeLog(LOG_TYPE_INFO, "Comparing exclude remarks...");
excluded = std::any_of(exclude_remarks.cbegin(), exclude_remarks.cend(), [&remarks](const auto &x) excluded = std::any_of(exclude_remarks.cbegin(), exclude_remarks.cend(), [&node](const auto &x)
{ {
return regFind(remarks, x); std::string real_rule;
if(applyMatcher(x, real_rule, node))
{
if(real_rule.empty()) return true;
return regFind(node.remarks, real_rule);
}
else
return false;
}); });
if(include_remarks.size() != 0) if(include_remarks.size() != 0)
{ {
//writeLog(LOG_TYPE_INFO, "Comparing include remarks..."); //writeLog(LOG_TYPE_INFO, "Comparing include remarks...");
included = std::any_of(include_remarks.cbegin(), include_remarks.cend(), [&remarks](const auto &x) included = std::any_of(include_remarks.cbegin(), include_remarks.cend(), [&node](const auto &x)
{ {
return regFind(remarks, x); std::string real_rule;
if(applyMatcher(x, real_rule, node))
{
if(real_rule.empty()) return true;
return regFind(node.remarks, real_rule);
}
else
return false;
}); });
} }
else else
@ -2051,6 +2067,7 @@ void explodeSub(std::string sub, bool sslibev, bool ssrlibev, const std::string
} }
catch (std::exception &e) catch (std::exception &e)
{ {
writeLog(0, e.what(), LOG_LEVEL_DEBUG);
//ignore //ignore
} }
@ -2091,7 +2108,6 @@ void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, st
{ {
int node_index = 0; int node_index = 0;
std::vector<nodeInfo>::iterator iter = nodes.begin(); std::vector<nodeInfo>::iterator iter = nodes.begin();
/*
while(iter != nodes.end()) while(iter != nodes.end())
{ {
if(chkIgnore(*iter, exclude_remarks, include_remarks)) if(chkIgnore(*iter, exclude_remarks, include_remarks))
@ -2108,8 +2124,7 @@ void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, st
++iter; ++iter;
} }
} }
*/ /*
std::vector<std::unique_ptr<pcre2_code, decltype(&pcre2_code_free)>> exclude_patterns, include_patterns; std::vector<std::unique_ptr<pcre2_code, decltype(&pcre2_code_free)>> exclude_patterns, include_patterns;
std::vector<std::unique_ptr<pcre2_match_data, decltype(&pcre2_match_data_free)>> exclude_match_data, include_match_data; std::vector<std::unique_ptr<pcre2_match_data, decltype(&pcre2_match_data_free)>> exclude_match_data, include_match_data;
unsigned int i = 0; unsigned int i = 0;
@ -2185,6 +2200,7 @@ void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, st
++iter; ++iter;
} }
} }
*/
writeLog(LOG_TYPE_INFO, "Filter done."); writeLog(LOG_TYPE_INFO, "Filter done.");
} }