Files
NeoTachyon/tachyon/files/usr/lib/singbox/urltest.uc
T

168 lines
4.6 KiB
Ucode

#!/usr/bin/env ucode
let common = require("core.common");
let as_string = common.as_string;
let array_or_empty = common.array_or_empty;
let object_or_empty = common.object_or_empty;
function contains(values, needle) {
for (let value in values) {
if (value == needle)
return true;
}
return false;
}
function regex_matches(value, pattern) {
pattern = as_string(pattern);
if (pattern == "")
return false;
try {
return match(as_string(value), regexp(pattern)) != null;
}
catch (e) {
return false;
}
}
function normalized_country_list(values) {
let result = [];
for (let value in array_or_empty(values)) {
value = uc(as_string(value));
if (length(value) == 2)
push(result, value);
}
return result;
}
function byte_at(value, index) {
return ord(value, index);
}
function regional_indicator_letter(value, index) {
if (index + 3 >= length(value))
return "";
if (byte_at(value, index) != 240 ||
byte_at(value, index + 1) != 159 ||
byte_at(value, index + 2) != 135)
return "";
let letter = byte_at(value, index + 3) - 166;
if (letter < 0 || letter > 25)
return "";
return chr(65 + letter);
}
function country_from_flag_emoji(value) {
value = as_string(value);
for (let i = 0; i + 7 < length(value); i++) {
let first = regional_indicator_letter(value, i);
if (first == "")
continue;
let second = regional_indicator_letter(value, i + 4);
if (second != "")
return first + second;
}
return "";
}
function countries_from_flag_names(names) {
names = object_or_empty(names);
let result = {};
for (let tag, name in names) {
let country = country_from_flag_emoji(name);
if (country != "")
result[tag] = country;
}
return result;
}
function regex_matching_tag_array(tags, names, regexes) {
tags = array_or_empty(tags);
names = object_or_empty(names);
regexes = array_or_empty(regexes);
let compiled = [];
for (let pattern in regexes) {
let pat_str = as_string(pattern);
if (pat_str != "") {
try {
push(compiled, regexp(pat_str));
} catch(e) {}
}
}
let result = [];
for (let tag in tags) {
let name = names[tag];
name = name == null || as_string(name) == "" ? tag : as_string(name);
for (let re in compiled) {
if (match(name, re) != null) {
push(result, tag);
break;
}
}
}
return result;
}
function filter_array(mode, tags, names, countries, name_filter, regex_tags, country_filter) {
tags = array_or_empty(tags);
names = object_or_empty(names);
countries = object_or_empty(countries);
name_filter = array_or_empty(name_filter);
regex_tags = array_or_empty(regex_tags);
country_filter = array_or_empty(country_filter);
let result = [];
for (let tag in tags) {
let name = as_string(names[tag] || tag);
let country = uc(as_string(countries[tag] || ""));
let matched = contains(name_filter, name) ||
contains(name_filter, tag) ||
(country != "" && contains(country_filter, country)) ||
contains(regex_tags, tag);
if ((mode == "include" && matched) || (mode == "exclude" && !matched))
push(result, tag);
}
return result;
}
function filter_mode(mode, tags, names, countries, include_names, include_regexes, include_countries, exclude_names, exclude_regexes, exclude_countries) {
include_countries = normalized_country_list(include_countries);
exclude_countries = normalized_country_list(exclude_countries);
let include_regex_tags = regex_matching_tag_array(tags, names, include_regexes);
let exclude_regex_tags = regex_matching_tag_array(tags, names, exclude_regexes);
if (mode == "include")
return filter_array("include", tags, names, countries, include_names, include_regex_tags, include_countries);
if (mode == "exclude")
return filter_array("exclude", tags, names, countries, exclude_names, exclude_regex_tags, exclude_countries);
if (mode == "mixed") {
let included = filter_array("include", tags, names, countries, include_names, include_regex_tags, include_countries);
return filter_array("exclude", included, names, countries, exclude_names, exclude_regex_tags, exclude_countries);
}
return array_or_empty(tags);
}
return {
normalized_country_list,
countries_from_flag_names,
regex_matching_tag_array,
filter_array,
filter_mode
};