get(); foreach ($vmess as $key => $v) { if (!$v['show']) continue; $vmess[$key]['type'] = 'vmess'; if (!in_array($user->group_id, $vmess[$key]['group_id'])) continue; if (strpos($vmess[$key]['port'], '-') !== false) { $vmess[$key]['port'] = Helper::randomPort($vmess[$key]['port']); } if ($vmess[$key]['parent_id']) { $vmess[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_VMESS_LAST_CHECK_AT', $vmess[$key]['parent_id'])); } else { $vmess[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_VMESS_LAST_CHECK_AT', $vmess[$key]['id'])); } $servers[] = $vmess[$key]->toArray(); } return $servers; } public function getAvailableTrojan(User $user):array { $servers = []; $model = ServerTrojan::orderBy('sort', 'ASC'); $trojan = $model->get(); foreach ($trojan as $key => $v) { if (!$v['show']) continue; $trojan[$key]['type'] = 'trojan'; if (!in_array($user->group_id, $trojan[$key]['group_id'])) continue; if (strpos($trojan[$key]['port'], '-') !== false) { $trojan[$key]['port'] = Helper::randomPort($trojan[$key]['port']); } if ($trojan[$key]['parent_id']) { $trojan[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $trojan[$key]['parent_id'])); } else { $trojan[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $trojan[$key]['id'])); } $servers[] = $trojan[$key]->toArray(); } return $servers; } public function getAvailableHysteria(User $user) { $availableServers = []; $model = ServerHysteria::orderBy('sort', 'ASC'); $servers = $model->get()->keyBy('id'); foreach ($servers as $key => $v) { if (!$v['show']) continue; $servers[$key]['type'] = 'hysteria'; $servers[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_HYSTERIA_LAST_CHECK_AT', $v['id'])); if (!in_array($user->group_id, $v['group_id'])) continue; if (strpos($v['port'], '-') !== false) { $servers[$key]['port'] = Helper::randomPort($v['port']); } if (isset($servers[$v['parent_id']])) { $servers[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_HYSTERIA_LAST_CHECK_AT', $v['parent_id'])); $servers[$key]['created_at'] = $servers[$v['parent_id']]['created_at']; } $servers[$key]['server_key'] = Helper::getServerKey($servers[$key]['created_at'], 16); $availableServers[] = $servers[$key]->toArray(); } return $availableServers; } public function getAvailableShadowsocks(User $user) { $servers = []; $model = ServerShadowsocks::orderBy('sort', 'ASC'); $shadowsocks = $model->get()->keyBy('id'); foreach ($shadowsocks as $key => $v) { if (!$v['show']) continue; $shadowsocks[$key]['type'] = 'shadowsocks'; $shadowsocks[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $v['id'])); if (!in_array($user->group_id, $v['group_id'])) continue; if (strpos($v['port'], '-') !== false) { $shadowsocks[$key]['port'] = Helper::randomPort($v['port']); } if (isset($shadowsocks[$v['parent_id']])) { $shadowsocks[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $v['parent_id'])); $shadowsocks[$key]['created_at'] = $shadowsocks[$v['parent_id']]['created_at']; } $servers[] = $shadowsocks[$key]->toArray(); } return $servers; } public function getAvailableServers(User $user) { $servers = array_merge( $this->getAvailableShadowsocks($user), $this->getAvailableVmess($user), $this->getAvailableTrojan($user), $this->getAvailableHysteria($user) ); $tmp = array_column($servers, 'sort'); array_multisort($tmp, SORT_ASC, $servers); return array_map(function ($server) { $server['port'] = (int)$server['port']; $server['is_online'] = (time() - 300 > $server['last_check_at']) ? 0 : 1; $server['cache_key'] = "{$server['type']}-{$server['id']}-{$server['updated_at']}-{$server['is_online']}"; return $server; }, $servers); } public function getAvailableUsers($groupId) { return User::whereIn('group_id', $groupId) ->whereRaw('u + d < transfer_enable') ->where(function ($query) { $query->where('expired_at', '>=', time()) ->orWhere('expired_at', NULL); }) ->where('banned', 0) ->select([ 'id', 'uuid', 'speed_limit' ]) ->get(); } public function log(int $userId, int $serverId, int $u, int $d, float $rate, string $method) { if (($u + $d) < 10240) return true; $timestamp = strtotime(date('Y-m-d')); $serverLog = ServerLog::where('log_at', '>=', $timestamp) ->where('log_at', '<', $timestamp + 3600) ->where('server_id', $serverId) ->where('user_id', $userId) ->where('rate', $rate) ->where('method', $method) ->first(); if ($serverLog) { try { $serverLog->increment('u', $u); $serverLog->increment('d', $d); return true; } catch (\Exception $e) { return false; } } else { $serverLog = new ServerLog(); $serverLog->user_id = $userId; $serverLog->server_id = $serverId; $serverLog->u = $u; $serverLog->d = $d; $serverLog->rate = $rate; $serverLog->log_at = $timestamp; $serverLog->method = $method; return $serverLog->save(); } } public function getAllShadowsocks() { $servers = ServerShadowsocks::orderBy('sort', 'ASC') ->get() ->toArray(); foreach ($servers as $k => $v) { $servers[$k]['type'] = 'shadowsocks'; } return $servers; } public function getAllVMess() { $servers = ServerVmess::orderBy('sort', 'ASC') ->get() ->toArray(); foreach ($servers as $k => $v) { $servers[$k]['type'] = 'vmess'; } return $servers; } public function getAllTrojan() { $servers = ServerTrojan::orderBy('sort', 'ASC') ->get() ->toArray(); foreach ($servers as $k => $v) { $servers[$k]['type'] = 'trojan'; } return $servers; } public function getAllHysteria() { $servers = ServerHysteria::orderBy('sort', 'ASC') ->get() ->toArray(); foreach ($servers as $k => $v) { $servers[$k]['type'] = 'hysteria'; } return $servers; } private function mergeData(&$servers) { foreach ($servers as $k => $v) { $serverType = strtoupper($v['type']); $servers[$k]['online'] = Cache::get(CacheKey::get("SERVER_{$serverType}_ONLINE_USER", $v['parent_id'] ?? $v['id'])); $servers[$k]['last_check_at'] = Cache::get(CacheKey::get("SERVER_{$serverType}_LAST_CHECK_AT", $v['parent_id'] ?? $v['id'])); $servers[$k]['last_push_at'] = Cache::get(CacheKey::get("SERVER_{$serverType}_LAST_PUSH_AT", $v['parent_id'] ?? $v['id'])); if ((time() - 300) >= $servers[$k]['last_check_at']) { $servers[$k]['available_status'] = 0; } else if ((time() - 300) >= $servers[$k]['last_push_at']) { $servers[$k]['available_status'] = 1; } else { $servers[$k]['available_status'] = 2; } } } public function getAllServers() { $servers = array_merge( $this->getAllShadowsocks(), $this->getAllVMess(), $this->getAllTrojan(), $this->getAllHysteria() ); $this->mergeData($servers); $tmp = array_column($servers, 'sort'); array_multisort($tmp, SORT_ASC, $servers); return $servers; } public function getRoutes(array $routeIds) { $routes = ServerRoute::select(['id', 'match', 'action', 'action_value'])->whereIn('id', $routeIds)->get(); // TODO: remove on 1.8.0 foreach ($routes as $k => $route) { $array = json_decode($route->match, true); if (is_array($array)) $routes[$k]['match'] = $array; } // TODO: remove on 1.8.0 return $routes; } public function getServer($serverId, $serverType) { switch ($serverType) { case 'vmess': return ServerVmess::find($serverId); case 'shadowsocks': return ServerShadowsocks::find($serverId); case 'trojan': return ServerTrojan::find($serverId); case 'hysteria': return ServerHysteria::find($serverId); default: return false; } } }