From b0b68f474ac80d7fe2bc6fac5852764a5cf4e4af Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Fri, 15 Aug 2025 15:13:34 -0700 Subject: [PATCH] feat: getShip import (#2627) Re #2592 Unsure about import note, is it okay that we leave the API path? Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2627 Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> --- src/controllers/custom/importController.ts | 14 ++++- src/services/importService.ts | 70 ++++++++++++++++++++++ src/types/personalRoomsTypes.ts | 4 +- static/webui/index.html | 5 +- static/webui/translations/de.js | 3 +- static/webui/translations/en.js | 3 +- static/webui/translations/es.js | 3 +- static/webui/translations/fr.js | 3 +- static/webui/translations/ru.js | 3 +- static/webui/translations/uk.js | 3 +- static/webui/translations/zh.js | 3 +- 11 files changed, 101 insertions(+), 13 deletions(-) diff --git a/src/controllers/custom/importController.ts b/src/controllers/custom/importController.ts index 93722fa0..b6b5571b 100644 --- a/src/controllers/custom/importController.ts +++ b/src/controllers/custom/importController.ts @@ -1,8 +1,10 @@ -import { importInventory, importLoadOutPresets } from "@/src/services/importService"; +import { importInventory, importLoadOutPresets, importPersonalRooms } from "@/src/services/importService"; import { getInventory } from "@/src/services/inventoryService"; import { getLoadout } from "@/src/services/loadoutService"; import { getAccountIdForRequest } from "@/src/services/loginService"; +import { getPersonalRooms } from "@/src/services/personalRoomsService"; import { IInventoryClient } from "@/src/types/inventoryTypes/inventoryTypes"; +import { IGetShipResponse } from "@/src/types/personalRoomsTypes"; import { RequestHandler } from "express"; export const importController: RequestHandler = async (req, res) => { @@ -13,15 +15,21 @@ export const importController: RequestHandler = async (req, res) => { importInventory(inventory, request.inventory); await inventory.save(); - if (request.inventory.LoadOutPresets) { + if ("LoadOutPresets" in request.inventory && request.inventory.LoadOutPresets) { const loadout = await getLoadout(accountId); importLoadOutPresets(loadout, request.inventory.LoadOutPresets); await loadout.save(); } + if ("Ship" in request.inventory || "Apartment" in request.inventory || "TailorShop" in request.inventory) { + const personalRooms = await getPersonalRooms(accountId); + importPersonalRooms(personalRooms, request.inventory); + await personalRooms.save(); + } + res.end(); }; interface IImportRequest { - inventory: Partial; + inventory: Partial | Partial; } diff --git a/src/services/importService.ts b/src/services/importService.ts index 1521fea4..3cfdaffc 100644 --- a/src/services/importService.ts +++ b/src/services/importService.ts @@ -44,6 +44,22 @@ import { IKubrowPetDetailsClient, IKubrowPetDetailsDatabase } from "@/src/types/equipmentTypes"; +import { + IApartmentClient, + IApartmentDatabase, + IFavouriteLoadout, + IFavouriteLoadoutDatabase, + IGetShipResponse, + IOrbiterClient, + IOrbiterDatabase, + IPersonalRoomsDatabase, + IPlantClient, + IPlantDatabase, + IPlanterClient, + IPlanterDatabase, + ITailorShop, + ITailorShopDatabase +} from "@/src/types/personalRoomsTypes"; const convertDate = (value: IMongoDate): Date => { return new Date(parseInt(value.$date.$numberLong)); @@ -429,3 +445,57 @@ export const importLoadOutPresets = (db: ILoadoutDatabase, client: ILoadOutPrese db.OPERATOR_ADULT = client.OPERATOR_ADULT.map(convertLoadOutConfig); db.DRIFTER = client.DRIFTER.map(convertLoadOutConfig); }; + +const convertShip = (client: IOrbiterClient): IOrbiterDatabase => { + return { + ...client, + ShipInterior: { + ...client.ShipInterior, + Colors: Array.isArray(client.ShipInterior.Colors) ? {} : client.ShipInterior.Colors + }, + FavouriteLoadoutId: client.FavouriteLoadoutId ? new Types.ObjectId(client.FavouriteLoadoutId.$oid) : undefined + }; +}; + +const convertPlant = (client: IPlantClient): IPlantDatabase => { + return { + ...client, + EndTime: convertDate(client.EndTime) + }; +}; + +const convertPlanter = (client: IPlanterClient): IPlanterDatabase => { + return { + ...client, + Plants: client.Plants.map(convertPlant) + }; +}; + +const convertFavouriteLoadout = (client: IFavouriteLoadout): IFavouriteLoadoutDatabase => { + return { + ...client, + LoadoutId: new Types.ObjectId(client.LoadoutId.$oid) + }; +}; + +const convertApartment = (client: IApartmentClient): IApartmentDatabase => { + return { + ...client, + Gardening: { Planters: client.Gardening.Planters.map(convertPlanter) }, + FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : [] + }; +}; + +const convertTailorShop = (client: ITailorShop): ITailorShopDatabase => { + return { + ...client, + Colors: Array.isArray(client.Colors) ? {} : client.Colors, + FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : [] + }; +}; + +export const importPersonalRooms = (db: IPersonalRoomsDatabase, client: Partial): void => { + if (client.Ship !== undefined) db.Ship = convertShip(client.Ship); + if (client.Apartment !== undefined) db.Apartment = convertApartment(client.Apartment); + if (client.TailorShop !== undefined) db.TailorShop = convertTailorShop(client.TailorShop); +}; diff --git a/src/types/personalRoomsTypes.ts b/src/types/personalRoomsTypes.ts index 2c5403f8..6a7723a2 100644 --- a/src/types/personalRoomsTypes.ts +++ b/src/types/personalRoomsTypes.ts @@ -90,7 +90,7 @@ export interface IGardeningDatabase { export interface IApartmentClient { Gardening: IGardeningClient; Rooms: IRoom[]; - FavouriteLoadouts: IFavouriteLoadout[]; + FavouriteLoadouts?: IFavouriteLoadout[]; VideoWallBackdrop?: string; Soundscape?: string; } @@ -210,7 +210,7 @@ export interface ITailorShopDatabase { } export interface ITailorShop extends Omit { - FavouriteLoadouts: IFavouriteLoadout[]; + FavouriteLoadouts?: IFavouriteLoadout[]; } export type RoomsType = { Name: string; MaxCapacity: number; PlacedDecos: Types.DocumentArray }; diff --git a/static/webui/index.html b/static/webui/index.html index 374459d8..48128f57 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -1147,7 +1147,10 @@
-

+

+ + +

diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index 8a0ee8a7..31c046ef 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -307,7 +307,8 @@ dict = { worldState_varziaFullyStocked: `Varzia hat volles Inventar`, worldState_varziaOverride: `Varzia-Angebotsüberschreibung`, - import_importNote: `Du kannst hier eine vollständige oder teilweise Inventarantwort (Client-Darstellung) einfügen. Alle Felder, die vom Importer unterstützt werden, werden in deinem Account überschrieben.`, + import_importNote: `[UNTRANSLATED] You can provide a full or partial inventory.php or getShip.php response (client representation) here.`, + import_importNote2: `Alle Felder, die vom Importer unterstützt werden, werden in deinem Account überschrieben.`, import_submit: `Absenden`, import_samples: `Beispiele:`, import_samples_maxFocus: `Alle Fokus-Schulen maximiert`, diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js index 2092335a..6a9fdea7 100644 --- a/static/webui/translations/en.js +++ b/static/webui/translations/en.js @@ -306,7 +306,8 @@ dict = { worldState_varziaFullyStocked: `Varzia Fully Stocked`, worldState_varziaOverride: `Varzia Rotation Override`, - import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer will be overwritten in your account.`, + import_importNote: `You can provide a full or partial inventory.php or getShip.php response (client representation) here.`, + import_importNote2: `All fields that are supported by the importer will be overwritten in your account.`, import_submit: `Submit`, import_samples: `Samples:`, import_samples_maxFocus: `All Focus Schools Maxed Out`, diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js index 4e607f9d..639be3e3 100644 --- a/static/webui/translations/es.js +++ b/static/webui/translations/es.js @@ -307,7 +307,8 @@ dict = { worldState_varziaFullyStocked: `Varzia con stock completo`, worldState_varziaOverride: `Cambio en rotación de Varzia`, - import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador serán sobrescritos en tu cuenta.`, + import_importNote: `[UNTRANSLATED] You can provide a full or partial inventory.php or getShip.php response (client representation) here.`, + import_importNote2: `Todos los campos compatibles con el importador serán sobrescritos en tu cuenta.`, import_submit: `Enviar`, import_samples: `Muestras:`, import_samples_maxFocus: `Todas las escuelas de enfoque al máximo`, diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index 750a7127..82ba28f8 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -307,7 +307,8 @@ dict = { worldState_varziaFullyStocked: `Stock de Varzia au max`, worldState_varziaOverride: `Rotation de Varzia`, - import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire écraseront celles présentes dans la base de données.`, + import_importNote: `[UNTRANSLATED] You can provide a full or partial inventory.php or getShip.php response (client representation) here.`, + import_importNote2: `[UNTRANSLATED] All fields that are supported by the importer will be overwritten in your account.`, import_submit: `Soumettre`, import_samples: `Échantillons :`, import_samples_maxFocus: `Toutes les écoles de focus au rang max`, diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index 9992d1b2..4dd80036 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -307,7 +307,8 @@ dict = { worldState_varziaFullyStocked: `Полный ассортимент Варзии`, worldState_varziaOverride: `Изменение ротации Варзии`, - import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля будут перезаписаны в вашем аккаунте.`, + import_importNote: `Вы можете загрузить полный или частичный ответ inventory.php или getShip.php (клиентское представление) здесь. `, + import_importNote2: `Все поддерживаемые поля будут перезаписаны в вашем аккаунте.`, import_submit: `Отправить`, import_samples: `Пример:`, import_samples_maxFocus: `Все школы Фокуса макс. уровня`, diff --git a/static/webui/translations/uk.js b/static/webui/translations/uk.js index 7240bb36..19002c24 100644 --- a/static/webui/translations/uk.js +++ b/static/webui/translations/uk.js @@ -307,7 +307,8 @@ dict = { worldState_varziaFullyStocked: `Повний асортимент Варзії`, worldState_varziaOverride: `Зміна ротації Варзії`, - import_importNote: `Ви можете завантажити повну або часткову відповідь спорядження (клієнтське представлення) тут. Всі підтримувані поля будуть перезаписані у вашому акаунті.`, + import_importNote: `[UNTRANSLATED] You can provide a full or partial inventory.php or getShip.php response (client representation) here.`, + import_importNote2: `Всі підтримувані поля будуть перезаписані у вашому акаунті.`, import_submit: `Відправити`, import_samples: `Приклад:`, import_samples_maxFocus: `Всі школи Фокусу макс. рівня`, diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js index e4cdbdac..440580e0 100644 --- a/static/webui/translations/zh.js +++ b/static/webui/translations/zh.js @@ -307,7 +307,8 @@ dict = { worldState_varziaFullyStocked: `瓦奇娅开启全部库存商品`, worldState_varziaOverride: `瓦奇娅(Prime重生)轮换状态`, - import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段将被覆盖到您的账户中。`, + import_importNote: `[UNTRANSLATED] You can provide a full or partial inventory.php or getShip.php response (client representation) here.`, + import_importNote2: `支持的所有字段将被覆盖到您的账户中。`, import_submit: `提交`, import_samples: `示例:`, import_samples_maxFocus: `所有专精学派完全精通`,