mirror of
https://github.com/HugoAura/Seewo-HugoAura.git
synced 2026-06-20 23:14:28 +08:00
Compare commits
6 Commits
v0.1.1-bet
...
v0.2.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd946a60fb | ||
|
|
a6c68782a0 | ||
|
|
d6db3e398a | ||
|
|
7afeb39275 | ||
|
|
b277a61923 | ||
|
|
08290301a3 |
2
.github/workflows/pack.yml
vendored
2
.github/workflows/pack.yml
vendored
@@ -1,8 +1,6 @@
|
||||
name: Pack source code & Create CI/CD Release
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 5 * * *'
|
||||
push:
|
||||
branches: [dev, stable]
|
||||
pull_request:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -15,6 +15,7 @@ autoConfiguration.json
|
||||
|
||||
# NPM Packages
|
||||
node_modules/
|
||||
package-lock.json
|
||||
|
||||
# OS Files
|
||||
desktop.ini
|
||||
|
||||
17
README.md
17
README.md
@@ -3,7 +3,7 @@
|
||||
<h1 align="center">HugoAura</h1>
|
||||
<h4 align="center">下一代希沃管家注入式修改方案</h4>
|
||||
<div align="center">
|
||||
<a href="https://github.com/HugoAura/HugoAura">首页</a> · <a href="https://hugo.aurax.cc/about">关于</a> · <a href="https://github.com/HugoAura/HugoAura/wiki">文档</a> · <a href="https://github.com/HugoAura/HugoAura/issues">反馈</a> · <a href="https://forum.aurax.cc/">社区</a>
|
||||
<a href="https://github.com/HugoAura/HugoAura">首页</a> · <a href="https://hugo.aurax.cc/about">关于 (WIP)</a> · <a href="https://docs.aurax.cc/HugoAura-Main/">文档 (WIP)</a> · <a href="https://github.com/HugoAura/HugoAura/issues">反馈</a> · <a href="https://forum.aurax.cc/">社区</a>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
@@ -14,17 +14,12 @@
|
||||
> [!IMPORTANT]
|
||||
> 已经过测试的希沃管家版本: v1.5.5.3878
|
||||
|
||||
> [!CAUTION]
|
||||
> 由于作者高三学业繁忙, 项目正处于缓慢更新阶段。
|
||||
> [!NOTE]
|
||||
> **社群信息**
|
||||
>
|
||||
> 作者将尽可能抽出时间维护项目, 但新功能的实现速度将大幅降低。
|
||||
|
||||
> [!WARNING]
|
||||
> 我们正在使用 C++ 重构 PLS, 新的子项目代号为 [Aikari](https://github.com/HugoAura/HugoAura-Aikari)。其将集成 MQTT 消息中转、HugoAura 自动更新、特权操作辅助等功能。
|
||||
>
|
||||
> 在 Aikari 的首个 Alpha 版本发布前, HugoAura 主项目与 [PLS](https://github.com/HugoAura/HugoAura-PLS) 的新功能更新频率将减弱。
|
||||
>
|
||||
> 您依然可以提出 Feature Request 或 Bug Report。开发者将在能力 / 时间限度内尽可能处理。
|
||||
> - [QQ 群 (用户自治)](https://qm.qq.com/q/buo7m9oHBK)
|
||||
> - [Telegram 群组](https://www.bilibili.com/video/BV1GJ411x7h7/) (暂时还没有...)
|
||||
> - [STCN 论坛讨论版块](https://www.bilibili.com/video/BV1GJ411x7h7/) (暂时还没有...)
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "HugoAura",
|
||||
"version": "0.1.1-beta-patch-1",
|
||||
"version": "0.2.0-rc1-p1",
|
||||
"description": "Aura for SeewoHugo",
|
||||
"main": "app.asar/main.js",
|
||||
"dependencies": {},
|
||||
|
||||
@@ -80,7 +80,7 @@ const buildIpcMain = (electron) => {
|
||||
const { applyDebugIpcHandler } = require("./ipcModules/debugIpcHandler");
|
||||
const { applyConfigIpcHandler } = require("./ipcModules/configIpcHandler");
|
||||
const { applyFsIpcHandler } = require("./ipcModules/fsIpcHandler");
|
||||
const { applyPlsIpcHandler } = require("./ipcModules/plsIpcHandler");
|
||||
const { applyAikariIpcHandler } = require("./ipcModules/aikariIpcHandler");
|
||||
|
||||
ipcMain.handle("$aura.base.restartApplication", async () => {
|
||||
app.relaunch();
|
||||
@@ -91,7 +91,7 @@ const buildIpcMain = (electron) => {
|
||||
applyDebugIpcHandler(ipcMain);
|
||||
applyConfigIpcHandler(ipcMain);
|
||||
applyFsIpcHandler(ipcMain);
|
||||
applyPlsIpcHandler(ipcMain);
|
||||
applyAikariIpcHandler(ipcMain);
|
||||
};
|
||||
|
||||
module.exports = { buildIpcMain };
|
||||
|
||||
363
src/aura/init/main/ipcModules/plsIpcHandler.js → src/aura/init/main/ipcModules/aikariIpcHandler.js
Executable file → Normal file
363
src/aura/init/main/ipcModules/plsIpcHandler.js → src/aura/init/main/ipcModules/aikariIpcHandler.js
Executable file → Normal file
@@ -68,7 +68,7 @@ const functions = {
|
||||
* @param {(arg: DownloadTask) => any} callbackFn
|
||||
* @param {string} binPath
|
||||
*/
|
||||
handlePLSDownload: async (channel, callbackFn, binPath) => {
|
||||
handleAikariDlAndInstall: async (channel, callbackFn, binPath) => {
|
||||
// TODO: Channel selection
|
||||
const apiInfo = global.__HUGO_AURA_API__;
|
||||
|
||||
@@ -78,7 +78,7 @@ const functions = {
|
||||
const reqPromise = new Promise((resolveHttpRequest) => {
|
||||
nodeHttps
|
||||
.get(
|
||||
`${apiDomain}${apiInfo.plsUpdate}?channel=${channel}`,
|
||||
`${apiDomain}${apiInfo.aikariUpdate}?channel=${channel}`,
|
||||
(rep) => {
|
||||
let dataChunk = "";
|
||||
rep.on("data", (chunk) => {
|
||||
@@ -167,12 +167,13 @@ const functions = {
|
||||
status: "failed",
|
||||
dlUrl: null,
|
||||
savePath: null,
|
||||
message: "未能获取 PLS 版本信息, 所有 API 域名均无法连接",
|
||||
message:
|
||||
"未能获取 Aikari 版本信息, 所有 API 域名均无法连接, 建议前往 GitHub 下载安装包并自行安装",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const plsVersionInfo = rawResInfo.data;
|
||||
const aikariVersionInfo = rawResInfo.data;
|
||||
|
||||
let deviceArch = process.env.PROCESSOR_ARCHITEW6432
|
||||
? process.env.PROCESSOR_ARCHITEW6432
|
||||
@@ -180,32 +181,92 @@ const functions = {
|
||||
// @ts-expect-error
|
||||
deviceArch = deviceArch.toLowerCase();
|
||||
|
||||
if (!Object.keys(plsVersionInfo.data.downloadUrl).includes(deviceArch)) {
|
||||
if (!Object.keys(aikariVersionInfo.data.downloadUrl).includes(deviceArch)) {
|
||||
callbackFn({
|
||||
id: "",
|
||||
progress: 0,
|
||||
status: "failed",
|
||||
dlUrl: null,
|
||||
savePath: null,
|
||||
message: `处理器架构识别失败, 检测到的架构: ${deviceArch}`,
|
||||
message: `不支持的处理器架构, 检测到的架构: "${deviceArch}"`,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
fsComposables.downloadFile(
|
||||
plsVersionInfo.data.downloadUrl[deviceArch],
|
||||
binPath,
|
||||
(...args) => {
|
||||
if (args[0].status === "done") {
|
||||
if (global.__HUGO_AURA__.plsStats) {
|
||||
global.__HUGO_AURA__.plsStats.installed = true;
|
||||
global.__HUGO_AURA__.plsStats.status = "dead";
|
||||
const downloadFilePromise = new Promise((resolve) => {
|
||||
fsComposables.downloadFile(
|
||||
aikariVersionInfo.data.downloadUrl[deviceArch],
|
||||
binPath,
|
||||
(...args) => {
|
||||
if (args[0].status === "done") {
|
||||
resolve(true);
|
||||
} else if (args[0].status === "failed") {
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
callbackFn(...args);
|
||||
callbackFn(...args);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const dlResult = await downloadFilePromise;
|
||||
|
||||
if (dlResult) {
|
||||
callbackFn({
|
||||
id: "INSTALL_STAGE",
|
||||
progress: 5,
|
||||
status: "waiting",
|
||||
dlUrl: null,
|
||||
savePath: null,
|
||||
message: "准备运行 Aikari 安装程序...",
|
||||
});
|
||||
|
||||
const runInstPromise = new Promise((resolve) => {
|
||||
exec(
|
||||
`"${binPath}" /VERYSILENT /SUPPRESSMSGBOXES /LOG="${binPath}\\..\\Aikari-Install.log"`,
|
||||
(err, stdout, stderr) => {
|
||||
if (err) {
|
||||
console.error(
|
||||
`[HugoAura / Main / Aikari IPC Handler / Install Aikari] Error running installer: ${stderr}`
|
||||
);
|
||||
resolve({ success: false });
|
||||
}
|
||||
resolve({ success: true });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
callbackFn({
|
||||
id: "INSTALL_STAGE",
|
||||
progress: 15,
|
||||
status: "progressing",
|
||||
dlUrl: null,
|
||||
savePath: null,
|
||||
message: "正在安装 Aikari...",
|
||||
});
|
||||
|
||||
const instResult = await runInstPromise;
|
||||
|
||||
callbackFn({
|
||||
id: "INSTALL_STAGE",
|
||||
progress: 100,
|
||||
status: instResult.success ? "done" : "failed",
|
||||
dlUrl: null,
|
||||
savePath: null,
|
||||
message: instResult.success
|
||||
? "Aikari 安装成功"
|
||||
: "安装失败, 请检查 %TEMP%/Aikari-Install-Temp 下的安装日志",
|
||||
});
|
||||
|
||||
if (instResult.success) {
|
||||
if (global.__HUGO_AURA__.aikariStats) {
|
||||
global.__HUGO_AURA__.aikariStats.installed = true;
|
||||
global.__HUGO_AURA__.aikariStats.status = "dead";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
fs.unlinkSync(binPath);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -213,37 +274,57 @@ const functions = {
|
||||
*
|
||||
* @param {import("../../../types/main/electron").AuraIPCMain} ipcMain
|
||||
*/
|
||||
const applyPlsIpcHandler = (ipcMain) => {
|
||||
const methodBase = "$aura.pls";
|
||||
const applyAikariIpcHandler = (ipcMain) => {
|
||||
const methodBase = "$aura.aikari";
|
||||
|
||||
const PLS_INSTALL_DIR = path.join("C:\\Program Files", "HugoAura PLS", "bin");
|
||||
const PLS_BIN_PATH = path.join(PLS_INSTALL_DIR, "HugoAura-PLS.exe");
|
||||
const PLS_SVC_NAME = "HugoAuraPLS";
|
||||
const AIKARI_DEFAULT_INSTALL_DIR = path.join(
|
||||
"C:\\Program Files",
|
||||
"HugoAura",
|
||||
"Aikari"
|
||||
);
|
||||
const AIKARI_LAUNCHER_PATH = path.join(
|
||||
AIKARI_DEFAULT_INSTALL_DIR,
|
||||
"Aikari-Launcher.exe"
|
||||
);
|
||||
const AIKARI_UNINSTALLER_PATH = path.join(
|
||||
AIKARI_DEFAULT_INSTALL_DIR,
|
||||
"unins000.exe"
|
||||
);
|
||||
const AIKARI_SVC_NAME = "HugoAuraAikari";
|
||||
|
||||
const isPlsDetached = process.argv.includes("--pls-detach");
|
||||
const AIKARI_TEMP_DL_DIR = path.join(
|
||||
require("os").tmpdir(),
|
||||
"Aikari-Install-Temp"
|
||||
);
|
||||
const AIKARI_TEMP_INSTALLER_FILENAME = path.join(
|
||||
AIKARI_TEMP_DL_DIR,
|
||||
"Aikari-Installer.exe"
|
||||
);
|
||||
|
||||
global.__HUGO_AURA__.plsStats = {
|
||||
const isAikariDetached = process.argv.includes("--aikari-detach");
|
||||
|
||||
global.__HUGO_AURA__.aikariStats = {
|
||||
installed: false,
|
||||
launched: false,
|
||||
detached: isPlsDetached,
|
||||
detached: isAikariDetached,
|
||||
connected: false,
|
||||
version: "unknown",
|
||||
status: "dead",
|
||||
authToken: global.__HUGO_AURA_CONFIG__.plsToken,
|
||||
authToken: global.__HUGO_AURA_CONFIG__.aikariToken,
|
||||
};
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.getPlsBinExists`,
|
||||
`${methodBase}.getIfAikariBinExists`,
|
||||
/**
|
||||
*
|
||||
* @returns {{ success: boolean; data: { isExists: boolean }; error?: Error }}
|
||||
*/
|
||||
(_event, _arg) => {
|
||||
try {
|
||||
const result = fs.existsSync(PLS_BIN_PATH);
|
||||
const result = fs.existsSync(AIKARI_LAUNCHER_PATH);
|
||||
|
||||
if (global.__HUGO_AURA__.plsStats?.status === "notInstalled") {
|
||||
global.__HUGO_AURA__.plsStats.status = "dead";
|
||||
if (global.__HUGO_AURA__.aikariStats?.status === "notInstalled") {
|
||||
global.__HUGO_AURA__.aikariStats.status = "dead";
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -252,7 +333,7 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
};
|
||||
} catch (e) {
|
||||
// @ts-expect-error
|
||||
global.__HUGO_AURA__.plsStats.status = "notInstalled";
|
||||
global.__HUGO_AURA__.aikariStats.status = "notInstalled";
|
||||
return {
|
||||
success: false,
|
||||
data: { isExists: false },
|
||||
@@ -263,7 +344,7 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.ensurePlsInstallDir`,
|
||||
`${methodBase}.ensureAikariInstallDir`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
@@ -271,24 +352,24 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
* @returns {{ success: boolean; data: { alreadyExists: boolean; createdDir: string; }; error?: Error }}
|
||||
*/
|
||||
(_event, _arg) => {
|
||||
const alreadyExists = fs.existsSync(PLS_INSTALL_DIR);
|
||||
const alreadyExists = fs.existsSync(AIKARI_DEFAULT_INSTALL_DIR);
|
||||
if (alreadyExists) {
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
alreadyExists: true,
|
||||
createdDir: PLS_INSTALL_DIR,
|
||||
createdDir: AIKARI_DEFAULT_INSTALL_DIR,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
fs.mkdirSync(PLS_INSTALL_DIR, { recursive: true });
|
||||
fs.mkdirSync(AIKARI_DEFAULT_INSTALL_DIR, { recursive: true });
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
alreadyExists: false,
|
||||
createdDir: PLS_INSTALL_DIR,
|
||||
createdDir: AIKARI_DEFAULT_INSTALL_DIR,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
@@ -296,7 +377,7 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
success: false,
|
||||
data: {
|
||||
alreadyExists: false,
|
||||
createdDir: PLS_INSTALL_DIR,
|
||||
createdDir: AIKARI_DEFAULT_INSTALL_DIR,
|
||||
},
|
||||
error: error,
|
||||
};
|
||||
@@ -305,30 +386,30 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.getPlsStats`,
|
||||
`${methodBase}.getAikariStatus`,
|
||||
/**
|
||||
*
|
||||
* @returns {{ success: boolean; data: import("../../../types/shared/pls/status").PLSStatus | null | undefined; }}
|
||||
* @returns {{ success: boolean; data: import("../../../types/shared/aikari/status").AikariStatus | null | undefined; }}
|
||||
*/
|
||||
(_event, _arg) => {
|
||||
return {
|
||||
success: true,
|
||||
data: global.__HUGO_AURA__.plsStats,
|
||||
data: global.__HUGO_AURA__.aikariStats,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.updatePlsStats`,
|
||||
`${methodBase}.updateAikariStatus`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
* @param {import("../../../types/shared/pls/status").PLSStatus} arg
|
||||
* @param {import("../../../types/shared/aikari/status").AikariStatus} arg
|
||||
* @returns
|
||||
*/
|
||||
(_event, arg) => {
|
||||
global.__HUGO_AURA__.plsStats = arg;
|
||||
ipcMain.send("assistant", `${methodBase}.post.onPlsStatsUpdate`, arg);
|
||||
global.__HUGO_AURA__.aikariStats = arg;
|
||||
ipcMain.send("assistant", `${methodBase}.post.onAikariStatsUpdate`, arg);
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
@@ -336,7 +417,7 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.getPlsSettings`,
|
||||
`${methodBase}.getAikariSettings`,
|
||||
/**
|
||||
*
|
||||
* @returns {{ success: boolean; data: Record<any, any> | null | undefined }}
|
||||
@@ -344,13 +425,13 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
(_event, _arg) => {
|
||||
return {
|
||||
success: true,
|
||||
data: global.__HUGO_AURA__.plsSettings,
|
||||
data: global.__HUGO_AURA__.aikariSettings,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.updatePlsSettings`,
|
||||
`${methodBase}.updateAikariSettings`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
@@ -358,8 +439,12 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
* @returns
|
||||
*/
|
||||
(_event, arg) => {
|
||||
global.__HUGO_AURA__.plsSettings = arg;
|
||||
ipcMain.send("assistant", `${methodBase}.post.onPlsSettingsUpdate`, arg);
|
||||
global.__HUGO_AURA__.aikariSettings = arg;
|
||||
ipcMain.send(
|
||||
"assistant",
|
||||
`${methodBase}.post.onAikariSettingsUpdate`,
|
||||
arg
|
||||
);
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
@@ -367,7 +452,7 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.getPlsRules`,
|
||||
`${methodBase}.getAikariRules`,
|
||||
/**
|
||||
*
|
||||
* @returns {{ success: boolean; data: Record<any, any> | null | undefined }}
|
||||
@@ -375,13 +460,13 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
(_event, _arg) => {
|
||||
return {
|
||||
success: true,
|
||||
data: global.__HUGO_AURA__.plsRules,
|
||||
data: global.__HUGO_AURA__.aikariRules,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.updatePlsRules`,
|
||||
`${methodBase}.updateAikariRules`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
@@ -389,8 +474,8 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
* @returns
|
||||
*/
|
||||
(_event, arg) => {
|
||||
global.__HUGO_AURA__.plsRules = arg;
|
||||
ipcMain.send("assistant", `${methodBase}.post.onPlsRulesUpdate`, arg);
|
||||
global.__HUGO_AURA__.aikariRules = arg;
|
||||
ipcMain.send("assistant", `${methodBase}.post.onAikariRulesUpdate`, arg);
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
@@ -402,7 +487,7 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainEvent} _event
|
||||
* @param {PLSResponse} arg
|
||||
* @param {AikariResponse} arg
|
||||
*/
|
||||
(_event, arg) => {
|
||||
ipcMain.send("assistant", `${methodBase}.ws.post.onNewMsgRecv`, arg);
|
||||
@@ -414,7 +499,7 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
* @param {ClientPLSRequest} arg
|
||||
* @param {ClientAikariRequest} arg
|
||||
*/
|
||||
(_event, arg) => {
|
||||
ipcMain.send(
|
||||
@@ -426,17 +511,17 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.syncPlsConfig`,
|
||||
`${methodBase}.syncAikariConfig`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} event
|
||||
* @param {{ basic: Record<any, any>, rules: Record<any, any> }} arg
|
||||
*/
|
||||
(event, arg) => {
|
||||
global.__HUGO_AURA__.plsRules = arg.rules;
|
||||
global.__HUGO_AURA__.plsSettings = arg.basic;
|
||||
global.__HUGO_AURA__.aikariRules = arg.rules;
|
||||
global.__HUGO_AURA__.aikariSettings = arg.basic;
|
||||
|
||||
ipcMain.send("*", `${methodBase}.syncPlsConfig`, arg, event.sender);
|
||||
ipcMain.send("*", `${methodBase}.syncAikariConfig`, arg, event.sender);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
@@ -445,24 +530,27 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.plsLifecycleQuery`,
|
||||
`${methodBase}.aikariLifecycleQuery`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
* @param {{ target: import("../../../types/shared/pls/status").PLSLifecycleType }} arg
|
||||
* @param {{ target: import("../../../types/shared/aikari/status").AikariLifecycleType }} arg
|
||||
* @returns {Promise<{ success: boolean, result: boolean }>}
|
||||
*/
|
||||
async (_event, arg) => {
|
||||
switch (arg.target) {
|
||||
case "isDetached":
|
||||
return { success: true, result: isPlsDetached };
|
||||
return { success: true, result: isAikariDetached };
|
||||
case "isSvcInstalled":
|
||||
return await functions.querySvcDetail(PLS_SVC_NAME, "SERVICE_NAME");
|
||||
return await functions.querySvcDetail(
|
||||
AIKARI_SVC_NAME,
|
||||
"SERVICE_NAME"
|
||||
);
|
||||
case "isSvcStart":
|
||||
return await functions.querySvcDetail(PLS_SVC_NAME, "RUNNING");
|
||||
return await functions.querySvcDetail(AIKARI_SVC_NAME, "RUNNING");
|
||||
default:
|
||||
console.warn(
|
||||
`[HugoAura / IPC / PLS] <plsLifecycleQuery> Invalid arg.target: ${arg.target}`
|
||||
`[HugoAura / IPC / Aikari] <AikariLifecycleQuery> Invalid arg.target: ${arg.target}`
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
@@ -473,98 +561,72 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.plsLifecycleControl`,
|
||||
`${methodBase}.aikariLifecycleControl`,
|
||||
/**
|
||||
*
|
||||
* @param {*} _event
|
||||
* @param {{ target: import("../../../types/shared/pls/status").PLSLifecycleControlType }} arg
|
||||
* @param {{ target: import("../../../types/shared/aikari/status").AikariLifecycleControlType }} arg
|
||||
* @returns {Promise<{ success: boolean, errorObj?: Error }>}
|
||||
*/
|
||||
async (_event, arg) => {
|
||||
const logHeader = "[HugoAura / IPC / PLS] <plsLifecycleControl>";
|
||||
const logHeader = "[HugoAura / IPC / Aikari] <AikariLifecycleControl>";
|
||||
|
||||
// TODO: Impl this
|
||||
switch (arg.target) {
|
||||
case "instSvc":
|
||||
return await functions.execCommand(
|
||||
logHeader,
|
||||
PLS_BIN_PATH,
|
||||
"--startup auto install"
|
||||
AIKARI_LAUNCHER_PATH,
|
||||
"--service install"
|
||||
);
|
||||
case "rmSvc": {
|
||||
case "uninstSvc": {
|
||||
const result = await functions.execCommand(
|
||||
logHeader,
|
||||
PLS_BIN_PATH,
|
||||
"remove"
|
||||
AIKARI_LAUNCHER_PATH,
|
||||
"--service uninstall"
|
||||
);
|
||||
return result;
|
||||
}
|
||||
case "startSvc":
|
||||
return await functions.execCommand(logHeader, PLS_BIN_PATH, "start");
|
||||
return await functions.execCommand(
|
||||
logHeader,
|
||||
"sc.exe",
|
||||
`start ${AIKARI_SVC_NAME}`
|
||||
);
|
||||
case "stopSvc": {
|
||||
const result = await functions.execCommand(
|
||||
logHeader,
|
||||
PLS_BIN_PATH,
|
||||
"stop"
|
||||
"sc.exe",
|
||||
`stop ${AIKARI_SVC_NAME}`
|
||||
);
|
||||
if (result.success && global.__HUGO_AURA__.plsStats) {
|
||||
global.__HUGO_AURA__.plsStats.connected = false;
|
||||
global.__HUGO_AURA__.plsStats.launched = false;
|
||||
global.__HUGO_AURA__.plsStats.version = "unknown";
|
||||
global.__HUGO_AURA__.plsStats.status = "dead";
|
||||
if (result.success && global.__HUGO_AURA__.aikariStats) {
|
||||
global.__HUGO_AURA__.aikariStats.connected = false;
|
||||
global.__HUGO_AURA__.aikariStats.launched = false;
|
||||
global.__HUGO_AURA__.aikariStats.version = "unknown";
|
||||
global.__HUGO_AURA__.aikariStats.status = "dead";
|
||||
|
||||
ipcMain.send(
|
||||
"assistant",
|
||||
`${methodBase}.post.onPlsStatsUpdate`,
|
||||
global.__HUGO_AURA__.plsStats
|
||||
`${methodBase}.post.onAikariStatsUpdate`,
|
||||
global.__HUGO_AURA__.aikariStats
|
||||
);
|
||||
|
||||
ipcMain.send(
|
||||
"auraWsKeepAlive",
|
||||
`${methodBase}.post.plsStopped`,
|
||||
`${methodBase}.post.aikariStopped`,
|
||||
{}
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case "rmBin":
|
||||
const unlinkPromise = new Promise((resolve) => {
|
||||
fs.unlink(PLS_BIN_PATH, (error) => {
|
||||
if (error) {
|
||||
resolve({
|
||||
success: false,
|
||||
errorObj: error,
|
||||
});
|
||||
console.error(
|
||||
`${logHeader} Failed to remove PLS bin, error:`,
|
||||
error
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
resolve({
|
||||
success: true,
|
||||
errorObj: null,
|
||||
});
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
const unlinkRet = await unlinkPromise;
|
||||
|
||||
if (unlinkRet.success && global.__HUGO_AURA__.plsStats) {
|
||||
global.__HUGO_AURA__.plsStats.connected = false;
|
||||
global.__HUGO_AURA__.plsStats.launched = false;
|
||||
global.__HUGO_AURA__.plsStats.installed = false;
|
||||
global.__HUGO_AURA__.plsStats.version = "unknown";
|
||||
|
||||
ipcMain.send(
|
||||
"assistant",
|
||||
`${methodBase}.post.onPlsStatsUpdate`,
|
||||
global.__HUGO_AURA__.plsStats
|
||||
);
|
||||
}
|
||||
|
||||
return unlinkRet;
|
||||
case "inst":
|
||||
// TODO: Impl Aikari INST
|
||||
case "uninst":
|
||||
return await functions.execCommand(
|
||||
logHeader,
|
||||
AIKARI_UNINSTALLER_PATH,
|
||||
""
|
||||
);
|
||||
default:
|
||||
return { success: false, errorObj: new Error("Method not found") };
|
||||
}
|
||||
@@ -572,32 +634,41 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.downloadPls`,
|
||||
`${methodBase}.downloadAndInstallAikari`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _evt
|
||||
* @param {{channel?: "stable" | "alpha", reportTo?: import("../../../types/main/core").WindowName}} arg
|
||||
* @returns {void}
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
(_evt, arg) => {
|
||||
async (_evt, arg) => {
|
||||
if (fs.existsSync(AIKARI_TEMP_DL_DIR)) {
|
||||
try {
|
||||
fs.unlinkSync(AIKARI_TEMP_DL_DIR);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
} else {
|
||||
fs.mkdirSync(AIKARI_TEMP_DL_DIR);
|
||||
}
|
||||
const channel = arg.channel ? arg.channel : "stable";
|
||||
const reportWin = arg.reportTo ? arg.reportTo : "assistant";
|
||||
functions.handlePLSDownload(
|
||||
functions.handleAikariDlAndInstall(
|
||||
channel,
|
||||
(status) => {
|
||||
ipcMain.send(
|
||||
reportWin,
|
||||
`${methodBase}.post.reportPlsDownloadStatus`,
|
||||
`${methodBase}.post.reportAikariInstallStep`,
|
||||
status
|
||||
);
|
||||
},
|
||||
PLS_BIN_PATH
|
||||
AIKARI_TEMP_INSTALLER_FILENAME
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.retryPlsConnect`,
|
||||
`${methodBase}.retryAikariConnect`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
@@ -605,13 +676,17 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
* @returns {{ success: boolean, status: "Already" | "Retrying" }}
|
||||
*/
|
||||
(_event, arg) => {
|
||||
if (global.__HUGO_AURA__.plsStats?.connected) {
|
||||
if (global.__HUGO_AURA__.aikariStats?.connected) {
|
||||
return {
|
||||
success: true,
|
||||
status: "Already",
|
||||
};
|
||||
} else {
|
||||
ipcMain.send("auraWsKeepAlive", `${methodBase}.retryPlsConnect`, arg);
|
||||
ipcMain.send(
|
||||
"auraWsKeepAlive",
|
||||
`${methodBase}.retryAikariConnect`,
|
||||
arg
|
||||
);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
@@ -621,13 +696,31 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.forceReloadKeepAliveWin`,
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
* @param {any} arg
|
||||
*/
|
||||
(_event, arg) => {
|
||||
ipcMain.send(
|
||||
"auraWsKeepAlive",
|
||||
`${methodBase}.post.onForceReloadRequested`,
|
||||
arg
|
||||
);
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
`${methodBase}.post.updateRetryStatus`,
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||
* @param {{ success: boolean }} arg
|
||||
* @param {{ success: boolean; message: string }} arg
|
||||
*/
|
||||
(_event, arg) => {
|
||||
ipcMain.send("assistant", `${methodBase}.post.updateRetryStatus`, arg);
|
||||
@@ -639,4 +732,4 @@ const applyPlsIpcHandler = (ipcMain) => {
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = { applyPlsIpcHandler };
|
||||
module.exports = { applyAikariIpcHandler };
|
||||
4
src/aura/types/render/global.d.ts
vendored
4
src/aura/types/render/global.d.ts
vendored
@@ -3,14 +3,14 @@ interface HugoAuraGlobal {
|
||||
}
|
||||
|
||||
interface AssistantHugoAuraGlobal extends HugoAuraGlobal {
|
||||
plsStatus: PLSStatus;
|
||||
plsStatus: AikariStatus;
|
||||
plsRules: Record<any, any>;
|
||||
plsSettings: Record<any, any>;
|
||||
}
|
||||
|
||||
interface AuraWSKeepAliveWindowHugoAuraGlobal extends HugoAuraGlobal {
|
||||
plsWs: WebSocket | null;
|
||||
plsStats: PLSStatus;
|
||||
plsStats: AikariStatus;
|
||||
}
|
||||
|
||||
type UIFunctionsObject = Record<string, any>;
|
||||
|
||||
17
src/aura/types/shared/pls/status.d.ts → src/aura/types/shared/aikari/status.d.ts
vendored
Executable file → Normal file
17
src/aura/types/shared/pls/status.d.ts → src/aura/types/shared/aikari/status.d.ts
vendored
Executable file → Normal file
@@ -1,28 +1,29 @@
|
||||
import { RendererProcessOnlyVal } from "../global";
|
||||
|
||||
type PLSStatusDesc =
|
||||
type AikariStatusDesc =
|
||||
| "dead"
|
||||
| "running"
|
||||
| "notReady"
|
||||
| "downloading"
|
||||
| "installing"
|
||||
| "notInstalled";
|
||||
|
||||
interface PLSStatus {
|
||||
interface AikariStatus {
|
||||
installed: boolean;
|
||||
detached: boolean;
|
||||
connected: boolean;
|
||||
launched: boolean;
|
||||
status: PLSStatusDesc;
|
||||
status: AikariStatusDesc;
|
||||
version: string;
|
||||
authToken: string;
|
||||
}
|
||||
|
||||
type PLSLifecycleType = "isDetached" | "isSvcInstalled" | "isSvcStart";
|
||||
type AikariLifecycleType = "isDetached" | "isSvcInstalled" | "isSvcStart";
|
||||
|
||||
type PLSLifecycleControlType =
|
||||
type AikariLifecycleControlType =
|
||||
| "instSvc"
|
||||
| "rmSvc"
|
||||
| "uninstSvc"
|
||||
| "startSvc"
|
||||
| "stopSvc"
|
||||
| "rmBin"
|
||||
| "dlBin";
|
||||
| "uninst"
|
||||
| "inst";
|
||||
7
src/aura/types/shared/pls/websocket.d.ts → src/aura/types/shared/aikari/websocket.d.ts
vendored
Executable file → Normal file
7
src/aura/types/shared/pls/websocket.d.ts → src/aura/types/shared/aikari/websocket.d.ts
vendored
Executable file → Normal file
@@ -1,17 +1,18 @@
|
||||
interface ClientPLSRequest {
|
||||
interface ClientAikariRequest {
|
||||
method: string;
|
||||
data: Record<any, any>;
|
||||
eventId: string;
|
||||
module: string;
|
||||
}
|
||||
|
||||
interface PLSResponse {
|
||||
interface AikariResponse {
|
||||
success: boolean;
|
||||
code: number;
|
||||
data: Record<any, any>;
|
||||
eventId: string;
|
||||
}
|
||||
|
||||
interface PLSPush {
|
||||
interface AikariPush {
|
||||
success: boolean;
|
||||
type: string;
|
||||
data: Record<any, any>;
|
||||
12
src/aura/types/shared/global.d.ts
vendored
12
src/aura/types/shared/global.d.ts
vendored
@@ -3,7 +3,7 @@ import type EventBus from "../../utils/eventBus";
|
||||
import { HookedWindowsMap, UIHooksMap, WindowHooksMap } from "../main/core";
|
||||
import { UIHooksObject } from "../render/uiHook";
|
||||
import ConfigManager from "../../init/shared/configManager";
|
||||
import { PLSStatus } from "./pls/status";
|
||||
import { AikariStatus } from "./aikari/status";
|
||||
|
||||
type MainProcessOnlyVal<T> = T;
|
||||
type RendererProcessOnlyVal<T> = T;
|
||||
@@ -15,10 +15,10 @@ interface GlobalHugoAuraInfo {
|
||||
hookedWindows?: MainProcessOnlyVal<HookedWindowsMap>;
|
||||
ipcInit?: MainProcessOnlyVal<boolean>;
|
||||
auraDir: MainProcessOnlyVal<string>;
|
||||
plsRules?: Record<any, any> | null;
|
||||
plsSettings?: Record<any, any> | null;
|
||||
plsStats?: PLSStatus | null;
|
||||
plsWs?: RendererProcessOnlyVal<WebSocket>;
|
||||
aikariRules?: Record<any, any> | null;
|
||||
aikariSettings?: Record<any, any> | null;
|
||||
aikariStats?: AikariStatus | null;
|
||||
aikariWs?: RendererProcessOnlyVal<WebSocket>;
|
||||
uiHooks?: MainProcessOnlyVal<UIHooksMap>;
|
||||
windowHooks?: MainProcessOnlyVal<WindowHooksMap>;
|
||||
version: RendererProcessOnlyVal<string>;
|
||||
@@ -26,7 +26,7 @@ interface GlobalHugoAuraInfo {
|
||||
|
||||
interface GlobalHugoAuraApiInfo {
|
||||
domains: string[];
|
||||
plsUpdate: string;
|
||||
aikariUpdate: string;
|
||||
auraUpdate: string;
|
||||
}
|
||||
|
||||
|
||||
112
src/aura/ui/aikari/onConnectedSeq.js
Normal file
112
src/aura/ui/aikari/onConnectedSeq.js
Normal file
@@ -0,0 +1,112 @@
|
||||
// @ts-check
|
||||
|
||||
const { genRandomHex } = require("../../utils/crypto");
|
||||
|
||||
const IPC_METHOD_BASE = "$aura.aikari";
|
||||
|
||||
/** @type {Map<string, any>} */
|
||||
const wsGetCallbacks = new Map();
|
||||
|
||||
const actions = {
|
||||
getAikariVersion: async (originalAikariStates, wsObj) => {
|
||||
const eventId = genRandomHex();
|
||||
wsObj.send(
|
||||
JSON.stringify({
|
||||
module: "launcher",
|
||||
eventId: eventId,
|
||||
method: "basic.props.getVersion",
|
||||
data: {},
|
||||
})
|
||||
);
|
||||
const promise = new Promise((resolve) => {
|
||||
wsGetCallbacks.set(eventId, resolve);
|
||||
});
|
||||
const data = await promise;
|
||||
if (data.success) {
|
||||
originalAikariStates.version = data.data.version;
|
||||
console.debug(
|
||||
"[HugoAura / UI / Aikari OCMS] Updated Aikari version info: " +
|
||||
data.data.version
|
||||
);
|
||||
}
|
||||
},
|
||||
getAikariLauncherConfig: async (wsObj) => {
|
||||
const eventId = genRandomHex();
|
||||
wsObj.send(
|
||||
JSON.stringify({
|
||||
module: "launcher",
|
||||
eventId,
|
||||
method: "config.actions.getConfig",
|
||||
data: {},
|
||||
})
|
||||
);
|
||||
const promise = new Promise((resolve) => {
|
||||
wsGetCallbacks.set(eventId, resolve);
|
||||
});
|
||||
const data = await promise;
|
||||
if (data.success) {
|
||||
console.debug(
|
||||
"[HugoAura / UI / Aikari OCMS] Received Aikari launcher config: ",
|
||||
data
|
||||
);
|
||||
return data.data;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
getAikariPLSRules: async (wsObj) => {
|
||||
const eventId = genRandomHex();
|
||||
wsObj.send(
|
||||
JSON.stringify({
|
||||
module: "pls",
|
||||
eventId,
|
||||
method: "config.rules.getConfig",
|
||||
})
|
||||
);
|
||||
const promise = new Promise((resolve) => {
|
||||
wsGetCallbacks.set(eventId, resolve);
|
||||
});
|
||||
const data = await promise;
|
||||
if (data.success) {
|
||||
console.debug(
|
||||
"[HugoAura / UI / Aikari OCMS] Received Aikari PLS rules: ",
|
||||
data
|
||||
);
|
||||
return data.data;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const onAikariConnectedMsgSeq = async ({ curAikariStates, wsObj }) => {
|
||||
const updatedAikariStates = { ...curAikariStates };
|
||||
const onMsgRecvListener = (data) => {
|
||||
if (wsGetCallbacks.has(data.detail.eventId)) {
|
||||
wsGetCallbacks.get(data.detail.eventId)(data.detail);
|
||||
}
|
||||
};
|
||||
document.addEventListener("onAikariMessageRecv", onMsgRecvListener);
|
||||
// Get Aikari Version
|
||||
await actions.getAikariVersion(updatedAikariStates, wsObj);
|
||||
// Get Aikari Launcher Config
|
||||
const aikariLauncherConfig = await actions.getAikariLauncherConfig(wsObj);
|
||||
if (aikariLauncherConfig) {
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updateAikariSettings`,
|
||||
aikariLauncherConfig
|
||||
);
|
||||
}
|
||||
// Get Aikari PLS Rules
|
||||
const aikariPLSRules = await actions.getAikariPLSRules(wsObj);
|
||||
if (aikariPLSRules) {
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updateAikariRules`,
|
||||
aikariPLSRules
|
||||
);
|
||||
}
|
||||
|
||||
return updatedAikariStates;
|
||||
};
|
||||
|
||||
module.exports = { onAikariConnectedMsgSeq };
|
||||
2
src/aura/ui/pls/pushHandler.js → src/aura/ui/aikari/pushHandler.js
Executable file → Normal file
2
src/aura/ui/pls/pushHandler.js → src/aura/ui/aikari/pushHandler.js
Executable file → Normal file
@@ -7,7 +7,7 @@ const { configRouteHandler } = require(`${REQUIRE_BASE}/routes/config`);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PLSPush} parsedWsMsg
|
||||
* @param {AikariPush} parsedWsMsg
|
||||
* @returns
|
||||
*/
|
||||
const pushMsgHandler = (parsedWsMsg) => {
|
||||
49
src/aura/ui/aikari/routes/basic.js
Normal file
49
src/aura/ui/aikari/routes/basic.js
Normal file
@@ -0,0 +1,49 @@
|
||||
// @ts-check
|
||||
|
||||
const IPC_METHOD_BASE = "$aura.aikari";
|
||||
|
||||
// TODO: REFACTOR
|
||||
/**
|
||||
*
|
||||
* @param {AikariPush} parsedWsMsg
|
||||
* @returns
|
||||
*/
|
||||
const basicRouteHandler = (parsedWsMsg) => {
|
||||
const target = parsedWsMsg.type.split(".").slice(-1)[0];
|
||||
switch (target) {
|
||||
case "pushPlsInfo":
|
||||
if (global.__HUGO_AURA__.aikariStats) {
|
||||
global.__HUGO_AURA__.aikariStats.status = parsedWsMsg.data.status;
|
||||
global.__HUGO_AURA__.aikariStats.version = parsedWsMsg.data.version;
|
||||
}
|
||||
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||
global.__HUGO_AURA__.aikariStats
|
||||
);
|
||||
|
||||
console.debug(
|
||||
"[HugoAura / UI / Aikari Routes / DEBUG] Updated aikariStats basic info:",
|
||||
global.__HUGO_AURA__.aikariStats
|
||||
);
|
||||
break;
|
||||
|
||||
case "plsNotReadyError":
|
||||
if (global.__HUGO_AURA__.aikariStats) {
|
||||
global.__HUGO_AURA__.aikariStats.launched = true;
|
||||
global.__HUGO_AURA__.aikariStats.connected = false;
|
||||
global.__HUGO_AURA__.aikariStats.status = "notReady";
|
||||
}
|
||||
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||
global.__HUGO_AURA__.aikariStats
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
module.exports = { basicRouteHandler };
|
||||
8
src/aura/ui/pls/routes/config.js → src/aura/ui/aikari/routes/config.js
Executable file → Normal file
8
src/aura/ui/pls/routes/config.js → src/aura/ui/aikari/routes/config.js
Executable file → Normal file
@@ -1,10 +1,10 @@
|
||||
// @ts-check
|
||||
|
||||
const IPC_METHOD_BASE = "$aura.pls";
|
||||
const IPC_METHOD_BASE = "$aura.aikari";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PLSPush} parsedWsMsg
|
||||
* @param {AikariPush} parsedWsMsg
|
||||
* @returns
|
||||
*/
|
||||
const configRouteHandler = (parsedWsMsg) => {
|
||||
@@ -12,13 +12,13 @@ const configRouteHandler = (parsedWsMsg) => {
|
||||
switch (target) {
|
||||
case "pushBasicConfig":
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updatePlsSettings`,
|
||||
`${IPC_METHOD_BASE}.updateAikariSettings`,
|
||||
parsedWsMsg.data
|
||||
);
|
||||
break;
|
||||
case "pushRuleSettings":
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updatePlsRules`,
|
||||
`${IPC_METHOD_BASE}.updateAikariRules`,
|
||||
parsedWsMsg.data
|
||||
);
|
||||
break;
|
||||
136
src/aura/ui/composables/aikariConfigManager.js
Normal file
136
src/aura/ui/composables/aikariConfigManager.js
Normal file
@@ -0,0 +1,136 @@
|
||||
// @ts-check
|
||||
|
||||
const __SCOPE = "assistant / rendererCommon";
|
||||
|
||||
const IPC_METHOD_BASE = "$aura.aikari";
|
||||
|
||||
const updateAikariStatusFromLocal = async () => {
|
||||
const aikariStatus = (
|
||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getAikariStatus`)
|
||||
).data;
|
||||
global.__HUGO_AURA__.aikariStats = aikariStatus;
|
||||
return aikariStatus;
|
||||
};
|
||||
|
||||
const updateAikariSettingsFromLocal = async () => {
|
||||
const aikariSettings = (
|
||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getAikariSettings`)
|
||||
).data;
|
||||
global.__HUGO_AURA__.aikariSettings = aikariSettings;
|
||||
return aikariSettings;
|
||||
};
|
||||
|
||||
const updateAikariRulesFromLocal = async () => {
|
||||
const aikariRules = (
|
||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getAikariRules`)
|
||||
).data;
|
||||
global.__HUGO_AURA__.aikariRules = aikariRules;
|
||||
return aikariRules;
|
||||
};
|
||||
|
||||
const { genRandomHex } = require("../../utils/crypto");
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} configKey
|
||||
* @param {any} configValue
|
||||
*/
|
||||
const updateAikariConfigToRemote = async (
|
||||
configKey,
|
||||
configValue,
|
||||
module = "launcher",
|
||||
writeToDisk = true
|
||||
) => {
|
||||
const configLevels = configKey.split(".");
|
||||
|
||||
const aikariConfigUpdateEvent = new CustomEvent("onAikariConfigUpdate", {
|
||||
detail: {
|
||||
path: configLevels,
|
||||
value: configValue,
|
||||
},
|
||||
});
|
||||
document.dispatchEvent(aikariConfigUpdateEvent);
|
||||
const settingsEntries = document.getElementsByClassName(
|
||||
"aura-settings-entry"
|
||||
);
|
||||
if (settingsEntries.length > 0) {
|
||||
Array.from(settingsEntries).forEach((entry) => {
|
||||
entry.dispatchEvent(aikariConfigUpdateEvent);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {ClientAikariRequest}
|
||||
*/
|
||||
const data = {
|
||||
method: "config.actions.updateConfig",
|
||||
data: {
|
||||
key: configKey,
|
||||
value: configValue,
|
||||
write: writeToDisk,
|
||||
},
|
||||
eventId: genRandomHex(), // 不用 crypto, 因为会带来不必要的性能开销
|
||||
module: module,
|
||||
};
|
||||
|
||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.ws.sendWsMessage`, data);
|
||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.syncAikariConfig`, {
|
||||
basic: global.__HUGO_AURA__.aikariSettings,
|
||||
rules: global.__HUGO_AURA__.aikariRules,
|
||||
});
|
||||
};
|
||||
|
||||
// [!] Will be deprecated
|
||||
const updateAikariPLSRulesToRemote = async (
|
||||
configKey,
|
||||
configValue,
|
||||
affiliated,
|
||||
writeToDisk = true
|
||||
) => {
|
||||
const configLevels = configKey.split(".");
|
||||
|
||||
const aikariRuleConfigUpdateEvent = new CustomEvent("onAikariConfigUpdate", {
|
||||
detail: {
|
||||
path: configLevels,
|
||||
value: configValue,
|
||||
},
|
||||
});
|
||||
document.dispatchEvent(aikariRuleConfigUpdateEvent);
|
||||
const settingsEntries = document.getElementsByClassName(
|
||||
"aura-settings-entry"
|
||||
);
|
||||
if (settingsEntries.length > 0) {
|
||||
Array.from(settingsEntries).forEach((entry) => {
|
||||
entry.dispatchEvent(aikariRuleConfigUpdateEvent);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {ClientAikariRequest}
|
||||
*/
|
||||
const data = {
|
||||
method: "config.rules.updateConfig",
|
||||
data: {
|
||||
key: configKey,
|
||||
value: configValue,
|
||||
write: writeToDisk,
|
||||
affiliated,
|
||||
},
|
||||
eventId: genRandomHex(),
|
||||
module: "pls",
|
||||
};
|
||||
|
||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.ws.sendWsMessage`, data);
|
||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.syncAikariConfig`, {
|
||||
basic: global.__HUGO_AURA__.aikariSettings,
|
||||
rules: global.__HUGO_AURA__.aikariRules,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
updateAikariRulesFromLocal,
|
||||
updateAikariStatusFromLocal,
|
||||
updateAikariSettingsFromLocal,
|
||||
updateAikariConfigToRemote,
|
||||
updateAikariPLSRulesToRemote,
|
||||
};
|
||||
@@ -1,81 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const __SCOPE = "assistant / rendererCommon";
|
||||
|
||||
const IPC_METHOD_BASE = "$aura.pls";
|
||||
|
||||
const updatePlsStatusFromLocal = async () => {
|
||||
const plsStatus = (
|
||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsStats`)
|
||||
).data;
|
||||
global.__HUGO_AURA__.plsStats = plsStatus;
|
||||
return plsStatus;
|
||||
};
|
||||
|
||||
const updatePlsSettingsFromLocal = async () => {
|
||||
const plsSettings = (
|
||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsSettings`)
|
||||
).data;
|
||||
global.__HUGO_AURA__.plsSettings = plsSettings;
|
||||
return plsSettings;
|
||||
};
|
||||
|
||||
const updatePlsRulesFromLocal = async () => {
|
||||
const plsRules = (
|
||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsRules`)
|
||||
).data;
|
||||
global.__HUGO_AURA__.plsRules = plsRules;
|
||||
return plsRules;
|
||||
};
|
||||
|
||||
const { genRandomHex } = require("../../utils/crypto");
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} configKey
|
||||
* @param {any} configValue
|
||||
*/
|
||||
const updatePlsConfigToRemote = async (configKey, configValue) => {
|
||||
const configLevels = configKey.split(".");
|
||||
|
||||
const plsConfigUpdateEvent = new CustomEvent("onPLSConfigUpdate", {
|
||||
detail: {
|
||||
path: configLevels,
|
||||
value: configValue,
|
||||
},
|
||||
});
|
||||
document.dispatchEvent(plsConfigUpdateEvent);
|
||||
const settingsEntries = document.getElementsByClassName(
|
||||
"aura-settings-entry"
|
||||
);
|
||||
if (settingsEntries.length > 0) {
|
||||
Array.from(settingsEntries).forEach((entry) => {
|
||||
entry.dispatchEvent(plsConfigUpdateEvent);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {ClientPLSRequest}
|
||||
*/
|
||||
const data = {
|
||||
method: "config.action.updateConfig",
|
||||
data: {
|
||||
key: configKey,
|
||||
value: configValue,
|
||||
},
|
||||
eventId: genRandomHex(), // 不用 crypto, 因为会带来不必要的性能开销
|
||||
};
|
||||
|
||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.ws.sendWsMessage`, data);
|
||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.syncPlsConfig`, {
|
||||
basic: global.__HUGO_AURA__.plsSettings,
|
||||
rules: global.__HUGO_AURA__.plsRules,
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
updatePlsRulesFromLocal,
|
||||
updatePlsStatusFromLocal,
|
||||
updatePlsSettingsFromLocal,
|
||||
updatePlsConfigToRemote,
|
||||
};
|
||||
34
src/aura/ui/composables/rawCmdExec/app.js
Normal file
34
src/aura/ui/composables/rawCmdExec/app.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const childProc = require("child_process");
|
||||
|
||||
const appRawCmds = {
|
||||
checkVcRedistInst: async () => {
|
||||
let deviceArch = process.env.PROCESSOR_ARCHITEW6432
|
||||
? process.env.PROCESSOR_ARCHITEW6432
|
||||
: process.env.PROCESSOR_ARCHITECTURE;
|
||||
// @ts-expect-error
|
||||
deviceArch = deviceArch.toLowerCase();
|
||||
if (deviceArch === "amd64") {
|
||||
deviceArch = "x64";
|
||||
} else if (deviceArch === "arm64") {
|
||||
// do nothing
|
||||
}
|
||||
const waitForCmd = new Promise((resolve) => {
|
||||
childProc.exec(
|
||||
`reg query "HKLM\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\${deviceArch}" /v Installed`,
|
||||
(error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.warn(
|
||||
`[HugoAura / UI / Composables / Raw CMD / APP] Detected VS Redist not installed: ${stderr}`
|
||||
);
|
||||
resolve({ installed: false, arch: deviceArch });
|
||||
} else {
|
||||
resolve({ installed: true, arch: deviceArch });
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
return waitForCmd;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = appRawCmds;
|
||||
28
src/aura/ui/composables/rawCmdExec/fs.js
Normal file
28
src/aura/ui/composables/rawCmdExec/fs.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const childProc = require("child_process");
|
||||
|
||||
const fileSystemRawCmds = {
|
||||
getDiskCaptions: async () => {
|
||||
const waitForCmd = new Promise((resolve) => {
|
||||
childProc.exec("fsutil fsinfo drives", (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`[HugoAura / UI / Composables / Raw CMD / FS] Failed to exec fsutil getCaption: ${error}`
|
||||
);
|
||||
resolve([]);
|
||||
}
|
||||
const finResult = [];
|
||||
stdout
|
||||
.trim()
|
||||
.split(": ")[1]
|
||||
.split(":\\")
|
||||
.forEach((line) => {
|
||||
if (line !== "") finResult.push(line.trim() + ":");
|
||||
});
|
||||
resolve(finResult);
|
||||
});
|
||||
});
|
||||
return waitForCmd;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = fileSystemRawCmds;
|
||||
@@ -18,12 +18,12 @@ const showRelaunchToast = () => {
|
||||
if (!toastBs.isShown()) toastBs.show();
|
||||
};
|
||||
|
||||
const showRelaunchPLSToast = () => {
|
||||
const toast = document.getElementById("relaunchPlsNotifyToast");
|
||||
const showRelaunchAikariToast = () => {
|
||||
const toast = document.getElementById("relaunchAikariNotifyToast");
|
||||
const toastBs = bootstrap.Toast.getOrCreateInstance(toast);
|
||||
|
||||
if (global.__HUGO_AURA__.plsStats.detached) {
|
||||
const relaunchBtn = document.getElementById("plsRelaunchBtn");
|
||||
if (global.__HUGO_AURA__.aikariStats.detached) {
|
||||
const relaunchBtn = document.getElementById("aikariRelaunchBtn");
|
||||
relaunchBtn.disabled = true;
|
||||
relaunchBtn.textContent = "分离模式下无法执行";
|
||||
}
|
||||
@@ -37,12 +37,6 @@ const showToast = (entry) => {
|
||||
} else if (entry.restart) {
|
||||
showRelaunchToast();
|
||||
}
|
||||
|
||||
/*
|
||||
else if (entry.restartPLS) {
|
||||
showRelaunchPLSToast();
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
const setDisableStatus = (el, isDisable, hint = null) => {
|
||||
@@ -56,9 +50,9 @@ const setDisableStatus = (el, isDisable, hint = null) => {
|
||||
tooltipIns.enable();
|
||||
}
|
||||
} else {
|
||||
el.setAttribute("data-bs-toggle", "tooltip");
|
||||
el.setAttribute("data-bs-placement", "top");
|
||||
el.setAttribute("data-bs-title", "None");
|
||||
el.removeAttribute("data-bs-toggle");
|
||||
el.removeAttribute("data-bs-placement");
|
||||
el.removeAttribute("data-bs-title");
|
||||
el.classList.remove("ase-operation-area-disabled");
|
||||
const tooltipIns = bootstrap.Tooltip.getInstance(el);
|
||||
if (tooltipIns) {
|
||||
@@ -106,7 +100,18 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
|
||||
case "radio": {
|
||||
const elValue = entry.valueGetter();
|
||||
const elArr = [];
|
||||
for (const template of entry.templates) {
|
||||
let targetTemplatesArr = [];
|
||||
let targetTemplateLablesArr = [];
|
||||
targetTemplatesArr =
|
||||
typeof entry.templates === "function"
|
||||
? entry.templates()
|
||||
: entry.templates;
|
||||
targetTemplateLablesArr =
|
||||
typeof entry.templateLabels === "function"
|
||||
? entry.templateLabels()
|
||||
: entry.templateLabels;
|
||||
|
||||
for (const template of targetTemplatesArr) {
|
||||
const inlineContainerEl = document.createElement("div");
|
||||
inlineContainerEl.classList.add("form-check", "form-check-inline");
|
||||
const radioEl = document.createElement("input");
|
||||
@@ -114,7 +119,7 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
|
||||
radioEl.classList.add("form-check-input");
|
||||
radioEl.type = "radio";
|
||||
radioEl.name = `${entry.id}Radios`;
|
||||
radioEl.id = `${entry.id}Radio${entry.templates.indexOf(template)}`;
|
||||
radioEl.id = `${entry.id}Radio${targetTemplatesArr.indexOf(template)}`;
|
||||
radioEl.checked = template === elValue ? true : false;
|
||||
radioEl.addEventListener("change", async (event) => {
|
||||
if (event.target.checked) {
|
||||
@@ -132,7 +137,53 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
|
||||
labelEl.classList.add("form-check-label");
|
||||
labelEl.setAttribute("for", radioEl.id);
|
||||
labelEl.textContent =
|
||||
entry.templateLabels[entry.templates.indexOf(template)];
|
||||
targetTemplateLablesArr[targetTemplatesArr.indexOf(template)];
|
||||
inlineContainerEl.appendChild(labelEl);
|
||||
elArr.push(inlineContainerEl);
|
||||
}
|
||||
return elArr;
|
||||
}
|
||||
case "checkbox": {
|
||||
const elValue = entry.valueGetter();
|
||||
const elArr = [];
|
||||
let targetTemplatesArr = [];
|
||||
let targetTemplateLablesArr = [];
|
||||
targetTemplatesArr =
|
||||
typeof entry.templates === "function"
|
||||
? entry.templates()
|
||||
: entry.templates;
|
||||
targetTemplateLablesArr =
|
||||
typeof entry.templateLabels === "function"
|
||||
? entry.templateLabels()
|
||||
: entry.templateLabels;
|
||||
|
||||
for (const templateName of targetTemplatesArr) {
|
||||
const inlineContainerEl = document.createElement("div");
|
||||
inlineContainerEl.classList.add("form-check", "form-check-inline");
|
||||
const chkBoxEl = document.createElement("input");
|
||||
chkBoxEl.value = templateName;
|
||||
chkBoxEl.classList.add("form-check-input");
|
||||
chkBoxEl.type = "checkbox";
|
||||
chkBoxEl.name = `${entry.id}Checkbox`;
|
||||
chkBoxEl.id = `${entry.id}Checkbox${targetTemplatesArr.indexOf(
|
||||
templateName
|
||||
)}`;
|
||||
chkBoxEl.checked = elValue.includes(templateName) ? true : false;
|
||||
chkBoxEl.addEventListener("change", async (event) => {
|
||||
showToast(entry);
|
||||
await entry.callbackFn(
|
||||
event.target.value,
|
||||
chkBoxEl,
|
||||
operationArea,
|
||||
descriptionArea
|
||||
);
|
||||
});
|
||||
inlineContainerEl.appendChild(chkBoxEl);
|
||||
const labelEl = document.createElement("label");
|
||||
labelEl.classList.add("form-check-label");
|
||||
labelEl.setAttribute("for", chkBoxEl.id);
|
||||
labelEl.textContent =
|
||||
targetTemplateLablesArr[targetTemplatesArr.indexOf(templateName)];
|
||||
inlineContainerEl.appendChild(labelEl);
|
||||
elArr.push(inlineContainerEl);
|
||||
}
|
||||
@@ -225,29 +276,29 @@ const renderNormalSettingsItem = (entry, formEl) => {
|
||||
powerIcon.setAttribute("data-bs-title", "需要重启 Electron 进程");
|
||||
entryTitle.appendChild(powerIcon);
|
||||
}
|
||||
if (entry.PLSRequired) {
|
||||
const plsIcon = document.createElement("i");
|
||||
plsIcon.classList.add(
|
||||
if (entry.aikariRequired) {
|
||||
const aikariIcon = document.createElement("i");
|
||||
aikariIcon.classList.add(
|
||||
"layui-icon",
|
||||
"layui-icon-component",
|
||||
"aura-settings-entry-property-icon"
|
||||
);
|
||||
plsIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||
plsIcon.setAttribute("data-bs-placement", "top");
|
||||
plsIcon.setAttribute("data-bs-title", "需要 PLS 支持");
|
||||
entryTitle.appendChild(plsIcon);
|
||||
aikariIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||
aikariIcon.setAttribute("data-bs-placement", "top");
|
||||
aikariIcon.setAttribute("data-bs-title", "需要 Aikari 支持");
|
||||
entryTitle.appendChild(aikariIcon);
|
||||
}
|
||||
if (entry.restartPLS) {
|
||||
const plsIcon = document.createElement("i");
|
||||
plsIcon.classList.add(
|
||||
if (entry.restartAikari) {
|
||||
const aikariIcon = document.createElement("i");
|
||||
aikariIcon.classList.add(
|
||||
"layui-icon",
|
||||
"layui-icon-logout",
|
||||
"aura-settings-entry-property-icon"
|
||||
);
|
||||
plsIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||
plsIcon.setAttribute("data-bs-placement", "top");
|
||||
plsIcon.setAttribute("data-bs-title", "需要重启 PLS 进程");
|
||||
entryTitle.appendChild(plsIcon);
|
||||
aikariIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||
aikariIcon.setAttribute("data-bs-placement", "top");
|
||||
aikariIcon.setAttribute("data-bs-title", "需要重启 Aikari 进程");
|
||||
entryTitle.appendChild(aikariIcon);
|
||||
}
|
||||
if (entry.reload) {
|
||||
const reloadIcon = document.createElement("i");
|
||||
@@ -308,33 +359,14 @@ const renderNormalSettingsItem = (entry, formEl) => {
|
||||
insertOrRemoveEl(entryOperationArea, targetEl, true);
|
||||
}
|
||||
};
|
||||
const channel = entry.PLSRequired
|
||||
? "onPLSConfigUpdate"
|
||||
const channel = entry.aikariRequired
|
||||
? "onAikariConfigUpdate"
|
||||
: "onHugoAuraConfigUpdate";
|
||||
entryContainerEl.addEventListener(channel, evtListener);
|
||||
// createOnLeaveEvtListener(channel, evtListener);
|
||||
}
|
||||
|
||||
if (entry.PLSRequired) {
|
||||
if (!global.__HUGO_AURA__.plsStats.connected) {
|
||||
setDisableStatus(entryOperationArea, true, "连接至 PLS 以继续");
|
||||
}
|
||||
|
||||
const evtListener = (event) => {
|
||||
if (event.detail.connected) {
|
||||
setDisableStatus(entryOperationArea, false);
|
||||
} else {
|
||||
setDisableStatus(entryOperationArea, true, "连接至 PLS 以继续");
|
||||
}
|
||||
};
|
||||
entryContainerEl.addEventListener("onPLSStatsUpdate", evtListener);
|
||||
// createOnLeaveEvtListener("onPLSStatsUpdate", evtListener);
|
||||
}
|
||||
entryContainerEl.appendChild(entryOperationArea);
|
||||
const isShow = entry.auraIf();
|
||||
if (!isShow) entryContainerEl.classList.add("aura-settings-entry-hidden");
|
||||
|
||||
const updateDisableStatus = () => {
|
||||
const updateDisableStatus = (entry) => {
|
||||
const isDisabledRet = entry.auraDisable();
|
||||
setDisableStatus(
|
||||
entryOperationArea,
|
||||
@@ -344,9 +376,32 @@ const renderNormalSettingsItem = (entry, formEl) => {
|
||||
};
|
||||
|
||||
if (entry.auraDisable) {
|
||||
updateDisableStatus();
|
||||
updateDisableStatus(entry);
|
||||
}
|
||||
|
||||
if (entry.aikariRequired) {
|
||||
if (!global.__HUGO_AURA__.aikariStats.connected) {
|
||||
setDisableStatus(entryOperationArea, true, "连接至 Aikari 以继续");
|
||||
}
|
||||
|
||||
const evtListener = (event) => {
|
||||
if (event.detail.connected) {
|
||||
try {
|
||||
updateDisableStatus(entry);
|
||||
} catch {
|
||||
setDisableStatus(entryOperationArea, false);
|
||||
}
|
||||
} else {
|
||||
setDisableStatus(entryOperationArea, true, "连接至 Aikari 以继续");
|
||||
}
|
||||
};
|
||||
entryContainerEl.addEventListener("onAikariStatsUpdate", evtListener);
|
||||
// createOnLeaveEvtListener("onAikariStatsUpdate", evtListener);
|
||||
}
|
||||
entryContainerEl.appendChild(entryOperationArea);
|
||||
const isShow = entry.auraIf();
|
||||
if (!isShow) entryContainerEl.classList.add("aura-settings-entry-hidden");
|
||||
|
||||
if (entry.associateVal) {
|
||||
const evtListener = (event) => {
|
||||
if (!entry.associateVal.includes(event.detail.path.join("."))) return;
|
||||
@@ -357,11 +412,11 @@ const renderNormalSettingsItem = (entry, formEl) => {
|
||||
: cls.add("aura-settings-entry-hidden");
|
||||
|
||||
if (entry.auraDisable) {
|
||||
updateDisableStatus();
|
||||
updateDisableStatus(entry);
|
||||
}
|
||||
};
|
||||
const channel = entry.PLSRequired
|
||||
? "onPLSConfigUpdate"
|
||||
const channel = entry.aikariRequired
|
||||
? "onAikariConfigUpdate"
|
||||
: "onHugoAuraConfigUpdate";
|
||||
entryContainerEl.addEventListener(channel, evtListener);
|
||||
// createOnLeaveEvtListener(channel, evtListener);
|
||||
@@ -403,7 +458,9 @@ const renderPreviewItem = (entry, formEl) => {
|
||||
};
|
||||
|
||||
document.addEventListener(
|
||||
eventChannel === "pls" ? "onPLSConfigUpdate" : "onHugoAuraConfigUpdate",
|
||||
eventChannel === "aikari"
|
||||
? "onAikariConfigUpdate"
|
||||
: "onHugoAuraConfigUpdate",
|
||||
eventListener
|
||||
);
|
||||
createOnLeaveEvtListener(eventListener); // Clean up
|
||||
|
||||
@@ -41,13 +41,13 @@ const def = {
|
||||
selectorMode: "appendChild",
|
||||
pageCSS: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.css",
|
||||
childs: {
|
||||
PlsStatus: {
|
||||
AikariStatus: {
|
||||
active: false,
|
||||
pageURI: "ui/pages/configSubPages/behaviourCtrl/plsStatus.html",
|
||||
pageScript: "ui/pages/configSubPages/behaviourCtrl/plsStatus.js",
|
||||
pageURI: "ui/pages/configSubPages/behaviourCtrl/aikariStatus.html",
|
||||
pageScript: "ui/pages/configSubPages/behaviourCtrl/aikariStatus.js",
|
||||
pageSelector: "#status-subpage",
|
||||
selectorMode: "appendChild",
|
||||
pageCSS: "ui/pages/configSubPages/behaviourCtrl/plsStatus.css",
|
||||
pageCSS: "ui/pages/configSubPages/behaviourCtrl/aikariStatus.css",
|
||||
},
|
||||
DeviceSecurity: {
|
||||
childs: {
|
||||
@@ -86,7 +86,7 @@ const def = {
|
||||
],
|
||||
globalJS: [
|
||||
"ui/js/global.js",
|
||||
"ui/js/plsListener.js",
|
||||
"ui/js/aikariListener.js",
|
||||
"ui/bootstrap/bootstrap.bundle.min.js",
|
||||
],
|
||||
onLoaded: `
|
||||
|
||||
388
src/aura/ui/js/aikariConnectionManager.js
Normal file
388
src/aura/ui/js/aikariConnectionManager.js
Normal file
@@ -0,0 +1,388 @@
|
||||
// @ts-check
|
||||
(() => {
|
||||
if (!global.__HUGO_AURA__)
|
||||
global.__HUGO_AURA__ = {
|
||||
configInit: true,
|
||||
auraDir: "",
|
||||
version: "",
|
||||
};
|
||||
|
||||
if (!global.__HUGO_AURA__.aikariStats)
|
||||
global.__HUGO_AURA__.aikariStats = {
|
||||
installed: false,
|
||||
detached: false,
|
||||
connected: false,
|
||||
launched: false,
|
||||
status: "dead",
|
||||
version: "unknown",
|
||||
authToken: "",
|
||||
};
|
||||
|
||||
const IPC_METHOD_BASE = "$aura.aikari";
|
||||
const REQUIRE_BASE = "../../..";
|
||||
const __SCOPE = "auraWsKeepAlive";
|
||||
|
||||
const AIKARI_RPC_CONFIG_REG_PATH = "Aikari\\RPC";
|
||||
|
||||
const { pushMsgHandler } = require(`${REQUIRE_BASE}/aikari/pushHandler`);
|
||||
const {
|
||||
onAikariConnectedMsgSeq,
|
||||
} = require(`${REQUIRE_BASE}/aikari/onConnectedSeq`);
|
||||
const RegistryManager = require(`${REQUIRE_BASE}/../init/shared/registryManager`);
|
||||
|
||||
const registryManager = new RegistryManager();
|
||||
|
||||
/** @type {number} */
|
||||
let failedCounter = 0;
|
||||
/** @type {boolean} */
|
||||
let isErrorOccurred = false;
|
||||
|
||||
/** @type {number} */
|
||||
let aikariPort = 22077;
|
||||
/** @type {"wss" | "ws"} */
|
||||
let aikariProtocol = "wss";
|
||||
|
||||
/** @type {boolean} */
|
||||
let isRetrying = false;
|
||||
|
||||
/** @type {any} */
|
||||
let curSendListener = null;
|
||||
let curSendGetListener = null;
|
||||
|
||||
const sendRetryStatusToMain = (
|
||||
/** @type {Boolean} */ status,
|
||||
/** @type {string?} */ message = null
|
||||
) => {
|
||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.post.updateRetryStatus`, {
|
||||
success: status,
|
||||
message: message,
|
||||
});
|
||||
};
|
||||
|
||||
const clearReqSendIpcListener = () => {
|
||||
if (curSendListener) {
|
||||
global.ipcRenderer.off(
|
||||
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
||||
curSendListener
|
||||
);
|
||||
curSendListener = null;
|
||||
}
|
||||
};
|
||||
|
||||
const clearSendGetIpcListener = () => {
|
||||
if (curSendGetListener) {
|
||||
global.ipcRenderer.off(
|
||||
`${IPC_METHOD_BASE}.ws.post.onSendGetMsg`,
|
||||
curSendListener
|
||||
);
|
||||
curSendGetListener = null;
|
||||
}
|
||||
};
|
||||
|
||||
const startConnAikariProc = async (updatedAikariStats) => {
|
||||
const authTokenRet = await registryManager.readRegKey(
|
||||
AIKARI_RPC_CONFIG_REG_PATH,
|
||||
"authToken",
|
||||
true
|
||||
);
|
||||
if (authTokenRet.success) {
|
||||
updatedAikariStats.authToken = authTokenRet.data;
|
||||
// @ts-expect-error
|
||||
global.__HUGO_AURA__.aikariStats.authToken = authTokenRet.data;
|
||||
} else {
|
||||
sendRetryStatusToMain(false, "E_AUTH_TOKEN_GET_FAILED");
|
||||
return;
|
||||
}
|
||||
const portRet = await registryManager.readRegKey(
|
||||
AIKARI_RPC_CONFIG_REG_PATH,
|
||||
"wsPort",
|
||||
true
|
||||
);
|
||||
if (portRet.success) {
|
||||
try {
|
||||
aikariPort = Number(portRet.data);
|
||||
} catch {
|
||||
console.warn(
|
||||
`[HugoAura / UI / Aikari Conn Manager] Invalid Aikari port: ${portRet.data}`
|
||||
);
|
||||
}
|
||||
}
|
||||
// TODO: wsHost
|
||||
createAikariConnection(
|
||||
updatedAikariStats.authToken,
|
||||
connectionResultCallback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} authToken
|
||||
* @param {any} callback
|
||||
* @returns
|
||||
*/
|
||||
const createAikariConnection = (authToken, callback) => {
|
||||
if (failedCounter >= 3) {
|
||||
console.error(
|
||||
`[HugoAura / UI / Aikari Conn Manager / ERROR] Failed connecting to Aikari WebSocket server, please check the status of Aikari process.`
|
||||
);
|
||||
sendRetryStatusToMain(false, "E_WS_CONN_FAILED_AFT_MULTIPLE_TRIES");
|
||||
return;
|
||||
}
|
||||
|
||||
/** @type {WebSocket} */
|
||||
const aikariWs = new WebSocket(
|
||||
`${aikariProtocol}://aikari.hugoaura.local:${aikariPort}/?auth=${authToken}`
|
||||
);
|
||||
|
||||
aikariWs.onopen = () => {
|
||||
failedCounter = 0;
|
||||
isErrorOccurred = false;
|
||||
callback(true, aikariWs);
|
||||
};
|
||||
|
||||
aikariWs.onerror = () => {
|
||||
isErrorOccurred = true;
|
||||
failedCounter += 1;
|
||||
callback(false, aikariWs);
|
||||
};
|
||||
|
||||
aikariWs.onclose = () => {
|
||||
clearReqSendIpcListener();
|
||||
if (global.__HUGO_AURA__.aikariStats) {
|
||||
if (global.__HUGO_AURA__.aikariStats.status === "notReady") {
|
||||
if (isRetrying) {
|
||||
sendRetryStatusToMain(false, "E_IS_LOADING");
|
||||
return;
|
||||
}
|
||||
console.warn(
|
||||
"[HugoAura / UI / Aikari Conn Manager / WARN] Aikari not ready, try again after 10s..."
|
||||
);
|
||||
isRetrying = true;
|
||||
setTimeout(async () => {
|
||||
isRetrying = false;
|
||||
startConnAikariProc(global.__HUGO_AURA__.aikariStats);
|
||||
}, 10000);
|
||||
sendRetryStatusToMain(false, "E_START_WAIT_FOR_LOADING");
|
||||
return;
|
||||
}
|
||||
|
||||
if (global.__HUGO_AURA__.aikariStats.launched === false) {
|
||||
console.warn(
|
||||
"[HugoAura / UI / Aikari Conn Manager / WARN] Aikari stopped, closing WebSocket connection."
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.error(
|
||||
"[HugoAura / UI / Aikari Conn Manager / ERROR] WebSocket connection closed."
|
||||
);
|
||||
if (isErrorOccurred) return;
|
||||
failedCounter += 1;
|
||||
callback(false, aikariWs);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {WebSocket} wsObj
|
||||
*/
|
||||
const registerSendReqListener = (wsObj) => {
|
||||
clearReqSendIpcListener();
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcRendererEvent} _evt
|
||||
* @param {any} arg
|
||||
*/
|
||||
curSendListener = (_evt, arg) => {
|
||||
wsObj.send(JSON.stringify(arg));
|
||||
};
|
||||
global.ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
||||
curSendListener
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {boolean} result
|
||||
* @param {WebSocket} wsObj
|
||||
* @returns
|
||||
*/
|
||||
const connectionResultCallback = async (result, wsObj) => {
|
||||
if (!global.__HUGO_AURA__.aikariStats) return; // 😅 typescript
|
||||
|
||||
global.__HUGO_AURA__.aikariStats.launched = result;
|
||||
global.__HUGO_AURA__.aikariStats.connected = result;
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||
global.__HUGO_AURA__.aikariStats
|
||||
);
|
||||
if (!result) {
|
||||
console.error(
|
||||
`[HugoAura / UI / Aikari Conn Manager / ERROR] Failed connecting to Aikari WebSocket server, retrying ...`
|
||||
);
|
||||
createAikariConnection(
|
||||
global.__HUGO_AURA__.aikariStats.authToken,
|
||||
connectionResultCallback
|
||||
);
|
||||
return;
|
||||
}
|
||||
wsObj.onmessage = aikariPushHandler;
|
||||
|
||||
registerSendReqListener(wsObj);
|
||||
|
||||
global.__HUGO_AURA__.aikariWs = wsObj;
|
||||
|
||||
global.__HUGO_AURA__.aikariStats = await onAikariConnectedMsgSeq({
|
||||
curAikariStates: global.__HUGO_AURA__.aikariStats,
|
||||
wsObj,
|
||||
});
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||
global.__HUGO_AURA__.aikariStats
|
||||
);
|
||||
|
||||
sendRetryStatusToMain(true, "SUCCESS");
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {MessageEvent} event
|
||||
*/
|
||||
const aikariPushHandler = (event) => {
|
||||
try {
|
||||
/** @type {Record<any, any>} */
|
||||
const parsedEvent = JSON.parse(event.data);
|
||||
console.debug(
|
||||
"[HugoAura / UI / Aikari Conn Manager / DEBUG] Received new server message: "
|
||||
);
|
||||
if (!parsedEvent.eventId || parsedEvent.eventId === "N/A") {
|
||||
// Push
|
||||
pushMsgHandler(parsedEvent);
|
||||
} else {
|
||||
// Not push
|
||||
global.ipcRenderer.send(
|
||||
`${IPC_METHOD_BASE}.ws.broadcastMessageRecv`,
|
||||
parsedEvent
|
||||
);
|
||||
|
||||
const msgRecvEvent = new CustomEvent("onAikariMessageRecv", {
|
||||
detail: parsedEvent,
|
||||
});
|
||||
document.dispatchEvent(msgRecvEvent);
|
||||
}
|
||||
} catch {
|
||||
console.error(
|
||||
"[HugoAura / UI / Aikari Conn Manager / ERROR] Failed to resolve server message: ",
|
||||
event.data
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const initAikariWebSocketConnection = async () => {
|
||||
if (!global.__HUGO_AURA__.aikariStats) return;
|
||||
|
||||
if (isRetrying) {
|
||||
sendRetryStatusToMain(false, "E_RETRY_PENDING");
|
||||
return;
|
||||
}
|
||||
|
||||
failedCounter = 0;
|
||||
isErrorOccurred = false;
|
||||
|
||||
const curAikariStats = await global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.getAikariStatus`
|
||||
);
|
||||
let updatedAikariStats = {};
|
||||
if (
|
||||
(curAikariStats === null || !curAikariStats.success) &&
|
||||
curAikariStats.status !== "downloading" &&
|
||||
curAikariStats.status !== "installing"
|
||||
) {
|
||||
updatedAikariStats = {
|
||||
installed: false,
|
||||
launched: false,
|
||||
detached: false,
|
||||
connected: false,
|
||||
version: "unknown",
|
||||
status: "dead",
|
||||
authToken: "",
|
||||
};
|
||||
} else {
|
||||
updatedAikariStats = curAikariStats.data;
|
||||
}
|
||||
|
||||
const isAikariBinExists = (
|
||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getIfAikariBinExists`)
|
||||
).data.isExists;
|
||||
updatedAikariStats.installed = isAikariBinExists;
|
||||
// @ts-expect-error
|
||||
global.__HUGO_AURA__.aikariStats = updatedAikariStats;
|
||||
console.debug(
|
||||
"[HugoAura / UI / Aikari Conn Manager / DEBUG] Updated early aikariStats:",
|
||||
global.__HUGO_AURA__.aikariStats
|
||||
);
|
||||
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||
updatedAikariStats
|
||||
);
|
||||
|
||||
/*
|
||||
if (updatedPlsStats.detached && updatedPlsStats.installed) {
|
||||
*/
|
||||
if (updatedAikariStats.installed || updatedAikariStats.detached) {
|
||||
await startConnAikariProc(updatedAikariStats);
|
||||
} else {
|
||||
sendRetryStatusToMain(false, "E_NOT_INSTALLED");
|
||||
}
|
||||
|
||||
/*
|
||||
global.ipcRenderer.on(`${IPC_METHOD_BASE}.post.onPlsLaunched`, (_event) => {
|
||||
setTimeout(() => {
|
||||
startConnPls();
|
||||
}, 5000);
|
||||
});
|
||||
*/
|
||||
};
|
||||
|
||||
const onSetup = () => {
|
||||
if (!global.ipcRenderer) {
|
||||
// @ts-ignore
|
||||
global.ipcRenderer = require("electron").ipcRenderer;
|
||||
}
|
||||
|
||||
initAikariWebSocketConnection();
|
||||
|
||||
global.ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.retryAikariConnect`,
|
||||
(_evt, _arg) => {
|
||||
if (!global.__HUGO_AURA__.aikariStats) return;
|
||||
if (global.__HUGO_AURA__.aikariStats.connected) return;
|
||||
initAikariWebSocketConnection();
|
||||
}
|
||||
);
|
||||
|
||||
global.ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.post.onForceReloadRequested`,
|
||||
(_evt, _arg) => {
|
||||
window.location.reload();
|
||||
}
|
||||
);
|
||||
|
||||
global.ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.post.aikariStopped`,
|
||||
(_evt, _arg) => {
|
||||
if (!global.__HUGO_AURA__.aikariStats) return;
|
||||
global.__HUGO_AURA__.aikariStats.launched = false;
|
||||
global.__HUGO_AURA__.aikariStats.connected = false;
|
||||
global.__HUGO_AURA__.aikariStats.version = "unknown";
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
onSetup();
|
||||
}, 1500);
|
||||
})();
|
||||
28
src/aura/ui/js/plsListener.js → src/aura/ui/js/aikariListener.js
Executable file → Normal file
28
src/aura/ui/js/plsListener.js → src/aura/ui/js/aikariListener.js
Executable file → Normal file
@@ -1,21 +1,21 @@
|
||||
(() => {
|
||||
const IPC_METHOD_BASE = "$aura.pls";
|
||||
const IPC_METHOD_BASE = "$aura.aikari";
|
||||
const REQUIRE_BASE = "../../aura/ui";
|
||||
const __SCOPE = "assistant";
|
||||
const {
|
||||
updatePlsStatusFromLocal,
|
||||
} = require(`${REQUIRE_BASE}/composables/plsConfigManager`);
|
||||
updateAikariStatusFromLocal,
|
||||
} = require(`${REQUIRE_BASE}/composables/aikariConfigManager`);
|
||||
|
||||
const setupListeners = () => {
|
||||
if (!global.ipcRenderer)
|
||||
global.ipcRenderer = require("electron").ipcRenderer;
|
||||
|
||||
ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.post.onPlsStatsUpdate`,
|
||||
`${IPC_METHOD_BASE}.post.onAikariStatsUpdate`,
|
||||
(_event, arg) => {
|
||||
global.__HUGO_AURA__.plsStats = arg;
|
||||
global.__HUGO_AURA__.aikariStats = arg;
|
||||
|
||||
const event = new CustomEvent("onPLSStatsUpdate", {
|
||||
const event = new CustomEvent("onAikariStatsUpdate", {
|
||||
detail: {
|
||||
connected: arg.connected,
|
||||
},
|
||||
@@ -35,11 +35,11 @@
|
||||
);
|
||||
|
||||
ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.post.onPlsSettingsUpdate`,
|
||||
`${IPC_METHOD_BASE}.post.onAikariSettingsUpdate`,
|
||||
(_event, arg) => {
|
||||
global.__HUGO_AURA__.plsSettings = arg;
|
||||
global.__HUGO_AURA__.aikariSettings = arg;
|
||||
|
||||
const event = new CustomEvent("onPLSConfigUpdate", {
|
||||
const event = new CustomEvent("onAikariConfigUpdate", {
|
||||
detail: {
|
||||
path: ["root", "settings"],
|
||||
value: arg,
|
||||
@@ -60,11 +60,11 @@
|
||||
);
|
||||
|
||||
ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.post.onPlsRulesUpdate`,
|
||||
`${IPC_METHOD_BASE}.post.onAikariRulesUpdate`,
|
||||
(_event, arg) => {
|
||||
global.__HUGO_AURA__.plsRules = arg;
|
||||
global.__HUGO_AURA__.aikariRules = arg;
|
||||
|
||||
const event = new CustomEvent("onPLSConfigUpdate", {
|
||||
const event = new CustomEvent("onAikariConfigUpdate", {
|
||||
detail: {
|
||||
path: ["root", "ruleSettings"],
|
||||
value: arg,
|
||||
@@ -87,7 +87,7 @@
|
||||
ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.post.updateRetryStatus`,
|
||||
(_event, arg) => {
|
||||
const event = new CustomEvent("onPLSStatsUpdate", {
|
||||
const event = new CustomEvent("onAikariStatsUpdate", {
|
||||
detail: {
|
||||
connected: arg.success,
|
||||
},
|
||||
@@ -107,6 +107,6 @@
|
||||
);
|
||||
};
|
||||
|
||||
updatePlsStatusFromLocal();
|
||||
updateAikariStatusFromLocal();
|
||||
setupListeners();
|
||||
})();
|
||||
@@ -6,9 +6,11 @@
|
||||
let tooltipTriggerCache = null;
|
||||
const refreshBsTooltip = (selector = '[data-bs-toggle="tooltip"]') => {
|
||||
if (tooltipTriggerCache) {
|
||||
[...tooltipTriggerCache].map((el) =>
|
||||
bootstrap.Tooltip.getInstance(el).disable()
|
||||
);
|
||||
[...tooltipTriggerCache].map((el) => {
|
||||
if (bootstrap.Tooltip.getInstance(el)) {
|
||||
bootstrap.Tooltip.getInstance(el).disable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const tooltipTriggerList = document.querySelectorAll(selector);
|
||||
|
||||
@@ -1,357 +0,0 @@
|
||||
// @ts-check
|
||||
(() => {
|
||||
if (!global.__HUGO_AURA__)
|
||||
global.__HUGO_AURA__ = {
|
||||
configInit: true,
|
||||
auraDir: "",
|
||||
version: "",
|
||||
};
|
||||
|
||||
if (!global.__HUGO_AURA__.plsStats)
|
||||
global.__HUGO_AURA__.plsStats = {
|
||||
installed: false,
|
||||
detached: false,
|
||||
connected: false,
|
||||
launched: false,
|
||||
status: "dead",
|
||||
version: "unknown",
|
||||
authToken: "",
|
||||
};
|
||||
|
||||
const IPC_METHOD_BASE = "$aura.pls";
|
||||
const REQUIRE_BASE = "../../..";
|
||||
const __SCOPE = "auraWsKeepAlive";
|
||||
|
||||
const PLS_REG_PATH = "ProxyLayerServices";
|
||||
|
||||
const { pushMsgHandler } = require(`${REQUIRE_BASE}/pls/pushHandler`);
|
||||
const RegistryManager = require(`${REQUIRE_BASE}/../init/shared/registryManager`);
|
||||
|
||||
const registryManager = new RegistryManager();
|
||||
|
||||
/** @type {number} */
|
||||
let failedCounter = 0;
|
||||
/** @type {boolean} */
|
||||
let isErrorOccurred = false;
|
||||
|
||||
/** @type {number} */
|
||||
let plsPort = 22077;
|
||||
/** @type {"wss" | "ws"} */
|
||||
let plsProtocol = "wss";
|
||||
|
||||
/** @type {boolean} */
|
||||
let isRetrying = false;
|
||||
|
||||
/** @type {any} */
|
||||
let curSendListener = null;
|
||||
|
||||
const sendRetryStatusToMain = (/** @type {Boolean} */ status) => {
|
||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.post.updateRetryStatus`, {
|
||||
success: status,
|
||||
});
|
||||
};
|
||||
|
||||
const calcFullAuthToken = (/** @type {string} */ authToken) => {
|
||||
const conjToken = authToken + "AuraXAuth 0xFFFFFF NeverEnds";
|
||||
const crypto = require("crypto");
|
||||
return crypto.createHash("sha512").update(conjToken).digest("hex");
|
||||
};
|
||||
|
||||
const clearIpcListener = () => {
|
||||
if (curSendListener) {
|
||||
global.ipcRenderer.off(
|
||||
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
||||
curSendListener
|
||||
);
|
||||
curSendListener = null;
|
||||
}
|
||||
};
|
||||
|
||||
const startConnPlsProc = async (updatedPlsStats) => {
|
||||
const authTokenRet = await registryManager.readRegKey(
|
||||
PLS_REG_PATH,
|
||||
"AuthToken",
|
||||
true
|
||||
);
|
||||
if (authTokenRet.success) {
|
||||
updatedPlsStats.authToken = authTokenRet.data;
|
||||
// @ts-expect-error
|
||||
global.__HUGO_AURA__.plsStats.authToken = authTokenRet.data;
|
||||
} else {
|
||||
sendRetryStatusToMain(false);
|
||||
return;
|
||||
}
|
||||
const portRet = await registryManager.readRegKey(
|
||||
PLS_REG_PATH,
|
||||
"WsPort",
|
||||
true
|
||||
);
|
||||
if (portRet.success) {
|
||||
try {
|
||||
plsPort = Number(portRet.data);
|
||||
} catch {
|
||||
console.warn(
|
||||
`[HugoAura / UI / PLS Manager] Invalid PLS port: ${portRet.data}`
|
||||
);
|
||||
}
|
||||
}
|
||||
const protoRet = await registryManager.readRegKey(
|
||||
PLS_REG_PATH,
|
||||
"Protocol",
|
||||
true
|
||||
);
|
||||
if (protoRet.success) {
|
||||
plsProtocol = protoRet.data;
|
||||
}
|
||||
createPlsConnection(updatedPlsStats.authToken, connectionResultCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} authToken
|
||||
* @param {any} callback
|
||||
* @returns
|
||||
*/
|
||||
const createPlsConnection = (authToken, callback) => {
|
||||
if (failedCounter >= 3) {
|
||||
console.error(
|
||||
`[HugoAura / UI / PLS Manager / ERROR] Failed connecting to PLS WebSocket server, please check the status of PLS process.`
|
||||
);
|
||||
sendRetryStatusToMain(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fullAuthToken = calcFullAuthToken(authToken);
|
||||
|
||||
/** @type {WebSocket} */
|
||||
const plsWs = new WebSocket(
|
||||
`${plsProtocol}://pls.hugoaura.local:${plsPort}/?auth=${fullAuthToken}`
|
||||
);
|
||||
|
||||
plsWs.onopen = () => {
|
||||
callback(true, plsWs);
|
||||
};
|
||||
|
||||
plsWs.onerror = () => {
|
||||
isErrorOccurred = true;
|
||||
failedCounter += 1;
|
||||
callback(false, plsWs);
|
||||
};
|
||||
|
||||
plsWs.onclose = () => {
|
||||
clearIpcListener();
|
||||
if (global.__HUGO_AURA__.plsStats) {
|
||||
if (global.__HUGO_AURA__.plsStats.status === "notReady") {
|
||||
if (isRetrying) {
|
||||
sendRetryStatusToMain(false);
|
||||
return;
|
||||
}
|
||||
console.warn(
|
||||
"[HugoAura / UI / PLS Manager / WARN] PLS not ready, try again after 10s..."
|
||||
);
|
||||
isRetrying = true;
|
||||
setTimeout(async () => {
|
||||
isRetrying = false;
|
||||
startConnPlsProc(global.__HUGO_AURA__.plsStats);
|
||||
}, 10000);
|
||||
sendRetryStatusToMain(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (global.__HUGO_AURA__.plsStats.launched === false) {
|
||||
console.warn(
|
||||
"[HugoAura / UI / PLS Manager / WARN] PLS stopped, closing WebSocket connection."
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.error(
|
||||
"[HugoAura / UI / PLS Manager / ERROR] WebSocket connection closed."
|
||||
);
|
||||
if (isErrorOccurred) return;
|
||||
failedCounter += 1;
|
||||
callback(false, plsWs);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {WebSocket} wsObj
|
||||
*/
|
||||
const registerSendReqListener = (wsObj) => {
|
||||
clearIpcListener();
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcRendererEvent} _evt
|
||||
* @param {any} arg
|
||||
*/
|
||||
curSendListener = (_evt, arg) => {
|
||||
wsObj.send(JSON.stringify(arg));
|
||||
};
|
||||
global.ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
||||
curSendListener
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {boolean} result
|
||||
* @param {WebSocket} wsObj
|
||||
* @returns
|
||||
*/
|
||||
const connectionResultCallback = (result, wsObj) => {
|
||||
if (!global.__HUGO_AURA__.plsStats) return; // 😅 typescript
|
||||
|
||||
global.__HUGO_AURA__.plsStats.launched = result;
|
||||
global.__HUGO_AURA__.plsStats.connected = result;
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
||||
global.__HUGO_AURA__.plsStats
|
||||
);
|
||||
if (!result) {
|
||||
console.error(
|
||||
`[HugoAura / UI / PLS Manager / ERROR] Failed connecting to PLS WebSocket server, retrying ...`
|
||||
);
|
||||
createPlsConnection(
|
||||
global.__HUGO_AURA__.plsStats.authToken,
|
||||
connectionResultCallback
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
sendRetryStatusToMain(true);
|
||||
|
||||
global.__HUGO_AURA__.plsWs = wsObj;
|
||||
registerSendReqListener(wsObj);
|
||||
wsObj.onmessage = plsPushHandler;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {MessageEvent} event
|
||||
*/
|
||||
const plsPushHandler = (event) => {
|
||||
try {
|
||||
/** @type {Record<any, any>} */
|
||||
const parsedEvent = JSON.parse(event.data);
|
||||
console.debug(
|
||||
"[HugoAura / UI / PLS Manager / DEBUG] Received new server message: "
|
||||
);
|
||||
if (!parsedEvent.eventId) {
|
||||
// Push
|
||||
pushMsgHandler(parsedEvent);
|
||||
} else {
|
||||
// Not push
|
||||
global.ipcRenderer.send(
|
||||
`${IPC_METHOD_BASE}.ws.broadcastMessageRecv`,
|
||||
parsedEvent
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
console.error(
|
||||
"[HugoAura / UI / PLS Manager / ERROR] Failed to resolve server message: ",
|
||||
event.data
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const initPlsConnection = async () => {
|
||||
if (!global.__HUGO_AURA__.plsStats) return;
|
||||
|
||||
if (isRetrying) {
|
||||
sendRetryStatusToMain(false);
|
||||
return;
|
||||
}
|
||||
|
||||
failedCounter = 0;
|
||||
isErrorOccurred = false;
|
||||
|
||||
const curPlsStats = await global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.getPlsStats`
|
||||
);
|
||||
let updatedPlsStats = {};
|
||||
if (
|
||||
(curPlsStats === null || !curPlsStats.success) &&
|
||||
curPlsStats.status !== "downloading"
|
||||
) {
|
||||
updatedPlsStats = {
|
||||
installed: false,
|
||||
launched: false,
|
||||
detached: false,
|
||||
connected: false,
|
||||
version: "unknown",
|
||||
status: "dead",
|
||||
authToken: "66ccff0d000721114514191981023333",
|
||||
};
|
||||
} else {
|
||||
updatedPlsStats = curPlsStats.data;
|
||||
}
|
||||
|
||||
const isPlsFolderExists = (
|
||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsBinExists`)
|
||||
).data.isExists;
|
||||
updatedPlsStats.installed = isPlsFolderExists;
|
||||
// @ts-expect-error
|
||||
global.__HUGO_AURA__.plsStats = updatedPlsStats;
|
||||
console.debug(
|
||||
"[HugoAura / UI / PLS Manager / DEBUG] Updated early plsStats:",
|
||||
global.__HUGO_AURA__.plsStats
|
||||
);
|
||||
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
||||
updatedPlsStats
|
||||
);
|
||||
|
||||
/*
|
||||
if (updatedPlsStats.detached && updatedPlsStats.installed) {
|
||||
*/
|
||||
if (updatedPlsStats.installed) {
|
||||
await startConnPlsProc(updatedPlsStats);
|
||||
} else {
|
||||
sendRetryStatusToMain(false);
|
||||
}
|
||||
|
||||
/*
|
||||
global.ipcRenderer.on(`${IPC_METHOD_BASE}.post.onPlsLaunched`, (_event) => {
|
||||
setTimeout(() => {
|
||||
startConnPls();
|
||||
}, 5000);
|
||||
});
|
||||
*/
|
||||
};
|
||||
|
||||
const onSetup = () => {
|
||||
if (!global.ipcRenderer) {
|
||||
// @ts-ignore
|
||||
global.ipcRenderer = require("electron").ipcRenderer;
|
||||
}
|
||||
|
||||
initPlsConnection();
|
||||
|
||||
global.ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.retryPlsConnect`,
|
||||
(_evt, _arg) => {
|
||||
if (!global.__HUGO_AURA__.plsStats) return;
|
||||
if (global.__HUGO_AURA__.plsStats.connected) return;
|
||||
initPlsConnection();
|
||||
}
|
||||
);
|
||||
|
||||
global.ipcRenderer.on(
|
||||
`${IPC_METHOD_BASE}.post.plsStopped`,
|
||||
(_evt, _arg) => {
|
||||
if (!global.__HUGO_AURA__.plsStats) return;
|
||||
global.__HUGO_AURA__.plsStats.launched = false;
|
||||
global.__HUGO_AURA__.plsStats.connected = false;
|
||||
global.__HUGO_AURA__.plsStats.version = "unknown";
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
onSetup();
|
||||
}, 1500);
|
||||
})();
|
||||
@@ -293,14 +293,14 @@
|
||||
|
||||
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||
<div
|
||||
id="relaunchPlsNotifyToast"
|
||||
id="relaunchAikariNotifyToast"
|
||||
class="toast acp-toast-emerg"
|
||||
aria-atomic="true"
|
||||
data-bs-autohide="false"
|
||||
>
|
||||
<div class="toast-header">
|
||||
<i class="layui-icon layui-icon-tips"></i>
|
||||
<strong class="me-auto">重启 PLS 进程以应用设置</strong>
|
||||
<strong class="me-auto">重启 Aikari 进程以应用设置</strong>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
@@ -308,13 +308,13 @@
|
||||
></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
<p>请重启 PLS 进程以应用修改的设置</p>
|
||||
<p>请重启 Aikari 进程以应用修改的设置</p>
|
||||
<p>已修改的配置将自动保存</p>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
id="plsRelaunchBtn"
|
||||
onclick="ipcRenderer.invoke('$aura.pls.relaunchPls')"
|
||||
id="aikariRelaunchBtn"
|
||||
onclick="ipcRenderer.invoke('$aura.aikari.relaunchPls')"
|
||||
>
|
||||
重启进程
|
||||
</button>
|
||||
|
||||
@@ -106,7 +106,7 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
||||
if (!side) {
|
||||
setTimeout(() => {
|
||||
global.__HUGO_AURA_LOADER__[
|
||||
"Aura.UI.Assistant.Config.BehaviourCtrl.PlsStatus"
|
||||
"Aura.UI.Assistant.Config.BehaviourCtrl.AikariStatus"
|
||||
].active = false;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
52
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.css → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.css
Executable file → Normal file
52
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.css → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.css
Executable file → Normal file
@@ -1,15 +1,15 @@
|
||||
.acs-behaviour-control-pls-status-page {
|
||||
.acs-behaviour-control-aikari-status-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.acs-behaviour-control-pls-status-page p {
|
||||
.acs-behaviour-control-aikari-status-page p {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-pls-description {
|
||||
.acs-bc-aikari-status-page-aikari-description {
|
||||
margin-top: 0.5rem;
|
||||
max-width: 80%;
|
||||
opacity: 0.35;
|
||||
@@ -17,11 +17,11 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-main-logo {
|
||||
max-width: 11%;
|
||||
.acs-bc-aikari-status-page-main-logo {
|
||||
max-width: 15%;
|
||||
opacity: 0.45;
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.acs-bc-psp-operations-container {
|
||||
@@ -133,7 +133,7 @@
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-el {
|
||||
.acs-bc-aikari-status-page-status-el {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 40%;
|
||||
@@ -141,17 +141,17 @@
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-el div {
|
||||
.acs-bc-aikari-status-page-status-el div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area {
|
||||
.acs-bc-aikari-status-page-status-area {
|
||||
flex-grow: 1;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area-circle {
|
||||
.acs-bc-aikari-status-page-status-area-circle {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
border-radius: 100%;
|
||||
@@ -159,48 +159,48 @@
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.pending
|
||||
.acs-bc-pls-status-page-status-area-circle {
|
||||
.acs-bc-aikari-status-page-status-area.pending
|
||||
.acs-bc-aikari-status-page-status-area-circle {
|
||||
background-color: rgba(0, 0, 0, 0.375);
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.pending p {
|
||||
.acs-bc-aikari-status-page-status-area.pending p {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.success
|
||||
.acs-bc-pls-status-page-status-area-circle {
|
||||
.acs-bc-aikari-status-page-status-area.success
|
||||
.acs-bc-aikari-status-page-status-area-circle {
|
||||
background-color: rgb(0, 175, 38);
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.success p {
|
||||
.acs-bc-aikari-status-page-status-area.success p {
|
||||
color: rgb(0, 150, 33);
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.failed
|
||||
.acs-bc-pls-status-page-status-area-circle {
|
||||
.acs-bc-aikari-status-page-status-area.failed
|
||||
.acs-bc-aikari-status-page-status-area-circle {
|
||||
background-color: rgb(175, 0, 0);
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.failed p {
|
||||
.acs-bc-aikari-status-page-status-area.failed p {
|
||||
color: rgb(175, 0, 0);
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.warning
|
||||
.acs-bc-pls-status-page-status-area-circle {
|
||||
.acs-bc-aikari-status-page-status-area.warning
|
||||
.acs-bc-aikari-status-page-status-area-circle {
|
||||
background-color: rgb(212, 127, 0);
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.warning p {
|
||||
.acs-bc-aikari-status-page-status-area.warning p {
|
||||
color: rgb(212, 127, 0);
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.info
|
||||
.acs-bc-pls-status-page-status-area-circle {
|
||||
.acs-bc-aikari-status-page-status-area.info
|
||||
.acs-bc-aikari-status-page-status-area-circle {
|
||||
background-color: #3d78ff;
|
||||
}
|
||||
|
||||
.acs-bc-pls-status-page-status-area.info p {
|
||||
.acs-bc-aikari-status-page-status-area.info p {
|
||||
color: #3d78ff;
|
||||
}
|
||||
|
||||
49
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.html → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.html
Executable file → Normal file
49
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.html → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.html
Executable file → Normal file
@@ -1,12 +1,11 @@
|
||||
<div class="acs-behaviour-control-pls-status-page">
|
||||
<p class="acs-bc-pls-status-page-pls-description">
|
||||
HugoAura ProxyLayerServices (Aura-PLS) 是基于 Python + MITMProxy
|
||||
实现的代理服务, 用于解密并修改希沃基础服务 (SeewoCore) 的 MQTT 数据包,
|
||||
实现行为监控、伪造上报等功能
|
||||
<div class="acs-behaviour-control-aikari-status-page">
|
||||
<p class="acs-bc-aikari-status-page-aikari-description">
|
||||
HugoAura Aikari 是基于 C++ 实现的 HugoAura 特权访问服务, 集成篡改 MQTT
|
||||
数据包、冰点穿透增强等功能, 实现行为监控、伪造上报
|
||||
</p>
|
||||
<img
|
||||
src="../../aura/ui/static/aura_pls.png"
|
||||
class="acs-bc-pls-status-page-main-logo"
|
||||
src="../../aura/ui/static/aikari_color_reversed.png"
|
||||
class="acs-bc-aikari-status-page-main-logo"
|
||||
/>
|
||||
|
||||
<div class="acs-bc-psp-operations-container">
|
||||
@@ -28,7 +27,7 @@
|
||||
<div
|
||||
class="acs-bc-psp-operation-btn"
|
||||
aura-disabled="true"
|
||||
id="acsBcPsp-operBtn-Download"
|
||||
id="acsBcPsp-operBtn-Install"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -45,10 +44,10 @@
|
||||
d="M17 26.17V14h-2v12.17l-2.59-2.58L11 25l5 5l5-5l-1.41-1.41z"
|
||||
/>
|
||||
</svg>
|
||||
<p>下载内核</p>
|
||||
<p>下载应用</p>
|
||||
</div>
|
||||
|
||||
<div class="acs-bc-psp-operation-btn" id="acsBcPsp-operBtn-Install">
|
||||
<div class="acs-bc-psp-operation-btn" id="acsBcPsp-operBtn-InstallSvc">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="32"
|
||||
@@ -73,7 +72,7 @@
|
||||
|
||||
<div
|
||||
class="acs-bc-psp-operation-btn acs-bc-psp-o-btn-dangerous"
|
||||
id="acsBcPsp-operBtn-Uninstall"
|
||||
id="acsBcPsp-operBtn-UninstallSvc"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -155,61 +154,61 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="acs-bc-pls-status-page-status-el">
|
||||
<div class="acs-bc-aikari-status-page-status-el">
|
||||
<p>安装状态</p>
|
||||
<div
|
||||
class="acs-bc-pls-status-page-status-area pending"
|
||||
class="acs-bc-aikari-status-page-status-area pending"
|
||||
id="acs-bc-psp-installStatus-container"
|
||||
>
|
||||
<span class="acs-bc-pls-status-page-status-area-circle"></span>
|
||||
<span class="acs-bc-aikari-status-page-status-area-circle"></span>
|
||||
<p id="acs-bc-psp-installStatus-text">未安装</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="acs-bc-pls-status-page-status-el">
|
||||
<div class="acs-bc-aikari-status-page-status-el">
|
||||
<p>启动状态</p>
|
||||
<div
|
||||
class="acs-bc-pls-status-page-status-area pending"
|
||||
class="acs-bc-aikari-status-page-status-area pending"
|
||||
id="acs-bc-psp-launchStatus-container"
|
||||
>
|
||||
<span class="acs-bc-pls-status-page-status-area-circle"></span>
|
||||
<span class="acs-bc-aikari-status-page-status-area-circle"></span>
|
||||
<p id="acs-bc-psp-launchStatus-text">未启动</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="acs-bc-pls-status-page-status-el">
|
||||
<div class="acs-bc-aikari-status-page-status-el">
|
||||
<p>连接状态</p>
|
||||
<div
|
||||
class="acs-bc-pls-status-page-status-area pending"
|
||||
class="acs-bc-aikari-status-page-status-area pending"
|
||||
id="acs-bc-psp-connStatus-container"
|
||||
>
|
||||
<span class="acs-bc-pls-status-page-status-area-circle"></span>
|
||||
<span class="acs-bc-aikari-status-page-status-area-circle"></span>
|
||||
<p id="acs-bc-psp-connStatus-text">已断开</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="acs-bc-pls-status-page-status-el" style="border-bottom: none">
|
||||
<div class="acs-bc-aikari-status-page-status-el" style="border-bottom: none">
|
||||
<p>版本</p>
|
||||
<div class="acs-bc-pls-status-page-status-area">
|
||||
<div class="acs-bc-aikari-status-page-status-area">
|
||||
<p id="acs-bc-psp-version-text">不可用</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||
<div
|
||||
id="plsStatusNotifyToast"
|
||||
id="aikariStatusNotifyToast"
|
||||
class="acs-bc-psp-toast toast"
|
||||
data-bs-autohide="false"
|
||||
>
|
||||
<div class="toast-header">
|
||||
<strong class="me-auto" id="plsStatusNotifyToastTitle"></strong>
|
||||
<strong class="me-auto" id="aikariStatusNotifyToastTitle"></strong>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="toast"
|
||||
></button>
|
||||
</div>
|
||||
<div class="toast-body" id="plsStatusNotifyToastBody"></div>
|
||||
<div class="toast-body" id="aikariStatusNotifyToastBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
663
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.js → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.js
Executable file → Normal file
663
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.js → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.js
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -36,13 +36,13 @@
|
||||
class="nav-link"
|
||||
id="security-config-tab"
|
||||
data-bs-toggle="pill"
|
||||
data-bs-target="#security-config-subpage"
|
||||
data-bs-target="#device-info-post-config-subpage"
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-controls="security-config-subpage"
|
||||
aria-controls="device-info-post-config-subpage"
|
||||
aria-selected="false"
|
||||
>
|
||||
设备安全
|
||||
信息上报
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -61,7 +61,7 @@
|
||||
></div>
|
||||
<div
|
||||
class="tab-pane fade"
|
||||
id="security-config-subpage"
|
||||
id="device-info-post-config-subpage"
|
||||
role="tabpanel"
|
||||
aria-labelledby="security-config-tab"
|
||||
></div>
|
||||
|
||||
@@ -7,45 +7,58 @@
|
||||
} = require(`${REQUIRE_BASE}/../../../../composables/settingsRenderer`);
|
||||
|
||||
const { basicSettings } = require(`${REQUIRE_BASE}/basic`);
|
||||
const { deviceSecuritySettings } = require(`${REQUIRE_BASE}/deviceSecurity`);
|
||||
const { deviceInfoPostSettings } = require(`${REQUIRE_BASE}/deviceInfoPost`);
|
||||
|
||||
const {
|
||||
updatePlsSettingsFromLocal,
|
||||
updatePlsRulesFromLocal,
|
||||
} = require(`${REQUIRE_BASE}/../../../../composables/plsConfigManager`);
|
||||
updateAikariSettingsFromLocal,
|
||||
updateAikariRulesFromLocal,
|
||||
} = require(`${REQUIRE_BASE}/../../../../composables/aikariConfigManager`);
|
||||
|
||||
const fileSystemRawCmds = require(`${REQUIRE_BASE}/../../../../composables/rawCmdExec/fs`);
|
||||
|
||||
const initStatusPage = () => {
|
||||
global.__HUGO_AURA_LOADER__[
|
||||
"Aura.UI.Assistant.Config.BehaviourCtrl.PlsStatus"
|
||||
"Aura.UI.Assistant.Config.BehaviourCtrl.AikariStatus"
|
||||
].active = true;
|
||||
};
|
||||
|
||||
const preInitUIReactives = async () => {
|
||||
if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
|
||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig = {};
|
||||
if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared)
|
||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared = {};
|
||||
|
||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared.diskCaptions =
|
||||
await fileSystemRawCmds.getDiskCaptions();
|
||||
};
|
||||
|
||||
const initBasicSettingsPage = () => {
|
||||
const basicSubPageEl = document.getElementById("basic-config-subpage");
|
||||
settingsRenderer(basicSubPageEl, basicSettings);
|
||||
};
|
||||
|
||||
const initDeviceSecuritySettingsPage = () => {
|
||||
const deviceSecuritySubPageEl = document.getElementById(
|
||||
"security-config-subpage"
|
||||
const initDeviceInfoPostSettingsPage = () => {
|
||||
const deviceInfoPostSubPageEl = document.getElementById(
|
||||
"device-info-post-config-subpage"
|
||||
);
|
||||
settingsRenderer(deviceSecuritySubPageEl, deviceSecuritySettings);
|
||||
settingsRenderer(deviceInfoPostSubPageEl, deviceInfoPostSettings);
|
||||
};
|
||||
|
||||
const renderSubPages = async () => {
|
||||
await updatePlsSettingsFromLocal();
|
||||
await updatePlsRulesFromLocal();
|
||||
await updateAikariSettingsFromLocal();
|
||||
await updateAikariRulesFromLocal();
|
||||
|
||||
initBasicSettingsPage();
|
||||
initDeviceSecuritySettingsPage();
|
||||
initDeviceInfoPostSettingsPage();
|
||||
};
|
||||
|
||||
const onMounted = () => {
|
||||
const rootEl = document.getElementById("acs-behaviour-control-el");
|
||||
preInitUIReactives();
|
||||
initStatusPage();
|
||||
setTimeout(() => {
|
||||
rootEl.classList.remove("acs-behaviour-control-hidden");
|
||||
renderSubPages(); // 如果立即渲染子页面, 此时 plsRules 还未初始化, 会导致子页面 auraIf 失效
|
||||
renderSubPages();
|
||||
}, 500);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,30 +1,8 @@
|
||||
const REQUIRE_BASE = ".";
|
||||
|
||||
const {
|
||||
updatePlsConfigToRemote,
|
||||
} = require(`${REQUIRE_BASE}/../../../../composables/plsConfigManager`);
|
||||
|
||||
const reusableChkFn = {
|
||||
checkRelativePath: () => {
|
||||
if (newVal === "" || !newVal)
|
||||
return { valid: false, hint: "请输入证书路径" };
|
||||
|
||||
if (newVal.includes(":/") || newVal.includes(":\\")) {
|
||||
return { valid: false, hint: "请输入相对路径, 而非绝对路径" };
|
||||
}
|
||||
|
||||
if (newVal.includes("\\")) {
|
||||
return {
|
||||
valid: false,
|
||||
hint: '请输入正确的路径, 使用 "/" 作为路径符',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
};
|
||||
},
|
||||
};
|
||||
updateAikariConfigToRemote,
|
||||
} = require(`${REQUIRE_BASE}/../../../../composables/aikariConfigManager`);
|
||||
|
||||
const basicSettings = [
|
||||
{
|
||||
@@ -33,137 +11,70 @@ const basicSettings = [
|
||||
child: [
|
||||
{
|
||||
index: 0,
|
||||
id: "plsListenPort",
|
||||
id: "aikarWsPreferPort",
|
||||
type: "input",
|
||||
subType: "number",
|
||||
name: "PLS WS 默认监听端口",
|
||||
description: "PLS 的 WebSocket 服务器将默认监听指定的端口",
|
||||
name: "Aikari WS 默认监听端口",
|
||||
description: "Aikari WebSocket 服务器默认监听的端口",
|
||||
reactive: true,
|
||||
reactiveVal: ["root.settings"],
|
||||
restart: false,
|
||||
reload: false,
|
||||
PLSRequired: true,
|
||||
restartPLS: false,
|
||||
aikariRequired: true,
|
||||
restartAikari: false,
|
||||
warning: true,
|
||||
warningContent: "PLS 仍会在默认端口被占用时, 自动随机端口重试",
|
||||
warningContent: "Aikari 仍会在默认端口被占用时, 自动随机端口重试",
|
||||
associateVal: null,
|
||||
auraIf: () => true,
|
||||
defaultValue: "",
|
||||
placeHolder: "输入端口号 (10000 ~ 65535)",
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.plsSettings) return "";
|
||||
return global.__HUGO_AURA__.plsSettings.wsPort;
|
||||
if (!global.__HUGO_AURA__.aikariSettings) return "";
|
||||
return global.__HUGO_AURA__.aikariSettings.wsPreferPort;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
if (newVal === "" || !newVal)
|
||||
return { valid: false, hint: "请输入端口号" };
|
||||
|
||||
const numberNewVal = Number(newVal);
|
||||
if (numberNewVal === NaN || !(10000 <= numberNewVal) || !(newVal <= 65535)) {
|
||||
if (
|
||||
numberNewVal === NaN ||
|
||||
!(10000 <= numberNewVal) ||
|
||||
!(newVal <= 65535)
|
||||
) {
|
||||
return { valid: false, hint: "请输入合法的端口号 (10000 ~ 65535)" };
|
||||
}
|
||||
|
||||
global.__HUGO_AURA__.plsSettings.wsPort = numberNewVal;
|
||||
updatePlsConfigToRemote("wsPort", numberNewVal);
|
||||
global.__HUGO_AURA__.aikariSettings.wsPreferPort = numberNewVal;
|
||||
updateAikariConfigToRemote("wsPreferPort", numberNewVal);
|
||||
return { valid: true };
|
||||
},
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
id: "plsCertPath",
|
||||
type: "input",
|
||||
subType: "text",
|
||||
name: "WSS TLS 证书相对路径",
|
||||
description: "PLS 将使用指定路径下的证书启动 WSS 服务器",
|
||||
reactive: true,
|
||||
reactiveVal: ["root.settings"],
|
||||
restart: false,
|
||||
reload: false,
|
||||
PLSRequired: true,
|
||||
restartPLS: true,
|
||||
tip: true,
|
||||
tipTitle:
|
||||
'路径相对于 "%PROGRAMDATA%\\HugoAura\\Aura-PLS\\", 使用 "/" 作为路径符',
|
||||
associateVal: null,
|
||||
auraIf: () => true,
|
||||
defaultValue: "",
|
||||
placeHolder: "输入相对路径, 例如: config/vme50/cert.crt",
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.plsSettings) return "";
|
||||
return global.__HUGO_AURA__.plsSettings.certPath;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
const validate = reusableChkFn.checkRelativePath();
|
||||
if (!validate.valid) {
|
||||
return validate;
|
||||
}
|
||||
|
||||
global.__HUGO_AURA__.plsSettings.certPath = newVal;
|
||||
updatePlsConfigToRemote("certPath", newVal);
|
||||
return { valid: true };
|
||||
},
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
id: "plsCertPath",
|
||||
type: "input",
|
||||
subType: "text",
|
||||
name: "WSS TLS 证书私钥相对路径",
|
||||
description: "PLS 将使用指定路径下的私钥启动 WSS 服务器",
|
||||
reactive: true,
|
||||
reactiveVal: ["root.settings"],
|
||||
restart: false,
|
||||
reload: false,
|
||||
PLSRequired: true,
|
||||
restartPLS: true,
|
||||
tip: true,
|
||||
tipTitle:
|
||||
'路径相对于 "%PROGRAMDATA%\\HugoAura\\Aura-PLS\\", 使用 "/" 作为路径符',
|
||||
warning: true,
|
||||
warningContent: "请使用 PEM 格式的密钥",
|
||||
associateVal: null,
|
||||
auraIf: () => true,
|
||||
defaultValue: "",
|
||||
placeHolder: "输入相对路径, 例如: config/vme50/cert.key",
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.plsSettings) return "";
|
||||
return global.__HUGO_AURA__.plsSettings.keyPath;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
const validate = reusableChkFn.checkRelativePath();
|
||||
if (!validate.valid) {
|
||||
return validate;
|
||||
}
|
||||
|
||||
global.__HUGO_AURA__.plsSettings.keyPath = newVal;
|
||||
updatePlsConfigToRemote("keyPath", newVal);
|
||||
return { valid: true };
|
||||
},
|
||||
},
|
||||
{
|
||||
index: 3,
|
||||
id: "plsRegenCertAftRelaunch",
|
||||
id: "aikariForceRegenWsTlsCert",
|
||||
type: "switch",
|
||||
name: "重新生成 TLS 证书",
|
||||
description: "PLS 将在下次启动时重新生成 TLS 证书",
|
||||
name: "重新生成 WS TLS 证书",
|
||||
description: "Aikari 将在下次启动时重新生成用于 WebSocket 的 TLS 证书",
|
||||
reactive: true,
|
||||
reactiveVal: ["root.settings"],
|
||||
restart: false,
|
||||
reload: false,
|
||||
PLSRequired: true,
|
||||
restartPLS: true,
|
||||
aikariRequired: true,
|
||||
restartAikari: true,
|
||||
associateVal: null,
|
||||
auraIf: () => true,
|
||||
defaultValue: false,
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.plsSettings) return "";
|
||||
return global.__HUGO_AURA__.plsSettings.regenCert;
|
||||
if (!global.__HUGO_AURA__.aikariSettings) return "";
|
||||
return global.__HUGO_AURA__.aikariSettings.tls.regenWsCertNextLaunch;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
if (typeof newVal !== "boolean") return false;
|
||||
|
||||
global.__HUGO_AURA__.plsSettings.regenCert = newVal;
|
||||
updatePlsConfigToRemote("regenCert", newVal);
|
||||
global.__HUGO_AURA__.aikariSettings.tls.regenWsCertNextLaunch =
|
||||
newVal;
|
||||
updateAikariConfigToRemote("tls.regenWsCertNextLaunch", newVal);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
// [!] Will be deprecated
|
||||
|
||||
const REQUIRE_BASE = ".";
|
||||
|
||||
const {
|
||||
updateAikariPLSRulesToRemote,
|
||||
} = require(`${REQUIRE_BASE}/../../../../composables/aikariConfigManager`);
|
||||
|
||||
const composables = {};
|
||||
|
||||
const deviceInfoPostSettings = [
|
||||
{
|
||||
id: 0,
|
||||
categoryName: "冰点管理",
|
||||
child: [
|
||||
{
|
||||
index: 0,
|
||||
id: "enableFreezeInfoReportOverride",
|
||||
type: "switch",
|
||||
name: "启用冰冻状态篡改",
|
||||
description: "篡改上报的冰冻数据, 可自定义集控端显示的状态",
|
||||
reactive: true,
|
||||
reactiveVal: ["root.ruleSettings"],
|
||||
restart: false,
|
||||
reload: false,
|
||||
aikariRequired: true,
|
||||
restartAikari: false,
|
||||
associateVal: null,
|
||||
auraIf: () => true,
|
||||
defaultValue: false,
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.aikariRules) return "";
|
||||
return global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||
.freezeManagement.freezeDiskInfoPost.enabled;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
if (typeof newVal !== "boolean") return;
|
||||
if (!global.__HUGO_AURA__.aikariRules) return;
|
||||
|
||||
global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.enabled =
|
||||
newVal;
|
||||
updateAikariPLSRulesToRemote(
|
||||
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.enabled",
|
||||
newVal,
|
||||
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost"
|
||||
);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
id: "freezeInfoReportFrozenDisks",
|
||||
type: "checkbox",
|
||||
name: "被冻结的磁盘",
|
||||
description: "选中的磁盘会<b>被上报</b>为冻结 (不是实际行为)",
|
||||
restart: false,
|
||||
reload: false,
|
||||
aikariRequired: true,
|
||||
restartAikari: false,
|
||||
warning: true,
|
||||
warningContent:
|
||||
"如果可选的磁盘盘符与下方预览不一致, 则多出的盘符可能为 DVD 驱动器 / 软盘 / 可移动磁盘, 忽略即可",
|
||||
reactive: true,
|
||||
reactiveVal: ["root.ruleSettings"],
|
||||
associateVal: [
|
||||
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.enabled",
|
||||
],
|
||||
auraIf: () => true,
|
||||
auraDisable: () => {
|
||||
if (!global.__HUGO_AURA__.aikariRules) return { value: true };
|
||||
if (
|
||||
!global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared
|
||||
.diskCaptions
|
||||
)
|
||||
return {
|
||||
value: true,
|
||||
tooltip: "发生错误, 请上报至 HugoAura GitHub Issues",
|
||||
};
|
||||
if (
|
||||
!global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared
|
||||
.diskCaptions.length === 0
|
||||
)
|
||||
return {
|
||||
value: true,
|
||||
tooltip: "发生错误, 请上报至 HugoAura GitHub Issues",
|
||||
};
|
||||
|
||||
return {
|
||||
value:
|
||||
!global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||
.freezeManagement.freezeDiskInfoPost.enabled,
|
||||
tooltip: "启用冰冻状态篡改以继续",
|
||||
};
|
||||
},
|
||||
defaultValue: [],
|
||||
templates: () => {
|
||||
try {
|
||||
if (
|
||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared
|
||||
.diskCaptions.length === 0
|
||||
) {
|
||||
return ["error"];
|
||||
} else {
|
||||
return global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared.diskCaptions.map(
|
||||
(element) => {
|
||||
return element.toLowerCase().replace(/:/g, "");
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return ["error"];
|
||||
}
|
||||
},
|
||||
templateLabels: () => {
|
||||
try {
|
||||
if (
|
||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared
|
||||
.diskCaptions.length === 0
|
||||
) {
|
||||
return ["获取盘符时发生错误, 请上报至 GitHub Issues"];
|
||||
} else {
|
||||
return global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared.diskCaptions.map(
|
||||
(element) => {
|
||||
return element.replace(/:/g, " 盘");
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return ["发生未知错误"];
|
||||
}
|
||||
},
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.aikariRules) return [];
|
||||
|
||||
return global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||
.freezeManagement.freezeDiskInfoPost.frozenDisks;
|
||||
},
|
||||
callbackFn: (affectedData, affectedEl) => {
|
||||
const targetArr =
|
||||
global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||
.freezeManagement.freezeDiskInfoPost.frozenDisks;
|
||||
if (affectedEl.checked) {
|
||||
targetArr.push(affectedData);
|
||||
} else {
|
||||
targetArr.splice(targetArr.indexOf(affectedData), 1);
|
||||
}
|
||||
updateAikariPLSRulesToRemote(
|
||||
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.frozenDisks",
|
||||
targetArr,
|
||||
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost"
|
||||
);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
id: "freezeInfoReportOverridePreview",
|
||||
type: "preview",
|
||||
loaderTarget:
|
||||
"Aura.UI.Assistant.Config.BehaviourCtrl.DeviceSecurity.FreezeOverridePreview",
|
||||
associateVal: [
|
||||
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.frozenDisks",
|
||||
],
|
||||
listenerType: "aikari",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
categoryName: "软件信息",
|
||||
child: [
|
||||
{
|
||||
index: 0,
|
||||
id: "enableSoftwareReportPostOverride",
|
||||
type: "switch",
|
||||
name: "启用软件信息上报覆写",
|
||||
description:
|
||||
'覆写上报的软件信息, 可自定义集控端 "设备管控" - <设备名> - "软件列表" 下的信息显示',
|
||||
reactive: true,
|
||||
reactiveVal: ["root.ruleSettings"],
|
||||
restart: false,
|
||||
reload: false,
|
||||
aikariRequired: true,
|
||||
restartAikari: false,
|
||||
warning: true,
|
||||
warningContent: '此功能与 "弹窗拦截" 等无关',
|
||||
associateVal: null,
|
||||
auraIf: () => true,
|
||||
defaultValue: false,
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.aikariRules) return false;
|
||||
return global.__HUGO_AURA__.aikariRules.deviceInfo.software
|
||||
.softwareReportPost.enabled;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
if (typeof newVal !== "boolean") return;
|
||||
if (!global.__HUGO_AURA__.aikariRules) return;
|
||||
|
||||
global.__HUGO_AURA__.aikariRules.deviceInfo.software.softwareReportPost.enabled =
|
||||
newVal;
|
||||
updateAikariPLSRulesToRemote(
|
||||
"deviceInfo.software.softwareReportPost.enabled",
|
||||
newVal,
|
||||
"deviceInfo.software.softwareReportPost"
|
||||
);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
id: "enableSoftwareReportPostSetAsEmpty",
|
||||
type: "switch",
|
||||
name: "清空软件上报列表",
|
||||
description: "将上报列表置空, 集控端将无法看到任何已安装应用",
|
||||
reactive: true,
|
||||
reactiveVal: ["root.ruleSettings"],
|
||||
restart: false,
|
||||
reload: false,
|
||||
aikariRequired: true,
|
||||
restartAikari: false,
|
||||
associateVal: ["deviceInfo.software.softwareReportPost.enabled"],
|
||||
auraIf: () => true,
|
||||
auraDisable: () => {
|
||||
if (!global.__HUGO_AURA__.aikariRules) return { value: true };
|
||||
|
||||
return {
|
||||
value:
|
||||
!global.__HUGO_AURA__.aikariRules.deviceInfo.software
|
||||
.softwareReportPost.enabled,
|
||||
tooltip: "启用软件信息上报覆写以继续",
|
||||
};
|
||||
},
|
||||
defaultValue: true,
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.aikariRules) return true;
|
||||
return global.__HUGO_AURA__.aikariRules.deviceInfo.software
|
||||
.softwareReportPost.setAsEmpty;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
if (typeof newVal !== "boolean") return;
|
||||
if (!global.__HUGO_AURA__.aikariRules) return;
|
||||
|
||||
global.__HUGO_AURA__.aikariRules.deviceInfo.software.softwareReportPost.setAsEmpty =
|
||||
newVal;
|
||||
updateAikariPLSRulesToRemote(
|
||||
"deviceInfo.software.softwareReportPost.setAsEmpty",
|
||||
newVal,
|
||||
"deviceInfo.software.softwareReportPost"
|
||||
);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
module.exports = { deviceInfoPostSettings };
|
||||
@@ -1,99 +0,0 @@
|
||||
const REQUIRE_BASE = ".";
|
||||
|
||||
const {
|
||||
updatePlsConfigToRemote,
|
||||
} = require(`${REQUIRE_BASE}/../../../../composables/plsConfigManager`);
|
||||
|
||||
const composables = {};
|
||||
|
||||
const deviceSecuritySettings = [
|
||||
{
|
||||
id: 0,
|
||||
categoryName: "冰点管理",
|
||||
child: [
|
||||
{
|
||||
index: 0,
|
||||
id: "enableFreezeInfoReportOverride",
|
||||
type: "switch",
|
||||
name: "启用冰冻状态篡改",
|
||||
description: "篡改上报的冰冻数据, 可自定义集控端显示的状态",
|
||||
reactive: true,
|
||||
reactiveVal: ["root.ruleSettings"],
|
||||
restart: false,
|
||||
reload: false,
|
||||
PLSRequired: true,
|
||||
restartPLS: false,
|
||||
associateVal: null,
|
||||
auraIf: () => true,
|
||||
defaultValue: false,
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.plsRules) return "";
|
||||
return global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
||||
.enable;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
if (typeof newVal !== "boolean") return;
|
||||
if (!global.__HUGO_AURA__.plsRules) return;
|
||||
|
||||
global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo.enable =
|
||||
newVal;
|
||||
updatePlsConfigToRemote(
|
||||
"ruleSettings.client.security.uploadFreezeInfo.enable",
|
||||
newVal
|
||||
);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
id: "freezeInfoReportOverrideType",
|
||||
type: "radio",
|
||||
name: "篡改模式",
|
||||
description:
|
||||
"选择一种篡改模式, 选中的磁盘范围会<b>被上报</b>为冻结 (不是实际行为)",
|
||||
restart: false,
|
||||
reload: false,
|
||||
PLSRequired: true,
|
||||
restartPLS: false,
|
||||
reactive: true,
|
||||
reactiveVal: ["root.ruleSettings"],
|
||||
associateVal: ["ruleSettings.client.security.uploadFreezeInfo.enable"],
|
||||
auraIf: () => {
|
||||
if (!global.__HUGO_AURA__.plsRules) return true;
|
||||
|
||||
return global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
||||
.enable;
|
||||
},
|
||||
defaultValue: "allFreeze",
|
||||
templates: ["allFreeze", "systemOnly", "exceptSecondDisk"],
|
||||
templateLabels: ["全部冻结", "仅系统盘", "第二磁盘除外"],
|
||||
valueGetter: () => {
|
||||
if (!global.__HUGO_AURA__.plsRules) return;
|
||||
|
||||
return global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
||||
.rewriteMode;
|
||||
},
|
||||
callbackFn: (newVal) => {
|
||||
global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo.rewriteMode =
|
||||
newVal;
|
||||
updatePlsConfigToRemote(
|
||||
"ruleSettings.client.security.uploadFreezeInfo.rewriteMode",
|
||||
newVal
|
||||
);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
id: "freezeInfoReportOverridePreview",
|
||||
type: "preview",
|
||||
loaderTarget:
|
||||
"Aura.UI.Assistant.Config.BehaviourCtrl.DeviceSecurity.FreezeOverridePreview",
|
||||
associateVal: ["ruleSettings.client.security.uploadFreezeInfo"],
|
||||
listenerType: "pls",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
module.exports = { deviceSecuritySettings };
|
||||
@@ -13,7 +13,7 @@
|
||||
<path fill="currentColor" d="M20.59 22L15 16.41V7h2v8.58l5 5.01z" />
|
||||
</svg>
|
||||
|
||||
<p>请稍候...</p>
|
||||
<p>无数据可用, 检查 Aikari 连接</p>
|
||||
</div>
|
||||
|
||||
<div class="acs-bc-dsc-fop-on-req-error" auraIf="false">
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
resolve({
|
||||
success: true,
|
||||
data: null,
|
||||
status: response.status
|
||||
})
|
||||
status: response.status,
|
||||
});
|
||||
}
|
||||
|
||||
const parsedData = await response.json();
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
const diskElTemplate = document.createElement("p");
|
||||
diskElTemplate.classList.add("acs-bc-dsc-fop-disk-el");
|
||||
if (!curConfig.enable) {
|
||||
if (!curConfig.enabled) {
|
||||
for (const disk of curDisks) {
|
||||
const curDiskEl = diskElTemplate.cloneNode();
|
||||
if (disk.status !== 0) {
|
||||
@@ -95,44 +95,16 @@
|
||||
diskContainerEl.appendChild(curDiskEl);
|
||||
}
|
||||
} else {
|
||||
switch (curConfig.rewriteMode) {
|
||||
case "allFreeze":
|
||||
{
|
||||
for (const disk of curDisks) {
|
||||
const curDiskEl = diskElTemplate.cloneNode();
|
||||
// @ts-expect-error
|
||||
curDiskEl.classList.add("active");
|
||||
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||
diskContainerEl.appendChild(curDiskEl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "systemOnly":
|
||||
{
|
||||
let idx = 0;
|
||||
for (const disk of curDisks) {
|
||||
const curDiskEl = diskElTemplate.cloneNode();
|
||||
// @ts-expect-error
|
||||
if (idx === 0) curDiskEl.classList.add("active");
|
||||
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||
diskContainerEl.appendChild(curDiskEl);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "exceptSecondDisk":
|
||||
{
|
||||
let idx = 0;
|
||||
for (const disk of curDisks) {
|
||||
const curDiskEl = diskElTemplate.cloneNode();
|
||||
// @ts-expect-error
|
||||
if (idx === 0) curDiskEl.classList.add("active");
|
||||
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||
diskContainerEl.appendChild(curDiskEl);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
let idx = 0;
|
||||
for (const disk of curDisks) {
|
||||
const curDiskEl = diskElTemplate.cloneNode();
|
||||
if (curConfig.frozenDisks.includes(disk.name.toLowerCase())) {
|
||||
// @ts-expect-error
|
||||
curDiskEl.classList.add("active");
|
||||
}
|
||||
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||
diskContainerEl.appendChild(curDiskEl);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,9 +120,10 @@
|
||||
)[0];
|
||||
|
||||
const eventListener = (_event) => {
|
||||
if (!global.__HUGO_AURA__.plsRules) return;
|
||||
if (!global.__HUGO_AURA__.aikariRules) return;
|
||||
composables.getAndUpdateDiskInfo(
|
||||
global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
||||
global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||
.freezeManagement.freezeDiskInfoPost
|
||||
);
|
||||
};
|
||||
rootEl.addEventListener("onAssociateValueUpdated", eventListener);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<script>
|
||||
let global = window;
|
||||
</script>
|
||||
<script src="../../../js/plsConnectionManager.js"></script>
|
||||
<script src="../../../js/aikariConnectionManager.js"></script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const IPC_METHOD_BASE = "$aura.pls";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PLSPush} parsedWsMsg
|
||||
* @returns
|
||||
*/
|
||||
const basicRouteHandler = (parsedWsMsg) => {
|
||||
const target = parsedWsMsg.type.split(".").slice(-1)[0];
|
||||
switch (target) {
|
||||
case "pushPlsInfo":
|
||||
if (global.__HUGO_AURA__.plsStats) {
|
||||
global.__HUGO_AURA__.plsStats.status = parsedWsMsg.data.status;
|
||||
global.__HUGO_AURA__.plsStats.version = parsedWsMsg.data.version;
|
||||
}
|
||||
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
||||
global.__HUGO_AURA__.plsStats
|
||||
);
|
||||
|
||||
console.debug(
|
||||
"[HugoAura / UI / PLS Routes / DEBUG] Updated plsStats basic info:",
|
||||
global.__HUGO_AURA__.plsStats
|
||||
);
|
||||
break;
|
||||
|
||||
case "plsNotReadyError":
|
||||
if (global.__HUGO_AURA__.plsStats) {
|
||||
global.__HUGO_AURA__.plsStats.launched = true;
|
||||
global.__HUGO_AURA__.plsStats.connected = false;
|
||||
global.__HUGO_AURA__.plsStats.status = "notReady";
|
||||
}
|
||||
|
||||
global.ipcRenderer.invoke(
|
||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
||||
global.__HUGO_AURA__.plsStats
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
module.exports = { basicRouteHandler };
|
||||
BIN
src/aura/ui/static/aikari_color_reversed.png
Normal file
BIN
src/aura/ui/static/aikari_color_reversed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
@@ -27,7 +27,7 @@ if (!global.__HUGO_AURA_API__) {
|
||||
"https://api-aura-projekts.minorice.moe",
|
||||
"https://api.aura.vim.moe",
|
||||
],
|
||||
plsUpdate: "/api/getPLSLatestVersion",
|
||||
aikariUpdate: "/api/getAikariLatestVersion",
|
||||
auraUpdate: "/api/getAuraLatestVersion",
|
||||
};
|
||||
global.__HUGO_AURA_API__ = __HUGO_AURA_API__;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @ts-check
|
||||
|
||||
const __AURA_VERSION__ = "0.1.1-beta-patch-1";
|
||||
const __AURA_VERSION__ = "0.2.0-rc1-p1";
|
||||
|
||||
(() => {
|
||||
if (require.main) return; // 如果只是导入 Aura Version, 不运行闭包逻辑
|
||||
|
||||
Reference in New Issue
Block a user