diff --git a/app/Http/Controllers/SakaiController.php b/app/Http/Controllers/SakaiController.php index 6917f352..4300b325 100755 --- a/app/Http/Controllers/SakaiController.php +++ b/app/Http/Controllers/SakaiController.php @@ -9,6 +9,10 @@ use voku\helper\AntiXSS; use App\Models\Tags; use App\Services\TomTool\Http; use App\Services\CountrySpeedService; +use App\Services\ServiceFnPoolV2rayTo; +use App\Models\FreenodePool as ModelFreenodePool; +use App\Services\Cron\ReportTraffic; + class SakaiController { @@ -22,10 +26,46 @@ class SakaiController public function test1() { - - $r = CountrySpeedService::fn_b(); - var_dump($r); + $oReportTraffic = new ReportTraffic(); + + $oReportTraffic->all(); + } + + public function test1__b() + { + $s = $this->xx1(); + + $s = json_decode($s, true); + + echo "
";
+ echo json_encode($s, JSON_PRETTY_PRINT);
exit;
+
+
+
+ print($s);
+ }
+
+ public function test1__a()
+ {
+ $sContent = ModelFreenodePool::whereDate("date", "2026-07-29")->first()?->content;
+ $aContent = json_decode($sContent, true);
+
+ $oServiceFnPoolV2rayTo = new ServiceFnPoolV2rayTo();
+
+ $oServiceFnPoolV2rayTo->singbox($aContent["v2ray"]);
+
+// $a = $oServiceFnPoolV2rayTo->test_allXieyi($aContent["v2ray"]);
+// tt($a);
+
+ exit;
+ }
+
+ private function xx1()
+ {
+ $s = '{"log":{"level":"error"},"dns":{"servers":[{"tag":"local","address":"local"}],"rules":[{"outbound":"any","server":"local"}],"final":"local","strategy":"prefer_ipv6"},"inbounds":[{"type":"tun","inet4_address":"172.19.0.1\/30","auto_route":true,"strict_route":true,"endpoint_independent_nat":true,"udp_timeout":60,"platform":{"http_proxy":{"enabled":true,"server":"127.0.0.1","server_port":7891}},"sniff":true},{"type":"mixed","listen":"127.0.0.1","listen_port":7891,"sniff":true,"domain_strategy":"prefer_ipv6"}],"outbounds":[{"type":"selector","tag":"default","outbounds":["\u9999\u6e2f 01","\u9999\u6e2f 02","\u9999\u6e2f 03","\u9999\u6e2f 04","\u9999\u6e2f 05","\u9999\u6e2f 06","\u9999\u6e2f 07","\u9999\u6e2f 08","\u9999\u6e2f 09","\u9999\u6e2f 10","\u9999\u6e2f 11","\u9999\u6e2f 12","\u9999\u6e2f 13\uff5c7\u500d\u7387 \u9ad8\u901f\u4e13\u7ebf","\u9999\u6e2f 14\uff5c7\u500d\u7387 \u9ad8\u901f\u4e13\u7ebf","\u65e5\u672c 01","\u65e5\u672c 02","\u65e5\u672c 03","\u65e5\u672c 04","\u65e5\u672c 05","\u65e5\u672c 06","\u65e5\u672c 07","\u65e5\u672c 08","\u65e5\u672c 09","\u65e5\u672c 10","\u65e5\u672c 11","\u65e5\u672c 12","\u65e5\u672c 13\uff5c\u589e\u5f3a\u89e3\u9501","\u65e5\u672c 14\uff5c\u589e\u5f3a\u89e3\u9501","\u65e5\u672c 15\uff5c\u589e\u5f3a\u89e3\u9501","\u65e5\u672c 16\uff5c\u589e\u5f3a\u89e3\u9501","\u7f8e\u56fd 01","\u7f8e\u56fd 02","\u7f8e\u56fd 03","\u7f8e\u56fd 04","\u7f8e\u56fd 05","\u7f8e\u56fd 06","\u7f8e\u56fd 07","\u7f8e\u56fd 08","\u7f8e\u56fd 09\uff5c\u589e\u5f3a\u89e3\u9501","\u7f8e\u56fd 10\uff5c\u589e\u5f3a\u89e3\u9501","\u7f8e\u56fd 11\uff5c\u589e\u5f3a\u89e3\u9501","\u7f8e\u56fd 12\uff5c\u589e\u5f3a\u89e3\u9501","\u65b0\u52a0\u5761 01","\u65b0\u52a0\u5761 02","\u65b0\u52a0\u5761 03","\u65b0\u52a0\u5761 04","\u65b0\u52a0\u5761 05","\u65b0\u52a0\u5761 06","\u65b0\u52a0\u5761 07","\u65b0\u52a0\u5761 08","\u65b0\u52a0\u5761 09","\u8d8a\u5357 01"]},{"type":"direct","tag":"direct"},{"type":"block","tag":"block"},{"type":"vless","tag":"\u9999\u6e2f 01","server":"0201.gembox-dns.com","server_port":45507,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk07.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 02","server":"0201.gembox-dns.com","server_port":45506,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk06.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 03","server":"0201.gembox-dns.com","server_port":45501,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk01.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 04","server":"0201.gembox-dns.com","server_port":45505,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk05.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 05","server":"0201.gembox-dns.com","server_port":45506,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk06.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 06","server":"0201.gembox-dns.com","server_port":45504,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk04.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 07","server":"0201.gembox-dns.com","server_port":45504,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk04.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 08","server":"0201.gembox-dns.com","server_port":45503,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk03.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 09","server":"0201.gembox-dns.com","server_port":45505,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk05.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 10","server":"0201.gembox-dns.com","server_port":45501,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk01.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 11","server":"0201.gembox-dns.com","server_port":45507,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk07.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 12","server":"0201.gembox-dns.com","server_port":45502,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk02.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 13\uff5c7\u500d\u7387 \u9ad8\u901f\u4e13\u7ebf","server":"i2plcwjnhrl6.gym0boy.com","server_port":46507,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk07.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u9999\u6e2f 14\uff5c7\u500d\u7387 \u9ad8\u901f\u4e13\u7ebf","server":"i2plcwjnhrl6.gym0boy.com","server_port":46506,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"hk06.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 01","server":"0201.gembox-dns.com","server_port":45208,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp08.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 02","server":"0201.gembox-dns.com","server_port":45202,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp02.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 03","server":"0201.gembox-dns.com","server_port":45205,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp05.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 04","server":"0201.gembox-dns.com","server_port":45205,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp05.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 05","server":"0201.gembox-dns.com","server_port":45206,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp06.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 06","server":"0201.gembox-dns.com","server_port":45202,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp02.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 07","server":"0201.gembox-dns.com","server_port":45203,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp03.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 08","server":"0201.gembox-dns.com","server_port":45208,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp08.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 09","server":"0201.gembox-dns.com","server_port":45206,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp06.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 10","server":"0201.gembox-dns.com","server_port":45207,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp07.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 11","server":"0201.gembox-dns.com","server_port":45204,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp04.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 12","server":"0201.gembox-dns.com","server_port":45207,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"jp07.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65e5\u672c 13\uff5c\u589e\u5f3a\u89e3\u9501","server":"151.242.165.111","server_port":443,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"xtls-rprx-vision","tls":{"enabled":true,"server_name":"y-taxacct.jp","utls":{"enabled":true,"fingerprint":"chrome"},"reality":{"enabled":true,"public_key":"S7DAIOws5ZIf_swZ3n1cO9JW5FztCJQDI7zytCljjl8","short_id":"32c3d894"}}},{"type":"vless","tag":"\u65e5\u672c 14\uff5c\u589e\u5f3a\u89e3\u9501","server":"r1.gembox-dns.com","server_port":443,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"xtls-rprx-vision","tls":{"enabled":true,"server_name":"www.amazon.com","utls":{"enabled":true,"fingerprint":"chrome"},"reality":{"enabled":true,"public_key":"_7-gwupJ-N6NNmsMPW9CipEBFiapfWZ88uKOavJRyGc","short_id":"8a8a8a"}}},{"type":"vless","tag":"\u65e5\u672c 15\uff5c\u589e\u5f3a\u89e3\u9501","server":"151.242.165.111","server_port":443,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"xtls-rprx-vision","tls":{"enabled":true,"server_name":"y-taxacct.jp","utls":{"enabled":true,"fingerprint":"chrome"},"reality":{"enabled":true,"public_key":"S7DAIOws5ZIf_swZ3n1cO9JW5FztCJQDI7zytCljjl8","short_id":"32c3d894"}}},{"type":"vless","tag":"\u65e5\u672c 16\uff5c\u589e\u5f3a\u89e3\u9501","server":"r1.gembox-dns.com","server_port":443,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"xtls-rprx-vision","tls":{"enabled":true,"server_name":"www.amazon.com","utls":{"enabled":true,"fingerprint":"chrome"},"reality":{"enabled":true,"public_key":"_7-gwupJ-N6NNmsMPW9CipEBFiapfWZ88uKOavJRyGc","short_id":"8a8a8a"}}},{"type":"vless","tag":"\u7f8e\u56fd 01","server":"0201.gembox-dns.com","server_port":45102,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"us02.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u7f8e\u56fd 02","server":"0201.gembox-dns.com","server_port":45102,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"us02.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u7f8e\u56fd 03","server":"0201.gembox-dns.com","server_port":45101,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"us01.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u7f8e\u56fd 04","server":"0201.gembox-dns.com","server_port":45103,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"us03.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u7f8e\u56fd 05","server":"0201.gembox-dns.com","server_port":45103,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"us03.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u7f8e\u56fd 06","server":"0201.gembox-dns.com","server_port":45101,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"us01.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u7f8e\u56fd 07","server":"0201.gembox-dns.com","server_port":45104,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"us04.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u7f8e\u56fd 08","server":"0201.gembox-dns.com","server_port":45104,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"us04.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u7f8e\u56fd 09\uff5c\u589e\u5f3a\u89e3\u9501","server":"23.144.20.205","server_port":443,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"xtls-rprx-vision","tls":{"enabled":true,"server_name":"millturnprecisionmachine.com","utls":{"enabled":true,"fingerprint":"chrome"},"reality":{"enabled":true,"public_key":"h15Fz4Kf1Wh5COIt1JOEzb3T9B15MCEVSFcChYEFskU","short_id":"32c3d894"}}},{"type":"vless","tag":"\u7f8e\u56fd 10\uff5c\u589e\u5f3a\u89e3\u9501","server":"154.29.150.101","server_port":443,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"xtls-rprx-vision","tls":{"enabled":true,"server_name":"www.amazon.com","utls":{"enabled":true,"fingerprint":"chrome"},"reality":{"enabled":true,"public_key":"0md1HDKBpWvvZsWltU1FhTW2qVB5JHl3sxNr_pILRyA","short_id":"094f6fe5"}}},{"type":"vless","tag":"\u7f8e\u56fd 11\uff5c\u589e\u5f3a\u89e3\u9501","server":"154.29.150.101","server_port":443,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"xtls-rprx-vision","tls":{"enabled":true,"server_name":"www.amazon.com","utls":{"enabled":true,"fingerprint":"chrome"},"reality":{"enabled":true,"public_key":"0md1HDKBpWvvZsWltU1FhTW2qVB5JHl3sxNr_pILRyA","short_id":"094f6fe5"}}},{"type":"vless","tag":"\u7f8e\u56fd 12\uff5c\u589e\u5f3a\u89e3\u9501","server":"23.144.20.205","server_port":443,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"xtls-rprx-vision","tls":{"enabled":true,"server_name":"millturnprecisionmachine.com","utls":{"enabled":true,"fingerprint":"chrome"},"reality":{"enabled":true,"public_key":"h15Fz4Kf1Wh5COIt1JOEzb3T9B15MCEVSFcChYEFskU","short_id":"32c3d894"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 01","server":"0201.gembox-dns.com","server_port":45301,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg01.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 02","server":"0201.gembox-dns.com","server_port":45302,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg02.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 03","server":"0201.gembox-dns.com","server_port":45305,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg05.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 04","server":"0201.gembox-dns.com","server_port":45302,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg02.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 05","server":"0201.gembox-dns.com","server_port":45305,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg05.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 06","server":"0201.gembox-dns.com","server_port":45304,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg04.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 07","server":"0201.gembox-dns.com","server_port":45303,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg03.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 08","server":"0201.gembox-dns.com","server_port":45304,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg04.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u65b0\u52a0\u5761 09","server":"0201.gembox-dns.com","server_port":45303,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"sg03.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}},{"type":"vless","tag":"\u8d8a\u5357 01","server":"0201.gembox-dns.com","server_port":45801,"uuid":"417b28b3-f814-409f-a895-e7f96fc22e4c","flow":"","tls":{"enabled":true,"server_name":"vn01.gembox-dns.com","utls":{"enabled":true,"fingerprint":"chrome"}}}],"route":{"rules":[{"clash_mode":"Direct","outbound":"direct"},{"clash_mode":"Rule","outbound":"default"},{"clash_mode":"Global","outbound":"default"},{"protocol":"stun","outbound":"block"},{"ip_is_private":true,"outbound":"direct"},{"rule_set":"geoip-cn","outbound":"direct"},{"rule_set":"geosite-cn","outbound":"direct"}],"rule_set":[{"tag":"geoip-cn","type":"remote","format":"binary","url":"https:\/\/fastly.jsdelivr.net\/gh\/SagerNet\/sing-geoip@rule-set\/geoip-cn.srs","download_detour":"direct"},{"tag":"geosite-cn","type":"remote","format":"binary","url":"https:\/\/fastly.jsdelivr.net\/gh\/SagerNet\/sing-geosite@rule-set\/geosite-cn.srs","download_detour":"direct"}],"auto_detect_interface":true},"experimental":{"cache_file":{"enabled":true,"cache_id":"\u798f\u4e91"},"clash_api":{"external_controller":"127.0.0.1:9090"}}}';
+
+ return $s;
}
function __construct()
diff --git a/app/Services/Cron.php b/app/Services/Cron.php
index a0b55c7d..fc089062 100755
--- a/app/Services/Cron.php
+++ b/app/Services/Cron.php
@@ -49,14 +49,13 @@ final class Cron
}
if ($h % 6 === 0 && $i === 3) {
- ShadowRocketCrawl::run();
- ShadowRocketPublish::run();
-// exit;
-
+ ShadowRocketCrawl::run(); // 爬取小火箭id
+ ShadowRocketPublish::run(); // 小火箭id发布到site
CronFreenodeCrawl::run(); // 1.爬免费节点
CronFreenodePool::save(); // 2.格式化入库
CronFreenodeMerge::save(); // 3.加工成文件
- CronFreenodeMerge::baseToSite(); // 4.文件分散为各站用
+ CronFreenodeMerge::baseToSite("fn_a"); // 4.文件分散为各站用
+ CronFreenodeMerge::baseToSite("fn_b");
}
if ($h % 3 === 0 && $i === 3) {
diff --git a/app/Services/Cron/FnSitePublish.php b/app/Services/Cron/FnSitePublish.php
index bdcc3cbc..2d21a27a 100755
--- a/app/Services/Cron/FnSitePublish.php
+++ b/app/Services/Cron/FnSitePublish.php
@@ -68,7 +68,12 @@ final class FnSitePublish
$sSiteFnClientNick = $sSiteFnClient;
if ($sSiteFnClient == "v2ray") {
$sSiteFnClientNick = "v2ray\shadowrocket\小火箭";
+ } else if ($sSiteFnClient == "singbox") {
+ $sSiteFnClientNick = "singbox\hiddify";
+ } else if ($sSiteFnClient == "clash") {
+ $sSiteFnClientNick = "clash\mihomo";
}
+
$sFeedLink = "https://".FreenodeHelperService::urlFeedToday($oSite->code_short, $sSiteFnClient);
$str = "";
$str .= "".$sSiteFnClientNick."订阅链接:\n\n";
diff --git a/app/Services/Cron/FreenodeCrawl.php b/app/Services/Cron/FreenodeCrawl.php
index 0a1ac144..e400700a 100755
--- a/app/Services/Cron/FreenodeCrawl.php
+++ b/app/Services/Cron/FreenodeCrawl.php
@@ -8,6 +8,8 @@ use App\Models\CrawlFreenode as ModelCrawlFreenode;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
//use Symfony\Component\Yaml\Yaml;
+
+// 第一步,从哪爬,run
final class FreenodeCrawl
{
diff --git a/app/Services/Cron/FreenodeFile.php b/app/Services/Cron/FreenodeFile.php
index de0be814..9f36f4cf 100755
--- a/app/Services/Cron/FreenodeFile.php
+++ b/app/Services/Cron/FreenodeFile.php
@@ -10,6 +10,7 @@ use App\Models\SiteMap as ModelSiteMap;
use App\Models\Option as ModelOption;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
+// 其实是清理文件
final class FreenodeFile
{
diff --git a/app/Services/Cron/FreenodeMerge.php b/app/Services/Cron/FreenodeMerge.php
index 97c1637c..401cfea8 100755
--- a/app/Services/Cron/FreenodeMerge.php
+++ b/app/Services/Cron/FreenodeMerge.php
@@ -12,6 +12,7 @@ use App\Models\Option as ModelOption;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
use Symfony\Component\Yaml\Yaml;
+// 应该是最终步骤,整合处理为对应站点的
final class FreenodeMerge
{
private static $aCountryOrder = [
@@ -148,6 +149,11 @@ final class FreenodeMerge
$aNode["config"]["name"] = $sFlagCountry;
$aNodeMerge[] = $aNode["config"];
$aNodeCountryList[] = $sFlagCountry;
+ } else if ($sPoolClient == "singbox") {
+ $sFlagCountry = self::countryJoinFlag($aNode["country"]);
+ $aNode["config"]["name"] = $sFlagCountry;
+ $aNodeMerge[] = $aNode["config"];
+ $aNodeCountryList[] = $sFlagCountry;
} else {
$aNodeMerge[] = json_encode($aNode);
}
@@ -203,10 +209,36 @@ final class FreenodeMerge
$sMerge = Yaml::dump($aClashTemplate, 4, 2);
$sPattern = '/(?<=^|\s)(cipher|name|type):\s+((?!\'|")[^\s"\'\n]+)/m';
- $sMerge = preg_replace($sPattern, '$1: "$2"', $sMerge);
+ $sMerge = preg_replace($sPattern, '$1: "$2"', $sMerge); // 什么作用
-// tomd($sMerge, 1);
+ } else if ($sPoolClient == "singbox") {
+ $sFile = $sDirBase."public/freenode/template/singbox.txt";
+
+ if (file_exists($sFile) && is_readable($sFile)) {
+ $sSingboxTemplate = file_get_contents($sFile); // data
+ } else {
+ $sMsg = "singbox的template不存在,这不应该 \n";
+ TeleSlave::warn()->send($sMsg);
+ echo $sMsg;
+ continue;
+ }
+
+ $aSingboxConfig = json_decode($sSingboxTemplate, true);
+
+ foreach ($aSingboxConfig["outbounds"] as &$aOutbounds) {
+
+ if ($aOutbounds["type"] == "selector") {
+ $aOutbounds["outbounds"] = $aNodeCountryList;
+ continue;
+ }
+ }
+
+ array_push($aSingboxConfig["outbounds"], $aNodeMerge);
+
+ $sMerge = json_encode($aSingboxConfig);
+ } else {
+ $sMerge = "?";
}
$sFileDir = $sDirBase."public/freenode/merge/base/".$sPoolClient;
@@ -224,7 +256,7 @@ final class FreenodeMerge
}
- public static function baseToSite()
+ public static function baseToSite($sSiteGroupCodeTom)
{
echo "\nFreenodeMerge::baseToSite - 开始 \n";
@@ -234,7 +266,7 @@ final class FreenodeMerge
$sDirBase = $_ENV["dir_base"];
- $sFnClientList = ModelOption::_hit("freenode_client-fn_a");
+ $sFnClientList = ModelOption::_hit("freenode_client-".$sSiteGroupCodeTom);
if (!$sFnClientList) {
throw new \Exception("未设置option的freenode_client?");
@@ -253,7 +285,7 @@ final class FreenodeMerge
}
}
- $oSiteMap = ModelSiteMap::whereIn("group_code", ["fn_a", "fn_b"])->get();
+ $oSiteMap = ModelSiteMap::whereIn("group_code", [$sSiteGroupCodeTom])->get();
if ($oSiteMap->isEmpty()) {
throw new \Exception("没找到siteMap的fn_a组?");
diff --git a/app/Services/Cron/FreenodePool.php b/app/Services/Cron/FreenodePool.php
index bf053a08..30317993 100755
--- a/app/Services/Cron/FreenodePool.php
+++ b/app/Services/Cron/FreenodePool.php
@@ -8,7 +8,9 @@ use App\Models\CrawlFreenode as ModelCrawlFreenode;
use App\Models\FreenodePool as ModelFreenodePool;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
use Symfony\Component\Yaml\Yaml;
+use App\Services\ServiceFnPoolV2rayTo;
+// 应该是第二步:入库先
final class FreenodePool
{
@@ -100,6 +102,12 @@ final class FreenodePool
}
$aMerge[$sFromFileRealClient][$sConfigMd5] = $aNodeFormat;
+
+ $aNodeFormat_singbox = (new ServiceFnPoolV2rayTo())->singbox_row($aNodeFormat);
+ if (!empty($aNodeFormat_singbox)) {
+ $aMerge["singbox"][$sConfigMd5] = $aNodeFormat_singbox;
+ }
+
}
} else if ($sFromFileRealClient == "clash") {
@@ -137,6 +145,8 @@ final class FreenodePool
}
}
}
+
+// $aMerge["singbox"] = ServiceFnPool::SingboxByV2ray($aMerge["v2ray"]); // 免费节点都是必有v2ray,clash则未必,所以默认必有v2ray
$oPool->content = $aMerge;
$oPool->save();
diff --git a/app/Services/Cron/FreenodeSync.php b/app/Services/Cron/FreenodeSync.php
index 2baa9c5d..4d032568 100755
--- a/app/Services/Cron/FreenodeSync.php
+++ b/app/Services/Cron/FreenodeSync.php
@@ -9,6 +9,7 @@ use App\Services\TomTool\Telegram\Slave as TeleSlave;
use App\Services\TomTool\HttpV2;
use Illuminate\Support\Facades\Http;
+// 这是向站点推送,步骤之外
final class FreenodeSync
{
static function run()
diff --git a/app/Services/Cron/ReportTraffic.php b/app/Services/Cron/ReportTraffic.php
new file mode 100755
index 00000000..f6c992f8
--- /dev/null
+++ b/app/Services/Cron/ReportTraffic.php
@@ -0,0 +1,53 @@
+umami();
+ }
+
+ public function umami()
+ {
+ $r = $this->umami_checkToken();
+
+ tt($r);
+ }
+
+ private function umami_checkToken()
+ {
+ $oResponse = Http::post('https://api.umami.is/api/auth/login', [
+ 'username' => "ad1473af-2b82-4e9b-a726-36bef6cc512b",
+ 'password' => "UOtaonihouzi123#",
+ ]);
+
+ // 工业级防御:非 2xx 响应直接抛出 Http 异常
+ $oResponse->throw();
+
+ // 解析 JSON
+ $aData = $oResponse->json();
+
+ // 检查 Key 是否符合预期(假设返回结构为 {"token": "xxx"})
+ if (empty($aData['token'])) {
+ throw new Exception('接口响应格式有误:缺失 token 字段');
+ }
+
+ return $aData['token'];
+ }
+}
diff --git a/app/Services/FreenodeHelperService.php b/app/Services/FreenodeHelperService.php
index 26f50349..9f9aca48 100644
--- a/app/Services/FreenodeHelperService.php
+++ b/app/Services/FreenodeHelperService.php
@@ -27,12 +27,13 @@ class FreenodeHelperService
return $sFeedUrl;
}
+ // 应该是没用上的,按理应该有code和groupcode映射
public static function getClients()
{
$aClients = [
"clash",
"v2ray",
-// "singbox",
+ "singbox",
];
return $aClients;
diff --git a/app/Services/ServiceFnPoolV2rayTo.php b/app/Services/ServiceFnPoolV2rayTo.php
new file mode 100644
index 00000000..60d59f5b
--- /dev/null
+++ b/app/Services/ServiceFnPoolV2rayTo.php
@@ -0,0 +1,514 @@
+";
+ if ($i <= 0) {
+// continue;
+ }
+
+ if ($i >= 100) {
+// continue;
+ }
+
+
+
+ $aPoolSingbox = $this->singbox_row($aPoolV2ray);
+ if (!$aPoolSingbox) continue; //测试用
+ t($aPoolV2ray);
+ t($aPoolSingbox);
+
+ echo "=======================================================";
+ }
+ exit;
+ }
+
+ public function singbox_row($aPoolV2ray)
+ {
+ $aNode = $aPoolV2ray;
+ if (isset($aPoolV2ray['protocolType'])) {
+ $aPoolV2ray['protocolType'] = $this->removeUtf8Bom($aPoolV2ray['protocolType']);
+ }
+
+ $sProtocol = $aPoolV2ray['protocolType'] ?? '';
+
+ if (isset($aPoolV2ray["config"]) && !is_array($aPoolV2ray["config"])) {
+ $aPoolV2ray["config"] = rawurldecode($aPoolV2ray["config"]);
+ }
+
+ $sModTo = 'mod_to_'.$sProtocol;
+ if (!method_exists($this, $sModTo)) {
+ return false; // 没做对应处理的直接排除
+ }
+
+ $aNode = $this->$sModTo($aPoolV2ray);
+
+ return $aNode;
+ }
+
+ private function mod_to_socks($aV2ray)
+ {
+ $sConfig = $aV2ray["config"] ?? '';
+
+ $aTmp = explode("@", $sConfig, 2);
+ $sPwd = $aTmp[0] ?? '';
+ $sConfig = $aTmp[1] ?? '';
+
+ $sPwd = $this->tomBase64Decode($sPwd);
+ $aTmp = explode(":", $sPwd, 2);
+ $sUser = $aTmp[0] ?? '';
+ $sPwd = $aTmp[1] ?? '';
+
+ $aTmp = explode(":", $sConfig, 2);
+ $sAddr = $aTmp[0] ?? '';
+ $iPort = (int) $aTmp[1] ?? '';
+
+ $aNode = [
+ "type" => "socks",
+ "tag" => $aV2ray['country'] ?? '',
+ "server"=> $sAddr,
+ "server_port" => $iPort,
+ "username" => $sUser,
+ "password" => $sPwd
+ ];
+
+ $aV2ray["config"] = $aNode;
+
+ return $aV2ray;
+ }
+
+ private function mod_to_trojan($aV2ray)
+ {
+ $sConfig = $aV2ray["config"] ?? '';
+
+ $aTmp = explode("@", $sConfig, 2);
+ $sPwd = $aTmp[0] ?? '';
+ $sConfig = $aTmp[1] ?? '';
+
+ $aTmp = explode("?", $sConfig, 2);
+ $sAddrFull = $aTmp[0] ?? '';
+ $sConfig = $aTmp[1] ?? '';
+
+ $aTmp = explode(":", $sAddrFull, 2);
+ $sAddr = $aTmp[0] ?? '';
+ $iPort = (int) $aTmp[1] ?? '';
+
+ $aNode = [
+ "type" => "trojan",
+ "tag" => $aV2ray['country'] ?? '',
+ "server"=> $sAddr,
+ "server_port" => $iPort,
+ "password" => $sPwd
+ ];
+
+ $aCustomYuan = explode("&", $sConfig);
+ $aCustom = [];
+ foreach ($aCustomYuan as $sRow) {
+ $aRow = explode("=", $sRow, 2);
+ $k = $aRow[0] ?? '';
+ $v = $aRow[1] ?? '';
+ $aCustom[$k] = $v;
+ }
+
+ $aTls = []; // 层1的tls
+ $aUtls = []; // 层2的utls
+
+ if (isset($aCustom["sni"])) { // 写层1的tls
+ $aTls["server_name"] = $this->parseServerName($aCustom["sni"], $aCustom["sni"]);
+ }
+ if (isset($aCustom["host"])) { // 写层1的tls -- host覆盖sni=host优先
+ $aTls["server_name"] = $this->parseServerName($aCustom["host"], $aCustom["host"]);
+ }
+ if (isset($aCustom["alpn"])) { // 写层1的tls
+ $aTls["alpn"] = explode(",", $aCustom["alpn"]);
+ }
+ if (isset($aCustom["allowInsecure"])) { // 写层1的tls
+ $aTls["insecure"] = (bool) $aCustom["allowInsecure"];
+ }
+
+ if (isset($aCustom["fp"])) { // 写层2的utls
+ $aUtls["fingerprint"] = $aCustom["fp"];
+ }
+ if (!empty($aUtls)) { // 层2的utls并入tls
+ $aUtls["enabled"] = true;
+ $aTls["utls"] = $aUtls;
+ }
+
+ if (!empty($aTls)) { // 层1的tlstls并入node
+ $aTls["enabled"] = true;
+ $aNode["tls"] = $aTls;
+ }
+
+ $aTransport = [];
+ if (isset($aCustom["type"]) && $aCustom["type"] != "none" && $aCustom["type"] != "tcp" && $aCustom["type"] != "raw") {
+ $aTransport["type"] = $aCustom["type"];
+ if ($aCustom["type"] == "ws" && isset($aTls["server_name"])) {
+ $aTransport["headers"]["Host"] = $aTls["server_name"];
+ }
+ }
+ if (isset($aCustom["path"])) {
+ $aTransport["path"] = rawurldecode($aCustom["path"]);
+ }
+ if (!empty($aTransport)) {
+ $aNode["transport"] = $aTransport;
+ }
+
+ $aV2ray["config"] = $aNode;
+
+ return $aV2ray;
+ }
+
+ private function mod_to_hysteria2($aV2ray)
+ {
+ $sConfig = $aV2ray["config"] ?? '';
+
+ $aTmp = explode("@", $sConfig, 2);
+ $sPwd = $aTmp[0] ?? '';
+ $sConfig = $aTmp[1] ?? '';
+
+ $aTmp = explode("?", $sConfig, 2);
+ $sAddrFull = $aTmp[0] ?? '';
+ $sConfig = $aTmp[1] ?? '';
+ $aTmp = explode(":", $sAddrFull, 2);
+ $sAddr = $aTmp[0] ?? '';
+ $iPort = (int) $aTmp[1] ?? '';
+
+ $cCustom = explode("&", $sConfig);
+ $aCustom = [];
+ foreach ($cCustom as $sCustom) {
+ $aTmp = explode("=", $sCustom);
+ $k = $aTmp[0] ?? '';
+ $v = $aTmp[1] ?? '';
+ $aCustom[$k] = $v;
+ }
+
+ $aNode = [
+ "type" => "hysteria2",
+ "tag" => $aV2ray['country'] ?? '',
+ "server"=> $sAddr,
+ "server_port" => $iPort,
+ "password" => $sPwd
+ ];
+
+ $aTls = [];
+ if (isset($aCustom['sni'])) {
+ $aTls['server_name'] = $this->parseServerName($aCustom['sni'], $aCustom['sni']);
+ }
+ if (isset($aCustom['insecure'])) {
+ $aTls['insecure'] = (bool) $aCustom['insecure'] ?? 0;
+ }
+ if (!empty($aTls)) {
+ $aTls['enabled'] = true;
+ $aNode["tls"] = $aTls;
+ }
+
+ $aObfs = [];
+ if (isset($aCustom["obfs"])) {
+ $aObfs["type"] = $aCustom["obfs"];
+ }
+ if (isset($aCustom["obfs-password"])) {
+ $aObfs["password"] = $aCustom["obfs-password"];
+ }
+ if (!empty($aObfs)) {
+ $aNode["obfs"] = $aObfs;
+ }
+
+ $aV2ray["config"] = $aNode;
+
+ return $aV2ray;
+ }
+
+ private function mod_to_ss($aV2ray)
+ {
+ $sConfig = $aV2ray["config"] ?? '';
+
+ $aTmp = explode("@", $sConfig, 2);
+ $sPwd = $aTmp[0] ?? '';
+ $sConfig = $aTmp[1] ?? '';
+
+ $sPwd = $this->tomBase64Decode($sPwd);
+
+ $aTmp = explode(":", $sPwd, 2);
+ $sPwdType = $aTmp[0] ?? '';
+ $sPwd = $aTmp[1] ?? '';
+
+ $aTmp = explode(":", $sConfig, 2);
+ $sAddr = $aTmp[0] ?? '';
+ $iPort = (int) $aTmp[1] ?? '';
+
+ // 推荐的现代化 SS 算法白名单
+ $aAllowedCiphers = [
+ '2022-blake3-aes-128-gcm',
+ '2022-blake3-aes-256-gcm',
+ '2022-blake3-chacha20-poly1305',
+ 'aes-128-gcm',
+ 'aes-192-gcm',
+ 'aes-256-gcm',
+ 'chacha20-ietf-poly1305',
+ 'xchacha20-ietf-poly1305',
+ ];
+
+ if (!in_array($sPwdType, $aAllowedCiphers, true)) {
+ return false;
+ }
+
+ $aNode = [
+ "type" => "shadowsocks",
+ "tag" => $aV2ray['country'] ?? '',
+ "server" => $sAddr,
+ "server_port" => $iPort,
+ "method" => $sPwdType,
+ "password" => $sPwd,
+ ];
+
+ return $aNode;
+ }
+
+ private function mod_to_vmess($aV2ray)
+ {
+ $aNode = [];
+ $aConfig = $aV2ray["config"];
+
+ $aNode["type"] = "vmess";
+ $aNode["tag"] = $aV2ray['country'] ?? '';
+ $aNode["server"] = $aConfig["add"] ?? '';
+ $aNode["server_port"] = (int) $aConfig["port"] ?? '';
+ $aNode["uuid"] = $aConfig["id"] ?? '';
+ $aNode["security"] = $aConfig["scy"] ?? 'auto';
+ $aNode["alter_id"] = (int) $aConfig["aid"] ?? 0; // 猜的
+
+ $aTransport = [];
+ if (isset($aConfig["net"]) && $aConfig["net"] != "tcp" && $aConfig["net"] != "none" && $aConfig["net"] != "raw") {
+ $aTransport["type"] = $aConfig["net"];
+ }
+ if (isset($aConfig["path"])) {
+ $aTransport["path"] = rawurldecode($aConfig["path"]);
+ }
+ if (isset($aConfig["host"])) {
+ $aTransport["headers"]["Host"] = $aConfig["host"];
+ }
+ if (!empty($aTransport)) {
+ $aNode["transport"] = $aTransport;
+ }
+
+ $aTls = [];
+ if (isset($aConfig["tls"])) {
+ if ($aConfig["tls"] == "tls") {
+ $aTls["server_name"] = !empty($aConfig['host']) ? $aConfig['host'] : $aConfig['add'];
+ $aTls["server_name"] = $this->parseServerName($aTls["server_name"], $aTls["server_name"]);
+ }
+ }
+ if (!empty($aTls)) {
+ $aTls["enabled"] = true;
+ $aNode["tls"] = $aTls;
+ }
+
+ $aV2ray["config"] = $aNode;
+
+ return $aV2ray;
+ }
+
+ private function mod_to_vless($aV2ray)
+ {
+ $sConfig = $aV2ray['config'] ?? '';
+
+ $aTmp = explode("@", $sConfig, 2);
+ $sPwd = $aTmp[0] ?? ''; // *
+ $sConfig = $aTmp[1] ?? '';
+
+ $aTmp = explode("?", $sConfig, 2);
+ $sAddrFull = $aTmp[0];
+ $sConfig = $aTmp[1];
+
+ $aTmp = explode(":", $sAddrFull, 2);
+ $sAddr = $aTmp[0] ?? ''; // *
+ $sPort = $aTmp[1] ?? ''; // *
+
+ $aCustomTmp = explode("&", $sConfig);
+ $aCustom = [];
+ foreach ($aCustomTmp as $aCustomRow) {
+ $aTmp = explode("=", $aCustomRow, 2);
+ $k = $aTmp[0] ?? '';
+ $v = $aTmp[1] ?? '';
+ $aCustom[$k] = $v; // *
+ }
+
+ $aNode = [
+ 'type' => 'vless',
+ 'tag' => $aV2ray['country'] ?? '',
+ 'server' => $sAddr,
+ 'server_port' => (int) $sPort,
+ 'uuid' => $sPwd,
+ ];
+ if (isset($aCustom["packetEncoding"]) && $aCustom["packetEncoding"] != "none") {
+ $aNode["packet_encoding"] = $aCustom["packetEncoding"];
+ }
+ if (isset($aCustom["flow"])) {
+ $aNode["flow"] = $aCustom["flow"];
+ }
+
+
+ $aTransport = [];
+ if (isset($aCustom["type"]) && $aCustom["type"] != "tcp" && $aCustom["type"] != "raw") {
+ $aTransport["type"] = $aCustom["type"];
+ }
+ if (isset($aCustom["headerType"]) && $aCustom["headerType"] == "http") {
+ $aTransport["type"] = "http"; // 整个http覆盖默认tcp
+ }
+ if (isset($aCustom["path"])) {
+ $aTransport["path"] = rawurldecode($aCustom["path"]);
+ }
+ if (isset($aCustom["host"])) {
+ $aTransport["headers"]["Host"] = $aCustom["host"];
+ }
+ if (isset($aCustom["serviceName"])) {
+ $aTransport["service_name"] = $aCustom["serviceName"];
+ }
+ if (!empty($aTransport)) {
+ $aNode["transport"] = $aTransport;
+ }
+
+
+ $aTls = []; // 本体
+ $aUtls = []; // 二层
+ $aReality = []; // 二层
+
+ if (isset($aCustom["fp"])) { // 二层的utls构建
+ if ($aCustom["fp"] == "random") {
+ $aCustom["fp"] = "chrome";
+ }
+ $aUtls["fingerprint"] = $aCustom["fp"];
+ }
+ if (!empty($aUtls)) { // 二层的utls封装进tls
+ $aUtls["enabled"] = true;
+ $aTls["utls"] = $aUtls;
+ }
+ if (isset($aCustom["security"])) {
+ $sSecurity = $aCustom["security"];
+ if ($sSecurity == "reality") { // 二层的reality构建
+ if (isset($aCustom["pbk"])) {
+ $aReality["public_key"] = $aCustom["pbk"];
+ }
+ if (isset($aCustom["sid"])) {
+ $aReality["short_id"] = (string) $aCustom["sid"];
+ }
+ }
+ }
+ if (!empty($aReality)) { // 二层的reality封建进tls
+ $aReality["enabled"] = true;
+ $aTls["reality"] = $aReality;
+ }
+
+ if (isset($aCustom["alpn"])) {
+ $sTmp = $aCustom["alpn"] ?? "";
+ $aTmp = explode(",", $sTmp);
+ $aTls["alpn"] = $aTmp;
+ }
+ if (isset($aCustom["sni"])) { // 本体的tls构建
+ $aTls["server_name"] = $this->parseServerName($aCustom["sni"], $aCustom["sni"]);
+ }
+ if (isset($aCustom["encryption"]) && $aCustom["encryption"] != "none") { // 本体的tls构建
+ $aTls["encryption"] = $aCustom["encryption"];
+ }
+ if (!empty($aTls)) { // 本体的tls封装进node
+ $aTls["enabled"] = true;
+ $aNode["tls"] = $aTls;
+ }
+
+ $aV2ray["config"] = $aNode;
+
+ return $aV2ray;
+ }
+
+ private function tomBase64Decode(mixed $xInput): string
+ {
+ // 1. 防御性类型检查
+ if (!is_string($xInput) || $xInput === '') {
+ return (string) $xInput;
+ }
+
+ // 2. 开启严格模式解码
+ $sDecoded = base64_decode($xInput, true);
+
+ if ($sDecoded === false) {
+ return $xInput;
+ }
+
+ // 3. 反向验证:确保它不是像 humanity 这种恰好能被解码的纯普通文本
+ if (base64_encode($sDecoded) !== $xInput) {
+ return $xInput;
+ }
+
+ // 4. 核心:校验解码后的数据是否为合法 UTF-8 文本,且不包含不可打印控制字符(\x00-\x08, \x0B-\x0C, \x0E-\x1F)
+ $bIsValidUtf8 = mb_check_encoding($sDecoded, 'UTF-8');
+ $bHasControlChars = (bool) preg_match('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', $sDecoded);
+
+ if ($bIsValidUtf8 && !$bHasControlChars) {
+ return $sDecoded; // 解码出来是合法的正常文本(包含中文、英文、数字等)
+ }
+
+ // 解码出来包含真正的二进制控制符(乱码),说明输入原本就是纯字符串,返回原值
+ return rawurldecode($xInput);
+ }
+
+ public function test_allXieyi($cPoolV2ray)
+ {
+ $aXieyi = [];
+ foreach ($cPoolV2ray as $aV2ray) {
+ $sXieyi = $aV2ray["protocolType"];
+ $sXieyi = $this->removeUtf8Bom($sXieyi);
+
+ $iXieyi = $aXieyi[$sXieyi] ?? 0;
+ $iXieyi++;
+
+ $aXieyi[$sXieyi] = $iXieyi;
+ }
+
+ return $aXieyi;
+ }
+
+ private function removeUtf8Bom(string $sInput): string
+ {
+ if (str_starts_with($sInput, "\xEF\xBB\xBF")) {
+ return substr($sInput, 3);
+ }
+
+ return $sInput;
+ }
+
+ private function parseServerName(string $sSni, string $sFallbackServer): string
+ {
+ $sSni = trim($sSni);
+ $sSni = rawurldecode($sSni);
+ if (empty($sSni)) {
+ return $sFallbackServer;
+ }
+
+ // 针对包含 http:// 或 https:// 的情况进行解析
+ if (preg_match('#^https?://#i', $sSni)) {
+ $aUrl = parse_url($sSni);
+ $sSni = $aUrl['host'] ?? '';
+ }
+
+ // 剔除可能残余的路径与端口号 (例如 domain.com/path 或 domain.com:8080)
+ if (str_contains($sSni, '/')) {
+ $sSni = explode('/', $sSni)[0];
+ }
+ if (str_contains($sSni, ':')) {
+ $sSni = explode(':', $sSni)[0];
+ }
+
+ // 若提取后仍为空,回退到节点自身的 server 字段
+ return !empty($sSni) ? $sSni : $sFallbackServer;
+ }
+
+}
diff --git a/public/freenode/template/singbox.txt b/public/freenode/template/singbox.txt
new file mode 100755
index 00000000..8c8f9d2a
--- /dev/null
+++ b/public/freenode/template/singbox.txt
@@ -0,0 +1,119 @@
+{
+ "log": {
+ "level": "error"
+ },
+ "dns": {
+ "servers": [
+ {
+ "tag": "local",
+ "address": "local"
+ }
+ ],
+ "rules": [
+ {
+ "outbound": "any",
+ "server": "local"
+ }
+ ],
+ "final": "local",
+ "strategy": "prefer_ipv6"
+ },
+ "inbounds": [
+ {
+ "type": "tun",
+ "inet4_address": "172.19.0.1\/30",
+ "auto_route": true,
+ "strict_route": true,
+ "endpoint_independent_nat": true,
+ "udp_timeout": 60,
+ "platform": {
+ "http_proxy": {
+ "enabled": true,
+ "server": "127.0.0.1",
+ "server_port": 7891
+ }
+ },
+ "sniff": true
+ },
+ {
+ "type": "mixed",
+ "listen": "127.0.0.1",
+ "listen_port": 7891,
+ "sniff": true,
+ "domain_strategy": "prefer_ipv6"
+ }
+ ],
+ "outbounds": [
+ {
+ "type": "selector",
+ "tag": "default",
+ "outbounds": []
+ },
+ {
+ "type": "direct",
+ "tag": "direct"
+ },
+ {
+ "type": "block",
+ "tag": "block"
+ }
+ ],
+ "route": {
+ "rules": [
+ {
+ "clash_mode": "Direct",
+ "outbound": "direct"
+ },
+ {
+ "clash_mode": "Rule",
+ "outbound": "default"
+ },
+ {
+ "clash_mode": "Global",
+ "outbound": "default"
+ },
+ {
+ "protocol": "stun",
+ "outbound": "block"
+ },
+ {
+ "ip_is_private": true,
+ "outbound": "direct"
+ },
+ {
+ "rule_set": "geoip-cn",
+ "outbound": "direct"
+ },
+ {
+ "rule_set": "geosite-cn",
+ "outbound": "direct"
+ }
+ ],
+ "rule_set": [
+ {
+ "tag": "geoip-cn",
+ "type": "remote",
+ "format": "binary",
+ "url": "https:\/\/fastly.jsdelivr.net\/gh\/SagerNet\/sing-geoip@rule-set\/geoip-cn.srs",
+ "download_detour": "direct"
+ },
+ {
+ "tag": "geosite-cn",
+ "type": "remote",
+ "format": "binary",
+ "url": "https:\/\/fastly.jsdelivr.net\/gh\/SagerNet\/sing-geosite@rule-set\/geosite-cn.srs",
+ "download_detour": "direct"
+ }
+ ],
+ "auto_detect_interface": true
+ },
+ "experimental": {
+ "cache_file": {
+ "enabled": true,
+ "cache_id": "clashfreenode"
+ },
+ "clash_api": {
+ "external_controller": "127.0.0.1:9090"
+ }
+ }
+}