Explorar o código

Fixed when user in user_group will case getServers to failed

BrettonYe hai 3 meses
pai
achega
44a0a09188
Modificáronse 2 ficheiros con 86 adicións e 89 borrados
  1. 7 18
      app/Http/Controllers/User/SubscribeController.php
  2. 79 71
      app/Services/ProxyService.php

+ 7 - 18
app/Http/Controllers/User/SubscribeController.php

@@ -24,19 +24,13 @@ class SubscribeController extends Controller
 
     public function index(Request $request, string $code)
     {
-        preg_match('/[0-9A-Za-z]+/', $code, $matches, PREG_UNMATCHED_AS_NULL);
-
-        if (empty($matches) || empty($code)) {
+        if (! preg_match('/^[0-9A-Za-z]+$/', $code)) {
             return redirect()->route('login');
         }
 
-        $code = $matches[0];
-        self::$subType = is_numeric($request->input('type')) ? $request->input('type') : null;
-
         // 检查订阅码是否有效
         $subscribe = UserSubscribe::whereCode($code)->firstOrFail();
         $user = $subscribe->user;
-
         $userService = new UserService($user);
 
         return view('user.subscribe', [
@@ -49,17 +43,13 @@ class SubscribeController extends Controller
 
     public function getSubscribeByCode(Request $request, string $code): RedirectResponse|string
     { // 通过订阅码获取订阅信息
-        preg_match('/[0-9A-Za-z]+/', $code, $matches, PREG_UNMATCHED_AS_NULL);
-
-        if (empty($matches) || empty($code)) {
-            return redirect()->route('login');
-        }
-        $code = $matches[0];
         self::$subType = is_numeric($request->input('type')) ? $request->input('type') : null;
-
         // 检查订阅码是否有效
-        $subscribe = UserSubscribe::whereCode($code)->firstOrFail();
+        if (! preg_match('/^[0-9A-Za-z]+$/', $code)) {
+            $this->failed(trans('errors.subscribe.unknown'));
+        }
 
+        $subscribe = UserSubscribe::whereCode($code)->first();
         if (! $subscribe) {
             $this->failed(trans('errors.subscribe.unknown'));
         }
@@ -82,12 +72,11 @@ class SubscribeController extends Controller
                 $this->failed(trans('errors.subscribe.banned_until', ['time' => $user->ban_time]));
             }
 
-            $unusedTraffic = $user->unused_traffic;
-            if ($unusedTraffic <= 0) {
+            if ($user->unused_traffic <= 0) {
                 $this->failed(trans('errors.subscribe.out'));
             }
 
-            if ($user->expiration_date < date('Y-m-d')) {
+            if ($user->expiration_date < now()->toDateString()) {
                 $this->failed(trans('errors.subscribe.expired'));
             }
 

+ 79 - 71
app/Services/ProxyService.php

@@ -45,24 +45,22 @@ class ProxyService
         return $this->getClientConfig($target);
     }
 
-    public function getServers(): ?array
+    public function getServers(): array
     {
-        return self::$servers ?? null;
+        return self::$servers ?? [];
     }
 
     public function getNodeList(?int $type = null, bool $isConfig = true): array
     {
         $query = $this->getUser()->nodes()->whereIn('is_display', [2, 3]); // 获取这个账号可用节点
 
-        if ($type) {
-            if ($type === 1) {
-                $query = $query->whereIn('type', [1, 4]);
-            } else {
-                $query = $query->whereType($type);
-            }
+        if ($type === 1) {
+            $query->whereIn('type', [1, 4]);
+        } elseif ($type !== null) {
+            $query->whereType($type);
         }
 
-        $nodes = $query->orderByDesc('sort')->orderBy('id')->get();
+        $nodes = $query->orderByDesc('node.sort')->orderBy('node.id')->get();
 
         if ($isConfig) {
             $servers = [];
@@ -110,58 +108,70 @@ class ProxyService
 
         // 如果是中转节点,递归处理父节点配置
         if ($node->relay_node_id) {
-            $parentConfig = $this->getProxyConfig($node->relayNode);
-            $config = array_merge($config, Arr::except($parentConfig, ['id', 'name', 'host', 'group', 'udp']));
-            if ($parentConfig['type'] === 'trojan') {
-                $config['sni'] = $parentConfig['host'];
+            $parent = $this->getProxyConfig($node->relayNode);
+            $config += Arr::except($parent, ['id', 'name', 'host', 'group', 'udp']);
+            if ($parent['type'] === 'trojan') {
+                $config['sni'] = $parent['host'];
             }
             $config['port'] = $node->port;
+
+            return $config;
+        }
+
+        // 按节点类型生成特定配置
+        return array_merge($config, $this->generateProtocolConfig($node, $user));
+    }
+
+    private function generateProtocolConfig(Node $node, User $user): array
+    {
+        return match ($node->type) {
+            0 => [ // Shadowsocks
+                'type' => 'shadowsocks',
+                'port' => $node->port ?: $user->port,
+                'passwd' => $user->passwd,
+                ...$node->profile,
+            ],
+            2 => [ // Vmess
+                'type' => 'vmess',
+                'port' => $node->port,
+                'uuid' => $user->vmess_id,
+                ...$node->profile,
+            ],
+            3 => [ // Trojan
+                'type' => 'trojan',
+                'port' => $node->port,
+                'passwd' => $user->passwd,
+                'sni' => '',
+                ...$node->profile,
+            ],
+            default => $this->generateSSRConfig($node, $user), // 1, 4 => SSR
+        };
+    }
+
+    private function generateSSRConfig(Node $node, User $user): array
+    {
+        $config = [
+            'type' => 'shadowsocksr',
+            ...$node->profile,
+        ];
+
+        if (! empty($node->profile['passwd']) && $node->port) { // 单端口使用中转的端口
+            $config += [
+                'port' => $node->port,
+                'protocol_param' => "$user->port:$user->passwd",
+            ];
         } else {
-            switch ($node->type) {
-                case 0:
-                    $config = array_merge($config, [
-                        'type' => 'shadowsocks',
-                        'passwd' => $user->passwd,
-                    ], $node->profile);
-                    if ($node->port && $node->port !== 0) {
-                        $config['port'] = $node->port;
-                    } else {
-                        $config['port'] = $user->port;
-                    }
-                    break;
-                case 2:
-                    $config = array_merge($config, [
-                        'type' => 'vmess',
-                        'port' => $node->port,
-                        'uuid' => $user->vmess_id,
-                    ], $node->profile);
-                    break;
-                case 3:
-                    $config = array_merge($config, [
-                        'type' => 'trojan',
-                        'port' => $node->port,
-                        'passwd' => $user->passwd,
-                        'sni' => '',
-                    ], $node->profile);
-                    break;
-                case 1:
-                case 4:
-                default:
-                    $config = array_merge($config, ['type' => 'shadowsocksr'], $node->profile);
-                    if ($node->profile['passwd'] && $node->port) {
-                        //单端口使用中转的端口
-                        $config['port'] = $node->port;
-                        $config['protocol_param'] = $user->port.':'.$user->passwd;
-                    } else {
-                        $config['port'] = $user->port;
-                        $config['passwd'] = $user->passwd;
-                        if ($node->type === 1) {
-                            $config['method'] = $user->method;
-                            $config['protocol'] = $user->protocol;
-                            $config['obfs'] = $user->obfs;
-                        }
-                    }
-                    break;
+            $config += [
+                'port' => $user->port,
+                'protocol_param' => $user->passwd,
+            ];
+
+            if ($node->type === 1) {
+                $config += [
+                    'method' => $user->method,
+                    'protocol' => $user->protocol,
+                    'obfs' => $user->obfs,
+                ];
             }
         }
 
@@ -170,15 +180,7 @@ class ProxyService
 
     public function failedProxyReturn(string $text, ?int $type = 0): void
     {
-        $url = sysConfig('website_url');
-
-        $data = [
-            'name' => $text,
-            'type' => [0 => 'shadowsocks', 1 => 'shadowsocksr', 2 => 'vmess', 3 => 'trojan'][$type],
-            'host' => $url,
-            'port' => 0,
-            'udp' => 0,
-        ];
+        $types = ['shadowsocks', 'shadowsocksr', 'vmess', 'trojan'];
 
         $addition = match ($type) {
             0 => ['method' => 'none', 'passwd' => 'error'],
@@ -187,7 +189,7 @@ class ProxyService
             3 => ['passwd' => 'error']
         };
 
-        $this->setServers([array_merge($data, $addition)]);
+        $this->setServers([['name' => $text, 'type' => $types[$type], 'host' => sysConfig('website_url'), 'port' => 0, 'udp' => 0, ...$addition]]);
     }
 
     private function setServers(array $servers): void
@@ -197,11 +199,17 @@ class ProxyService
 
     private function getClientConfig(string $target): string
     {
-        foreach (glob(app_path('Utils/Clients').'/*.php') as $file) {
+        $classes = glob(app_path('Utils/Clients').'/*.php');
+        foreach ($classes as $file) {
             $class = 'App\\Utils\\Clients\\'.basename($file, '.php');
-            $reflectionClass = new ReflectionClass($class);
+            $ref = new ReflectionClass($class);
+
+            $agents = $ref->getConstant('AGENT');
+            if (! is_array($agents)) {
+                continue;
+            }
 
-            foreach ($reflectionClass->getConstant('AGENT') as $agent) {
+            foreach ($agents as $agent) {
                 if (str_contains($target, $agent)) {
                     return (new $class)->getConfig($this->getServers(), $this->getUser(), $target);
                 }