feat: Add client.subscribe.servers hook for plugin-based server extension

- Add HookManager::filter('client.subscribe.servers') hook in ClientController::subscribe()
- Allow plugins to inject custom servers into subscription responses
- Update protocol classes to support extended server configurations
- Enable dynamic server list modification before protocol processing
This commit is contained in:
xboard
2025-07-11 21:19:23 +08:00
parent 1e59bc8ca1
commit 97788e3c8f
13 changed files with 48 additions and 47 deletions
+5 -5
View File
@@ -42,19 +42,19 @@ class Clash extends AbstractProtocol
array_push($proxies, $item['name']);
}
if ($item['type'] === 'vmess') {
array_push($proxy, self::buildVmess($user['uuid'], $item));
array_push($proxies, $item['name']);
array_push($proxy, self::buildVmess($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'trojan') {
array_push($proxy, self::buildTrojan($user['uuid'], $item));
array_push($proxy, self::buildTrojan($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'socks') {
array_push($proxy, self::buildSocks5($user['uuid'], $item));
array_push($proxy, self::buildSocks5($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'http') {
array_push($proxy, self::buildHttp($user['uuid'], $item));
array_push($proxy, self::buildHttp($item['password'], $item));
array_push($proxies, $item['name']);
}
}
+9 -9
View File
@@ -84,42 +84,42 @@ class ClashMeta extends AbstractProtocol
array_push($proxies, $item['name']);
}
if ($item['type'] === 'vmess') {
array_push($proxy, self::buildVmess($user['uuid'], $item));
array_push($proxy, self::buildVmess($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'trojan') {
array_push($proxy, self::buildTrojan($user['uuid'], $item));
array_push($proxy, self::buildTrojan($item['password'], $item));
array_push($proxies, $item['name']);
}
if (
$item['type'] === 'vless'
&& in_array(data_get($protocol_settings, 'network'), ['tcp', 'ws', 'grpc', 'http', 'h2'])
) {
array_push($proxy, self::buildVless($user['uuid'], $item));
array_push($proxy, self::buildVless($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'hysteria') {
array_push($proxy, self::buildHysteria($user['uuid'], $item, $user));
array_push($proxy, self::buildHysteria($item['password'], $item, $user));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'tuic') {
array_push($proxy, self::buildTuic($user['uuid'], $item));
array_push($proxy, self::buildTuic($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'anytls') {
array_push($proxy, self::buildAnyTLS($user['uuid'], $item));
array_push($proxy, self::buildAnyTLS($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'socks') {
array_push($proxy, self::buildSocks5($user['uuid'], $item));
array_push($proxy, self::buildSocks5($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'http') {
array_push($proxy, self::buildHttp($user['uuid'], $item));
array_push($proxy, self::buildHttp($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'mieru') {
array_push($proxy, self::buildMieru($user['uuid'], $item));
array_push($proxy, self::buildMieru($item['password'], $item));
array_push($proxies, $item['name']);
}
}
+5 -5
View File
@@ -35,22 +35,22 @@ class General extends AbstractProtocol
foreach ($servers as $item) {
if ($item['type'] === 'vmess') {
$uri .= self::buildVmess($user['uuid'], $item);
$uri .= self::buildVmess($item['password'], $item);
}
if ($item['type'] === 'vless') {
$uri .= self::buildVless($user['uuid'], $item);
$uri .= self::buildVless($item['password'], $item);
}
if ($item['type'] === 'shadowsocks') {
$uri .= self::buildShadowsocks($item['password'], $item);
}
if ($item['type'] === 'trojan') {
$uri .= self::buildTrojan($user['uuid'], $item);
$uri .= self::buildTrojan($item['password'], $item);
}
if ($item['type'] === 'hysteria') {
$uri .= self::buildHysteria($user['uuid'], $item);
$uri .= self::buildHysteria($item['password'], $item);
}
if ($item['type'] === 'socks') {
$uri .= self::buildSocks($user['uuid'], $item);
$uri .= self::buildSocks($item['password'], $item);
}
}
return response(base64_encode($uri))->header('content-type', 'text/plain');
+3 -3
View File
@@ -32,13 +32,13 @@ class Loon extends AbstractProtocol
$uri .= self::buildShadowsocks($item['password'], $item);
}
if ($item['type'] === 'vmess') {
$uri .= self::buildVmess($user['uuid'], $item);
$uri .= self::buildVmess($item['password'], $item);
}
if ($item['type'] === 'trojan') {
$uri .= self::buildTrojan($user['uuid'], $item);
$uri .= self::buildTrojan($item['password'], $item);
}
if ($item['type'] === 'hysteria') {
$uri .= self::buildHysteria($user['uuid'], $item, $user);
$uri .= self::buildHysteria($item['password'], $item, $user);
}
}
return response($uri)
+2 -2
View File
@@ -18,10 +18,10 @@ class QuantumultX extends AbstractProtocol
$uri .= self::buildShadowsocks($item['password'], $item);
}
if ($item['type'] === 'vmess') {
$uri .= self::buildVmess($user['uuid'], $item);
$uri .= self::buildVmess($item['password'], $item);
}
if ($item['type'] === 'trojan') {
$uri .= self::buildTrojan($user['uuid'], $item);
$uri .= self::buildTrojan($item['password'], $item);
}
}
return response(base64_encode($uri))
+7 -7
View File
@@ -39,25 +39,25 @@ class Shadowrocket extends AbstractProtocol
$uri .= self::buildShadowsocks($item['password'], $item);
}
if ($item['type'] === 'vmess') {
$uri .= self::buildVmess($user['uuid'], $item);
$uri .= self::buildVmess($item['password'], $item);
}
if ($item['type'] === 'vless') {
$uri .= self::buildVless($user['uuid'], $item);
$uri .= self::buildVless($item['password'], $item);
}
if ($item['type'] === 'trojan') {
$uri .= self::buildTrojan($user['uuid'], $item);
$uri .= self::buildTrojan($item['password'], $item);
}
if ($item['type'] === 'hysteria') {
$uri .= self::buildHysteria($user['uuid'], $item);
$uri .= self::buildHysteria($item['password'], $item);
}
if ($item['type'] === 'tuic') {
$uri .= self::buildTuic($user['uuid'], $item);
$uri .= self::buildTuic($item['password'], $item);
}
if ($item['type'] === 'anytls') {
$uri .= self::buildAnyTLS($user['uuid'], $item);
$uri .= self::buildAnyTLS($item['password'], $item);
}
if ($item['type'] === 'socks') {
$uri .= self::buildSocks($user['uuid'], $item);
$uri .= self::buildSocks($item['password'], $item);
}
}
return response(base64_encode($uri))
+1 -1
View File
@@ -47,7 +47,7 @@ class Shadowsocks extends AbstractProtocol
"remarks" => $server['name'],
"server" => $server['host'],
"server_port" => $server['port'],
"password" => $user['uuid'],
"password" => $item['password'],
"method" => data_get($server, 'protocol_settings.cipher')
];
return $config;
+8 -8
View File
@@ -85,35 +85,35 @@ class Stash extends AbstractProtocol
array_push($proxies, $item['name']);
}
if ($item['type'] === 'vmess') {
array_push($proxy, self::buildVmess($user['uuid'], $item));
array_push($proxy, self::buildVmess($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'vless') {
array_push($proxy, $this->buildVless($user['uuid'], $item));
array_push($proxy, $this->buildVless($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'hysteria') {
array_push($proxy, self::buildHysteria($user['uuid'], $item));
array_push($proxy, self::buildHysteria($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'trojan') {
array_push($proxy, self::buildTrojan($user['uuid'], $item));
array_push($proxy, self::buildTrojan($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'tuic') {
array_push($proxy, self::buildTuic($user['uuid'], $item));
array_push($proxy, self::buildTuic($item['password'], $item));
array_push($proxies, $item['name']);
}
// if ($item['type'] === 'anytls') {
// array_push($proxy, self::buildAnyTLS($user['uuid'], $item));
// array_push($proxy, self::buildAnyTLS($item['password'], $item));
// array_push($proxies, $item['name']);
// }
if ($item['type'] === 'socks') {
array_push($proxy, self::buildSocks5($user['uuid'], $item));
array_push($proxy, self::buildSocks5($item['password'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'http') {
array_push($proxy, self::buildHttp($user['uuid'], $item));
array_push($proxy, self::buildHttp($item['password'], $item));
array_push($proxies, $item['name']);
}
}
+2 -2
View File
@@ -40,13 +40,13 @@ class Surfboard extends AbstractProtocol
}
if ($item['type'] === 'vmess') {
// [Proxy]
$proxies .= self::buildVmess($user['uuid'], $item);
$proxies .= self::buildVmess($item['password'], $item);
// [Proxy Group]
$proxyGroup .= $item['name'] . ', ';
}
if ($item['type'] === 'trojan') {
// [Proxy]
$proxies .= self::buildTrojan($user['uuid'], $item);
$proxies .= self::buildTrojan($item['password'], $item);
// [Proxy Group]
$proxyGroup .= $item['name'] . ', ';
}
+3 -3
View File
@@ -46,15 +46,15 @@ class Surge extends AbstractProtocol
$proxyGroup .= $item['name'] . ', ';
}
if ($item['type'] === 'vmess') {
$proxies .= self::buildVmess($user['uuid'], $item);
$proxies .= self::buildVmess($item['password'], $item);
$proxyGroup .= $item['name'] . ', ';
}
if ($item['type'] === 'trojan') {
$proxies .= self::buildTrojan($user['uuid'], $item);
$proxies .= self::buildTrojan($item['password'], $item);
$proxyGroup .= $item['name'] . ', ';
}
if ($item['type'] === 'hysteria') {
$proxies .= self::buildHysteria($user['uuid'], $item);
$proxies .= self::buildHysteria($item['password'], $item);
$proxyGroup .= $item['name'] . ', ';
}
}