mirror of
https://github.com/lkddi/Xboard.git
synced 2026-04-14 11:20:53 +08:00
feat: new xboard
This commit is contained in:
@@ -9,22 +9,30 @@ use App\Utils\CacheKey;
|
||||
use App\Utils\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Services\UserOnlineService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class UniProxyController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserOnlineService $userOnlineService
|
||||
) {
|
||||
}
|
||||
|
||||
// 后端获取用户
|
||||
public function user(Request $request)
|
||||
{
|
||||
ini_set('memory_limit', -1);
|
||||
Cache::put(CacheKey::get('SERVER_' . strtoupper($request->input('node_type')) . '_LAST_CHECK_AT', $request->input('node_id')), time(), 3600);
|
||||
$users = ServerService::getAvailableUsers($request->input('node_info')->group_id)->toArray();
|
||||
$node = $request->input('node_info');
|
||||
$nodeType = $node->type;
|
||||
$nodeId = $node->id;
|
||||
Cache::put(CacheKey::get('SERVER_' . strtoupper($nodeType) . '_LAST_CHECK_AT', $nodeId), time(), 3600);
|
||||
$users = ServerService::getAvailableUsers($node->group_ids);
|
||||
|
||||
$response['users'] = $users;
|
||||
|
||||
$eTag = sha1(json_encode($response));
|
||||
if (strpos($request->header('If-None-Match'), $eTag) !== false) {
|
||||
if (strpos($request->header('If-None-Match', ''), $eTag) !== false) {
|
||||
return response(null, 304);
|
||||
}
|
||||
|
||||
@@ -34,131 +42,142 @@ class UniProxyController extends Controller
|
||||
// 后端提交数据
|
||||
public function push(Request $request)
|
||||
{
|
||||
$res = json_decode(get_request_content(), true);
|
||||
$data = array_filter($res, function ($item) {
|
||||
return is_array($item) && count($item) === 2 && is_numeric($item[0]) && is_numeric($item[1]);
|
||||
});
|
||||
$nodeType = $request->input('node_type');
|
||||
$nodeId = $request->input('node_id');
|
||||
// 增加单节点多服务器统计在线人数
|
||||
$ip = $request->ip();
|
||||
$id = $request->input("id");
|
||||
$time = time();
|
||||
$cacheKey = CacheKey::get('MULTI_SERVER_' . strtoupper($nodeType) . '_ONLINE_USER', $nodeId);
|
||||
|
||||
// 1、获取节点节点在线人数缓存
|
||||
$onlineUsers = Cache::get($cacheKey) ?? [];
|
||||
$onlineCollection = collect($onlineUsers);
|
||||
// 过滤掉超过600秒的记录
|
||||
$onlineCollection = $onlineCollection->reject(function ($item) use ($time) {
|
||||
return $item['time'] < ($time - 600);
|
||||
});
|
||||
// 定义数据
|
||||
$updatedItem = [
|
||||
'id' => $id ?? $ip,
|
||||
'ip' => $ip,
|
||||
'online_user' => count($data),
|
||||
'time' => $time
|
||||
];
|
||||
|
||||
$existingItemIndex = $onlineCollection->search(function ($item) use ($updatedItem) {
|
||||
return ($item['id'] ?? '') === $updatedItem['id'];
|
||||
});
|
||||
if ($existingItemIndex !== false) {
|
||||
$onlineCollection[$existingItemIndex] = $updatedItem;
|
||||
} else {
|
||||
$onlineCollection->push($updatedItem);
|
||||
$res = json_decode(request()->getContent(), true);
|
||||
if (!is_array($res)) {
|
||||
return $this->fail([422, 'Invalid data format']);
|
||||
}
|
||||
$onlineUsers = $onlineCollection->all();
|
||||
Cache::put($cacheKey, $onlineUsers, 3600);
|
||||
$data = array_filter($res, function ($item) {
|
||||
return is_array($item)
|
||||
&& count($item) === 2
|
||||
&& is_numeric($item[0])
|
||||
&& is_numeric($item[1]);
|
||||
});
|
||||
if (empty($data)) {
|
||||
return $this->success(true);
|
||||
}
|
||||
$node = $request->input('node_info');
|
||||
$nodeType = $node->type;
|
||||
$nodeId = $node->id;
|
||||
|
||||
Cache::put(
|
||||
CacheKey::get('SERVER_' . strtoupper($nodeType) . '_ONLINE_USER', $nodeId),
|
||||
count($data),
|
||||
3600
|
||||
);
|
||||
Cache::put(
|
||||
CacheKey::get('SERVER_' . strtoupper($nodeType) . '_LAST_PUSH_AT', $nodeId),
|
||||
time(),
|
||||
3600
|
||||
);
|
||||
|
||||
$online_user = $onlineCollection->sum('online_user');
|
||||
Cache::put(CacheKey::get('SERVER_' . strtoupper($nodeType) . '_ONLINE_USER', $nodeId), $online_user, 3600);
|
||||
Cache::put(CacheKey::get('SERVER_' . strtoupper($nodeType) . '_LAST_PUSH_AT', $nodeId), time(), 3600);
|
||||
$userService = new UserService();
|
||||
$userService->trafficFetch($request->input('node_info')->toArray(), $nodeType, $data, $ip);
|
||||
$userService->trafficFetch($node->toArray(), $nodeType, $data);
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
// 后端获取配置
|
||||
public function config(Request $request)
|
||||
{
|
||||
$nodeType = $request->input('node_type');
|
||||
$nodeInfo = $request->input('node_info');
|
||||
switch ($nodeType) {
|
||||
case 'shadowsocks':
|
||||
$response = [
|
||||
'server_port' => $nodeInfo->server_port,
|
||||
'cipher' => $nodeInfo->cipher,
|
||||
'obfs' => $nodeInfo->obfs,
|
||||
'obfs_settings' => $nodeInfo->obfs_settings
|
||||
];
|
||||
$node = $request->input('node_info');
|
||||
$nodeType = $node->type;
|
||||
$protocolSettings = $node->protocol_settings;
|
||||
|
||||
$serverPort = $node->server_port;
|
||||
$host = $node->host;
|
||||
|
||||
$baseConfig = [
|
||||
'server_port' => (int) $serverPort,
|
||||
'network' => data_get($protocolSettings, 'network'),
|
||||
'networkSettings' => data_get($protocolSettings, 'network_settings') ?: null,
|
||||
];
|
||||
|
||||
$response = match ($nodeType) {
|
||||
'shadowsocks' => [
|
||||
...$baseConfig,
|
||||
'cipher' => $protocolSettings['cipher'],
|
||||
'obfs' => $protocolSettings['obfs'],
|
||||
'obfs_settings' => $protocolSettings['obfs_settings'],
|
||||
'server_key' => match ($protocolSettings['cipher']) {
|
||||
'2022-blake3-aes-128-gcm' => Helper::getServerKey($node->created_at, 16),
|
||||
'2022-blake3-aes-256-gcm' => Helper::getServerKey($node->created_at, 32),
|
||||
default => null
|
||||
}
|
||||
],
|
||||
'vmess' => [
|
||||
...$baseConfig,
|
||||
'tls' => (int) $protocolSettings['tls']
|
||||
],
|
||||
'trojan' => [
|
||||
...$baseConfig,
|
||||
'host' => $host,
|
||||
'server_name' => $protocolSettings['server_name'],
|
||||
],
|
||||
'vless' => [
|
||||
...$baseConfig,
|
||||
'tls' => (int) $protocolSettings['tls'],
|
||||
'flow' => $protocolSettings['flow'],
|
||||
'tls_settings' =>
|
||||
match ((int) $protocolSettings['tls']) {
|
||||
2 => $protocolSettings['reality_settings'],
|
||||
default => $protocolSettings['tls_settings']
|
||||
}
|
||||
],
|
||||
'hysteria' => [
|
||||
'server_port' => (int) $serverPort,
|
||||
'version' => (int) $protocolSettings['version'],
|
||||
'host' => $host,
|
||||
'server_name' => $protocolSettings['tls']['server_name'],
|
||||
'up_mbps' => (int) $protocolSettings['bandwidth']['up'],
|
||||
'down_mbps' => (int) $protocolSettings['bandwidth']['down'],
|
||||
...match ((int) $protocolSettings['version']) {
|
||||
1 => ['obfs' => $protocolSettings['obfs']['password'] ?? null],
|
||||
2 => [
|
||||
'obfs' => $protocolSettings['obfs']['open'] ? $protocolSettings['obfs']['type'] : null,
|
||||
'obfs-password' => $protocolSettings['obfs']['password'] ?? null
|
||||
],
|
||||
default => []
|
||||
}
|
||||
],
|
||||
default => []
|
||||
};
|
||||
|
||||
if ($nodeInfo->cipher === '2022-blake3-aes-128-gcm') {
|
||||
$response['server_key'] = Helper::getServerKey($nodeInfo->created_at, 16);
|
||||
}
|
||||
if ($nodeInfo->cipher === '2022-blake3-aes-256-gcm') {
|
||||
$response['server_key'] = Helper::getServerKey($nodeInfo->created_at, 32);
|
||||
}
|
||||
break;
|
||||
case 'vmess':
|
||||
$response = [
|
||||
'server_port' => $nodeInfo->server_port,
|
||||
'network' => $nodeInfo->network,
|
||||
'networkSettings' => $nodeInfo->networkSettings,
|
||||
'tls' => $nodeInfo->tls
|
||||
];
|
||||
break;
|
||||
case 'trojan':
|
||||
$response = [
|
||||
'host' => $nodeInfo->host,
|
||||
'server_port' => $nodeInfo->server_port,
|
||||
'server_name' => $nodeInfo->server_name,
|
||||
'network' => $nodeInfo->network,
|
||||
'networkSettings' => $nodeInfo->networkSettings,
|
||||
];
|
||||
break;
|
||||
case 'hysteria':
|
||||
$response = [
|
||||
'version' => $nodeInfo->version,
|
||||
'host' => $nodeInfo->host,
|
||||
'server_port' => $nodeInfo->server_port,
|
||||
'server_name' => $nodeInfo->server_name,
|
||||
'up_mbps' => $nodeInfo->up_mbps,
|
||||
'down_mbps' => $nodeInfo->down_mbps,
|
||||
'obfs' => $nodeInfo->is_obfs ? Helper::getServerKey($nodeInfo->created_at, 16) : null
|
||||
];
|
||||
break;
|
||||
case "vless":
|
||||
$response = [
|
||||
'server_port' => $nodeInfo->server_port,
|
||||
'network' => $nodeInfo->network,
|
||||
'network_settings' => $nodeInfo->network_settings,
|
||||
'networkSettings' => $nodeInfo->network_settings,
|
||||
'tls' => $nodeInfo->tls,
|
||||
'flow' => $nodeInfo->flow,
|
||||
'tls_settings' => $nodeInfo->tls_settings
|
||||
];
|
||||
break;
|
||||
}
|
||||
$response['base_config'] = [
|
||||
'push_interval' => (int) admin_setting('server_push_interval', 60),
|
||||
'pull_interval' => (int) admin_setting('server_pull_interval', 60)
|
||||
];
|
||||
if ($nodeInfo['route_id']) {
|
||||
$response['routes'] = ServerService::getRoutes($nodeInfo['route_id']);
|
||||
}
|
||||
$eTag = sha1(json_encode($response));
|
||||
if (strpos($request->header('If-None-Match'), $eTag) !== false) {
|
||||
return response(null, 304);
|
||||
|
||||
if (!empty($node['route_ids'])) {
|
||||
$response['routes'] = ServerService::getRoutes($node['route_ids']);
|
||||
}
|
||||
|
||||
$eTag = sha1(json_encode($response));
|
||||
if (strpos($request->header('If-None-Match', '') ?? '', $eTag) !== false) {
|
||||
return response(null, 304);
|
||||
}
|
||||
return response($response)->header('ETag', "\"{$eTag}\"");
|
||||
}
|
||||
|
||||
// 后端提交在线数据
|
||||
public function alive(Request $request)
|
||||
// 获取在线用户数据(wyx2685
|
||||
public function alivelist(Request $request): JsonResponse
|
||||
{
|
||||
return $this->success(true);
|
||||
$node = $request->input('node_info');
|
||||
$deviceLimitUsers = ServerService::getAvailableUsers($node->group_ids)
|
||||
->where('device_limit', '>', 0);
|
||||
$alive = $this->userOnlineService->getAliveList($deviceLimitUsers);
|
||||
return response()->json(['alive' => (object) $alive]);
|
||||
}
|
||||
|
||||
// 后端提交在线数据
|
||||
public function alive(Request $request): JsonResponse
|
||||
{
|
||||
$node = $request->input('node_info');
|
||||
$data = json_decode(request()->getContent(), true);
|
||||
if ($data === null) {
|
||||
return response()->json([
|
||||
'error' => 'Invalid online data'
|
||||
], 400);
|
||||
}
|
||||
$this->userOnlineService->updateAliveData($data, $node->type, $node->id);
|
||||
return response()->json(['data' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user