mirror of
https://github.com/asdlokj1qpi233/subconverter.git
synced 2026-11-04 02:34:06 +00:00
Enhancements
Add Subscription-UserInfo header to exporter, supports extracting from original headers and from info nodes. Optimize codes.
This commit is contained in:
10 files changed
+365
-114
No files matched your search
@@ -35,6 +35,21 @@ proxy_subscription=NONE
|
|||||||
;Append a proxy type string ([SS] [SSR] [VMess]) to node remark.
|
;Append a proxy type string ([SS] [SSR] [VMess]) to node remark.
|
||||||
append_proxy_type=false
|
append_proxy_type=false
|
||||||
|
|
||||||
|
[userinfo]
|
||||||
|
;Rules to extract stream data from node
|
||||||
|
;Format: full_match_regex|new_format_regex
|
||||||
|
;where new_format_regex should be like "total=$1&left=$2&used=$3"
|
||||||
|
stream_rule=^剩余流量:(.*?) (.*)$|total=$1&left=$2
|
||||||
|
stream_rule=^Bandwidth: (.*?)/(.*)$|used=$1&total=$2
|
||||||
|
stream_rule=^\[.*?\]剩余(.*?)@(?:.*)$|total=$1
|
||||||
|
|
||||||
|
;Rules to extract expire time data from node
|
||||||
|
;Format: full_match_regex|new_format_regex
|
||||||
|
;where new_format_regex should follow this example: yyyy:mm:dd:hh:mm:ss
|
||||||
|
time_rule=^过期时间:(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$|$1:$2:$3:$4:$5:$6
|
||||||
|
time_rule=^到期时间:(\d+)-(\d+)-(\d+)$|$1:$2:$3:0:0:0
|
||||||
|
time_rule=^Smart Access expire: (\d+)/(\d+)/(\d+)$|$1:$2:$3:0:0:0
|
||||||
|
|
||||||
[node_pref]
|
[node_pref]
|
||||||
udp_flag=false
|
udp_flag=false
|
||||||
tcp_fast_open_flag=false
|
tcp_fast_open_flag=false
|
||||||
|
|||||||
+26
-16
@@ -9,12 +9,15 @@
|
|||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
#define INIREADER_EXCEPTION_NONE 0
|
enum
|
||||||
#define INIREADER_EXCEPTION_EMPTY -1
|
{
|
||||||
#define INIREADER_EXCEPTION_DUPLICATE -2
|
INIREADER_EXCEPTION_EMPTY = -5,
|
||||||
#define INIREADER_EXCEPTION_OUTOFBOUND -3
|
INIREADER_EXCEPTION_DUPLICATE,
|
||||||
#define INIREADER_EXCEPTION_NOTEXIST -4
|
INIREADER_EXCEPTION_OUTOFBOUND,
|
||||||
#define INIREADER_EXCEPTION_NOTPARSED -5
|
INIREADER_EXCEPTION_NOTEXIST,
|
||||||
|
INIREADER_EXCEPTION_NOTPARSED,
|
||||||
|
INIREADER_EXCEPTION_NONE
|
||||||
|
};
|
||||||
|
|
||||||
#define __SAVE_ERROR_AND_RETURN(x) {last_error = x; return last_error;}
|
#define __SAVE_ERROR_AND_RETURN(x) {last_error = x; return last_error;}
|
||||||
|
|
||||||
@@ -80,6 +83,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool allow_dup_section_titles = false;
|
bool allow_dup_section_titles = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Keep an empty section while parsing
|
||||||
|
*/
|
||||||
|
bool keep_empty_section = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the reader.
|
* @brief Initialize the reader.
|
||||||
*/
|
*/
|
||||||
@@ -224,23 +232,24 @@ public:
|
|||||||
thisSection = strLine.substr(1, lineSize - 2); //save section title
|
thisSection = strLine.substr(1, lineSize - 2); //save section title
|
||||||
inExcludedSection = chkIgnore(thisSection); //check if this section is excluded
|
inExcludedSection = chkIgnore(thisSection); //check if this section is excluded
|
||||||
|
|
||||||
if(curSection.size() && itemGroup.size()) //just finished reading a section
|
if(curSection.size() && (keep_empty_section || itemGroup.size())) //just finished reading a section
|
||||||
{
|
{
|
||||||
if(ini_content.count(curSection)) //a section with the same name has been inserted
|
if(ini_content.count(curSection)) //a section with the same name has been inserted
|
||||||
{
|
{
|
||||||
if(allow_dup_section_titles)
|
if(allow_dup_section_titles || !ini_content.at(curSection).size())
|
||||||
{
|
{
|
||||||
eraseElements(existItemGroup);
|
eraseElements(existItemGroup);
|
||||||
existItemGroup = ini_content.at(curSection); //get the old items
|
existItemGroup = ini_content.at(curSection); //get the old items
|
||||||
for(auto &x : existItemGroup)
|
for(auto &x : existItemGroup)
|
||||||
itemGroup.emplace(x); //insert them all into new section
|
itemGroup.emplace(x); //insert them all into new section
|
||||||
ini_content.erase(curSection); //remove the old section
|
|
||||||
}
|
}
|
||||||
else
|
else if(ini_content.at(curSection).size())
|
||||||
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_DUPLICATE); //not allowed, stop
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_DUPLICATE); //not allowed, stop
|
||||||
|
ini_content.erase(curSection); //remove the old section
|
||||||
}
|
}
|
||||||
|
else if(itemGroup.size())
|
||||||
|
read_sections.push_back(curSection); //add to read sections list
|
||||||
ini_content.emplace(curSection, itemGroup); //insert previous section to content map
|
ini_content.emplace(curSection, itemGroup); //insert previous section to content map
|
||||||
read_sections.push_back(curSection); //add to read sections list
|
|
||||||
if(std::count(section_order.cbegin(), section_order.cend(), curSection) == 0)
|
if(std::count(section_order.cbegin(), section_order.cend(), curSection) == 0)
|
||||||
section_order.emplace_back(curSection);
|
section_order.emplace_back(curSection);
|
||||||
}
|
}
|
||||||
@@ -255,7 +264,7 @@ public:
|
|||||||
if(include_sections.size() && include_sections == read_sections) //all included sections has been read
|
if(include_sections.size() && include_sections == read_sections) //all included sections has been read
|
||||||
break; //exit now
|
break; //exit now
|
||||||
}
|
}
|
||||||
if(curSection.size() && itemGroup.size()) //final section
|
if(curSection.size() && (keep_empty_section || itemGroup.size())) //final section
|
||||||
{
|
{
|
||||||
if(ini_content.count(curSection)) //a section with the same name has been inserted
|
if(ini_content.count(curSection)) //a section with the same name has been inserted
|
||||||
{
|
{
|
||||||
@@ -265,13 +274,14 @@ public:
|
|||||||
existItemGroup = ini_content.at(curSection); //get the old items
|
existItemGroup = ini_content.at(curSection); //get the old items
|
||||||
for(auto &x : existItemGroup)
|
for(auto &x : existItemGroup)
|
||||||
itemGroup.emplace(x); //insert them all into new section
|
itemGroup.emplace(x); //insert them all into new section
|
||||||
ini_content.erase(curSection); //remove the old section
|
|
||||||
}
|
}
|
||||||
else
|
else if(ini_content.at(curSection).size())
|
||||||
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_DUPLICATE); //not allowed, stop
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_DUPLICATE); //not allowed, stop
|
||||||
|
ini_content.erase(curSection); //remove the old section
|
||||||
}
|
}
|
||||||
|
else if(itemGroup.size())
|
||||||
|
read_sections.emplace_back(curSection); //add to read sections list
|
||||||
ini_content.emplace(curSection, itemGroup); //insert this section to content map
|
ini_content.emplace(curSection, itemGroup); //insert this section to content map
|
||||||
read_sections.emplace_back(curSection); //add to read sections list
|
|
||||||
if(std::count(section_order.cbegin(), section_order.cend(), curSection) == 0)
|
if(std::count(section_order.cbegin(), section_order.cend(), curSection) == 0)
|
||||||
section_order.emplace_back(curSection);
|
section_order.emplace_back(curSection);
|
||||||
}
|
}
|
||||||
@@ -803,7 +813,7 @@ public:
|
|||||||
content += "\n";
|
content += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return content.substr(0, content.size() - 2);
|
return content.erase(content.size() - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+49
-10
@@ -20,7 +20,7 @@
|
|||||||
//common settings
|
//common settings
|
||||||
std::string pref_path = "pref.ini";
|
std::string pref_path = "pref.ini";
|
||||||
bool generator_mode = false;
|
bool generator_mode = false;
|
||||||
string_array def_exclude_remarks, def_include_remarks, rulesets;
|
string_array def_exclude_remarks, def_include_remarks, rulesets, stream_rules, time_rules;
|
||||||
std::vector<ruleset_content> ruleset_content_array;
|
std::vector<ruleset_content> ruleset_content_array;
|
||||||
std::string listen_address = "127.0.0.1", default_url, managed_config_prefix;
|
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;
|
int listen_port = 25500, max_pending_connections = 10, max_concurrent_threads = 4;
|
||||||
@@ -151,7 +151,7 @@ void readConf()
|
|||||||
eraseElements(def_include_remarks);
|
eraseElements(def_include_remarks);
|
||||||
eraseElements(clash_extra_group);
|
eraseElements(clash_extra_group);
|
||||||
eraseElements(rulesets);
|
eraseElements(rulesets);
|
||||||
string_array emojis_temp, renames_temp;
|
string_array tempArray;
|
||||||
|
|
||||||
ini.EnterSection("common");
|
ini.EnterSection("common");
|
||||||
if(ini.ItemExist("api_mode"))
|
if(ini.ItemExist("api_mode"))
|
||||||
@@ -201,8 +201,26 @@ void readConf()
|
|||||||
filter_deprecated = ini.GetBool("filter_deprecated_nodes");
|
filter_deprecated = ini.GetBool("filter_deprecated_nodes");
|
||||||
if(ini.ItemPrefixExist("rename_node"))
|
if(ini.ItemPrefixExist("rename_node"))
|
||||||
{
|
{
|
||||||
ini.GetAll("rename_node", renames_temp);
|
ini.GetAll("rename_node", tempArray);
|
||||||
safe_set_renames(renames_temp);
|
safe_set_renames(tempArray);
|
||||||
|
eraseElements(tempArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ini.SectionExist("userinfo"))
|
||||||
|
{
|
||||||
|
ini.EnterSection("userinfo");
|
||||||
|
if(ini.ItemPrefixExist("stream_rule"))
|
||||||
|
{
|
||||||
|
ini.GetAll("stream_rule", tempArray);
|
||||||
|
safe_set_streams(tempArray);
|
||||||
|
eraseElements(tempArray);
|
||||||
|
}
|
||||||
|
if(ini.ItemPrefixExist("time_rule"))
|
||||||
|
{
|
||||||
|
ini.GetAll("time_rule", tempArray);
|
||||||
|
safe_set_times(tempArray);
|
||||||
|
eraseElements(tempArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,8 +237,9 @@ void readConf()
|
|||||||
remove_old_emoji = ini.GetBool("remove_old_emoji");
|
remove_old_emoji = ini.GetBool("remove_old_emoji");
|
||||||
if(ini.ItemPrefixExist("rule"))
|
if(ini.ItemPrefixExist("rule"))
|
||||||
{
|
{
|
||||||
ini.GetAll("rule", emojis_temp);
|
ini.GetAll("rule", tempArray);
|
||||||
safe_set_emojis(emojis_temp);
|
safe_set_emojis(tempArray);
|
||||||
|
eraseElements(tempArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
ini.EnterSection("ruleset");
|
ini.EnterSection("ruleset");
|
||||||
@@ -284,6 +303,7 @@ int loadExternalConfig(std::string &path, ExternalConfig &ext, std::string proxy
|
|||||||
|
|
||||||
INIReader ini;
|
INIReader ini;
|
||||||
ini.store_isolated_line = true;
|
ini.store_isolated_line = true;
|
||||||
|
ini.keep_empty_section = false;
|
||||||
ini.SetIsolatedItemsSection("custom");
|
ini.SetIsolatedItemsSection("custom");
|
||||||
if(ini.Parse(base_content) != INIREADER_EXCEPTION_NONE)
|
if(ini.Parse(base_content) != INIREADER_EXCEPTION_NONE)
|
||||||
{
|
{
|
||||||
@@ -361,6 +381,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
|||||||
std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups")), ruleset = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), config = UrlDecode(getUrlArg(argument, "config"));
|
std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups")), ruleset = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), config = UrlDecode(getUrlArg(argument, "config"));
|
||||||
std::vector<ruleset_content> rca;
|
std::vector<ruleset_content> rca;
|
||||||
extra_settings ext;
|
extra_settings ext;
|
||||||
|
std::string subInfo;
|
||||||
|
|
||||||
if(std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), include) != regex_blacklist.cend() || std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), exclude) != regex_blacklist.cend())
|
if(std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), include) != regex_blacklist.cend() || std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), exclude) != regex_blacklist.cend())
|
||||||
return "Invalid request!";
|
return "Invalid request!";
|
||||||
@@ -512,11 +533,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
|||||||
custom_group = group;
|
custom_group = group;
|
||||||
|
|
||||||
//start parsing urls
|
//start parsing urls
|
||||||
|
string_array stream_temp = safe_get_streams(), time_temp = safe_get_times();
|
||||||
for(std::string &x : urls)
|
for(std::string &x : urls)
|
||||||
{
|
{
|
||||||
x = trim(x);
|
x = trim(x);
|
||||||
std::cerr<<"Fetching node data from url '"<<x<<"'."<<std::endl;
|
std::cerr<<"Fetching node data from url '"<<x<<"'."<<std::endl;
|
||||||
if(addNodes(x, nodes, groupID, proxy, exclude_remarks, include_remarks) == -1)
|
if(addNodes(x, nodes, groupID, proxy, exclude_remarks, include_remarks, stream_temp, time_temp, subInfo) == -1)
|
||||||
{
|
{
|
||||||
*status_code = 400;
|
*status_code = 400;
|
||||||
return std::string("The following link doesn't contain any valid node info: " + x);
|
return std::string("The following link doesn't contain any valid node info: " + x);
|
||||||
@@ -530,6 +552,9 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
|||||||
return "No nodes were found!";
|
return "No nodes were found!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(subInfo.size() && groupID == 1)
|
||||||
|
extra_headers.emplace("Subscription-UserInfo", subInfo);
|
||||||
|
|
||||||
std::cerr<<"Generate target: ";
|
std::cerr<<"Generate target: ";
|
||||||
if(target == "clash" || target == "clashr")
|
if(target == "clash" || target == "clashr")
|
||||||
{
|
{
|
||||||
@@ -672,6 +697,7 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
|
|||||||
std::vector<nodeInfo> nodes;
|
std::vector<nodeInfo> nodes;
|
||||||
string_array extra_group, extra_ruleset, include_remarks, exclude_remarks;
|
string_array extra_group, extra_ruleset, include_remarks, exclude_remarks;
|
||||||
std::vector<ruleset_content> rca;
|
std::vector<ruleset_content> rca;
|
||||||
|
std::string subInfo;
|
||||||
|
|
||||||
if(!url.size())
|
if(!url.size())
|
||||||
url = default_url;
|
url = default_url;
|
||||||
@@ -707,9 +733,22 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
|
|||||||
include_remarks = def_include_remarks;
|
include_remarks = def_include_remarks;
|
||||||
exclude_remarks = def_exclude_remarks;
|
exclude_remarks = def_exclude_remarks;
|
||||||
|
|
||||||
std::cerr<<"Fetching node data from url '"<<url<<"'.\n";
|
//start parsing urls
|
||||||
addNodes(url, nodes, 0, proxy, exclude_remarks, include_remarks);
|
int groupID = 0;
|
||||||
|
string_array dummy;
|
||||||
|
string_array urls = split(url, "|");
|
||||||
|
for(std::string &x : urls)
|
||||||
|
{
|
||||||
|
x = trim(x);
|
||||||
|
std::cerr<<"Fetching node data from url '"<<x<<"'."<<std::endl;
|
||||||
|
if(addNodes(x, nodes, groupID, proxy, exclude_remarks, include_remarks, dummy, dummy, subInfo) == -1)
|
||||||
|
{
|
||||||
|
*status_code = 400;
|
||||||
|
return std::string("The following link doesn't contain any valid node info: " + x);
|
||||||
|
}
|
||||||
|
groupID++;
|
||||||
|
}
|
||||||
|
//exit if found nothing
|
||||||
if(!nodes.size())
|
if(!nodes.size())
|
||||||
{
|
{
|
||||||
*status_code = 400;
|
*status_code = 400;
|
||||||
|
|||||||
+26
-1
@@ -4,9 +4,10 @@
|
|||||||
|
|
||||||
//safety lock for multi-thread
|
//safety lock for multi-thread
|
||||||
typedef std::lock_guard<std::mutex> guarded_mutex;
|
typedef std::lock_guard<std::mutex> guarded_mutex;
|
||||||
std::mutex on_configuring, on_emoji, on_rename;
|
std::mutex on_configuring, on_emoji, on_rename, on_stream, on_time;
|
||||||
|
|
||||||
extern string_array emojis, renames;
|
extern string_array emojis, renames;
|
||||||
|
extern string_array stream_rules, time_rules;
|
||||||
|
|
||||||
string_array safe_get_emojis()
|
string_array safe_get_emojis()
|
||||||
{
|
{
|
||||||
@@ -20,6 +21,18 @@ string_array safe_get_renames()
|
|||||||
return renames;
|
return renames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string_array safe_get_streams()
|
||||||
|
{
|
||||||
|
guarded_mutex guard(on_stream);
|
||||||
|
return stream_rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_array safe_get_times()
|
||||||
|
{
|
||||||
|
guarded_mutex guard(on_time);
|
||||||
|
return time_rules;
|
||||||
|
}
|
||||||
|
|
||||||
void safe_set_emojis(string_array &data)
|
void safe_set_emojis(string_array &data)
|
||||||
{
|
{
|
||||||
guarded_mutex guard(on_emoji);
|
guarded_mutex guard(on_emoji);
|
||||||
@@ -31,3 +44,15 @@ void safe_set_renames(string_array &data)
|
|||||||
guarded_mutex guard(on_rename);
|
guarded_mutex guard(on_rename);
|
||||||
renames.swap(data);
|
renames.swap(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void safe_set_streams(string_array &data)
|
||||||
|
{
|
||||||
|
guarded_mutex guard(on_stream);
|
||||||
|
stream_rules.swap(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void safe_set_times(string_array &data)
|
||||||
|
{
|
||||||
|
guarded_mutex guard(on_time);
|
||||||
|
time_rules.swap(data);
|
||||||
|
}
|
||||||
+4
-3
@@ -6,12 +6,13 @@
|
|||||||
|
|
||||||
typedef std::lock_guard<std::mutex> guarded_mutex;
|
typedef std::lock_guard<std::mutex> guarded_mutex;
|
||||||
|
|
||||||
void try_config_lock();
|
|
||||||
void try_emoji_lock();
|
|
||||||
void try_rename_lock();
|
|
||||||
string_array safe_get_emojis();
|
string_array safe_get_emojis();
|
||||||
string_array safe_get_renames();
|
string_array safe_get_renames();
|
||||||
|
string_array safe_get_streams();
|
||||||
|
string_array safe_get_times();
|
||||||
void safe_set_emojis(string_array &data);
|
void safe_set_emojis(string_array &data);
|
||||||
void safe_set_renames(string_array &data);
|
void safe_set_renames(string_array &data);
|
||||||
|
void safe_set_streams(string_array &data);
|
||||||
|
void safe_set_times(string_array &data);
|
||||||
|
|
||||||
#endif // MULTITHREAD_H_INCLUDED
|
#endif // MULTITHREAD_H_INCLUDED
|
||||||
+10
-5
@@ -22,12 +22,12 @@ void copyNodes(std::vector<nodeInfo> &source, std::vector<nodeInfo> &dest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks)
|
int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks, string_array &stream_rules, string_array &time_rules, std::string &subInfo)
|
||||||
{
|
{
|
||||||
int linkType = -1;
|
int linkType = -1;
|
||||||
std::vector<nodeInfo> nodes;
|
std::vector<nodeInfo> nodes;
|
||||||
nodeInfo node;
|
nodeInfo node;
|
||||||
std::string strSub;
|
std::string strSub, extra_headers;
|
||||||
|
|
||||||
link = replace_all_distinct(link, "\"", "");
|
link = replace_all_distinct(link, "\"", "");
|
||||||
writeLog(LOG_TYPE_INFO, "Received Link.");
|
writeLog(LOG_TYPE_INFO, "Received Link.");
|
||||||
@@ -52,7 +52,7 @@ int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std
|
|||||||
writeLog(LOG_TYPE_INFO, "Downloading subscription data...");
|
writeLog(LOG_TYPE_INFO, "Downloading subscription data...");
|
||||||
if(strFind(link, "surge:///install-config")) //surge config link
|
if(strFind(link, "surge:///install-config")) //surge config link
|
||||||
link = UrlDecode(getUrlArg(link, "url"));
|
link = UrlDecode(getUrlArg(link, "url"));
|
||||||
strSub = webGet(link, proxy);
|
strSub = webGet(link, proxy, extra_headers);
|
||||||
/*
|
/*
|
||||||
if(strSub.size() == 0)
|
if(strSub.size() == 0)
|
||||||
{
|
{
|
||||||
@@ -70,11 +70,14 @@ int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std
|
|||||||
if(strSub.size())
|
if(strSub.size())
|
||||||
{
|
{
|
||||||
writeLog(LOG_TYPE_INFO, "Parsing subscription data...");
|
writeLog(LOG_TYPE_INFO, "Parsing subscription data...");
|
||||||
if(explodeConfContent(strSub, override_conf_port, socksport, ss_libev, ssr_libev, nodes, exclude_remarks, include_remarks) == SPEEDTEST_ERROR_UNRECOGFILE)
|
if(explodeConfContent(strSub, override_conf_port, socksport, ss_libev, ssr_libev, nodes) == SPEEDTEST_ERROR_UNRECOGFILE)
|
||||||
{
|
{
|
||||||
writeLog(LOG_TYPE_ERROR, "Invalid subscription!");
|
writeLog(LOG_TYPE_ERROR, "Invalid subscription!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if(!getSubInfoFromHeader(extra_headers, subInfo))
|
||||||
|
getSubInfoFromNodes(nodes, stream_rules, time_rules, subInfo);
|
||||||
|
filterNodes(nodes, exclude_remarks, include_remarks, groupID);
|
||||||
for(nodeInfo &x : nodes)
|
for(nodeInfo &x : nodes)
|
||||||
x.groupID = groupID;
|
x.groupID = groupID;
|
||||||
copyNodes(nodes, allNodes);
|
copyNodes(nodes, allNodes);
|
||||||
@@ -89,11 +92,13 @@ int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std
|
|||||||
if(api_mode)
|
if(api_mode)
|
||||||
return -1;
|
return -1;
|
||||||
writeLog(LOG_TYPE_INFO, "Parsing configuration file data...");
|
writeLog(LOG_TYPE_INFO, "Parsing configuration file data...");
|
||||||
if(explodeConf(link, override_conf_port, socksport, ss_libev, ssr_libev, nodes, exclude_remarks, include_remarks) == SPEEDTEST_ERROR_UNRECOGFILE)
|
if(explodeConf(link, override_conf_port, socksport, ss_libev, ssr_libev, nodes) == SPEEDTEST_ERROR_UNRECOGFILE)
|
||||||
{
|
{
|
||||||
writeLog(LOG_TYPE_ERROR, "Invalid configuration file!");
|
writeLog(LOG_TYPE_ERROR, "Invalid configuration file!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
getSubInfoFromNodes(nodes, stream_rules, time_rules, subInfo);
|
||||||
|
filterNodes(nodes, exclude_remarks, include_remarks, groupID);
|
||||||
for(nodeInfo &x : nodes)
|
for(nodeInfo &x : nodes)
|
||||||
x.groupID = groupID;
|
x.groupID = groupID;
|
||||||
copyNodes(nodes, allNodes);
|
copyNodes(nodes, allNodes);
|
||||||
|
|||||||
+1
-1
@@ -6,6 +6,6 @@
|
|||||||
|
|
||||||
#include "nodeinfo.h"
|
#include "nodeinfo.h"
|
||||||
|
|
||||||
int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks);
|
int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks, string_array &stream_rules, string_array &time_rules, std::string &subInfo);
|
||||||
|
|
||||||
#endif // NODEMANIP_H_INCLUDED
|
#endif // NODEMANIP_H_INCLUDED
|
||||||
+56
-50
@@ -8,57 +8,63 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "nodeinfo.h"
|
#include "nodeinfo.h"
|
||||||
|
|
||||||
#define SPEEDTEST_ERROR_NONE 0
|
enum
|
||||||
#define SPEEDTEST_ERROR_UNDEFINED 100
|
{
|
||||||
#define SPEEDTEST_ERROR_WSAERR 99
|
SPEEDTEST_ERROR_UNDEFINED = -13,
|
||||||
#define SPEEDTEST_ERROR_SOCKETERR 98
|
SPEEDTEST_ERROR_WSAERR,
|
||||||
#define SPEEDTEST_ERROR_NORECOGLINK 97
|
SPEEDTEST_ERROR_SOCKETERR,
|
||||||
#define SPEEDTEST_ERROR_NOCONNECTION 96
|
SPEEDTEST_ERROR_NORECOGLINK,
|
||||||
#define SPEEDTEST_ERROR_INVALIDSUB 95
|
SPEEDTEST_ERROR_NOCONNECTION,
|
||||||
#define SPEEDTEST_ERROR_NONODES 94
|
SPEEDTEST_ERROR_INVALIDSUB,
|
||||||
#define SPEEDTEST_ERROR_NORESOLVE 93
|
SPEEDTEST_ERROR_NONODES,
|
||||||
#define SPEEDTEST_ERROR_RETEST 92
|
SPEEDTEST_ERROR_NORESOLVE,
|
||||||
#define SPEEDTEST_ERROR_NOSPEED 91
|
SPEEDTEST_ERROR_RETEST,
|
||||||
#define SPEEDTEST_ERROR_UNRECOGFILE 90
|
SPEEDTEST_ERROR_NOSPEED,
|
||||||
#define SPEEDTEST_ERROR_SUBFETCHERR 89
|
SPEEDTEST_ERROR_UNRECOGFILE,
|
||||||
#define SPEEDTEST_ERROR_GEOIPERR 88
|
SPEEDTEST_ERROR_SUBFETCHERR,
|
||||||
|
SPEEDTEST_ERROR_GEOIPERR,
|
||||||
|
SPEEDTEST_ERROR_NONE
|
||||||
|
};
|
||||||
|
|
||||||
#define SPEEDTEST_MESSAGE_WELCOME 0
|
enum
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDVMESS 1
|
{
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDSS 2
|
SPEEDTEST_MESSAGE_WELCOME = 1,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDSSR 3
|
SPEEDTEST_MESSAGE_FOUNDVMESS,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDSUB 4
|
SPEEDTEST_MESSAGE_FOUNDSS,
|
||||||
#define SPEEDTEST_MESSAGE_GOTSERVER 5
|
SPEEDTEST_MESSAGE_FOUNDSSR,
|
||||||
#define SPEEDTEST_MESSAGE_STARTPING 6
|
SPEEDTEST_MESSAGE_FOUNDSUB,
|
||||||
#define SPEEDTEST_MESSAGE_GOTPING 7
|
SPEEDTEST_MESSAGE_GOTSERVER,
|
||||||
#define SPEEDTEST_MESSAGE_STARTSPEED 8
|
SPEEDTEST_MESSAGE_STARTPING,
|
||||||
#define SPEEDTEST_MESSAGE_GOTSPEED 9
|
SPEEDTEST_MESSAGE_GOTPING,
|
||||||
#define SPEEDTEST_MESSAGE_GOTRESULT 10
|
SPEEDTEST_MESSAGE_STARTSPEED,
|
||||||
#define SPEEDTEST_MESSAGE_TRAFFIC 11
|
SPEEDTEST_MESSAGE_GOTSPEED,
|
||||||
#define SPEEDTEST_MESSAGE_PICSAVING 12
|
SPEEDTEST_MESSAGE_GOTRESULT,
|
||||||
#define SPEEDTEST_MESSAGE_PICSAVED 13
|
SPEEDTEST_MESSAGE_TRAFFIC,
|
||||||
#define SPEEDTEST_MESSAGE_GROUP 14
|
SPEEDTEST_MESSAGE_PICSAVING,
|
||||||
#define SPEEDTEST_MESSAGE_FETCHSUB 15
|
SPEEDTEST_MESSAGE_PICSAVED,
|
||||||
#define SPEEDTEST_MESSAGE_BEGIN 16
|
SPEEDTEST_MESSAGE_GROUP,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDLOCAL 17
|
SPEEDTEST_MESSAGE_FETCHSUB,
|
||||||
#define SPEEDTEST_MESSAGE_PARSING 18
|
SPEEDTEST_MESSAGE_BEGIN,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDUPD 19
|
SPEEDTEST_MESSAGE_FOUNDLOCAL,
|
||||||
#define SPEEDTEST_MESSAGE_PICDATA 20
|
SPEEDTEST_MESSAGE_PARSING,
|
||||||
#define SPEEDTEST_MESSAGE_STARTGPING 21
|
SPEEDTEST_MESSAGE_FOUNDUPD,
|
||||||
#define SPEEDTEST_MESSAGE_GOTGPING 22
|
SPEEDTEST_MESSAGE_PICDATA,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDSOCKS 23
|
SPEEDTEST_MESSAGE_STARTGPING,
|
||||||
#define SPEEDTEST_MESSAGE_STARTGEOIP 24
|
SPEEDTEST_MESSAGE_GOTGPING,
|
||||||
#define SPEEDTEST_MESSAGE_GOTGEOIP 25
|
SPEEDTEST_MESSAGE_FOUNDSOCKS,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDSSCONF 26
|
SPEEDTEST_MESSAGE_STARTGEOIP,
|
||||||
#define SPEEDTEST_MESSAGE_MULTILINK 27
|
SPEEDTEST_MESSAGE_GOTGEOIP,
|
||||||
#define SPEEDTEST_MESSAGE_PICSAVINGMULTI 28
|
SPEEDTEST_MESSAGE_FOUNDSSCONF,
|
||||||
#define SPEEDTEST_MESSAGE_PICSAVEDMULTI 29
|
SPEEDTEST_MESSAGE_MULTILINK,
|
||||||
#define SPEEDTEST_MESSAGE_STARTUPD 30
|
SPEEDTEST_MESSAGE_PICSAVINGMULTI,
|
||||||
#define SPEEDTEST_MESSAGE_GOTUPD 31
|
SPEEDTEST_MESSAGE_PICSAVEDMULTI,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDSSTAP 32
|
SPEEDTEST_MESSAGE_STARTUPD,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDNETCH 33
|
SPEEDTEST_MESSAGE_GOTUPD,
|
||||||
#define SPEEDTEST_MESSAGE_FOUNDHTTP 34
|
SPEEDTEST_MESSAGE_FOUNDSSTAP,
|
||||||
#define SPEEDTEST_MESSAGE_EOF 49
|
SPEEDTEST_MESSAGE_FOUNDNETCH,
|
||||||
|
SPEEDTEST_MESSAGE_FOUNDHTTP,
|
||||||
|
SPEEDTEST_MESSAGE_EOF
|
||||||
|
};
|
||||||
|
|
||||||
#define SS_DEFAULT_GROUP "SSProvider"
|
#define SS_DEFAULT_GROUP "SSProvider"
|
||||||
#define SSR_DEFAULT_GROUP "SSRProvider"
|
#define SSR_DEFAULT_GROUP "SSRProvider"
|
||||||
|
|||||||
+172
-25
@@ -1,7 +1,10 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
|
#include <pcrecpp.h>
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "printout.h"
|
#include "printout.h"
|
||||||
@@ -997,6 +1000,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ini.store_isolated_line = true;
|
ini.store_isolated_line = true;
|
||||||
|
ini.keep_empty_section = false;
|
||||||
ini.SetIsolatedItemsSection("Proxy");
|
ini.SetIsolatedItemsSection("Proxy");
|
||||||
ini.IncludeSection("Proxy");
|
ini.IncludeSection("Proxy");
|
||||||
ini.Parse(surge);
|
ini.Parse(surge);
|
||||||
@@ -1388,7 +1392,7 @@ bool chkIgnore(const nodeInfo &node, string_array &exclude_remarks, string_array
|
|||||||
return excluded || !included;
|
return excluded || !included;
|
||||||
}
|
}
|
||||||
|
|
||||||
int explodeConf(std::string filepath, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks)
|
int explodeConf(std::string filepath, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes)
|
||||||
{
|
{
|
||||||
std::ifstream infile;
|
std::ifstream infile;
|
||||||
std::stringstream contentstrm;
|
std::stringstream contentstrm;
|
||||||
@@ -1397,12 +1401,11 @@ int explodeConf(std::string filepath, std::string custom_port, int local_port, b
|
|||||||
contentstrm << infile.rdbuf();
|
contentstrm << infile.rdbuf();
|
||||||
infile.close();
|
infile.close();
|
||||||
|
|
||||||
return explodeConfContent(contentstrm.str(), custom_port, local_port, sslibev, ssrlibev, nodes, exclude_remarks, include_remarks);
|
return explodeConfContent(contentstrm.str(), custom_port, local_port, sslibev, ssrlibev, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
int explodeConfContent(std::string content, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks)
|
int explodeConfContent(std::string content, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes)
|
||||||
{
|
{
|
||||||
unsigned int index = 0;
|
|
||||||
int filetype = -1;
|
int filetype = -1;
|
||||||
std::vector<nodeInfo>::iterator iter;
|
std::vector<nodeInfo>::iterator iter;
|
||||||
|
|
||||||
@@ -1443,32 +1446,13 @@ int explodeConfContent(std::string content, std::string custom_port, int local_p
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//try to parse as a local subscription
|
//try to parse as a local subscription
|
||||||
explodeSub(content, sslibev, ssrlibev, custom_port, local_port, nodes, exclude_remarks, include_remarks);
|
explodeSub(content, sslibev, ssrlibev, custom_port, local_port, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nodes.size() == 0)
|
if(nodes.size() == 0)
|
||||||
return SPEEDTEST_ERROR_UNRECOGFILE;
|
return SPEEDTEST_ERROR_UNRECOGFILE;
|
||||||
else
|
else
|
||||||
return SPEEDTEST_ERROR_NONE;
|
return SPEEDTEST_ERROR_NONE;
|
||||||
|
|
||||||
iter = nodes.begin();
|
|
||||||
while(iter != nodes.end())
|
|
||||||
{
|
|
||||||
if(chkIgnore(*iter, exclude_remarks, include_remarks))
|
|
||||||
{
|
|
||||||
writeLog(LOG_TYPE_INFO, "Node " + iter->group + " - " + iter->remarks + " has been ignored and will not be added.");
|
|
||||||
nodes.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
writeLog(LOG_TYPE_INFO, "Node " + iter->group + " - " + iter->remarks + " has been added.");
|
|
||||||
iter->id = index;
|
|
||||||
++index;
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SPEEDTEST_ERROR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void explode(std::string link, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, nodeInfo &node)
|
void explode(std::string link, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, nodeInfo &node)
|
||||||
@@ -1485,7 +1469,7 @@ void explode(std::string link, bool sslibev, bool ssrlibev, std::string custom_p
|
|||||||
explodeNetch(link, sslibev, ssrlibev, custom_port, local_port, node);
|
explodeNetch(link, sslibev, ssrlibev, custom_port, local_port, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks)
|
void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, std::vector<nodeInfo> &nodes)
|
||||||
{
|
{
|
||||||
std::stringstream strstream;
|
std::stringstream strstream;
|
||||||
std::string strLink;
|
std::string strLink;
|
||||||
@@ -1540,7 +1524,10 @@ void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom
|
|||||||
nodes.push_back(node);
|
nodes.push_back(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks, int groupID)
|
||||||
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
std::vector<nodeInfo>::iterator iter = nodes.begin();
|
std::vector<nodeInfo>::iterator iter = nodes.begin();
|
||||||
while(iter != nodes.end())
|
while(iter != nodes.end())
|
||||||
@@ -1554,8 +1541,168 @@ void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom
|
|||||||
{
|
{
|
||||||
writeLog(LOG_TYPE_INFO, "Node " + iter->group + " - " + iter->remarks + " has been added.");
|
writeLog(LOG_TYPE_INFO, "Node " + iter->group + " - " + iter->remarks + " has been added.");
|
||||||
iter->id = index;
|
iter->id = index;
|
||||||
|
iter->groupID = groupID;
|
||||||
++index;
|
++index;
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned long long streamToInt(std::string stream)
|
||||||
|
{
|
||||||
|
if(!stream.size())
|
||||||
|
return 0;
|
||||||
|
double streamval = 1.0;
|
||||||
|
if(stream.find("GB") != std::string::npos)
|
||||||
|
streamval = std::pow(1024, 3) * stof(stream.substr(0, stream.size() - 2));
|
||||||
|
else if(stream.find("TB") != std::string::npos)
|
||||||
|
streamval = std::pow(1024, 4) * stof(stream.substr(0, stream.size() - 2));
|
||||||
|
else if(stream.find("PB") != std::string::npos)
|
||||||
|
streamval = std::pow(1024, 5) * stof(stream.substr(0, stream.size() - 2));
|
||||||
|
else if(stream.find("MB") != std::string::npos)
|
||||||
|
streamval = std::pow(1024, 2) * stof(stream.substr(0, stream.size() - 2));
|
||||||
|
else if(stream.find("KB") != std::string::npos)
|
||||||
|
streamval = 1024.0 * stof(stream.substr(0, stream.size() - 2));
|
||||||
|
else if(stream.find("B") != std::string::npos)
|
||||||
|
streamval = 1.0 * stof(stream.substr(0, stream.size() - 1));
|
||||||
|
return (unsigned long long)streamval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double percentToDouble(std::string percent)
|
||||||
|
{
|
||||||
|
return stof(percent.erase(percent.size() - 1)) / 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t dateStringToTimestamp(std::string date)
|
||||||
|
{
|
||||||
|
std::vector<std::string> date_array = split(date, ":");
|
||||||
|
if(date_array.size() != 6)
|
||||||
|
return 0;
|
||||||
|
time_t rawtime;
|
||||||
|
struct tm *expire_time;
|
||||||
|
time(&rawtime);
|
||||||
|
expire_time = localtime(&rawtime);
|
||||||
|
expire_time->tm_year = to_int(date_array[0], 1900) - 1900;
|
||||||
|
expire_time->tm_mon = to_int(date_array[1], 1) - 1;
|
||||||
|
expire_time->tm_mday = to_int(date_array[2]);
|
||||||
|
expire_time->tm_hour = to_int(date_array[3]);
|
||||||
|
expire_time->tm_min = to_int(date_array[4]);
|
||||||
|
expire_time->tm_sec = to_int(date_array[5]);
|
||||||
|
return mktime(expire_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getSubInfoFromHeader(std::string &header, std::string &result)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
pcrecpp::RE reg("^(?i:Subscription-UserInfo): (.*?)\\r$", pcrecpp::MULTILINE());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ret = reg.PartialMatch(header, &result);
|
||||||
|
}
|
||||||
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getSubInfoFromNodes(std::vector<nodeInfo> &nodes, string_array &stream_rules, string_array &time_rules, std::string &result)
|
||||||
|
{
|
||||||
|
std::string remarks, pattern, target, stream_info, time_info;
|
||||||
|
string_array vArray;
|
||||||
|
|
||||||
|
for(nodeInfo &x : nodes)
|
||||||
|
{
|
||||||
|
remarks = x.remarks;
|
||||||
|
if(!stream_info.size())
|
||||||
|
{
|
||||||
|
for(std::string &y : stream_rules)
|
||||||
|
{
|
||||||
|
vArray = split(y, "|");
|
||||||
|
if(vArray.size() != 2)
|
||||||
|
continue;
|
||||||
|
pattern = vArray[0];
|
||||||
|
target = vArray[1];
|
||||||
|
pcrecpp::RE reg(pattern, pcrecpp::UTF8());
|
||||||
|
if(reg.FullMatch(remarks))
|
||||||
|
{
|
||||||
|
if(target.find("$") != target.npos)
|
||||||
|
target = replace_all_distinct(target, "$", "\\");
|
||||||
|
if(reg.GlobalReplace(target, &remarks))
|
||||||
|
stream_info = remarks;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remarks = x.remarks;
|
||||||
|
if(!time_info.size())
|
||||||
|
{
|
||||||
|
for(std::string &y : time_rules)
|
||||||
|
{
|
||||||
|
vArray = split(y, "|");
|
||||||
|
if(vArray.size() != 2)
|
||||||
|
continue;
|
||||||
|
pattern = vArray[0];
|
||||||
|
target = vArray[1];
|
||||||
|
pcrecpp::RE reg(pattern, pcrecpp::UTF8());
|
||||||
|
if(reg.FullMatch(remarks))
|
||||||
|
{
|
||||||
|
if(target.find("$") != target.npos)
|
||||||
|
target = replace_all_distinct(target, "$", "\\");
|
||||||
|
if(reg.GlobalReplace(target, &remarks))
|
||||||
|
time_info = remarks;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stream_info.size() && time_info.size())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!stream_info.size() && !time_info.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//calculate how much stream left
|
||||||
|
unsigned long long total = 0, left = 0, used = 0, expire = 0;
|
||||||
|
std::string total_str = getUrlArg(stream_info, "total"), left_str = getUrlArg(stream_info, "left"), used_str = getUrlArg(stream_info, "used");
|
||||||
|
if(strFind(total_str, "%"))
|
||||||
|
{
|
||||||
|
if(used_str.size())
|
||||||
|
{
|
||||||
|
used = streamToInt(used_str);
|
||||||
|
total = used / (1 - percentToDouble(total_str));
|
||||||
|
}
|
||||||
|
else if(left_str.size())
|
||||||
|
{
|
||||||
|
left = streamToInt(left_str);
|
||||||
|
total = left / percentToDouble(total_str);
|
||||||
|
used = total - left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
total = streamToInt(total_str);
|
||||||
|
if(used_str.size())
|
||||||
|
{
|
||||||
|
used = streamToInt(used_str);
|
||||||
|
}
|
||||||
|
else if(left_str.size())
|
||||||
|
{
|
||||||
|
left = streamToInt(left_str);
|
||||||
|
used = total - left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = "upload=0; download=" + std::to_string(used) + "; total=" + std::to_string(total) + ";";
|
||||||
|
|
||||||
|
//calculate expire time
|
||||||
|
expire = dateStringToTimestamp(time_info);
|
||||||
|
if(expire != 0)
|
||||||
|
result += " expire=" + std::to_string(expire) + ";";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
+6
-3
@@ -20,9 +20,12 @@ void explodeShadowrocket(std::string kit, std::string custom_port, int local_por
|
|||||||
void explodeKitsunebi(std::string kit, std::string custom_port, int local_port, nodeInfo &node);
|
void explodeKitsunebi(std::string kit, std::string custom_port, int local_port, nodeInfo &node);
|
||||||
void explode(std::string link, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, nodeInfo &node);
|
void explode(std::string link, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, nodeInfo &node);
|
||||||
void explodeSSD(std::string link, bool libev, std::string custom_port, int local_port, std::vector<nodeInfo> &nodes);
|
void explodeSSD(std::string link, bool libev, std::string custom_port, int local_port, std::vector<nodeInfo> &nodes);
|
||||||
void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks);
|
void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, std::vector<nodeInfo> &nodes);
|
||||||
int explodeConf(std::string filepath, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks);
|
int explodeConf(std::string filepath, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes);
|
||||||
int explodeConfContent(std::string content, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks);
|
int explodeConfContent(std::string content, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes);
|
||||||
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);
|
||||||
|
void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks, int groupID);
|
||||||
|
bool getSubInfoFromHeader(std::string &header, std::string &result);
|
||||||
|
bool getSubInfoFromNodes(std::vector<nodeInfo> &nodes, string_array &stream_rules, string_array &time_rules, std::string &result);
|
||||||
|
|
||||||
#endif // SPEEDTESTUTIL_H_INCLUDED
|
#endif // SPEEDTESTUTIL_H_INCLUDED
|
||||||
Reference in new issue
Block a user