feat: Kinematic Instant Messaging #801
85
src/controllers/api/saveDialogueController.ts
Normal file
85
src/controllers/api/saveDialogueController.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { ICompletedDialogue } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const saveDialogueController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const request = JSON.parse(String(req.body)) as SaveDialogueRequest;
|
||||
|
||||
if ("YearIteration" in request) {
|
||||
const inventory = await getInventory(accountId);
|
||||
if (inventory.DialogueHistory) {
|
||||
inventory.DialogueHistory.YearIteration = request.YearIteration;
|
||||
} else {
|
||||
inventory.DialogueHistory = { YearIteration: request.YearIteration };
|
||||
}
|
||||
await inventory.save();
|
||||
res.end();
|
||||
} else {
|
||||
const inventory = await getInventory(accountId);
|
||||
if (!inventory.DialogueHistory) {
|
||||
throw new Error("bad inventory state");
|
||||
}
|
||||
if (request.QueuedDialogues.length != 0 || request.OtherDialogueInfos.length != 0) {
|
||||
logger.error(`saveDialogue request not fully handled: ${String(req.body)}`);
|
||||
}
|
||||
inventory.DialogueHistory.Dialogues ??= [];
|
||||
let dialogue = inventory.DialogueHistory.Dialogues.find(x => x.DialogueName == request.DialogueName);
|
||||
if (!dialogue) {
|
||||
dialogue =
|
||||
inventory.DialogueHistory.Dialogues[
|
||||
inventory.DialogueHistory.Dialogues.push({
|
||||
Rank: 0,
|
||||
Chemistry: 0,
|
||||
AvailableDate: new Date(0),
|
||||
AvailableGiftDate: new Date(0),
|
||||
RankUpExpiry: new Date(0),
|
||||
BountyChemExpiry: new Date(0),
|
||||
Gifts: [],
|
||||
Booleans: [],
|
||||
Completed: [],
|
||||
DialogueName: request.DialogueName
|
||||
}) - 1
|
||||
];
|
||||
}
|
||||
dialogue.Rank = request.Rank;
|
||||
dialogue.Chemistry = request.Chemistry;
|
||||
//dialogue.QueuedDialogues = request.QueuedDialogues;
|
||||
for (const bool of request.Booleans) {
|
||||
dialogue.Booleans.push(bool);
|
||||
}
|
||||
for (const bool of request.ResetBooleans) {
|
||||
const index = dialogue.Booleans.findIndex(x => x == bool);
|
||||
if (index != -1) {
|
||||
dialogue.Booleans.splice(index, 1);
|
||||
}
|
||||
}
|
||||
dialogue.Completed.push(request.Data);
|
||||
const tomorrowAt0Utc = (Math.trunc(Date.now() / (86400 * 1000)) + 1) * 86400 * 1000;
|
||||
dialogue.AvailableDate = new Date(tomorrowAt0Utc);
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: [],
|
||||
AvailableDate: { $date: { $numberLong: tomorrowAt0Utc.toString() } }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
type SaveDialogueRequest = SaveYearIterationRequest | SaveCompletedDialogueRequest;
|
||||
|
||||
interface SaveYearIterationRequest {
|
||||
YearIteration: number;
|
||||
}
|
||||
|
||||
interface SaveCompletedDialogueRequest {
|
||||
DialogueName: string;
|
||||
Rank: number;
|
||||
Chemistry: number;
|
||||
CompletionType: number;
|
||||
QueuedDialogues: string[]; // unsure
|
||||
Booleans: string[];
|
||||
ResetBooleans: string[];
|
||||
Data: ICompletedDialogue;
|
||||
OtherDialogueInfos: string[]; // unsure
|
||||
}
|
@ -47,7 +47,12 @@ import {
|
||||
ICrewShipPilotWeapon,
|
||||
IShipExterior,
|
||||
IHelminthFoodRecord,
|
||||
ICrewShipMembersDatabase
|
||||
ICrewShipMembersDatabase,
|
||||
IDialogueHistoryDatabase,
|
||||
IDialogueDatabase,
|
||||
IDialogueGift,
|
||||
ICompletedDialogue,
|
||||
IDialogueClient
|
||||
} from "../../types/inventoryTypes/inventoryTypes";
|
||||
import { IOid } from "../../types/commonTypes";
|
||||
import {
|
||||
@ -710,6 +715,60 @@ crewShipSchema.set("toJSON", {
|
||||
}
|
||||
});
|
||||
|
||||
const dialogueGiftSchema = new Schema<IDialogueGift>(
|
||||
{
|
||||
Item: String,
|
||||
GiftedQuantity: Number
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const completedDialogueSchema = new Schema<ICompletedDialogue>(
|
||||
{
|
||||
Id: { type: String, required: true },
|
||||
Booleans: { type: [String], required: true },
|
||||
Choices: { type: [Number], required: true }
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const dialogueSchema = new Schema<IDialogueDatabase>(
|
||||
{
|
||||
Rank: Number,
|
||||
Chemistry: Number,
|
||||
AvailableDate: Date,
|
||||
AvailableGiftDate: Date,
|
||||
RankUpExpiry: Date,
|
||||
BountyChemExpiry: Date,
|
||||
//QueuedDialogues: ???
|
||||
Gifts: { type: [dialogueGiftSchema], default: [] },
|
||||
Booleans: { type: [String], default: [] },
|
||||
Completed: { type: [completedDialogueSchema], default: [] },
|
||||
DialogueName: String
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
dialogueSchema.set("toJSON", {
|
||||
virtuals: true,
|
||||
transform(_doc, ret) {
|
||||
const db = ret as IDialogueDatabase;
|
||||
const client = ret as IDialogueClient;
|
||||
|
||||
client.AvailableDate = toMongoDate(db.AvailableDate);
|
||||
client.AvailableGiftDate = toMongoDate(db.AvailableGiftDate);
|
||||
client.RankUpExpiry = toMongoDate(db.RankUpExpiry);
|
||||
client.BountyChemExpiry = toMongoDate(db.BountyChemExpiry);
|
||||
}
|
||||
});
|
||||
|
||||
const dialogueHistorySchema = new Schema<IDialogueHistoryDatabase>(
|
||||
{
|
||||
YearIteration: { type: Number, required: true },
|
||||
Dialogues: { type: [dialogueSchema], required: false }
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
{
|
||||
accountOwnerId: Schema.Types.ObjectId,
|
||||
@ -1069,7 +1128,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
//Grustag three
|
||||
DeathSquadable: Boolean,
|
||||
|
||||
EndlessXP: { type: [endlessXpProgressSchema], default: undefined }
|
||||
EndlessXP: { type: [endlessXpProgressSchema], default: undefined },
|
||||
|
||||
DialogueHistory: dialogueHistorySchema
|
||||
},
|
||||
{ timestamps: { createdAt: "Created" } }
|
||||
);
|
||||
|
@ -52,6 +52,7 @@ import { projectionManagerController } from "../controllers/api/projectionManage
|
||||
import { purchaseController } from "@/src/controllers/api/purchaseController";
|
||||
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
|
||||
import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
|
||||
import { saveDialogueController } from "@/src/controllers/api/saveDialogueController";
|
||||
import { saveLoadoutController } from "@/src/controllers/api/saveLoadout";
|
||||
import { sellController } from "@/src/controllers/api/sellController";
|
||||
import { setActiveQuestController } from "@/src/controllers/api/setActiveQuestController";
|
||||
@ -142,6 +143,7 @@ apiRouter.post("/playerSkills.php", playerSkillsController);
|
||||
apiRouter.post("/projectionManager.php", projectionManagerController);
|
||||
apiRouter.post("/purchase.php", purchaseController);
|
||||
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
|
||||
apiRouter.post("/saveDialogue.php", saveDialogueController);
|
||||
apiRouter.post("/saveLoadout.php", saveLoadoutController);
|
||||
apiRouter.post("/sell.php", sellController);
|
||||
apiRouter.post("/setEquippedInstrument.php", setEquippedInstrumentController);
|
||||
|
@ -306,6 +306,7 @@ export interface IInventoryResponse extends IDailyAffiliations {
|
||||
Harvestable: boolean;
|
||||
DeathSquadable: boolean;
|
||||
EndlessXP?: IEndlessXpProgress[];
|
||||
DialogueHistory?: IDialogueHistoryDatabase;
|
||||
}
|
||||
|
||||
export interface IAffiliation {
|
||||
@ -948,3 +949,46 @@ export interface IEndlessXpProgress {
|
||||
Category: TEndlessXpCategory;
|
||||
Choices: string[];
|
||||
}
|
||||
|
||||
export interface IDialogueHistoryClient {
|
||||
YearIteration: number;
|
||||
Dialogues?: IDialogueClient[];
|
||||
}
|
||||
|
||||
export interface IDialogueHistoryDatabase {
|
||||
YearIteration: number;
|
||||
Dialogues?: IDialogueDatabase[];
|
||||
}
|
||||
|
||||
export interface IDialogueClient {
|
||||
Rank: number;
|
||||
Chemistry: number;
|
||||
AvailableDate: IMongoDate;
|
||||
AvailableGiftDate: IMongoDate;
|
||||
RankUpExpiry: IMongoDate;
|
||||
BountyChemExpiry: IMongoDate;
|
||||
//QueuedDialogues: any[];
|
||||
Gifts: IDialogueGift[];
|
||||
Booleans: string[];
|
||||
Completed: ICompletedDialogue[];
|
||||
DialogueName: string;
|
||||
}
|
||||
|
||||
export interface IDialogueDatabase
|
||||
extends Omit<IDialogueClient, "AvailableDate" | "AvailableGiftDate" | "RankUpExpiry" | "BountyChemExpiry"> {
|
||||
AvailableDate: Date;
|
||||
AvailableGiftDate: Date;
|
||||
RankUpExpiry: Date;
|
||||
BountyChemExpiry: Date;
|
||||
}
|
||||
|
||||
export interface IDialogueGift {
|
||||
Item: string;
|
||||
GiftedQuantity: number;
|
||||
}
|
||||
|
||||
export interface ICompletedDialogue {
|
||||
Id: string;
|
||||
Booleans: string[];
|
||||
Choices: number[];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user
⚠️ Potential issue
Add error handling for JSON parsing and type validation.
The JSON parsing operation could throw an exception if the request body is malformed.
Apply this diff to add error handling:
📝 Committable suggestion