From cd61d08dc0073b327110aab45a6e40aeb5881e3f Mon Sep 17 00:00:00 2001
From: ChunghwaMC <92585552+ChunghwaMC@users.noreply.github.com>
Date: Wed, 7 Aug 2024 23:09:21 +0800
Subject: [PATCH 1/7] add README_JP.md link
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index c4bf2799..bf2b1469 100644
--- a/README.md
+++ b/README.md
@@ -16,8 +16,8 @@
[Official Website](http://mcsmanager.com/) | [Docs](https://docs.mcsmanager.com/) | [Discord](https://discord.gg/BNpYMVX7Cd)
-[English](README.md) | [简体中文](README_ZH.md) | [繁體中文](README_TW.md) | [Português BR](README_PTBR.md)
-
+[English](README.md) | [简体中文](README_ZH.md) | [繁體中文](README_TW.md) | [Português BR](README_PTBR.md) |
+[日本語](README_JP.md)
From 454fdd43bf0cddecf1cf4c33e7050681f00e4905 Mon Sep 17 00:00:00 2001
From: ChunghwaMC <92585552+ChunghwaMC@users.noreply.github.com>
Date: Wed, 7 Aug 2024 23:09:34 +0800
Subject: [PATCH 2/7] add README_JP.md link
---
README_ZH.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/README_ZH.md b/README_ZH.md
index 63cffabf..b4740804 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -16,7 +16,8 @@
[官方网站](http://mcsmanager.com/) | [使用文档](https://docs.mcsmanager.com/#/zh-cn/) | [QQ 群](https://jq.qq.com/?_wv=1027&k=Pgl9ScGw) | [TG 群](https://t.me/MCSManager_dev) | [成为赞助者](https://afdian.net/a/mcsmanager)
-[English](README.md) | [简体中文](README_ZH.md) | [繁體中文](README_TW.md) | [Português BR](README_PTBR.md)
+[English](README.md) | [简体中文](README_ZH.md) | [繁體中文](README_TW.md) | [Português BR](README_PTBR.md) |
+[日本語](README_JP.md)
From aed4ac1550e74cc047e4f2d598932f3657421ab9 Mon Sep 17 00:00:00 2001
From: ChunghwaMC <92585552+ChunghwaMC@users.noreply.github.com>
Date: Wed, 7 Aug 2024 23:10:03 +0800
Subject: [PATCH 3/7] add README_JP.md link
---
README_TW.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/README_TW.md b/README_TW.md
index 45589dee..6977bc39 100644
--- a/README_TW.md
+++ b/README_TW.md
@@ -16,7 +16,8 @@
[官方網站](http://mcsmanager.com/) | [教學說明](https://docs.mcsmanager.com/#/zh-cn/) | [TG 群組](https://t.me/MCSManager_dev) | [成為贊助者](https://afdian.net/a/mcsmanager)
-[English](README.md) | [简体中文](README_ZH.md) | [繁體中文](README_TW.md) | [Português BR](README_PTBR.md)
+[English](README.md) | [简体中文](README_ZH.md) | [繁體中文](README_TW.md) | [Português BR](README_PTBR.md) |
+[日本語](README_JP.md)
From 772d9537eecccbccd8901a6715a4003617e77f58 Mon Sep 17 00:00:00 2001
From: ChunghwaMC <92585552+ChunghwaMC@users.noreply.github.com>
Date: Wed, 7 Aug 2024 23:10:16 +0800
Subject: [PATCH 4/7] add README_JP.md link
---
README_PTBR.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/README_PTBR.md b/README_PTBR.md
index 9bf9e72e..0b9207e1 100644
--- a/README_PTBR.md
+++ b/README_PTBR.md
@@ -16,7 +16,8 @@
[Website Oficial](http://mcsmanager.com/) | [Documentação](https://docs.mcsmanager.com/) | [Discord](https://discord.gg/BNpYMVX7Cd)
-[English](README.md) | [简体中文](README_ZH.md) | [繁體中文](README_TW.md) | [Português BR](README_PTBR.md)
+[English](README.md) | [简体中文](README_ZH.md) | [繁體中文](README_TW.md) | [Português BR](README_PTBR.md) |
+[日本語](README_JP.md)
From 874ac73a2ab0f87b91ff7cc70446fef1a8372f01 Mon Sep 17 00:00:00 2001
From: Unitwk
Date: Thu, 8 Aug 2024 12:00:10 +0800
Subject: [PATCH 5/7] Feat: Exchange Platform API
---
panel/package-lock.json | 23 +++++
panel/package.json | 1 +
panel/src/app/index.ts | 16 +--
panel/src/app/routers/general_user_router.ts | 80 ++-------------
.../app/routers/instance_exchange_router.ts | 38 ++++++++
panel/src/app/service/exchange_service.ts | 97 +++++++++++++++++++
panel/src/app/service/instance_service.ts | 74 ++++++++++++++
panel/src/app/service/remote_command.ts | 7 +-
8 files changed, 249 insertions(+), 87 deletions(-)
create mode 100755 panel/src/app/routers/instance_exchange_router.ts
create mode 100644 panel/src/app/service/exchange_service.ts
diff --git a/panel/package-lock.json b/panel/package-lock.json
index a295f787..ecdbc0af 100644
--- a/panel/package-lock.json
+++ b/panel/package-lock.json
@@ -25,6 +25,7 @@
"log4js": "^6.4.0",
"md5": "^2.3.0",
"module-alias": "^2.2.3",
+ "nanoid": "^5.0.7",
"node-schedule": "^2.0.0",
"open": "^8.4.0",
"os-utils": "0.0.14",
@@ -3268,6 +3269,23 @@
"mustache": "bin/mustache"
}
},
+ "node_modules/nanoid": {
+ "version": "5.0.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
+ "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.js"
+ },
+ "engines": {
+ "node": "^18 || >=20"
+ }
+ },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -7355,6 +7373,11 @@
"resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
"integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="
},
+ "nanoid": {
+ "version": "5.0.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
+ "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ=="
+ },
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
diff --git a/panel/package.json b/panel/package.json
index 6b132999..739f73da 100644
--- a/panel/package.json
+++ b/panel/package.json
@@ -34,6 +34,7 @@
"log4js": "^6.4.0",
"md5": "^2.3.0",
"module-alias": "^2.2.3",
+ "nanoid": "^5.0.7",
"node-schedule": "^2.0.0",
"open": "^8.4.0",
"os-utils": "0.0.14",
diff --git a/panel/src/app/index.ts b/panel/src/app/index.ts
index bdfd7dbc..b8306a6c 100755
--- a/panel/src/app/index.ts
+++ b/panel/src/app/index.ts
@@ -1,39 +1,27 @@
-// Define subsystem loading and routing loading for the application
-
import Koa from "koa";
import Router from "@koa/router";
-// Load subsystem
import "./service/user_service";
import "./service/visual_data";
import "./service/remote_service";
import "./service/user_statistics";
-// Load routes
import overviewRouter from "./routers/overview_router";
-
import userRouter from "./routers/user_overview_router";
import loginRouter from "./routers/login_router";
import lowUserRouter from "./routers/general_user_router";
-
import settingsRouter from "./routers/settings_router";
-
import instanceRouter from "./routers/instance_admin_router";
import userInstanceRouter from "./routers/instance_operate_router";
-
import serviceRouter from "./routers/daemon_router";
import filemanager_router from "./routers/filemananger_router";
-
import businessInstanceRouter from "./routers/business_instance_router";
import businessUserRouter from "./routers/manage_user_router";
-
import scheduleRouter from "./routers/schedule_router";
-
import environmentRouter from "./routers/environment_router";
+import exchangeRouter from "./routers/instance_exchange_router";
-// all routes load entry points
export function mountRouters(app: Koa) {
- // API router
const apiRouter = new Router({ prefix: "/api" });
apiRouter.use(overviewRouter.routes()).use(overviewRouter.allowedMethods());
apiRouter.use(userInstanceRouter.routes()).use(userInstanceRouter.allowedMethods());
@@ -48,7 +36,7 @@ export function mountRouters(app: Koa) {
apiRouter.use(scheduleRouter.routes()).use(scheduleRouter.allowedMethods());
apiRouter.use(settingsRouter.routes()).use(settingsRouter.allowedMethods());
apiRouter.use(environmentRouter.routes()).use(environmentRouter.allowedMethods());
+ apiRouter.use(exchangeRouter.routes()).use(exchangeRouter.allowedMethods());
- // Top router
app.use(apiRouter.routes()).use(apiRouter.allowedMethods());
}
diff --git a/panel/src/app/routers/general_user_router.ts b/panel/src/app/routers/general_user_router.ts
index c854004a..51dad05c 100755
--- a/panel/src/app/routers/general_user_router.ts
+++ b/panel/src/app/routers/general_user_router.ts
@@ -4,13 +4,13 @@ import permission from "../middleware/permission";
import { bind2FA, confirm2FaQRCode, getUserUuid, logout } from "../service/passport_service";
import userSystem from "../service/user_service";
import { getToken, isAjax } from "../service/passport_service";
-import RemoteServiceSubsystem from "../service/remote_service";
-import RemoteRequest from "../service/remote_command";
import { isTopPermissionByUuid } from "../service/permission_service";
import validator from "../middleware/validator";
import { v4 } from "uuid";
import { $t } from "../i18n";
import { ROLE } from "../entity/user";
+import { getInstancesByUuid } from "../service/instance_service";
+import { toBoolean } from "common";
const router = new Router({ prefix: "/auth" });
@@ -36,79 +36,15 @@ router.get("/", permission({ level: ROLE.USER, token: false, speedLimit: false }
let uuid = getUserUuid(ctx);
// The front end can choose to require advanced data
const advanced = ctx.query.advanced;
+
// Admin permissions can be obtained from anyone
- if (isTopPermissionByUuid(uuid)) {
- if (ctx.query.uuid) uuid = String(ctx.query.uuid);
- }
+ if (isTopPermissionByUuid(uuid) && ctx.query.uuid) uuid = String(ctx.query.uuid);
+
// Some and only Ajax requests grant access
if (isAjax(ctx)) {
- const user = userSystem.getInstance(uuid);
- if (!user) throw new Error("The UID does not exist");
-
- // Advanced functions are optional, analyze each instance data
- let resInstances = [];
- if (advanced) {
- const instances = user.instances;
- for (const iterator of instances) {
- const remoteService = RemoteServiceSubsystem.getInstance(iterator.daemonId);
- // If the remote service doesn't exist at all, load a deleted prompt
- if (!remoteService) {
- resInstances.push({
- hostIp: "-- Unknown --",
- instanceUuid: iterator.instanceUuid,
- daemonId: iterator.daemonId,
- status: -1,
- nickname: "--",
- remarks: "--"
- });
- continue;
- }
- try {
- // Note: UUID can be integrated here to save the returned traffic, and this optimization will not be done for the time being
- let instancesInfo = await new RemoteRequest(remoteService).request("instance/section", {
- instanceUuids: [iterator.instanceUuid]
- });
- instancesInfo = instancesInfo[0];
- resInstances.push({
- hostIp: `${remoteService.config.ip}:${remoteService.config.port}`,
- remarks: remoteService.config.remarks,
- instanceUuid: instancesInfo.instanceUuid,
- daemonId: remoteService.uuid,
- status: instancesInfo.status,
- nickname: instancesInfo.config.nickname,
- ie: instancesInfo.config.ie,
- oe: instancesInfo.config.oe,
- endTime: instancesInfo.config.endTime,
- lastDatetime: instancesInfo.config.lastDatetime,
- stopCommand: instancesInfo.config.stopCommand
- });
- } catch (error: any) {
- resInstances.push({
- hostIp: `${remoteService.config.ip}:${remoteService.config.port}`,
- instanceUuid: iterator.instanceUuid,
- daemonId: iterator.daemonId,
- status: -1,
- nickname: "--"
- });
- }
- }
- } else {
- resInstances = user.instances;
- }
- // respond to user data
- ctx.body = {
- uuid: user.uuid,
- userName: user.userName,
- loginTime: user.loginTime,
- registerTime: user.registerTime,
- instances: resInstances,
- permission: user.permission,
- token: getToken(ctx),
- apiKey: user.apiKey,
- isInit: user.isInit,
- open2FA: user.open2FA,
- secret: user.secret
- };
+ const res = await getInstancesByUuid(uuid, toBoolean(advanced) || false);
+ res.token = getToken(ctx);
+ ctx.body = res;
}
});
diff --git a/panel/src/app/routers/instance_exchange_router.ts b/panel/src/app/routers/instance_exchange_router.ts
new file mode 100755
index 00000000..22595443
--- /dev/null
+++ b/panel/src/app/routers/instance_exchange_router.ts
@@ -0,0 +1,38 @@
+import Router from "@koa/router";
+import permission from "../middleware/permission";
+import validator from "../middleware/validator";
+import { ROLE } from "../entity/user";
+import {
+ buyOrRenewInstance,
+ queryInstanceByUserId,
+ RequestAction
+} from "../service/exchange_service";
+
+const router = new Router({ prefix: "/exchange" });
+
+router.post(
+ "/",
+ permission({ level: ROLE.ADMIN }),
+ validator({
+ body: {
+ request_action: String
+ }
+ }),
+ async (ctx) => {
+ try {
+ const requestAction = ctx.request.body.request_action;
+ const params = ctx.request.body.data ?? {};
+ if ([RequestAction.RENEW, RequestAction.BUY].includes(requestAction)) {
+ ctx.body = await buyOrRenewInstance(requestAction, params);
+ return;
+ }
+ if (requestAction === RequestAction.QUERY_INSTANCE) {
+ ctx.body = await queryInstanceByUserId(params);
+ }
+ } catch (err) {
+ ctx.body = err;
+ }
+ }
+);
+
+export default router;
diff --git a/panel/src/app/service/exchange_service.ts b/panel/src/app/service/exchange_service.ts
new file mode 100644
index 00000000..b6d7ab14
--- /dev/null
+++ b/panel/src/app/service/exchange_service.ts
@@ -0,0 +1,97 @@
+import RemoteServiceSubsystem from "../service/remote_service";
+import RemoteRequest from "../service/remote_command";
+import user_service from "../service/user_service";
+import { customAlphabet } from "nanoid";
+import { t } from "i18next";
+import { toNumber, toText } from "common";
+import { getInstancesByUuid } from "./instance_service";
+
+const getNanoId = customAlphabet(
+ "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+ 6
+);
+
+export enum RequestAction {
+ BUY = "buy",
+ RENEW = "sell",
+ QUERY_INSTANCE = "query_instance"
+}
+
+export async function buyOrRenewInstance(
+ request_action: RequestAction,
+ params: Record
+) {
+ const node_id = toText(params.node_id) ?? "";
+ const instance_id = toText(params.instance_id) ?? "";
+ const username = toText(params.username) ?? "";
+ const hours = toNumber(params.hours) ?? 0;
+ const payload = params.payload ?? {};
+
+ const remoteService = RemoteServiceSubsystem.getInstance(node_id || "");
+ if (!remoteService?.available) {
+ throw new Error(t("远程节点处于离线状态,请联系管理员检查面板在线状态!"));
+ }
+
+ const { request: remoteRequest } = new RemoteRequest(remoteService);
+
+ if (request_action === RequestAction.BUY) {
+ payload.endTime = (payload.endTime ? payload.endTime : Date.now()) + hours * 3600 * 1000;
+ const { instanceUuid: newInstanceId, config: newInstanceConfig } = await remoteRequest(
+ "instance/new",
+ payload
+ );
+ if (!newInstanceId) throw new Error(t("创建实例失败,请稍后重试"));
+ const newPassword = getNanoId(12);
+ const newUser = await user_service.create({
+ userName: username + "-" + getNanoId(6),
+ passWord: newPassword,
+ permission: 1,
+ instances: [
+ {
+ instanceUuid: newInstanceId,
+ daemonId: node_id
+ }
+ ]
+ });
+
+ return {
+ instance_id: newInstanceId,
+ instance_config: newInstanceConfig,
+ username: newUser.userName,
+ password: newPassword,
+ uuid: newUser.uuid,
+ expire: toNumber(newInstanceConfig.endTime)
+ };
+ }
+
+ if (request_action === RequestAction.RENEW) {
+ const instanceInfo = await remoteRequest("instance/detail", {
+ instanceUuid: instance_id
+ });
+ if (!instanceInfo.config) throw new Error(t("获取指定实例详情失败,请重试!"));
+ instanceInfo.config.endTime =
+ (instanceInfo.config?.endTime ? instanceInfo.config.endTime : Date.now()) +
+ hours * 3600 * 1000;
+ await remoteRequest("instance/update", {
+ instanceUuid: instance_id,
+ config: instanceInfo.config
+ });
+ return {
+ instance_id,
+ instance_config: instanceInfo.config,
+ expire: toNumber(instanceInfo.config.endTime),
+ username: "",
+ password: "",
+ uuid: ""
+ };
+ }
+
+ throw new Error(t("请求类型错误,请重试!"));
+}
+
+export async function queryInstanceByUserId(params: Record) {
+ const uuid = toText(params.uuid) || "";
+ const user = user_service.getInstance(uuid);
+ if (!user) throw new Error(t("用户不存在,请重试"));
+ return await getInstancesByUuid(uuid, false);
+}
diff --git a/panel/src/app/service/instance_service.ts b/panel/src/app/service/instance_service.ts
index f067443d..4a5c026e 100755
--- a/panel/src/app/service/instance_service.ts
+++ b/panel/src/app/service/instance_service.ts
@@ -1,3 +1,7 @@
+import userSystem from "../service/user_service";
+import RemoteServiceSubsystem from "../service/remote_service";
+import RemoteRequest from "../service/remote_command";
+
// Multi-forward operation method
export function multiOperationForwarding(
instances: any[],
@@ -22,3 +26,73 @@ export function multiOperationForwarding(
callback(daemonId, instanceUuids);
}
}
+
+export async function getInstancesByUuid(uuid: string, advanced: boolean = false) {
+ const user = userSystem.getInstance(uuid);
+ if (!user) throw new Error("The UID does not exist");
+
+ // Advanced functions are optional, analyze each instance data
+ let resInstances = [];
+ if (advanced) {
+ const instances = user.instances;
+ for (const iterator of instances) {
+ const remoteService = RemoteServiceSubsystem.getInstance(iterator.daemonId);
+ // If the remote service doesn't exist at all, load a deleted prompt
+ if (!remoteService) {
+ resInstances.push({
+ hostIp: "-- Unknown --",
+ instanceUuid: iterator.instanceUuid,
+ daemonId: iterator.daemonId,
+ status: -1,
+ nickname: "--",
+ remarks: "--"
+ });
+ continue;
+ }
+ try {
+ // Note: UUID can be integrated here to save the returned traffic, and this optimization will not be done for the time being
+ let instancesInfo = await new RemoteRequest(remoteService).request("instance/section", {
+ instanceUuids: [iterator.instanceUuid]
+ });
+ instancesInfo = instancesInfo[0];
+ resInstances.push({
+ hostIp: `${remoteService.config.ip}:${remoteService.config.port}`,
+ remarks: remoteService.config.remarks,
+ instanceUuid: instancesInfo.instanceUuid,
+ daemonId: remoteService.uuid,
+ status: instancesInfo.status,
+ nickname: instancesInfo.config.nickname,
+ ie: instancesInfo.config.ie,
+ oe: instancesInfo.config.oe,
+ endTime: instancesInfo.config.endTime,
+ lastDatetime: instancesInfo.config.lastDatetime,
+ stopCommand: instancesInfo.config.stopCommand
+ });
+ } catch (error: any) {
+ resInstances.push({
+ hostIp: `${remoteService.config.ip}:${remoteService.config.port}`,
+ instanceUuid: iterator.instanceUuid,
+ daemonId: iterator.daemonId,
+ status: -1,
+ nickname: "--"
+ });
+ }
+ }
+ } else {
+ resInstances = user.instances;
+ }
+ // respond to user data
+ return {
+ uuid: user.uuid,
+ userName: user.userName,
+ loginTime: user.loginTime,
+ registerTime: user.registerTime,
+ instances: resInstances,
+ permission: user.permission,
+ apiKey: user.apiKey,
+ isInit: user.isInit,
+ open2FA: user.open2FA,
+ secret: user.secret,
+ token: ""
+ };
+}
diff --git a/panel/src/app/service/remote_command.ts b/panel/src/app/service/remote_command.ts
index 4cff2399..b21e1f70 100755
--- a/panel/src/app/service/remote_command.ts
+++ b/panel/src/app/service/remote_command.ts
@@ -23,7 +23,12 @@ export default class RemoteRequest {
}
// request to remote daemon
- public async request(event: string, data?: any, timeout = 6000, force = false): Promise {
+ public async request(
+ event: string,
+ data?: any,
+ timeout = 6000,
+ force = false
+ ): Promise {
if (!this.rService || !this.rService.socket) throw new Error($t("TXT_CODE_3d94ea16"));
if (!this.rService.available && !force)
throw new Error($t("TXT_CODE_b7d38e78") + ` IP: ${this.rService.config.ip}`);
From 04c4c978578c3af9e2d199b805f0fc2a58c23f5f Mon Sep 17 00:00:00 2001
From: Unitwk
Date: Thu, 8 Aug 2024 12:01:45 +0800
Subject: [PATCH 6/7] Feat: i18n
---
languages/zh_CN.json | 7 ++++++-
panel/src/app/service/exchange_service.ts | 10 +++++-----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/languages/zh_CN.json b/languages/zh_CN.json
index a0b1c259..e3a47418 100644
--- a/languages/zh_CN.json
+++ b/languages/zh_CN.json
@@ -1901,5 +1901,10 @@
"TXT_CODE_23a3bd72": "异常",
"TXT_CODE_6b4a27dd": "网页前端无法与节点建立 WebSocket 连接,请检查网络代理配置或防火墙配置!",
"TXT_CODE_a788e3eb": "内存 & 处理器",
- "TXT_CODE_c5ed896f": "此刻瞬时输出内容过长,已拒绝显示..."
+ "TXT_CODE_c5ed896f": "此刻瞬时输出内容过长,已拒绝显示...",
+ "TXT_CODE_bed32084": "远程节点处于离线状态,请联系管理员检查面板在线状态!",
+ "TXT_CODE_728fdabf": "创建实例失败,请稍后重试",
+ "TXT_CODE_348c9098": "获取指定实例详情失败,请重试!",
+ "TXT_CODE_4aaec75c": "请求类型错误,请重试!",
+ "TXT_CODE_903b6c50": "用户不存在,请重试"
}
diff --git a/panel/src/app/service/exchange_service.ts b/panel/src/app/service/exchange_service.ts
index b6d7ab14..5c48adb9 100644
--- a/panel/src/app/service/exchange_service.ts
+++ b/panel/src/app/service/exchange_service.ts
@@ -29,7 +29,7 @@ export async function buyOrRenewInstance(
const remoteService = RemoteServiceSubsystem.getInstance(node_id || "");
if (!remoteService?.available) {
- throw new Error(t("远程节点处于离线状态,请联系管理员检查面板在线状态!"));
+ throw new Error(t("TXT_CODE_bed32084"));
}
const { request: remoteRequest } = new RemoteRequest(remoteService);
@@ -40,7 +40,7 @@ export async function buyOrRenewInstance(
"instance/new",
payload
);
- if (!newInstanceId) throw new Error(t("创建实例失败,请稍后重试"));
+ if (!newInstanceId) throw new Error(t("TXT_CODE_728fdabf"));
const newPassword = getNanoId(12);
const newUser = await user_service.create({
userName: username + "-" + getNanoId(6),
@@ -68,7 +68,7 @@ export async function buyOrRenewInstance(
const instanceInfo = await remoteRequest("instance/detail", {
instanceUuid: instance_id
});
- if (!instanceInfo.config) throw new Error(t("获取指定实例详情失败,请重试!"));
+ if (!instanceInfo.config) throw new Error(t("TXT_CODE_348c9098"));
instanceInfo.config.endTime =
(instanceInfo.config?.endTime ? instanceInfo.config.endTime : Date.now()) +
hours * 3600 * 1000;
@@ -86,12 +86,12 @@ export async function buyOrRenewInstance(
};
}
- throw new Error(t("请求类型错误,请重试!"));
+ throw new Error(t("TXT_CODE_4aaec75c"));
}
export async function queryInstanceByUserId(params: Record) {
const uuid = toText(params.uuid) || "";
const user = user_service.getInstance(uuid);
- if (!user) throw new Error(t("用户不存在,请重试"));
+ if (!user) throw new Error(t("TXT_CODE_903b6c50"));
return await getInstancesByUuid(uuid, false);
}
From d326814e0d7e790da46b6fc780307f1f44a31ca0 Mon Sep 17 00:00:00 2001
From: Unitwk
Date: Thu, 8 Aug 2024 12:02:46 +0800
Subject: [PATCH 7/7] Feat: i18n
---
languages/en_US.json | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/languages/en_US.json b/languages/en_US.json
index 40250526..ccc82f91 100644
--- a/languages/en_US.json
+++ b/languages/en_US.json
@@ -1901,5 +1901,10 @@
"TXT_CODE_930d2524": "Direct connection to web page",
"TXT_CODE_e039b9b5": "normal",
"TXT_CODE_a788e3eb": "Memory & Processor",
- "TXT_CODE_c5ed896f": "The instantaneous output content is too long and has been rejected...."
+ "TXT_CODE_c5ed896f": "The instantaneous output content is too long and has been rejected....",
+ "TXT_CODE_bed32084": "The remote node is offline, please contact the administrator to check the online status of the panel!",
+ "TXT_CODE_728fdabf": "Failed to create the instance, please try again later",
+ "TXT_CODE_348c9098": "Failed to obtain the details of the specified instance, please try again!",
+ "TXT_CODE_4aaec75c": "Wrong request type, please try again!",
+ "TXT_CODE_903b6c50": "User does not exist, please try again"
}