diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index ea7964d1..b47eed5a 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -38,6 +38,10 @@ class Test extends Command */ public function handle() { - dd(Order::where('user_id', 4)->delete()); + foreach (glob(app_path('Http//Controllers//Client//Protocols') . '/*.php') as $file) { + $file = 'App\\Http\\Controllers\\Client\\Protocols' . basename($file, '.php'); + new $file(); + var_dump($file); + } } } diff --git a/app/Http/Controllers/Client/ClientController.php b/app/Http/Controllers/Client/ClientController.php index dcc7eca9..fb25d14b 100644 --- a/app/Http/Controllers/Client/ClientController.php +++ b/app/Http/Controllers/Client/ClientController.php @@ -4,15 +4,7 @@ namespace App\Http\Controllers\Client; use App\Http\Controllers\Controller; use App\Services\ServerService; -use App\Utils\Clash; -use App\Utils\Origin; -use App\Utils\QuantumultX; -use App\Utils\Shadowrocket; -use App\Utils\Shadowsocks; -use App\Utils\Surge; -use App\Utils\Surfboard; use Illuminate\Http\Request; -use Symfony\Component\Yaml\Yaml; use App\Services\UserService; class ClientController extends Controller @@ -31,227 +23,15 @@ class ClientController extends Controller $serverService = new ServerService(); $servers = $serverService->getAvailableServers($user); if ($flag) { - if (strpos($flag, 'quantumult%20x') !== false) { - die($this->quantumultX($user, $servers)); - } - if (strpos($flag, 'clash') !== false) { - die($this->clash($user, $servers)); - } - if (strpos($flag, 'surfboard') !== false) { - die($this->surfboard($user, $servers)); - } - if (strpos($flag, 'surge') !== false) { - die($this->surge($user, $servers)); - } - if (strpos($flag, 'shadowrocket') !== false) { - die($this->shadowrocket($user, $servers)); - } - if (strpos($flag, 'shadowsocks') !== false) { - die($this->shaodowsocksSIP008($user, $servers)); + foreach (glob(app_path('Http//Controllers//Client//Protocols') . '/*.php') as $file) { + $file = 'App\\Http\\Controllers\\Client\\Protocols\\' . basename($file, '.php'); + $class = new $file($user, $servers); + if (strpos($flag, $class->flag) !== false) { + die($class->handle()); + } } } die('该客户端暂不支持进行订阅'); } } - - private function origin($user, $servers = []) - { - $uri = ''; - foreach ($servers as $item) { - if ($item['type'] === 'shadowsocks') { - $uri .= Origin::buildShadowsocks($item, $user); - } - if ($item['type'] === 'v2ray') { - $uri .= Origin::buildVmess($item, $user); - } - if ($item['type'] === 'trojan') { - $uri .= Origin::buildTrojan($item, $user); - } - } - return base64_encode($uri); - } - - private function shadowrocket($user, $servers = []) - { - $uri = ''; - //display remaining traffic and expire date - $upload = round($user['u'] / (1024*1024*1024), 2); - $download = round($user['d'] / (1024*1024*1024), 2); - $totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2); - $expiredDate = date('Y-m-d', $user['expired_at']); - $uri .= "STATUS=🚀↑:{$upload}GB,↓:{$download}GB,TOT:{$totalTraffic}GB💡Expires:{$expiredDate}\r\n"; - foreach ($servers as $item) { - if ($item['type'] === 'shadowsocks') { - $uri .= Shadowrocket::buildShadowsocks($user['uuid'], $item); - } - if ($item['type'] === 'v2ray') { - $uri .= Shadowrocket::buildVmess($user['uuid'], $item); - } - if ($item['type'] === 'trojan') { - $uri .= Shadowrocket::buildTrojan($user['uuid'], $item); - } - } - return base64_encode($uri); - } - - private function quantumultX($user, $servers = []) - { - $uri = ''; - header("subscription-userinfo: upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}"); - foreach ($servers as $item) { - if ($item['type'] === 'shadowsocks') { - $uri .= QuantumultX::buildShadowsocks($user['uuid'], $item); - } - if ($item['type'] === 'v2ray') { - $uri .= QuantumultX::buildVmess($user['uuid'], $item); - } - if ($item['type'] === 'trojan') { - $uri .= QuantumultX::buildTrojan($user['uuid'], $item); - } - } - return base64_encode($uri); - } - - private function shaodowsocksSIP008($user, $servers = []) - { - $configs = []; - $subs = []; - $subs['servers'] = []; - $subs['bytes_used'] = ''; - $subs['bytes_remaining'] = ''; - - $bytesUsed = $user['u'] + $user['d']; - $bytesRemaining = $user['transfer_enable'] - $bytesUsed; - - foreach ($servers as $item) { - if ($item['type'] === 'shadowsocks') { - array_push($configs, Shadowsocks::SIP008($item, $user)); - } - } - - $subs['version'] = 1; - $subs['bytes_used'] = $bytesUsed; - $subs['bytes_remaining'] = $bytesRemaining; - $subs['servers'] = array_merge($subs['servers'] ? $subs['servers'] : [], $configs); - - return json_encode($subs, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT); - } - - private function surge($user, $servers = []) - { - $proxies = ''; - $proxyGroup = ''; - - foreach ($servers as $item) { - if ($item['type'] === 'shadowsocks') { - // [Proxy] - $proxies .= Surge::buildShadowsocks($user['uuid'], $item); - // [Proxy Group] - $proxyGroup .= $item['name'] . ', '; - } - if ($item['type'] === 'v2ray') { - // [Proxy] - $proxies .= Surge::buildVmess($user['uuid'], $item); - // [Proxy Group] - $proxyGroup .= $item['name'] . ', '; - } - if ($item['type'] === 'trojan') { - // [Proxy] - $proxies .= Surge::buildTrojan($user['uuid'], $item); - // [Proxy Group] - $proxyGroup .= $item['name'] . ', '; - } - } - - $defaultConfig = base_path() . '/resources/rules/default.surge.conf'; - $customConfig = base_path() . '/resources/rules/custom.surge.conf'; - if (\File::exists($customConfig)) { - $config = file_get_contents("$customConfig"); - } else { - $config = file_get_contents("$defaultConfig"); - } - - // Subscription link - $subsURL = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token']; - - $config = str_replace('$subs_link', $subsURL, $config); - $config = str_replace('$proxies', $proxies, $config); - $config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config); - return $config; - } - - private function surfboard($user, $servers = []) - { - $proxies = ''; - $proxyGroup = ''; - - foreach ($servers as $item) { - if ($item['type'] === 'shadowsocks') { - // [Proxy] - $proxies .= Surfboard::buildShadowsocks($user['uuid'], $item); - // [Proxy Group] - $proxyGroup .= $item['name'] . ', '; - } - if ($item['type'] === 'v2ray') { - // [Proxy] - $proxies .= Surfboard::buildVmess($user['uuid'], $item); - // [Proxy Group] - $proxyGroup .= $item['name'] . ', '; - } - } - - $defaultConfig = base_path() . '/resources/rules/default.surfboard.conf'; - $customConfig = base_path() . '/resources/rules/custom.surfboard.conf'; - if (\File::exists($customConfig)) { - $config = file_get_contents("$customConfig"); - } else { - $config = file_get_contents("$defaultConfig"); - } - - // Subscription link - $subsURL = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token']; - - $config = str_replace('$subs_link', $subsURL, $config); - $config = str_replace('$proxies', $proxies, $config); - $config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config); - return $config; - } - - private function clash($user, $servers = []) - { - header("subscription-userinfo: upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}"); - $defaultConfig = base_path() . '/resources/rules/default.clash.yaml'; - $customConfig = base_path() . '/resources/rules/custom.clash.yaml'; - if (\File::exists($customConfig)) { - $config = Yaml::parseFile($customConfig); - } else { - $config = Yaml::parseFile($defaultConfig); - } - $proxy = []; - $proxies = []; - - foreach ($servers as $item) { - if ($item['type'] === 'shadowsocks') { - array_push($proxy, Clash::buildShadowsocks($user['uuid'], $item)); - array_push($proxies, $item['name']); - } - if ($item['type'] === 'v2ray') { - array_push($proxy, Clash::buildVmess($user['uuid'], $item)); - array_push($proxies, $item['name']); - } - if ($item['type'] === 'trojan') { - array_push($proxy, Clash::buildTrojan($user['uuid'], $item)); - array_push($proxies, $item['name']); - } - } - - $config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy); - foreach ($config['proxy-groups'] as $k => $v) { - if (!is_array($config['proxy-groups'][$k]['proxies'])) continue; - $config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies); - } - $yaml = Yaml::dump($config); - $yaml = str_replace('$app_name', config('v2board.app_name', 'V2Board'), $yaml); - return $yaml; - } } diff --git a/app/Utils/Clash.php b/app/Http/Controllers/Client/Protocols/Clash.php similarity index 58% rename from app/Utils/Clash.php rename to app/Http/Controllers/Client/Protocols/Clash.php index 457e51ca..7b61f7ba 100644 --- a/app/Utils/Clash.php +++ b/app/Http/Controllers/Client/Protocols/Clash.php @@ -1,10 +1,61 @@ user = $user; + $this->servers = $servers; + } + + public function handle() + { + $servers = $this->servers; + $user = $this->user; + header("subscription-userinfo: upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}"); + $defaultConfig = base_path() . '/resources/rules/default.clash.yaml'; + $customConfig = base_path() . '/resources/rules/custom.clash.yaml'; + if (\File::exists($customConfig)) { + $config = Yaml::parseFile($customConfig); + } else { + $config = Yaml::parseFile($defaultConfig); + } + $proxy = []; + $proxies = []; + + foreach ($servers as $item) { + if ($item['type'] === 'shadowsocks') { + array_push($proxy, self::buildShadowsocks($user['uuid'], $item)); + array_push($proxies, $item['name']); + } + if ($item['type'] === 'v2ray') { + array_push($proxy, self::buildVmess($user['uuid'], $item)); + array_push($proxies, $item['name']); + } + if ($item['type'] === 'trojan') { + array_push($proxy, self::buildTrojan($user['uuid'], $item)); + array_push($proxies, $item['name']); + } + } + + $config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy); + foreach ($config['proxy-groups'] as $k => $v) { + if (!is_array($config['proxy-groups'][$k]['proxies'])) continue; + $config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies); + } + $yaml = Yaml::dump($config); + $yaml = str_replace('$app_name', config('v2board.app_name', 'V2Board'), $yaml); + return $yaml; + } + public static function buildShadowsocks($uuid, $server) { $array = []; diff --git a/app/Utils/QuantumultX.php b/app/Http/Controllers/Client/Protocols/QuantumultX.php similarity index 75% rename from app/Utils/QuantumultX.php rename to app/Http/Controllers/Client/Protocols/QuantumultX.php index a9aa577b..79c67d3a 100644 --- a/app/Utils/QuantumultX.php +++ b/app/Http/Controllers/Client/Protocols/QuantumultX.php @@ -1,10 +1,40 @@ user = $user; + $this->servers = $servers; + } + + public function handle() + { + $servers = $this->servers; + $user = $this->user; + $uri = ''; + header("subscription-userinfo: upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}"); + foreach ($servers as $item) { + if ($item['type'] === 'shadowsocks') { + $uri .= self::buildShadowsocks($user['uuid'], $item); + } + if ($item['type'] === 'v2ray') { + $uri .= self::buildVmess($user['uuid'], $item); + } + if ($item['type'] === 'trojan') { + $uri .= self::buildTrojan($user['uuid'], $item); + } + } + return base64_encode($uri); + } + public static function buildShadowsocks($password, $server) { $config = [ diff --git a/app/Utils/Shadowrocket.php b/app/Http/Controllers/Client/Protocols/Shadowrocket.php similarity index 69% rename from app/Utils/Shadowrocket.php rename to app/Http/Controllers/Client/Protocols/Shadowrocket.php index 95db5020..e683edad 100644 --- a/app/Utils/Shadowrocket.php +++ b/app/Http/Controllers/Client/Protocols/Shadowrocket.php @@ -1,10 +1,46 @@ user = $user; + $this->servers = $servers; + } + + public function handle() + { + $servers = $this->servers; + $user = $this->user; + + $uri = ''; + //display remaining traffic and expire date + $upload = round($user['u'] / (1024*1024*1024), 2); + $download = round($user['d'] / (1024*1024*1024), 2); + $totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2); + $expiredDate = date('Y-m-d', $user['expired_at']); + $uri .= "STATUS=🚀↑:{$upload}GB,↓:{$download}GB,TOT:{$totalTraffic}GB💡Expires:{$expiredDate}\r\n"; + foreach ($servers as $item) { + if ($item['type'] === 'shadowsocks') { + $uri .= self::buildShadowsocks($user['uuid'], $item); + } + if ($item['type'] === 'v2ray') { + $uri .= self::buildVmess($user['uuid'], $item); + } + if ($item['type'] === 'trojan') { + $uri .= self::buildTrojan($user['uuid'], $item); + } + } + return base64_encode($uri); + } + + public static function buildShadowsocks($password, $server) { $name = rawurlencode($server['name']); diff --git a/app/Http/Controllers/Client/Protocols/Shadowsocks.php b/app/Http/Controllers/Client/Protocols/Shadowsocks.php new file mode 100644 index 00000000..3587dd97 --- /dev/null +++ b/app/Http/Controllers/Client/Protocols/Shadowsocks.php @@ -0,0 +1,57 @@ +user = $user; + $this->servers = $servers; + } + + public function handle() + { + $servers = $this->servers; + $user = $this->user; + + $configs = []; + $subs = []; + $subs['servers'] = []; + $subs['bytes_used'] = ''; + $subs['bytes_remaining'] = ''; + + $bytesUsed = $user['u'] + $user['d']; + $bytesRemaining = $user['transfer_enable'] - $bytesUsed; + + foreach ($servers as $item) { + if ($item['type'] === 'shadowsocks') { + array_push($configs, self::SIP008($item, $user)); + } + } + + $subs['version'] = 1; + $subs['bytes_used'] = $bytesUsed; + $subs['bytes_remaining'] = $bytesRemaining; + $subs['servers'] = array_merge($subs['servers'] ? $subs['servers'] : [], $configs); + + return json_encode($subs, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT); + } + + public static function SIP008($server, $user) + { + $config = [ + "id" => $server['id'], + "remarks" => $server['name'], + "server" => $server['host'], + "server_port" => $server['port'], + "password" => $user['uuid'], + "method" => $server['cipher'] + ]; + return $config; + } +} diff --git a/app/Utils/Surfboard.php b/app/Http/Controllers/Client/Protocols/Surfboard.php similarity index 55% rename from app/Utils/Surfboard.php rename to app/Http/Controllers/Client/Protocols/Surfboard.php index 564d4bcc..17042a95 100644 --- a/app/Utils/Surfboard.php +++ b/app/Http/Controllers/Client/Protocols/Surfboard.php @@ -1,10 +1,61 @@ user = $user; + $this->servers = $servers; + } + + public function handle() + { + $servers = $this->servers; + $user = $this->user; + + $proxies = ''; + $proxyGroup = ''; + + foreach ($servers as $item) { + if ($item['type'] === 'shadowsocks') { + // [Proxy] + $proxies .= Surfboard::buildShadowsocks($user['uuid'], $item); + // [Proxy Group] + $proxyGroup .= $item['name'] . ', '; + } + if ($item['type'] === 'v2ray') { + // [Proxy] + $proxies .= Surfboard::buildVmess($user['uuid'], $item); + // [Proxy Group] + $proxyGroup .= $item['name'] . ', '; + } + } + + $defaultConfig = base_path() . '/resources/rules/default.surfboard.conf'; + $customConfig = base_path() . '/resources/rules/custom.surfboard.conf'; + if (\File::exists($customConfig)) { + $config = file_get_contents("$customConfig"); + } else { + $config = file_get_contents("$defaultConfig"); + } + + // Subscription link + $subsURL = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token']; + + $config = str_replace('$subs_link', $subsURL, $config); + $config = str_replace('$proxies', $proxies, $config); + $config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config); + return $config; + } + + public static function buildShadowsocks($password, $server) { $config = [ diff --git a/app/Utils/Surge.php b/app/Http/Controllers/Client/Protocols/Surge.php similarity index 58% rename from app/Utils/Surge.php rename to app/Http/Controllers/Client/Protocols/Surge.php index 34873996..0d9e3dc5 100644 --- a/app/Utils/Surge.php +++ b/app/Http/Controllers/Client/Protocols/Surge.php @@ -1,10 +1,66 @@ user = $user; + $this->servers = $servers; + } + + public function handle() + { + $servers = $this->servers; + $user = $this->user; + + $proxies = ''; + $proxyGroup = ''; + + foreach ($servers as $item) { + if ($item['type'] === 'shadowsocks') { + // [Proxy] + $proxies .= self::buildShadowsocks($user['uuid'], $item); + // [Proxy Group] + $proxyGroup .= $item['name'] . ', '; + } + if ($item['type'] === 'v2ray') { + // [Proxy] + $proxies .= self::buildVmess($user['uuid'], $item); + // [Proxy Group] + $proxyGroup .= $item['name'] . ', '; + } + if ($item['type'] === 'trojan') { + // [Proxy] + $proxies .= self::buildTrojan($user['uuid'], $item); + // [Proxy Group] + $proxyGroup .= $item['name'] . ', '; + } + } + + $defaultConfig = base_path() . '/resources/rules/default.surge.conf'; + $customConfig = base_path() . '/resources/rules/custom.surge.conf'; + if (\File::exists($customConfig)) { + $config = file_get_contents("$customConfig"); + } else { + $config = file_get_contents("$defaultConfig"); + } + + // Subscription link + $subsURL = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token']; + + $config = str_replace('$subs_link', $subsURL, $config); + $config = str_replace('$proxies', $proxies, $config); + $config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config); + return $config; + } + + public static function buildShadowsocks($password, $server) { $config = [ diff --git a/app/Utils/Origin.php b/app/Utils/Origin.php deleted file mode 100644 index 75b9e04d..00000000 --- a/app/Utils/Origin.php +++ /dev/null @@ -1,59 +0,0 @@ - "2", - "ps" => $server['name'], - "add" => $server['host'], - "port" => (string)$server['port'], - "id" => $user['uuid'], - "aid" => (string)$server['alter_id'], - "net" => $server['network'], - "type" => "none", - "host" => "", - "path" => "", - "tls" => $server['tls'] ? "tls" : "", - "sni" => $server['tls'] ? json_decode($server['tlsSettings'], true)['serverName'] : "" - ]; - if ((string)$server['network'] === 'ws') { - $wsSettings = json_decode($server['networkSettings'], true); - if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path']; - if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host']; - } - if ((string)$server['network'] === 'grpc') { - $grpcSettings = json_decode($server['networkSettings'], true); - if (isset($grpcSettings['path'])) $config['path'] = $grpcSettings['serviceName']; - } - return "vmess://" . base64_encode(json_encode($config)) . "\r\n"; - } - - public static function buildTrojan($server, User $user) - { - $name = rawurlencode($server['name']); - $query = http_build_query([ - 'allowInsecure' => $server['allow_insecure'], - 'peer' => $server['server_name'], - 'sni' => $server['server_name'] - ]); - $uri = "trojan://{$user['uuid']}@{$server['host']}:{$server['port']}?{$query}#{$name}"; - $uri .= "\r\n"; - return $uri; - } -} diff --git a/app/Utils/Shadowsocks.php b/app/Utils/Shadowsocks.php deleted file mode 100644 index 0aab3435..00000000 --- a/app/Utils/Shadowsocks.php +++ /dev/null @@ -1,20 +0,0 @@ - $server['id'], - "remarks" => $server['name'], - "server" => $server['host'], - "server_port" => $server['port'], - "password" => $user['uuid'], - "method" => $server['cipher'] - ]; - return $config; - } -}