Merge remote-tracking branch 'upstream/master'
# Conflicts: # app/Services/UserOnlineService.php # public/assets/admin
This commit is contained in:
@@ -80,7 +80,8 @@ class ClientController extends Controller
|
||||
'user' => $user,
|
||||
'servers' => $serversFiltered,
|
||||
'clientName' => $clientInfo['name'] ?? null,
|
||||
'clientVersion' => $clientInfo['version'] ?? null
|
||||
'clientVersion' => $clientInfo['version'] ?? null,
|
||||
'userAgent' => $clientInfo['flag'] ?? null
|
||||
]);
|
||||
|
||||
return $protocolInstance->handle();
|
||||
|
||||
@@ -29,7 +29,7 @@ class CommController extends Controller
|
||||
|
||||
// 检查白名单后缀限制
|
||||
if ((int) admin_setting('email_whitelist_enable', 0)) {
|
||||
$isRegisteredEmail = User::where('email', $email)->exists();
|
||||
$isRegisteredEmail = User::byEmail($email)->exists();
|
||||
if (!$isRegisteredEmail) {
|
||||
$allowedSuffixes = Helper::getEmailSuffix();
|
||||
$emailSuffix = substr(strrchr($email, '@'), 1);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace App\Http\Controllers\V1\Server;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\UserAliveSyncJob;
|
||||
use App\Services\DeviceStateService;
|
||||
use App\Services\NodeSyncService;
|
||||
use App\Services\ServerService;
|
||||
use App\Services\UserService;
|
||||
@@ -11,13 +11,12 @@ use App\Utils\CacheKey;
|
||||
use App\Utils\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use App\Services\UserOnlineService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class UniProxyController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserOnlineService $userOnlineService
|
||||
private readonly DeviceStateService $deviceStateService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -103,13 +102,15 @@ class UniProxyController extends Controller
|
||||
return response($response)->header('ETag', "\"{$eTag}\"");
|
||||
}
|
||||
|
||||
// 获取在线用户数据(wyx2685
|
||||
// 获取在线用户数据
|
||||
public function alivelist(Request $request): JsonResponse
|
||||
{
|
||||
$node = $this->getNodeInfo($request);
|
||||
$deviceLimitUsers = ServerService::getAvailableUsers($node)
|
||||
->where('device_limit', '>', 0);
|
||||
$alive = $this->userOnlineService->getAliveList($deviceLimitUsers);
|
||||
|
||||
$alive = $this->deviceStateService->getAliveList(collect($deviceLimitUsers));
|
||||
|
||||
return response()->json(['alive' => (object) $alive]);
|
||||
}
|
||||
|
||||
@@ -123,7 +124,11 @@ class UniProxyController extends Controller
|
||||
'error' => 'Invalid online data'
|
||||
], 400);
|
||||
}
|
||||
UserAliveSyncJob::dispatch($data, $node->type, $node->id);
|
||||
|
||||
foreach ($data as $uid => $ips) {
|
||||
$this->deviceStateService->setDevices((int) $uid, $node->id, $ips);
|
||||
}
|
||||
|
||||
return response()->json(['data' => true]);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,14 @@ class UserController extends Controller
|
||||
if (!$user->save()) {
|
||||
return $this->fail([400, __('Save failed')]);
|
||||
}
|
||||
|
||||
$currentToken = $user->currentAccessToken();
|
||||
if ($currentToken) {
|
||||
$user->tokens()->where('id', '!=', $currentToken->id)->delete();
|
||||
} else {
|
||||
$user->tokens()->delete();
|
||||
}
|
||||
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ class OrderController extends Controller
|
||||
public function assign(OrderAssign $request)
|
||||
{
|
||||
$plan = Plan::find($request->input('plan_id'));
|
||||
$user = User::where('email', $request->input('email'))->first();
|
||||
$user = User::byEmail($request->input('email'))->first();
|
||||
|
||||
if (!$user) {
|
||||
return $this->fail([400202, '该用户不存在']);
|
||||
|
||||
@@ -111,6 +111,94 @@ class ManageController extends Controller
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除节点
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function batchDelete(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'ids' => 'required|array',
|
||||
'ids.*' => 'integer',
|
||||
]);
|
||||
|
||||
$ids = $request->input('ids');
|
||||
if (empty($ids)) {
|
||||
return $this->fail([400, '请选择要删除的节点']);
|
||||
}
|
||||
|
||||
try {
|
||||
$deleted = Server::whereIn('id', $ids)->delete();
|
||||
if ($deleted === false) {
|
||||
return $this->fail([500, '批量删除失败']);
|
||||
}
|
||||
return $this->success(true);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e);
|
||||
return $this->fail([500, '批量删除失败']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置节点流量
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function resetTraffic(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'id' => 'required|integer',
|
||||
]);
|
||||
|
||||
$server = Server::find($request->id);
|
||||
if (!$server) {
|
||||
return $this->fail([400202, '服务器不存在']);
|
||||
}
|
||||
|
||||
try {
|
||||
$server->u = 0;
|
||||
$server->d = 0;
|
||||
$server->save();
|
||||
|
||||
Log::info("Server {$server->id} ({$server->name}) traffic reset by admin");
|
||||
return $this->success(true);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e);
|
||||
return $this->fail([500, '重置失败']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量重置节点流量
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function batchResetTraffic(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'ids' => 'required|array',
|
||||
'ids.*' => 'integer',
|
||||
]);
|
||||
|
||||
$ids = $request->input('ids');
|
||||
if (empty($ids)) {
|
||||
return $this->fail([400, '请选择要重置的节点']);
|
||||
}
|
||||
|
||||
try {
|
||||
Server::whereIn('id', $ids)->update([
|
||||
'u' => 0,
|
||||
'd' => 0,
|
||||
]);
|
||||
|
||||
Log::info("Servers " . implode(',', $ids) . " traffic reset by admin");
|
||||
return $this->success(true);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e);
|
||||
return $this->fail([500, '批量重置失败']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制节点
|
||||
@@ -120,12 +208,17 @@ class ManageController extends Controller
|
||||
public function copy(Request $request)
|
||||
{
|
||||
$server = Server::find($request->input('id'));
|
||||
$server->show = 0;
|
||||
$server->code = null;
|
||||
if (!$server) {
|
||||
return $this->fail([400202, '服务器不存在']);
|
||||
}
|
||||
Server::create($server->toArray());
|
||||
|
||||
$copiedServer = $server->replicate();
|
||||
$copiedServer->show = 0;
|
||||
$copiedServer->code = null;
|
||||
$copiedServer->u = 0;
|
||||
$copiedServer->d = 0;
|
||||
$copiedServer->save();
|
||||
|
||||
return $this->success(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,17 @@ class UserController extends Controller
|
||||
collect($request->input('filter'))->each(function ($filter) use ($builder) {
|
||||
$field = $filter['id'];
|
||||
$value = $filter['value'];
|
||||
$logic = strtolower($filter['logic'] ?? 'and');
|
||||
|
||||
$builder->where(function ($query) use ($field, $value) {
|
||||
$this->buildFilterQuery($query, $field, $value);
|
||||
});
|
||||
if ($logic === 'or') {
|
||||
$builder->orWhere(function ($query) use ($field, $value) {
|
||||
$this->buildFilterQuery($query, $field, $value);
|
||||
});
|
||||
} else {
|
||||
$builder->where(function ($query) use ($field, $value) {
|
||||
$this->buildFilterQuery($query, $field, $value);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -213,7 +220,7 @@ class UserController extends Controller
|
||||
return $this->fail([400202, '用户不存在']);
|
||||
}
|
||||
if (isset($params['email'])) {
|
||||
if (User::where('email', $params['email'])->first() && $user->email !== $params['email']) {
|
||||
if (User::byEmail($params['email'])->first() && $user->email !== $params['email']) {
|
||||
return $this->fail([400201, '邮箱已被使用']);
|
||||
}
|
||||
}
|
||||
@@ -233,7 +240,7 @@ class UserController extends Controller
|
||||
$params['group_id'] = $plan->group_id;
|
||||
}
|
||||
// 处理邀请用户
|
||||
if ($request->input('invite_user_email') && $inviteUser = User::where('email', $request->input('invite_user_email'))->first()) {
|
||||
if ($request->input('invite_user_email') && $inviteUser = User::byEmail($request->input('invite_user_email'))->first()) {
|
||||
$params['invite_user_id'] = $inviteUser->id;
|
||||
} else {
|
||||
$params['invite_user_id'] = null;
|
||||
@@ -356,9 +363,15 @@ class UserController extends Controller
|
||||
public function generate(UserGenerate $request)
|
||||
{
|
||||
if ($request->input('email_prefix')) {
|
||||
// If generate_count is specified with email_prefix, generate multiple users with incremented emails
|
||||
if ($request->input('generate_count')) {
|
||||
return $this->multiGenerateWithPrefix($request);
|
||||
}
|
||||
|
||||
// Single user generation with email_prefix
|
||||
$email = $request->input('email_prefix') . '@' . $request->input('email_suffix');
|
||||
|
||||
if (User::where('email', $email)->exists()) {
|
||||
if (User::byEmail($email)->exists()) {
|
||||
return $this->fail([400201, '邮箱已存在于系统中']);
|
||||
}
|
||||
|
||||
@@ -452,6 +465,87 @@ class UserController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
private function multiGenerateWithPrefix(Request $request)
|
||||
{
|
||||
$userService = app(UserService::class);
|
||||
$usersData = [];
|
||||
$emailPrefix = $request->input('email_prefix');
|
||||
$emailSuffix = $request->input('email_suffix');
|
||||
$generateCount = $request->input('generate_count');
|
||||
|
||||
// Check if any of the emails with prefix already exist
|
||||
for ($i = 1; $i <= $generateCount; $i++) {
|
||||
$email = $emailPrefix . '_' . $i . '@' . $emailSuffix;
|
||||
if (User::where('email', $email)->exists()) {
|
||||
return $this->fail([400201, '邮箱 ' . $email . ' 已存在于系统中']);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate user data for batch creation
|
||||
for ($i = 1; $i <= $generateCount; $i++) {
|
||||
$email = $emailPrefix . '_' . $i . '@' . $emailSuffix;
|
||||
$usersData[] = [
|
||||
'email' => $email,
|
||||
'password' => $request->input('password') ?? $email,
|
||||
'plan_id' => $request->input('plan_id'),
|
||||
'expired_at' => $request->input('expired_at'),
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$users = [];
|
||||
foreach ($usersData as $userData) {
|
||||
$user = $userService->createUser($userData);
|
||||
$user->save();
|
||||
$users[] = $user;
|
||||
}
|
||||
DB::commit();
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return $this->fail([500, '生成失败']);
|
||||
}
|
||||
|
||||
// 判断是否导出 CSV
|
||||
if ($request->input('download_csv')) {
|
||||
$headers = [
|
||||
'Content-Type' => 'text/csv',
|
||||
'Content-Disposition' => 'attachment; filename="users.csv"',
|
||||
];
|
||||
$callback = function () use ($users, $request) {
|
||||
$handle = fopen('php://output', 'w');
|
||||
fputcsv($handle, ['账号', '密码', '过期时间', 'UUID', '创建时间', '订阅地址']);
|
||||
foreach ($users as $user) {
|
||||
$user = $user->refresh();
|
||||
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
|
||||
$createDate = date('Y-m-d H:i:s', $user['created_at']);
|
||||
$password = $request->input('password') ?? $user['email'];
|
||||
$subscribeUrl = Helper::getSubscribeUrl($user['token']);
|
||||
fputcsv($handle, [$user['email'], $password, $expireDate, $user['uuid'], $createDate, $subscribeUrl]);
|
||||
}
|
||||
fclose($handle);
|
||||
};
|
||||
return response()->streamDownload($callback, 'users.csv', $headers);
|
||||
}
|
||||
|
||||
// 默认返回 JSON
|
||||
$data = collect($users)->map(function ($user) use ($request) {
|
||||
return [
|
||||
'email' => $user['email'],
|
||||
'password' => $request->input('password') ?? $user['email'],
|
||||
'expired_at' => $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']),
|
||||
'uuid' => $user['uuid'],
|
||||
'created_at' => date('Y-m-d H:i:s', $user['created_at']),
|
||||
'subscribe_url' => Helper::getSubscribeUrl($user['token']),
|
||||
];
|
||||
});
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
'message' => '批量生成成功',
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function sendMail(UserSendMail $request)
|
||||
{
|
||||
ini_set('memory_limit', '-1');
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V2\Client;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\ServerService;
|
||||
use App\Services\UserService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class AppController extends Controller
|
||||
{
|
||||
public function getConfig(Request $request)
|
||||
{
|
||||
$config = [
|
||||
'app_info' => [
|
||||
'app_name' => admin_setting('app_name', 'XB加速器'), // 应用名称
|
||||
'app_description' => admin_setting('app_description', '专业的网络加速服务'), // 应用描述
|
||||
'app_url' => admin_setting('app_url', 'https://app.example.com'), // 应用官网 URL
|
||||
'logo' => admin_setting('logo', 'https://example.com/logo.png'), // 应用 Logo URL
|
||||
'version' => admin_setting('app_version', '1.0.0'), // 应用版本号
|
||||
],
|
||||
'features' => [
|
||||
'enable_register' => (bool) admin_setting('app_enable_register', true), // 是否开启注册功能
|
||||
'enable_invite_system' => (bool) admin_setting('app_enable_invite_system', true), // 是否开启邀请系统
|
||||
'enable_telegram_bot' => (bool) admin_setting('telegram_bot_enable', false), // 是否开启 Telegram 机器人
|
||||
'enable_ticket_system' => (bool) admin_setting('app_enable_ticket_system', true), // 是否开启工单系统
|
||||
'ticket_must_wait_reply' => (bool) admin_setting('ticket_must_wait_reply', 0), // 工单是否需要等待管理员回复后才可继续发消息
|
||||
'enable_commission_system' => (bool) admin_setting('app_enable_commission_system', true), // 是否开启佣金系统
|
||||
'enable_traffic_log' => (bool) admin_setting('app_enable_traffic_log', true), // 是否开启流量日志
|
||||
'enable_knowledge_base' => (bool) admin_setting('app_enable_knowledge_base', true), // 是否开启知识库
|
||||
'enable_announcements' => (bool) admin_setting('app_enable_announcements', true), // 是否开启公告系统
|
||||
'enable_auto_renewal' => (bool) admin_setting('app_enable_auto_renewal', false), // 是否开启自动续费
|
||||
'enable_coupon_system' => (bool) admin_setting('app_enable_coupon_system', true), // 是否开启优惠券系统
|
||||
'enable_speed_test' => (bool) admin_setting('app_enable_speed_test', true), // 是否开启测速功能
|
||||
'enable_server_ping' => (bool) admin_setting('app_enable_server_ping', true), // 是否开启服务器延迟检测
|
||||
],
|
||||
'ui_config' => [
|
||||
'theme' => [
|
||||
'primary_color' => admin_setting('app_primary_color', '#00C851'), // 主色调 (十六进制)
|
||||
'secondary_color' => admin_setting('app_secondary_color', '#007E33'), // 辅助色 (十六进制)
|
||||
'accent_color' => admin_setting('app_accent_color', '#FF6B35'), // 强调色 (十六进制)
|
||||
'background_color' => admin_setting('app_background_color', '#F5F5F5'), // 背景色 (十六进制)
|
||||
'text_color' => admin_setting('app_text_color', '#333333'), // 文字色 (十六进制)
|
||||
],
|
||||
'home_screen' => [
|
||||
'show_speed_test' => (bool) admin_setting('app_show_speed_test', true), // 是否显示测速
|
||||
'show_traffic_chart' => (bool) admin_setting('app_show_traffic_chart', true), // 是否显示流量图表
|
||||
'show_server_ping' => (bool) admin_setting('app_show_server_ping', true), // 是否显示服务器延迟
|
||||
'default_server_sort' => admin_setting('app_default_server_sort', 'ping'), // 默认服务器排序方式
|
||||
'show_connection_status' => (bool) admin_setting('app_show_connection_status', true), // 是否显示连接状态
|
||||
],
|
||||
'server_list' => [
|
||||
'show_country_flags' => (bool) admin_setting('app_show_country_flags', true), // 是否显示国家旗帜
|
||||
'show_ping_values' => (bool) admin_setting('app_show_ping_values', true), // 是否显示延迟值
|
||||
'show_traffic_usage' => (bool) admin_setting('app_show_traffic_usage', true), // 是否显示流量使用
|
||||
'group_by_country' => (bool) admin_setting('app_group_by_country', false), // 是否按国家分组
|
||||
'show_server_status' => (bool) admin_setting('app_show_server_status', true), // 是否显示服务器状态
|
||||
],
|
||||
],
|
||||
'business_rules' => [
|
||||
'min_password_length' => (int) admin_setting('app_min_password_length', 8), // 最小密码长度
|
||||
'max_login_attempts' => (int) admin_setting('app_max_login_attempts', 5), // 最大登录尝试次数
|
||||
'session_timeout_minutes' => (int) admin_setting('app_session_timeout_minutes', 30), // 会话超时时间(分钟)
|
||||
'auto_disconnect_after_minutes' => (int) admin_setting('app_auto_disconnect_after_minutes', 60), // 自动断开连接时间(分钟)
|
||||
'max_concurrent_connections' => (int) admin_setting('app_max_concurrent_connections', 3), // 最大并发连接数
|
||||
'traffic_warning_threshold' => (float) admin_setting('app_traffic_warning_threshold', 0.8), // 流量警告阈值(0-1)
|
||||
'subscription_reminder_days' => admin_setting('app_subscription_reminder_days', [7, 3, 1]), // 订阅到期提醒天数
|
||||
'connection_timeout_seconds' => (int) admin_setting('app_connection_timeout_seconds', 10), // 连接超时时间(秒)
|
||||
'health_check_interval_seconds' => (int) admin_setting('app_health_check_interval_seconds', 30), // 健康检查间隔(秒)
|
||||
],
|
||||
'server_config' => [
|
||||
'default_kernel' => admin_setting('app_default_kernel', 'clash'), // 默认内核 (clash/singbox)
|
||||
'auto_select_fastest' => (bool) admin_setting('app_auto_select_fastest', true), // 是否自动选择最快服务器
|
||||
'fallback_servers' => admin_setting('app_fallback_servers', ['server1', 'server2']), // 备用服务器列表
|
||||
'enable_auto_switch' => (bool) admin_setting('app_enable_auto_switch', true), // 是否开启自动切换
|
||||
'switch_threshold_ms' => (int) admin_setting('app_switch_threshold_ms', 1000), // 切换阈值(毫秒)
|
||||
],
|
||||
'security_config' => [
|
||||
'tos_url' => admin_setting('tos_url', 'https://example.com/tos'), // 服务条款 URL
|
||||
'privacy_policy_url' => admin_setting('app_privacy_policy_url', 'https://example.com/privacy'), // 隐私政策 URL
|
||||
'is_email_verify' => (int) admin_setting('email_verify', 1), // 是否开启邮箱验证 (0/1)
|
||||
'is_invite_force' => (int) admin_setting('invite_force', 0), // 是否强制邀请码 (0/1)
|
||||
'email_whitelist_suffix' => (int) admin_setting('email_whitelist_suffix', 0), // 邮箱白名单后缀 (0/1)
|
||||
'is_captcha' => (int) admin_setting('captcha_enable', 1), // 是否开启验证码 (0/1)
|
||||
'captcha_type' => admin_setting('captcha_type', 'recaptcha'), // 验证码类型 (recaptcha/turnstile)
|
||||
'recaptcha_site_key' => admin_setting('recaptcha_site_key', '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'), // reCAPTCHA 站点密钥
|
||||
'recaptcha_v3_site_key' => admin_setting('recaptcha_v3_site_key', '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'), // reCAPTCHA v3 站点密钥
|
||||
'recaptcha_v3_score_threshold' => (float) admin_setting('recaptcha_v3_score_threshold', 0.5), // reCAPTCHA v3 分数阈值
|
||||
'turnstile_site_key' => admin_setting('turnstile_site_key', '0x4AAAAAAAABkMYinukE8nzUg'), // Turnstile 站点密钥
|
||||
],
|
||||
'payment_config' => [
|
||||
'currency' => admin_setting('currency', 'CNY'), // 货币类型
|
||||
'currency_symbol' => admin_setting('currency_symbol', '¥'), // 货币符号
|
||||
'withdraw_methods' => admin_setting('app_withdraw_methods', ['alipay', 'wechat', 'bank']), // 提现方式列表
|
||||
'min_withdraw_amount' => (int) admin_setting('app_min_withdraw_amount', 100), // 最小提现金额(分)
|
||||
'withdraw_fee_rate' => (float) admin_setting('app_withdraw_fee_rate', 0.01), // 提现手续费率
|
||||
],
|
||||
'notification_config' => [
|
||||
'enable_push_notifications' => (bool) admin_setting('app_enable_push_notifications', true), // 是否开启推送通知
|
||||
'enable_email_notifications' => (bool) admin_setting('app_enable_email_notifications', true), // 是否开启邮件通知
|
||||
'enable_sms_notifications' => (bool) admin_setting('app_enable_sms_notifications', false), // 是否开启短信通知
|
||||
'notification_schedule' => [
|
||||
'traffic_warning' => (bool) admin_setting('app_notification_traffic_warning', true), // 流量警告通知
|
||||
'subscription_expiry' => (bool) admin_setting('app_notification_subscription_expiry', true), // 订阅到期通知
|
||||
'server_maintenance' => (bool) admin_setting('app_notification_server_maintenance', true), // 服务器维护通知
|
||||
'promotional_offers' => (bool) admin_setting('app_notification_promotional_offers', false), // 促销优惠通知
|
||||
],
|
||||
],
|
||||
'cache_config' => [
|
||||
'config_cache_duration' => (int) admin_setting('app_config_cache_duration', 3600), // 配置缓存时长(秒)
|
||||
'server_list_cache_duration' => (int) admin_setting('app_server_list_cache_duration', 1800), // 服务器列表缓存时长(秒)
|
||||
'user_info_cache_duration' => (int) admin_setting('app_user_info_cache_duration', 900), // 用户信息缓存时长(秒)
|
||||
],
|
||||
'last_updated' => time(), // 最后更新时间戳
|
||||
];
|
||||
$config['config_hash'] = md5(json_encode($config)); // 配置哈希值(用于校验)
|
||||
|
||||
$config = $config ?? [];
|
||||
return response()->json(['data' => $config]);
|
||||
}
|
||||
|
||||
public function getVersion(Request $request)
|
||||
{
|
||||
if (
|
||||
strpos($request->header('user-agent'), 'tidalab/4.0.0') !== false
|
||||
|| strpos($request->header('user-agent'), 'tunnelab/4.0.0') !== false
|
||||
) {
|
||||
if (strpos($request->header('user-agent'), 'Win64') !== false) {
|
||||
$data = [
|
||||
'version' => admin_setting('windows_version'),
|
||||
'download_url' => admin_setting('windows_download_url')
|
||||
];
|
||||
} else {
|
||||
$data = [
|
||||
'version' => admin_setting('macos_version'),
|
||||
'download_url' => admin_setting('macos_download_url')
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$data = [
|
||||
'windows_version' => admin_setting('windows_version'),
|
||||
'windows_download_url' => admin_setting('windows_download_url'),
|
||||
'macos_version' => admin_setting('macos_version'),
|
||||
'macos_download_url' => admin_setting('macos_download_url'),
|
||||
'android_version' => admin_setting('android_version'),
|
||||
'android_download_url' => admin_setting('android_download_url')
|
||||
];
|
||||
}
|
||||
return $this->success($data);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace App\Http\Controllers\V2\Server;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\UserAliveSyncJob;
|
||||
use App\Services\DeviceStateService;
|
||||
use App\Services\ServerService;
|
||||
use App\Services\UserService;
|
||||
use App\Utils\CacheKey;
|
||||
@@ -83,7 +83,10 @@ class ServerController extends Controller
|
||||
// handle alive data
|
||||
$alive = $request->input('alive');
|
||||
if (is_array($alive) && !empty($alive)) {
|
||||
UserAliveSyncJob::dispatch($alive, $nodeType, $nodeId);
|
||||
$deviceStateService = app(DeviceStateService::class);
|
||||
foreach ($alive as $uid => $ips) {
|
||||
$deviceStateService->setDevices((int) $uid, $nodeId, (array) $ips);
|
||||
}
|
||||
}
|
||||
|
||||
// handle active connections
|
||||
@@ -127,7 +130,7 @@ class ServerController extends Controller
|
||||
// handle node metrics (Metrics)
|
||||
$metrics = $request->input('metrics');
|
||||
if (is_array($metrics) && !empty($metrics)) {
|
||||
ServerService::updateMetrics($node, $metrics);
|
||||
ServerService::updateMetrics($node, $metrics);
|
||||
}
|
||||
|
||||
return response()->json(['data' => true]);
|
||||
|
||||
Reference in New Issue
Block a user