use crate::{
models::ExtraSettings,
utils::{
matcher::{apply_matcher, reg_find},
starts_with,
},
Proxy,
};
pub fn group_generate(
rule: &str,
nodelist: &[Proxy],
filtered_nodelist: &mut Vec<String>,
add_direct: bool,
ext: &ExtraSettings,
) {
if starts_with(rule, "[]") && add_direct {
filtered_nodelist.push(rule[2..].to_string());
} else if starts_with(rule, "script:") && ext.authorized {
} else {
for node in nodelist {
let mut real_rule = String::new();
if apply_matcher(rule, &mut real_rule, node) {
if real_rule.is_empty() || reg_find(&node.remark, &real_rule) {
filtered_nodelist.push(node.remark.clone());
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::models::{Proxy, ProxyType};
fn create_test_nodes() -> Vec<Proxy> {
vec![
Proxy {
id: 1,
group_id: 1,
group: "HK".to_string(),
remark: "HK Node 1".to_string(),
hostname: "hk1.example.com".to_string(),
port: 443,
proxy_type: ProxyType::Shadowsocks,
udp: Some(true),
..Default::default()
},
Proxy {
id: 2,
group_id: 1,
group: "HK".to_string(),
remark: "HK Node 2".to_string(),
hostname: "hk2.example.com".to_string(),
port: 8388,
proxy_type: ProxyType::Shadowsocks,
..Default::default()
},
Proxy {
id: 3,
group_id: 2,
group: "JP".to_string(),
remark: "JP Node 1".to_string(),
hostname: "jp1.example.com".to_string(),
port: 443,
proxy_type: ProxyType::VMess,
..Default::default()
},
Proxy {
id: 4,
group_id: 3,
group: "US".to_string(),
remark: "US Node 1".to_string(),
hostname: "us1.example.com".to_string(),
port: 8080,
proxy_type: ProxyType::Trojan,
..Default::default()
},
]
}
#[test]
fn test_group_generate_direct_string() {
let nodes = create_test_nodes();
let mut filtered = Vec::new();
let ext = ExtraSettings::default();
group_generate("[]DIRECT", &nodes, &mut filtered, true, &ext);
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0], "DIRECT");
}
#[test]
fn test_group_generate_with_group_match() {
let nodes = create_test_nodes();
let mut filtered = Vec::new();
let ext = ExtraSettings::default();
group_generate("!!GROUP=HK", &nodes, &mut filtered, true, &ext);
assert_eq!(filtered.len(), 2);
assert!(filtered.contains(&"HK Node 1".to_string()));
assert!(filtered.contains(&"HK Node 2".to_string()));
}
#[test]
fn test_group_generate_with_type_match() {
let nodes = create_test_nodes();
let mut filtered = Vec::new();
let ext = ExtraSettings::default();
group_generate("!!TYPE=VMESS", &nodes, &mut filtered, true, &ext);
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0], "JP Node 1");
}
#[test]
fn test_group_generate_with_port_match() {
let nodes = create_test_nodes();
let mut filtered = Vec::new();
let ext = ExtraSettings::default();
group_generate("!!PORT=443", &nodes, &mut filtered, true, &ext);
assert_eq!(filtered.len(), 2);
assert!(filtered.contains(&"HK Node 1".to_string()));
assert!(filtered.contains(&"JP Node 1".to_string()));
}
#[test]
fn test_group_generate_empty_result_with_direct() {
let nodes = create_test_nodes();
let mut filtered = Vec::new();
let ext = ExtraSettings::default();
group_generate("!!GROUP=SG", &nodes, &mut filtered, true, &ext);
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0], "DIRECT");
}
#[test]
fn test_group_generate_empty_result_without_direct() {
let nodes = create_test_nodes();
let mut filtered = Vec::new();
let ext = ExtraSettings::default();
group_generate("!!GROUP=SG", &nodes, &mut filtered, false, &ext);
assert_eq!(filtered.len(), 0);
}
#[test]
fn test_group_generate_with_regex_match() {
let nodes = create_test_nodes();
let mut filtered = Vec::new();
let ext = ExtraSettings::default();
group_generate("Node \\d", &nodes, &mut filtered, true, &ext);
assert_eq!(filtered.len(), 4);
assert!(filtered.contains(&"HK Node 1".to_string()));
assert!(filtered.contains(&"HK Node 2".to_string()));
assert!(filtered.contains(&"JP Node 1".to_string()));
assert!(filtered.contains(&"US Node 1".to_string()));
}
}