mirror of
https://github.com/MetaCubeX/subconverter.git
synced 2025-11-04 18:19:42 +08:00
Enhanced Profile Configuration Parsing and Tag Matching in profile.ini (#820)
1. exclude/include supports tag matching for "!!GROUP=", "!!GROUPID=", and "!!INSERT=". 2. exclude/include supports multiple expressions separated by the delimiter '`'. 3. Supports parsing multi-line contents for "url=", "rename=", and "exclude/include=" by merging them into a single line using delimiters.
This commit is contained in:
parent
e17246df7c
commit
c2610a3804
@ -174,13 +174,13 @@ int addNodes(std::string link, std::vector<Proxy> &allNodes, int groupID, parse_
|
|||||||
if(!getSubInfoFromHeader(extra_headers, subInfo))
|
if(!getSubInfoFromHeader(extra_headers, subInfo))
|
||||||
getSubInfoFromNodes(nodes, stream_rules, time_rules, subInfo);
|
getSubInfoFromNodes(nodes, stream_rules, time_rules, subInfo);
|
||||||
}
|
}
|
||||||
filterNodes(nodes, exclude_remarks, include_remarks, groupID);
|
|
||||||
for(Proxy &x : nodes)
|
for(Proxy &x : nodes)
|
||||||
{
|
{
|
||||||
x.GroupId = groupID;
|
x.GroupId = groupID;
|
||||||
if(custom_group.size())
|
if(custom_group.size())
|
||||||
x.Group = custom_group;
|
x.Group = custom_group;
|
||||||
}
|
}
|
||||||
|
filterNodes(nodes, exclude_remarks, include_remarks, groupID);
|
||||||
copyNodes(nodes, allNodes);
|
copyNodes(nodes, allNodes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -206,13 +206,13 @@ int addNodes(std::string link, std::vector<Proxy> &allNodes, int groupID, parse_
|
|||||||
{
|
{
|
||||||
getSubInfoFromNodes(nodes, stream_rules, time_rules, subInfo);
|
getSubInfoFromNodes(nodes, stream_rules, time_rules, subInfo);
|
||||||
}
|
}
|
||||||
filterNodes(nodes, exclude_remarks, include_remarks, groupID);
|
|
||||||
for(Proxy &x : nodes)
|
for(Proxy &x : nodes)
|
||||||
{
|
{
|
||||||
x.GroupId = groupID;
|
x.GroupId = groupID;
|
||||||
if(!custom_group.empty())
|
if(!custom_group.empty())
|
||||||
x.Group = custom_group;
|
x.Group = custom_group;
|
||||||
}
|
}
|
||||||
|
filterNodes(nodes, exclude_remarks, include_remarks, groupID);
|
||||||
copyNodes(nodes, allNodes);
|
copyNodes(nodes, allNodes);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -531,10 +531,58 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
|||||||
ext.rename_array = safe_get_renames();
|
ext.rename_array = safe_get_renames();
|
||||||
|
|
||||||
/// check custom include/exclude settings
|
/// check custom include/exclude settings
|
||||||
if(!argIncludeRemark.empty() && regValid(argIncludeRemark))
|
if (!argIncludeRemark.empty())
|
||||||
|
{
|
||||||
|
// Check if the delimiter ` is present
|
||||||
|
if (argIncludeRemark.find('`') != std::string::npos)
|
||||||
|
{
|
||||||
|
// Split argIncludeRemark using ` as the delimiter
|
||||||
|
string_array splitIncludeRemarks = split(argIncludeRemark, "`");
|
||||||
|
// Filter out invalid regular expressions
|
||||||
|
string_array tempValidRemarks;
|
||||||
|
for (const auto& remark : splitIncludeRemarks)
|
||||||
|
{
|
||||||
|
if (!remark.empty() && regValid(remark)) // Validate each split element using regValid
|
||||||
|
{
|
||||||
|
tempValidRemarks.push_back(remark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!tempValidRemarks.empty())
|
||||||
|
lIncludeRemarks = tempValidRemarks;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If no delimiter is found, follow the original logic
|
||||||
|
if (regValid(argIncludeRemark))
|
||||||
lIncludeRemarks = string_array{argIncludeRemark};
|
lIncludeRemarks = string_array{argIncludeRemark};
|
||||||
if(!argExcludeRemark.empty() && regValid(argExcludeRemark))
|
}
|
||||||
|
}
|
||||||
|
if (!argExcludeRemark.empty())
|
||||||
|
{
|
||||||
|
// Check if the delimiter ` is present
|
||||||
|
if (argExcludeRemark.find('`') != std::string::npos)
|
||||||
|
{
|
||||||
|
// Split argExcludeRemark using ` as the delimiter
|
||||||
|
string_array splitExcludeRemarks = split(argExcludeRemark, "`");
|
||||||
|
// Filter out invalid regular expressions
|
||||||
|
string_array tempValidRemarks;
|
||||||
|
for (const auto& remark : splitExcludeRemarks)
|
||||||
|
{
|
||||||
|
if (!remark.empty() && regValid(remark)) // Validate each split element using regValid
|
||||||
|
{
|
||||||
|
tempValidRemarks.push_back(remark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!tempValidRemarks.empty())
|
||||||
|
lExcludeRemarks = tempValidRemarks;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If no delimiter is found, follow the original logic
|
||||||
|
if (regValid(argExcludeRemark))
|
||||||
lExcludeRemarks = string_array{argExcludeRemark};
|
lExcludeRemarks = string_array{argExcludeRemark};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// initialize script runtime
|
/// initialize script runtime
|
||||||
if(authorized && !global.scriptCleanContext)
|
if(authorized && !global.scriptCleanContext)
|
||||||
@ -569,6 +617,8 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
|||||||
{
|
{
|
||||||
groupID = -1;
|
groupID = -1;
|
||||||
urls = split(global.insertUrls, "|");
|
urls = split(global.insertUrls, "|");
|
||||||
|
// Remove empty urls
|
||||||
|
urls.erase(std::remove_if(urls.begin(), urls.end(), [](const std::string& str) { return str.empty(); }), urls.end());
|
||||||
importItems(urls, true);
|
importItems(urls, true);
|
||||||
for(std::string &x : urls)
|
for(std::string &x : urls)
|
||||||
{
|
{
|
||||||
@ -588,6 +638,8 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
urls = split(argUrl, "|");
|
urls = split(argUrl, "|");
|
||||||
|
// Remove empty urls
|
||||||
|
urls.erase(std::remove_if(urls.begin(), urls.end(), [](const std::string& str) { return str.empty(); }), urls.end());
|
||||||
importItems(urls, true);
|
importItems(urls, true);
|
||||||
groupID = 0;
|
groupID = 0;
|
||||||
for(std::string &x : urls)
|
for(std::string &x : urls)
|
||||||
@ -1154,6 +1206,34 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
|
|||||||
return YAML::Dump(clash);
|
return YAML::Dump(clash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge multiple key-values based on delimiters
|
||||||
|
static void merge_values(const string_multimap& source,
|
||||||
|
const std::string& key,
|
||||||
|
std::string& merged,
|
||||||
|
char delimiter)
|
||||||
|
{
|
||||||
|
auto range = source.equal_range(key);
|
||||||
|
for (auto iter = range.first; iter != range.second; ++iter)
|
||||||
|
{
|
||||||
|
if (!iter->second.empty())
|
||||||
|
{
|
||||||
|
if (!merged.empty()) merged += delimiter;
|
||||||
|
merged += iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update container
|
||||||
|
static void update_container(string_multimap& container,
|
||||||
|
const std::string& key,
|
||||||
|
const std::string& merged)
|
||||||
|
{
|
||||||
|
if (!merged.empty()) {
|
||||||
|
container.erase(key);
|
||||||
|
container.emplace(key, merged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string getProfile(RESPONSE_CALLBACK_ARGS)
|
std::string getProfile(RESPONSE_CALLBACK_ARGS)
|
||||||
{
|
{
|
||||||
auto &argument = request.argument;
|
auto &argument = request.argument;
|
||||||
@ -1221,14 +1301,13 @@ std::string getProfile(RESPONSE_CALLBACK_ARGS)
|
|||||||
return "Forbidden";
|
return "Forbidden";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// check if more than one profile is provided
|
|
||||||
|
// Handle url
|
||||||
|
std::string all_urls;
|
||||||
|
merge_values(contents, "url", all_urls, '|');
|
||||||
if(profiles.size() > 1)
|
if(profiles.size() > 1)
|
||||||
{
|
{
|
||||||
writeLog(0, "Multiple profiles are provided. Trying to combine profiles...", LOG_TYPE_INFO);
|
writeLog(0, "Multiple profiles are provided. Trying to combine profiles...", LOG_TYPE_INFO);
|
||||||
std::string all_urls, url;
|
|
||||||
auto iter = contents.find("url");
|
|
||||||
if(iter != contents.end())
|
|
||||||
all_urls = iter->second;
|
|
||||||
for(size_t i = 1; i < profiles.size(); i++)
|
for(size_t i = 1; i < profiles.size(); i++)
|
||||||
{
|
{
|
||||||
name = profiles[i];
|
name = profiles[i];
|
||||||
@ -1242,10 +1321,12 @@ std::string getProfile(RESPONSE_CALLBACK_ARGS)
|
|||||||
writeLog(0, "Ignoring broken profile '" + name + "'...", LOG_LEVEL_WARNING);
|
writeLog(0, "Ignoring broken profile '" + name + "'...", LOG_LEVEL_WARNING);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
url = ini.get("Profile", "url");
|
string_multimap profile_items;
|
||||||
if(!url.empty())
|
ini.get_items("Profile", profile_items); // Get all key-value pairs in the [Profile] section
|
||||||
|
size_t before_length = all_urls.length();
|
||||||
|
merge_values(profile_items, "url", all_urls, '|');
|
||||||
|
if (all_urls.length() > before_length)
|
||||||
{
|
{
|
||||||
all_urls += "|" + url;
|
|
||||||
writeLog(0, "Profile url from '" + name + "' added.", LOG_LEVEL_INFO);
|
writeLog(0, "Profile url from '" + name + "' added.", LOG_LEVEL_INFO);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1253,8 +1334,24 @@ std::string getProfile(RESPONSE_CALLBACK_ARGS)
|
|||||||
writeLog(0, "Profile '" + name + "' does not have url key. Skipping...", LOG_LEVEL_INFO);
|
writeLog(0, "Profile '" + name + "' does not have url key. Skipping...", LOG_LEVEL_INFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iter->second = all_urls;
|
|
||||||
}
|
}
|
||||||
|
// Update the url key-value pairs in contents uniformly
|
||||||
|
update_container(contents, "url", all_urls);
|
||||||
|
|
||||||
|
// Handle rename
|
||||||
|
std::string all_renames;
|
||||||
|
merge_values(contents, "rename", all_renames, '`');
|
||||||
|
update_container(contents, "rename", all_renames);
|
||||||
|
|
||||||
|
// Handle exclude
|
||||||
|
std::string all_excludes;
|
||||||
|
merge_values(contents, "exclude", all_excludes, '`');
|
||||||
|
update_container(contents, "exclude", all_excludes);
|
||||||
|
|
||||||
|
// Handle include
|
||||||
|
std::string all_includes;
|
||||||
|
merge_values(contents, "include", all_includes, '`');
|
||||||
|
update_container(contents, "include", all_includes);
|
||||||
|
|
||||||
contents.emplace("token", token);
|
contents.emplace("token", token);
|
||||||
contents.emplace("profile_data", base64Encode(global.managedConfigPrefix + "/getprofile?" + joinArguments(argument)));
|
contents.emplace("profile_data", base64Encode(global.managedConfigPrefix + "/getprofile?" + joinArguments(argument)));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user