[️ BREAKING / Feat] Bump version to v0.2.0-RC1

- [+] 完成了下载 & 安装 Aikari 的步骤
- [*] 修复了部分状态管理错误, 但没修全
This commit is contained in:
Minoricew
2025-11-17 00:36:23 +08:00
committed by Minorice
parent b277a61923
commit 7afeb39275
7 changed files with 288 additions and 127 deletions

View File

@@ -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,18 +14,6 @@
> [!IMPORTANT]
> 已经过测试的希沃管家版本: v1.5.5.3878
> [!CAUTION]
> 由于作者高三学业繁忙, 项目正处于缓慢更新阶段。
>
> 作者将尽可能抽出时间维护项目, 但新功能的实现速度将大幅降低。
> [!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。开发者将在能力 / 时间限度内尽可能处理。
![Repobeats](https://repobeats.axiom.co/api/embed/69b5be5daacef624b8f5e4b8966a0b5898439a22.svg "Repobeats analytics image")
## ✨ 概览

View File

@@ -1,6 +1,6 @@
{
"name": "HugoAura",
"version": "0.1.1-beta-patch-1",
"version": "0.2.0-rc1",
"description": "Aura for SeewoHugo",
"main": "app.asar/main.js",
"dependencies": {},

View File

@@ -68,7 +68,7 @@ const functions = {
* @param {(arg: DownloadTask) => any} callbackFn
* @param {string} binPath
*/
handleAikariDownload: async (channel, callbackFn, binPath) => {
handleAikariDlAndInstall: async (channel, callbackFn, binPath) => {
// TODO: Channel selection
const apiInfo = global.__HUGO_AURA_API__;
@@ -167,7 +167,8 @@ const functions = {
status: "failed",
dlUrl: null,
savePath: null,
message: "未能获取 Aikari 版本信息, 所有 API 域名均无法连接",
message:
"未能获取 Aikari 版本信息, 所有 API 域名均无法连接, 建议前往 GitHub 下载安装包并自行安装",
});
return false;
}
@@ -187,25 +188,85 @@ const functions = {
status: "failed",
dlUrl: null,
savePath: null,
message: `处理器架构识别失败, 检测到的架构: ${deviceArch}`,
message: `不支持的处理器架构, 检测到的架构: "${deviceArch}"`,
});
return false;
}
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);
}
);
});
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";
}
}
callbackFn(...args);
fs.unlinkSync(binPath);
}
);
},
};
@@ -231,6 +292,15 @@ const applyAikariIpcHandler = (ipcMain) => {
);
const AIKARI_SVC_NAME = "HugoAuraAikari";
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"
);
const isAikariDetached = process.argv.includes("--aikari-detach");
global.__HUGO_AURA__.aikariStats = {
@@ -569,12 +639,21 @@ const applyAikariIpcHandler = (ipcMain) => {
*
* @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.handleAikariDownload(
functions.handleAikariDlAndInstall(
channel,
(status) => {
ipcMain.send(
@@ -583,7 +662,7 @@ const applyAikariIpcHandler = (ipcMain) => {
status
);
},
AIKARI_LAUNCHER_PATH
AIKARI_TEMP_INSTALLER_FILENAME
);
}
);

View File

@@ -3,23 +3,23 @@ const childProc = require("child_process");
const fileSystemRawCmds = {
getDiskCaptions: async () => {
const waitForCmd = new Promise((resolve) => {
childProc.exec(
"wmic logicaldisk get caption",
(error, stdout, stderr) => {
childProc.exec("fsutil fsinfo drives", (error, stdout, stderr) => {
if (error) {
console.error(
`[HugoAura / UI / Composables / Raw CMD / FS] Failed to exec wmic getCaption: ${error}`
`[HugoAura / UI / Composables / Raw CMD / FS] Failed to exec fsutil getCaption: ${error}`
);
resolve([]);
}
const drives = stdout
const finResult = [];
stdout
.trim()
.split("\r\n")
.slice(1)
.map((line) => line.trim());
resolve(drives);
}
);
.split(": ")[1]
.split(":\\")
.forEach((line) => {
if (line !== "") finResult.push(line.trim() + ":");
});
resolve(finResult);
});
});
return waitForCmd;
},

View File

@@ -284,6 +284,8 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
false,
null
);
const isHostNotInit =
await global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.showWarnToastIfHostsNotInitialized();
const ret = await ipcRenderer.invoke(
`${IPC_METHOD_BASE}.aikariLifecycleControl`,
{ target: "startSvc" }
@@ -291,6 +293,7 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
if (ret.success) {
lifecycleStatus.svcRunning = true;
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.updateStatusContent();
if (!isHostNotInit) {
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.updateToast(
"success",
"Aikari 已启动",
@@ -299,6 +302,7 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
true,
2000
);
}
await global.__HUGO_AURA_GLOBAL__.utils.sleep(100);
await ipcRenderer.invoke(
`${IPC_METHOD_BASE}.retryAikariConnect`
@@ -396,7 +400,12 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", true);
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", true);
} else {
updateStatusEl(acIdInst, atIdInst, "SUCCESS", "已安装");
updateStatusEl(
acIdInst,
atIdInst,
"SUCCESS",
"应用已安装, 服务已安装"
);
GLOBAL_FUNCTIONS.updateOperationBtnStatus("InstallSvc", true);
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
"UninstallSvc",
@@ -465,6 +474,30 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
}
},
showWarnToastIfHostsNotInitialized: async () => {
const dnsModule = require("dns");
const lookupPromise = new Promise((resolve) => {
dnsModule.lookup("iot-broker-mis.seewo.com", (err, result) => {
resolve(err ? err : result);
});
});
const result = await lookupPromise;
if (result) {
if (!result.startsWith("127.")) {
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.updateToast(
"error",
"警告: 页面即将刷新",
`<p>您似乎是首次运行 Aikari, 基于 Aikari PLS 模块的实现原理, 我们需要修改 Hosts 文件并重启 SeewoCore 进程以开始拦截流量。</p>
<p>重启 SeewoCore 进程会导致管家前端页面<b>在重启完成后自动发生刷新</b>, 因此稍后请留意此变更。</p>`,
true,
false,
null
);
return true;
}
}
},
refreshAikariStatus: async (init = false) => {
const isDetachedRet = await ipcRenderer.invoke(
`${IPC_METHOD_BASE}.aikariLifecycleQuery`,
@@ -636,7 +669,7 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
}
},
downloadAikariBin: async (retrieveMode = false) => {
downloadAndInstallAikariBin: async (retrieveMode = false) => {
const GLOBAL_FUNCTIONS =
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus;
const CUR_CHANNEL = `${IPC_METHOD_BASE}.post.reportAikariInstallStep`;
@@ -671,6 +704,7 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
const callbackFn = (_evt, info) => {
switch (info.status) {
case "failed":
if (info.id !== "INSTALL_STAGE") {
GLOBAL_FUNCTIONS.updateToast(
"error",
"下载失败",
@@ -690,6 +724,30 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
"danger",
false
);
} else {
GLOBAL_FUNCTIONS.updateToast(
"error",
"安装失败",
`<p>${
info.message
? info.message
: "检查 HugoAura 日志或安装器日志 (%TEMP%/Aikari-Install-Temp) 以获取错误信息"
}</p><p>
${info.errorObj ? info.errorObj : ""}
</p>`,
true,
true,
15000
);
GLOBAL_FUNCTIONS.updatePBarStatus(
100,
`发生错误: ${info.message}`,
"danger",
false
);
}
setTimeout(() => {
GLOBAL_FUNCTIONS.switchPBarShowStatus(false);
}, 1000);
@@ -703,6 +761,7 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
);
break;
case "done":
if (info.id !== "INSTALL_STAGE") {
GLOBAL_FUNCTIONS.updateToast(
"success",
"下载成功",
@@ -718,6 +777,24 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
"success",
false
);
break;
} else {
GLOBAL_FUNCTIONS.updateToast(
"success",
"安装成功",
null,
true,
true,
2500
);
GLOBAL_FUNCTIONS.updatePBarStatus(
100,
"Aikari 安装成功",
"success",
false
);
setTimeout(() => {
GLOBAL_FUNCTIONS.switchPBarShowStatus(false);
}, 1000);
@@ -731,25 +808,34 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
);
lifecycleStatus.installed = true;
global.__HUGO_AURA__.aikariStats.installed = true;
setTimeout(() => {
ipcRenderer.invoke(
`${IPC_METHOD_BASE}.updateAikariStatus`,
global.__HUGO_AURA__.aikariStats
);
GLOBAL_FUNCTIONS.updateStatusContent();
}, 500);
break;
}
case "waiting":
GLOBAL_FUNCTIONS.updatePBarStatus(0, "正在连接", "normal");
GLOBAL_FUNCTIONS.updatePBarStatus(
0,
info.message ? info.message : "正在连接",
"normal"
);
if (
!global.__HUGO_AURA_UI_REACTIVES__.subConfig.aikariStatus
(!global.__HUGO_AURA_UI_REACTIVES__.subConfig.aikariStatus
.curDlTaskId ||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.aikariStatus
.curDlTaskId !== info.id
.curDlTaskId !== info.id) &&
info.id !== "INSTALL_STAGE"
) {
global.__HUGO_AURA_UI_REACTIVES__.subConfig.aikariStatus.curDlTaskId =
info.id;
}
break;
case "progressing":
if (info.id !== "INSTALL_STAGE") {
const roundProgress = Math.round(info.progress);
GLOBAL_FUNCTIONS.updatePBarStatus(
roundProgress,
@@ -763,6 +849,14 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
"normal",
true
);
} else {
GLOBAL_FUNCTIONS.updatePBarStatus(
info.progress,
`正在安装 Aikari...`,
"normal",
false
);
}
break;
case "struggling":
GLOBAL_FUNCTIONS.updatePBarStatus(100, info.message, "warning");

View File

@@ -27,7 +27,7 @@ if (!global.__HUGO_AURA_API__) {
"https://api-aura-projekts.minorice.moe",
"https://api.aura.vim.moe",
],
aikariUpdate: "/api/getPLSLatestVersion",
aikariUpdate: "/api/getAikariLatestVersion",
auraUpdate: "/api/getAuraLatestVersion",
};
global.__HUGO_AURA_API__ = __HUGO_AURA_API__;

View File

@@ -1,6 +1,6 @@
// @ts-check
const __AURA_VERSION__ = "0.1.1-beta-patch-1";
const __AURA_VERSION__ = "0.2.0-rc1";
(() => {
if (require.main) return; // 如果只是导入 Aura Version, 不运行闭包逻辑