Compare commits

...

7 Commits

Author SHA1 Message Date
eb4698109e merge upstream 2025-06-21 23:43:44 -07:00
3bcd5827f9 chore(webui): unset nonce when logging out (#2242)
Reviewed-on: OpenWF/SpaceNinjaServer#2242
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-06-21 14:38:48 -07:00
d16d763977 chore: handle logout POST request for older versions (#2240)
Reviewed-on: OpenWF/SpaceNinjaServer#2240
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-06-21 14:38:24 -07:00
ff8ec8dbed chore(webui): update bootstrap, add sourcemaps for it (#2238)
Reviewed-on: OpenWF/SpaceNinjaServer#2238
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-06-21 14:38:04 -07:00
6cdd103c3d chore(dev): improve bulk change handling (#2234)
Fixed abandoned build processes sometimes still triggering a start (causing double-starts) made it more robust in regards to webui changes being intermixed: making the fetch a fire-and-forget to avoid errors, and waiting for the websocket connection to be re-established to avoid the browser attempting to reload when the server may not be up for a few seconds.

Reviewed-on: OpenWF/SpaceNinjaServer#2234
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-06-21 11:33:59 -07:00
b6f79c1e5c fix: save steel path mission completion (#2233)
Fixes #2228

Reviewed-on: OpenWF/SpaceNinjaServer#2233
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-06-21 11:25:42 -07:00
2bb3e2afdd chore(webui): update to Spanish translation (#2236)
Reviewed-on: OpenWF/SpaceNinjaServer#2236
Co-authored-by: hxedcl <hxedcl@noreply.localhost>
Co-committed-by: hxedcl <hxedcl@noreply.localhost>
2025-06-21 10:51:57 -07:00
11 changed files with 55 additions and 24 deletions

View File

@ -28,8 +28,12 @@ function run(changedFile) {
runproc = undefined; runproc = undefined;
} }
buildproc = spawn("npm", ["run", "build:dev"], { stdio: "inherit", shell: true }); const thisbuildproc = spawn("npm", ["run", "build:dev"], { stdio: "inherit", shell: true });
buildproc = thisbuildproc;
buildproc.on("exit", code => { buildproc.on("exit", code => {
if (buildproc !== thisbuildproc) {
return;
}
buildproc = undefined; buildproc = undefined;
if (code === 0) { if (code === 0) {
runproc = spawn("npm", ["run", "start", "--", ...args], { stdio: "inherit", shell: true }); runproc = spawn("npm", ["run", "start", "--", ...args], { stdio: "inherit", shell: true });
@ -44,6 +48,8 @@ run();
chokidar.watch("src").on("change", run); chokidar.watch("src").on("change", run);
chokidar.watch("static/fixed_responses").on("change", run); chokidar.watch("static/fixed_responses").on("change", run);
chokidar.watch("static/webui").on("change", () => { chokidar.watch("static/webui").on("change", async () => {
fetch("http://localhost/custom/webuiFileChangeDetected?secret=" + secret); try {
await fetch("http://localhost/custom/webuiFileChangeDetected?secret=" + secret);
} catch (e) {}
}); });

View File

@ -1,11 +1,10 @@
import { args } from "@/src/helpers/commandLineArguments"; import { args } from "@/src/helpers/commandLineArguments";
import { config } from "@/src/services/configService";
import { sendWsBroadcast } from "@/src/services/webService"; import { sendWsBroadcast } from "@/src/services/webService";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
export const webuiFileChangeDetectedController: RequestHandler = (req, res) => { export const webuiFileChangeDetectedController: RequestHandler = (req, res) => {
if (args.dev && args.secret && req.query.secret == args.secret) { if (args.dev && args.secret && req.query.secret == args.secret) {
sendWsBroadcast({ ports: { http: config.httpPort, https: config.httpsPort } }); sendWsBroadcast({ reload: true });
} }
res.end(); res.end();
}; };

View File

@ -284,6 +284,7 @@ apiRouter.post("/inventorySlots.php", inventorySlotsController);
apiRouter.post("/joinSession.php", joinSessionController); apiRouter.post("/joinSession.php", joinSessionController);
apiRouter.post("/login.php", loginController); apiRouter.post("/login.php", loginController);
apiRouter.post("/loginRewardsSelection.php", loginRewardsSelectionController); apiRouter.post("/loginRewardsSelection.php", loginRewardsSelectionController);
apiRouter.post("/logout.php", logoutController); // from ~U16, don't know when they changed it to GET
apiRouter.post("/maturePet.php", maturePetController); apiRouter.post("/maturePet.php", maturePetController);
apiRouter.post("/missionInventoryUpdate.php", missionInventoryUpdateController); apiRouter.post("/missionInventoryUpdate.php", missionInventoryUpdateController);
apiRouter.post("/modularWeaponCrafting.php", modularWeaponCraftingController); apiRouter.post("/modularWeaponCrafting.php", modularWeaponCraftingController);

View File

@ -1825,12 +1825,15 @@ export const addChallenges = (
return affiliationMods; return affiliationMods;
}; };
export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag, Completes }: IMission): void => { export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag, Completes, Tier }: IMission): void => {
const { Missions } = inventory; const { Missions } = inventory;
const itemIndex = Missions.findIndex(item => item.Tag === Tag); const itemIndex = Missions.findIndex(item => item.Tag === Tag);
if (itemIndex !== -1) { if (itemIndex !== -1) {
Missions[itemIndex].Completes += Completes; Missions[itemIndex].Completes += Completes;
if (Tier) {
Missions[itemIndex].Tier = Tier;
}
} else { } else {
Missions.push({ Tag, Completes }); Missions.push({ Tag, Completes });
} }

View File

@ -110,6 +110,7 @@ interface IWsMsgFromClient {
} }
interface IWsMsgToClient { interface IWsMsgToClient {
reload?: boolean;
ports?: { ports?: {
http: number | undefined; http: number | undefined;
https: number | undefined; https: number | undefined;
@ -175,7 +176,17 @@ const wsOnConnect = (ws: ws, _req: http.IncomingMessage): void => {
} }
} }
if (data.logout) { if (data.logout) {
const accountId = (ws as IWsCustomData).accountId;
(ws as IWsCustomData).accountId = undefined; (ws as IWsCustomData).accountId = undefined;
await Account.updateOne(
{
_id: accountId,
ClientType: "webui"
},
{
Nonce: 0
}
);
} }
}); });
}; };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -9,9 +9,10 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable @typescript-eslint/explicit-function-return-type */
let auth_pending = false, let auth_pending = false,
did_initial_auth = false; did_initial_auth = false,
ws_is_open = false;
const sendAuth = isRegister => { const sendAuth = isRegister => {
if (localStorage.getItem("email") && localStorage.getItem("password")) { if (ws_is_open && localStorage.getItem("email") && localStorage.getItem("password")) {
auth_pending = true; auth_pending = true;
window.ws.send( window.ws.send(
JSON.stringify({ JSON.stringify({
@ -28,10 +29,18 @@ const sendAuth = isRegister => {
function openWebSocket() { function openWebSocket() {
window.ws = new WebSocket("/custom/ws"); window.ws = new WebSocket("/custom/ws");
window.ws.onopen = () => { window.ws.onopen = () => {
ws_is_open = true;
sendAuth(false); sendAuth(false);
}; };
window.ws.onmessage = e => { window.ws.onmessage = e => {
const msg = JSON.parse(e.data); const msg = JSON.parse(e.data);
if ("reload" in msg) {
setTimeout(() => {
getWebSocket().then(() => {
location.reload();
});
}, 100);
}
if ("ports" in msg) { if ("ports" in msg) {
location.port = location.protocol == "https:" ? msg.ports.https : msg.ports.http; location.port = location.protocol == "https:" ? msg.ports.https : msg.ports.http;
} }
@ -72,7 +81,7 @@ function openWebSocket() {
} }
}; };
window.ws.onclose = function () { window.ws.onclose = function () {
window.ws = undefined; ws_is_open = false;
setTimeout(openWebSocket, 3000); setTimeout(openWebSocket, 3000);
}; };
} }
@ -82,7 +91,7 @@ function getWebSocket() {
return new Promise(resolve => { return new Promise(resolve => {
let interval; let interval;
interval = setInterval(() => { interval = setInterval(() => {
if (window.ws) { if (ws_is_open) {
clearInterval(interval); clearInterval(interval);
resolve(window.ws); resolve(window.ws);
} }
@ -117,7 +126,7 @@ function logout() {
function doLogout() { function doLogout() {
logout(); logout();
if (window.ws) { if (ws_is_open) {
// Unsubscribe from notifications about nonce invalidation // Unsubscribe from notifications about nonce invalidation
window.ws.send(JSON.stringify({ logout: true })); window.ws.send(JSON.stringify({ logout: true }));
} }

View File

@ -100,7 +100,7 @@ dict = {
inventory_bulkRankUpSentinels: `Maximizar rango de todos los centinelas`, inventory_bulkRankUpSentinels: `Maximizar rango de todos los centinelas`,
inventory_bulkRankUpSentinelWeapons: `Maximizar rango de todas las armas de centinela`, inventory_bulkRankUpSentinelWeapons: `Maximizar rango de todas las armas de centinela`,
inventory_bulkRankUpEvolutionProgress: `Maximizar todo el progreso de evolución Incarnon`, inventory_bulkRankUpEvolutionProgress: `Maximizar todo el progreso de evolución Incarnon`,
inventory_maxPlexus: `[UNTRANSLATED] Max Rank Plexus`, inventory_maxPlexus: `Rango máximo de Plexus`,
quests_list: `Misiones`, quests_list: `Misiones`,
quests_completeAll: `Completar todas las misiones`, quests_completeAll: `Completar todas las misiones`,
@ -135,10 +135,10 @@ dict = {
cheats_infiniteRegalAya: `Aya Real infinita`, cheats_infiniteRegalAya: `Aya Real infinita`,
cheats_infiniteHelminthMaterials: `Materiales Helminto infinitos`, cheats_infiniteHelminthMaterials: `Materiales Helminto infinitos`,
cheats_claimingBlueprintRefundsIngredients: `Reclamar ingredientes devueltos por planos`, cheats_claimingBlueprintRefundsIngredients: `Reclamar ingredientes devueltos por planos`,
cheats_dontSubtractPurchaseCreditCost: `[UNTRANSLATED] Don't Subtract Purchase Credit Cost`, cheats_dontSubtractPurchaseCreditCost: `No restar costo en créditos de la compra`,
cheats_dontSubtractPurchasePlatinumCost: `[UNTRANSLATED] Don't Subtract Purchase Platinum Cost`, cheats_dontSubtractPurchasePlatinumCost: `No restar costo en platino de la compra`,
cheats_dontSubtractPurchaseItemCost: `[UNTRANSLATED] Don't Subtract Purchase Item Cost`, cheats_dontSubtractPurchaseItemCost: `No restar costo de ítem en la compra`,
cheats_dontSubtractPurchaseStandingCost: `[UNTRANSLATED] Don't Subtract Purchase Standing Cost`, cheats_dontSubtractPurchaseStandingCost: `No restar costo en reputación de la compra`,
cheats_dontSubtractVoidTraces: `No descontar vestigios del Vacío`, cheats_dontSubtractVoidTraces: `No descontar vestigios del Vacío`,
cheats_dontSubtractConsumables: `No restar consumibles`, cheats_dontSubtractConsumables: `No restar consumibles`,
cheats_unlockAllShipFeatures: `Desbloquear todas las funciones de nave`, cheats_unlockAllShipFeatures: `Desbloquear todas las funciones de nave`,
@ -159,7 +159,7 @@ dict = {
cheats_noDeathMarks: `Sin marcas de muerte`, cheats_noDeathMarks: `Sin marcas de muerte`,
cheats_noKimCooldowns: `Sin tiempo de espera para conversaciones KIM`, cheats_noKimCooldowns: `Sin tiempo de espera para conversaciones KIM`,
cheats_syndicateMissionsRepeatable: `Misiones de sindicato rejugables`, cheats_syndicateMissionsRepeatable: `Misiones de sindicato rejugables`,
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`, cheats_unlockAllProfitTakerStages: `Deslobquea todas las etapas del Roba-ganancias`,
cheats_instantFinishRivenChallenge: `Terminar desafío de agrietado inmediatamente`, cheats_instantFinishRivenChallenge: `Terminar desafío de agrietado inmediatamente`,
cheats_instantResourceExtractorDrones: `Drones de extracción de recursos instantáneos`, cheats_instantResourceExtractorDrones: `Drones de extracción de recursos instantáneos`,
cheats_noResourceExtractorDronesDamage: `Sin daño a los drones extractores de recursos`, cheats_noResourceExtractorDronesDamage: `Sin daño a los drones extractores de recursos`,
@ -170,7 +170,7 @@ dict = {
cheats_noDojoResearchCosts: `Sin costo de investigación del dojo`, cheats_noDojoResearchCosts: `Sin costo de investigación del dojo`,
cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`, cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`,
cheats_fastClanAscension: `Ascenso rápido del clan`, cheats_fastClanAscension: `Ascenso rápido del clan`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`, cheats_missionsCanGiveAllRelics: `Las misiones pueden otorgar todas las reliquias`,
cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`, cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`,
cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`, cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`,
cheats_save: `Guardar`, cheats_save: `Guardar`,