[🔄 Chore] Prepare for Aikari (1/2)

1. [/] 一些无意义的重命名工作
2. [*] 修改了 WebSocket 对接逻辑
This commit is contained in:
Minoricew
2025-11-14 02:58:09 +08:00
committed by Minorice
parent 5a29e909f2
commit 08290301a3
33 changed files with 1006 additions and 926 deletions

View File

@@ -0,0 +1,372 @@
// @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 plsPort = 22077;
/** @type {"wss" | "ws"} */
let plsProtocol = "wss";
/** @type {boolean} */
let isRetrying = false;
/** @type {any} */
let curSendListener = null;
let curSendGetListener = null;
const sendRetryStatusToMain = (/** @type {Boolean} */ status) => {
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.post.updateRetryStatus`, {
success: status,
});
};
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);
return;
}
const portRet = await registryManager.readRegKey(
AIKARI_RPC_CONFIG_REG_PATH,
"wsPort",
true
);
if (portRet.success) {
try {
plsPort = 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 PLS WebSocket server, please check the status of PLS process.`
);
sendRetryStatusToMain(false);
return;
}
/** @type {WebSocket} */
const aikariWs = new WebSocket(
`${plsProtocol}://aikari.hugoaura.local:${plsPort}/?auth=${authToken}`
);
aikariWs.onopen = () => {
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);
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);
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);
};
/**
*
* @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);
return;
}
failedCounter = 0;
isErrorOccurred = false;
const curPlsStats = await global.ipcRenderer.invoke(
`${IPC_METHOD_BASE}.getAikariStatus`
);
let updatedAikariStats = {};
if (
(curPlsStats === null || !curPlsStats.success) &&
curPlsStats.status !== "downloading" &&
curPlsStats.status !== "installing"
) {
updatedAikariStats = {
installed: false,
launched: false,
detached: false,
connected: false,
version: "unknown",
status: "dead",
authToken: "",
};
} else {
updatedAikariStats = curPlsStats.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);
}
/*
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.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);
})();