forked from OpenWF/SpaceNinjaServer
feat: Inbox (#876)
This commit is contained in:
parent
cf196430b7
commit
50c280cf01
@ -26,7 +26,9 @@
|
|||||||
"no-case-declarations": "warn",
|
"no-case-declarations": "warn",
|
||||||
"prettier/prettier": "error",
|
"prettier/prettier": "error",
|
||||||
"@typescript-eslint/semi": "error",
|
"@typescript-eslint/semi": "error",
|
||||||
"no-mixed-spaces-and-tabs": "error"
|
"no-mixed-spaces-and-tabs": "error",
|
||||||
|
"require-await": "off",
|
||||||
|
"@typescript-eslint/require-await": "error"
|
||||||
},
|
},
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
|
@ -1,8 +1,83 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import inbox from "@/static/fixed_responses/inbox.json";
|
import { Inbox } from "@/src/models/inboxModel";
|
||||||
|
import {
|
||||||
|
createNewEventMessages,
|
||||||
|
deleteAllMessagesRead,
|
||||||
|
deleteMessageRead,
|
||||||
|
getAllMessagesSorted,
|
||||||
|
getMessage
|
||||||
|
} from "@/src/services/inboxService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { addItems, getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { logger } from "@/src/utils/logger";
|
||||||
|
|
||||||
const inboxController: RequestHandler = (_req, res) => {
|
export const inboxController: RequestHandler = async (req, res) => {
|
||||||
res.json(inbox);
|
const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
|
||||||
|
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
|
||||||
|
if (deleteId) {
|
||||||
|
if (deleteId === "DeleteAllRead") {
|
||||||
|
await deleteAllMessagesRead(accountId);
|
||||||
|
res.status(200).end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await deleteMessageRead(deleteId as string);
|
||||||
|
res.status(200).end();
|
||||||
|
} else if (messageId) {
|
||||||
|
const message = await getMessage(messageId as string);
|
||||||
|
message.r = true;
|
||||||
|
const attachmentItems = message.att;
|
||||||
|
const attachmentCountedItems = message.countedAtt;
|
||||||
|
|
||||||
|
if (!attachmentItems && !attachmentCountedItems) {
|
||||||
|
await message.save();
|
||||||
|
|
||||||
|
res.status(200).end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const inventoryChanges = {};
|
||||||
|
if (attachmentItems) {
|
||||||
|
await addItems(
|
||||||
|
inventory,
|
||||||
|
attachmentItems.map(attItem => ({ ItemType: attItem, ItemCount: 1 })),
|
||||||
|
inventoryChanges
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (attachmentCountedItems) {
|
||||||
|
await addItems(inventory, attachmentCountedItems, inventoryChanges);
|
||||||
|
}
|
||||||
|
await inventory.save();
|
||||||
|
await message.save();
|
||||||
|
|
||||||
|
res.json({ InventoryChanges: inventoryChanges });
|
||||||
|
} else if (latestClientMessageId) {
|
||||||
|
await createNewEventMessages(req);
|
||||||
|
const messages = await Inbox.find({ ownerId: accountId }).sort({ date: 1 });
|
||||||
|
|
||||||
|
const latestClientMessage = messages.find(m => m._id.toString() === latestClientMessageId);
|
||||||
|
|
||||||
|
if (!latestClientMessage) {
|
||||||
|
logger.debug(`this should only happen after DeleteAllRead `);
|
||||||
|
res.json({ Inbox: messages });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newMessages = messages.filter(m => m.date > latestClientMessage.date);
|
||||||
|
|
||||||
|
if (newMessages.length === 0) {
|
||||||
|
res.send("no-new");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({ Inbox: newMessages });
|
||||||
|
} else {
|
||||||
|
//newly created event messages must be newer than account.LatestEventMessageDate
|
||||||
|
await createNewEventMessages(req);
|
||||||
|
const messages = await getAllMessagesSorted(accountId);
|
||||||
|
const inbox = messages.map(m => m.toJSON());
|
||||||
|
res.json({ Inbox: inbox });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { inboxController };
|
|
||||||
|
@ -12,7 +12,7 @@ import { logger } from "@/src/utils/logger";
|
|||||||
export const loginController: RequestHandler = async (request, response) => {
|
export const loginController: RequestHandler = async (request, response) => {
|
||||||
const loginRequest = JSON.parse(String(request.body)) as ILoginRequest; // parse octet stream of json data to json object
|
const loginRequest = JSON.parse(String(request.body)) as ILoginRequest; // parse octet stream of json data to json object
|
||||||
|
|
||||||
const account = await Account.findOne({ email: loginRequest.email }); //{ _id: 0, __v: 0 }
|
const account = await Account.findOne({ email: loginRequest.email });
|
||||||
const nonce = Math.round(Math.random() * Number.MAX_SAFE_INTEGER);
|
const nonce = Math.round(Math.random() * Number.MAX_SAFE_INTEGER);
|
||||||
|
|
||||||
const buildLabel: string =
|
const buildLabel: string =
|
||||||
@ -41,7 +41,8 @@ export const loginController: RequestHandler = async (request, response) => {
|
|||||||
ForceLogoutVersion: 0,
|
ForceLogoutVersion: 0,
|
||||||
ConsentNeeded: false,
|
ConsentNeeded: false,
|
||||||
TrackedSettings: [],
|
TrackedSettings: [],
|
||||||
Nonce: nonce
|
Nonce: nonce,
|
||||||
|
LatestEventMessageDate: new Date(0)
|
||||||
});
|
});
|
||||||
logger.debug("created new account");
|
logger.debug("created new account");
|
||||||
response.json(createLoginResponse(newAccount, buildLabel));
|
response.json(createLoginResponse(newAccount, buildLabel));
|
||||||
|
14
src/controllers/custom/createMessageController.ts
Normal file
14
src/controllers/custom/createMessageController.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { createMessage, IMessageCreationTemplate } from "@/src/services/inboxService";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const createMessageController: RequestHandler = async (req, res) => {
|
||||||
|
const message = req.body as (IMessageCreationTemplate & { ownerId: string })[] | undefined;
|
||||||
|
|
||||||
|
if (!message) {
|
||||||
|
res.status(400).send("No message provided");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const savedMessages = await createMessage(message[0].ownerId, message);
|
||||||
|
|
||||||
|
res.json(savedMessages);
|
||||||
|
};
|
@ -48,7 +48,8 @@ const toDatabaseAccount = (createAccount: IAccountCreation): IDatabaseAccount =>
|
|||||||
CrossPlatformAllowed: true,
|
CrossPlatformAllowed: true,
|
||||||
ForceLogoutVersion: 0,
|
ForceLogoutVersion: 0,
|
||||||
TrackedSettings: [],
|
TrackedSettings: [],
|
||||||
Nonce: 0
|
Nonce: 0,
|
||||||
|
LatestEventMessageDate: new Date(0)
|
||||||
} satisfies IDatabaseAccount;
|
} satisfies IDatabaseAccount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
130
src/models/inboxModel.ts
Normal file
130
src/models/inboxModel.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { model, Schema, Types } from "mongoose";
|
||||||
|
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
|
||||||
|
import { typeCountSchema } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
|
import { IMongoDate, IOid } from "@/src/types/commonTypes";
|
||||||
|
import { ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
|
||||||
|
export interface IMessageClient extends Omit<IMessageDatabase, "_id" | "date" | "startDate" | "endDate" | "ownerId"> {
|
||||||
|
_id?: IOid;
|
||||||
|
date: IMongoDate;
|
||||||
|
startDate?: IMongoDate;
|
||||||
|
endDate?: IMongoDate;
|
||||||
|
messageId: IOid;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMessageDatabase {
|
||||||
|
ownerId: Types.ObjectId;
|
||||||
|
date: Date;
|
||||||
|
_id: Types.ObjectId;
|
||||||
|
sndr: string;
|
||||||
|
msg: string;
|
||||||
|
sub: string;
|
||||||
|
icon: string;
|
||||||
|
highPriority?: boolean;
|
||||||
|
lowPrioNewPlayers?: boolean;
|
||||||
|
startDate?: Date;
|
||||||
|
endDate?: Date;
|
||||||
|
r?: boolean;
|
||||||
|
att?: string[];
|
||||||
|
countedAtt?: ITypeCount[];
|
||||||
|
transmission?: string;
|
||||||
|
arg?: Arg[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Arg {
|
||||||
|
Key: string;
|
||||||
|
Tag: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
//types are wrong
|
||||||
|
// export interface IMessageDatabase {
|
||||||
|
// _id: Types.ObjectId;
|
||||||
|
// messageId: string;
|
||||||
|
// sub: string;
|
||||||
|
// sndr: string;
|
||||||
|
// msg: string;
|
||||||
|
// startDate: Date;
|
||||||
|
// endDate: Date;
|
||||||
|
// date: Date;
|
||||||
|
// contextInfo: string;
|
||||||
|
// icon: string;
|
||||||
|
// att: string[];
|
||||||
|
// modPacks: string[];
|
||||||
|
// countedAtt: string[];
|
||||||
|
// attSpecial: string[];
|
||||||
|
// transmission: string;
|
||||||
|
// ordisReactionTransmission: string;
|
||||||
|
// arg: string[];
|
||||||
|
// r: string;
|
||||||
|
// acceptAction: string;
|
||||||
|
// declineAction: string;
|
||||||
|
// highPriority: boolean;
|
||||||
|
// lowPrioNewPlayers: boolean
|
||||||
|
// gifts: string[];
|
||||||
|
// teleportLoc: string;
|
||||||
|
// RegularCredits: string;
|
||||||
|
// PremiumCredits: string;
|
||||||
|
// PrimeTokens: string;
|
||||||
|
// Coupons: string[];
|
||||||
|
// syndicateAttachment: string[];
|
||||||
|
// tutorialTag: string;
|
||||||
|
// url: string;
|
||||||
|
// urlButtonText: string;
|
||||||
|
// cinematic: string;
|
||||||
|
// requiredLevel: string;
|
||||||
|
// }
|
||||||
|
const messageSchema = new Schema<IMessageDatabase>(
|
||||||
|
{
|
||||||
|
ownerId: Schema.Types.ObjectId,
|
||||||
|
sndr: String,
|
||||||
|
msg: String,
|
||||||
|
sub: String,
|
||||||
|
icon: String,
|
||||||
|
highPriority: Boolean,
|
||||||
|
lowPrioNewPlayers: Boolean,
|
||||||
|
startDate: Date,
|
||||||
|
endDate: Date,
|
||||||
|
r: Boolean,
|
||||||
|
att: { type: [String], default: undefined },
|
||||||
|
countedAtt: { type: [typeCountSchema], default: undefined },
|
||||||
|
transmission: String,
|
||||||
|
arg: {
|
||||||
|
type: [
|
||||||
|
{
|
||||||
|
Key: String,
|
||||||
|
Tag: String,
|
||||||
|
_id: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ timestamps: { createdAt: "date", updatedAt: false }, id: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
messageSchema.virtual("messageId").get(function (this: IMessageDatabase) {
|
||||||
|
return toOid(this._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
messageSchema.set("toJSON", {
|
||||||
|
virtuals: true,
|
||||||
|
transform(_document, returnedObject) {
|
||||||
|
delete returnedObject.ownerId;
|
||||||
|
|
||||||
|
const messageDatabase = returnedObject as IMessageDatabase;
|
||||||
|
const messageClient = returnedObject as IMessageClient;
|
||||||
|
|
||||||
|
delete returnedObject._id;
|
||||||
|
delete returnedObject.__v;
|
||||||
|
|
||||||
|
messageClient.date = toMongoDate(messageDatabase.date);
|
||||||
|
|
||||||
|
if (messageDatabase.startDate && messageDatabase.endDate) {
|
||||||
|
messageClient.startDate = toMongoDate(messageDatabase.startDate);
|
||||||
|
|
||||||
|
messageClient.endDate = toMongoDate(messageDatabase.endDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const Inbox = model<IMessageDatabase>("Inbox", messageSchema, "inbox");
|
@ -1,4 +1,4 @@
|
|||||||
import { Document, Model, Schema, Types, model } from "mongoose";
|
import { Document, HydratedDocument, Model, Schema, Types, model } from "mongoose";
|
||||||
import {
|
import {
|
||||||
IFlavourItem,
|
IFlavourItem,
|
||||||
IRawUpgrade,
|
IRawUpgrade,
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
IBooster,
|
IBooster,
|
||||||
IInventoryClient,
|
IInventoryClient,
|
||||||
ISlots,
|
ISlots,
|
||||||
IMailbox,
|
IMailboxDatabase,
|
||||||
IDuviriInfo,
|
IDuviriInfo,
|
||||||
IPendingRecipe as IPendingRecipeDatabase,
|
IPendingRecipe as IPendingRecipeDatabase,
|
||||||
IPendingRecipeResponse,
|
IPendingRecipeResponse,
|
||||||
@ -53,6 +53,7 @@ import {
|
|||||||
IUpgradeDatabase,
|
IUpgradeDatabase,
|
||||||
ICrewShipMemberDatabase,
|
ICrewShipMemberDatabase,
|
||||||
ICrewShipMemberClient,
|
ICrewShipMemberClient,
|
||||||
|
IMailboxClient,
|
||||||
TEquipmentKey,
|
TEquipmentKey,
|
||||||
equipmentKeys,
|
equipmentKeys,
|
||||||
IKubrowPetDetailsDatabase,
|
IKubrowPetDetailsDatabase,
|
||||||
@ -298,22 +299,18 @@ FlavourItemSchema.set("toJSON", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// "Mailbox": { "LastInboxId": { "$oid": "123456780000000000000000" } }
|
const MailboxSchema = new Schema<IMailboxDatabase>(
|
||||||
const MailboxSchema = new Schema<IMailbox>(
|
|
||||||
{
|
{
|
||||||
LastInboxId: {
|
LastInboxId: Schema.Types.ObjectId
|
||||||
type: Schema.Types.ObjectId,
|
|
||||||
set: (v: IMailbox["LastInboxId"]): string => v.$oid.toString()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{ id: false, _id: false }
|
{ id: false, _id: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
MailboxSchema.set("toJSON", {
|
MailboxSchema.set("toJSON", {
|
||||||
transform(_document, returnedObject) {
|
transform(_document, returnedObject) {
|
||||||
delete returnedObject.__v;
|
const mailboxDatabase = returnedObject as HydratedDocument<IMailboxDatabase, { __v?: number }>;
|
||||||
//TODO: there is a lot of any here
|
delete mailboxDatabase.__v;
|
||||||
returnedObject.LastInboxId = toOid(returnedObject.LastInboxId as Types.ObjectId);
|
(returnedObject as IMailboxClient).LastInboxId = toOid(mailboxDatabase.LastInboxId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6,20 +6,6 @@ const opts = {
|
|||||||
toObject: { virtuals: true }
|
toObject: { virtuals: true }
|
||||||
} satisfies SchemaOptions;
|
} satisfies SchemaOptions;
|
||||||
|
|
||||||
// {
|
|
||||||
// toJSON: { virtuals: true }
|
|
||||||
// }
|
|
||||||
// {
|
|
||||||
// virtuals: {
|
|
||||||
// id: {
|
|
||||||
// get() {
|
|
||||||
// return "test";
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// toJSON: { virtuals: true }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
|
const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
|
||||||
{
|
{
|
||||||
email: { type: String, required: true, unique: true },
|
email: { type: String, required: true, unique: true },
|
||||||
@ -34,14 +20,14 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
|
|||||||
ConsentNeeded: { type: Boolean, required: true },
|
ConsentNeeded: { type: Boolean, required: true },
|
||||||
TrackedSettings: { type: [String], default: [] },
|
TrackedSettings: { type: [String], default: [] },
|
||||||
Nonce: { type: Number, default: 0 },
|
Nonce: { type: Number, default: 0 },
|
||||||
LastLoginDay: { type: Number }
|
LastLoginDay: { type: Number },
|
||||||
|
LatestEventMessageDate: { type: Date, required: true }
|
||||||
},
|
},
|
||||||
opts
|
opts
|
||||||
);
|
);
|
||||||
|
|
||||||
databaseAccountSchema.set("toJSON", {
|
databaseAccountSchema.set("toJSON", {
|
||||||
transform(_document, returnedObject) {
|
transform(_document, returnedObject) {
|
||||||
//returnedObject.id = returnedObject._id.toString();
|
|
||||||
delete returnedObject._id;
|
delete returnedObject._id;
|
||||||
delete returnedObject.__v;
|
delete returnedObject.__v;
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,7 @@ import { importController } from "@/src/controllers/custom/importController";
|
|||||||
|
|
||||||
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
||||||
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
||||||
|
import { createMessageController } from "@/src/controllers/custom/createMessageController";
|
||||||
|
|
||||||
const customRouter = express.Router();
|
const customRouter = express.Router();
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ customRouter.get("/deleteAccount", deleteAccountController);
|
|||||||
customRouter.get("/renameAccount", renameAccountController);
|
customRouter.get("/renameAccount", renameAccountController);
|
||||||
|
|
||||||
customRouter.post("/createAccount", createAccountController);
|
customRouter.post("/createAccount", createAccountController);
|
||||||
|
customRouter.post("/createMessage", createMessageController);
|
||||||
customRouter.post("/addItems", addItemsController);
|
customRouter.post("/addItems", addItemsController);
|
||||||
customRouter.post("/addXp", addXpController);
|
customRouter.post("/addXp", addXpController);
|
||||||
customRouter.post("/import", importController);
|
customRouter.post("/import", importController);
|
||||||
|
66
src/services/inboxService.ts
Normal file
66
src/services/inboxService.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { IMessageDatabase, Inbox } from "@/src/models/inboxModel";
|
||||||
|
import { getAccountForRequest } from "@/src/services/loginService";
|
||||||
|
import { HydratedDocument } from "mongoose";
|
||||||
|
import { Request } from "express";
|
||||||
|
import messages from "@/static/fixed_responses/messages.json";
|
||||||
|
import { logger } from "@/src/utils/logger";
|
||||||
|
|
||||||
|
export const getAllMessagesSorted = async (accountId: string): Promise<HydratedDocument<IMessageDatabase>[]> => {
|
||||||
|
const inbox = await Inbox.find({ ownerId: accountId }).sort({ date: -1 });
|
||||||
|
return inbox;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMessage = async (messageId: string): Promise<HydratedDocument<IMessageDatabase>> => {
|
||||||
|
const message = await Inbox.findOne({ _id: messageId });
|
||||||
|
|
||||||
|
if (!message) {
|
||||||
|
throw new Error(`Message not found ${messageId}`);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteMessageRead = async (messageId: string): Promise<void> => {
|
||||||
|
await Inbox.findOneAndDelete({ _id: messageId, r: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteAllMessagesRead = async (accountId: string): Promise<void> => {
|
||||||
|
await Inbox.deleteMany({ ownerId: accountId, r: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createNewEventMessages = async (req: Request) => {
|
||||||
|
const account = await getAccountForRequest(req);
|
||||||
|
const latestEventMessageDate = account.LatestEventMessageDate;
|
||||||
|
|
||||||
|
//TODO: is baroo there? create these kind of messages too (periodical messages)
|
||||||
|
const newEventMessages = messages.Messages.filter(m => new Date(m.eventMessageDate) > latestEventMessageDate);
|
||||||
|
|
||||||
|
if (newEventMessages.length === 0) {
|
||||||
|
logger.debug(`No new event messages. Latest event message date: ${latestEventMessageDate.toISOString()}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const savedEventMessages = await createMessage(account._id.toString(), newEventMessages);
|
||||||
|
logger.debug("created event messages", savedEventMessages);
|
||||||
|
|
||||||
|
const latestEventMessage = newEventMessages.reduce((prev, current) =>
|
||||||
|
prev.eventMessageDate > current.eventMessageDate ? prev : current
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("latestEventMessage", latestEventMessage);
|
||||||
|
account.LatestEventMessageDate = new Date(latestEventMessage.eventMessageDate);
|
||||||
|
await account.save();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createMessage = async (accountId: string, messages: IMessageCreationTemplate[]) => {
|
||||||
|
const ownerIdMessages = messages.map(m => ({
|
||||||
|
...m,
|
||||||
|
ownerId: accountId
|
||||||
|
}));
|
||||||
|
|
||||||
|
const savedMessages = await Inbox.insertMany(ownerIdMessages);
|
||||||
|
return savedMessages;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IMessageCreationTemplate extends Omit<IMessageDatabase, "_id" | "date" | "ownerId"> {
|
||||||
|
ownerId?: string;
|
||||||
|
}
|
@ -474,6 +474,18 @@ export const addItem = async (
|
|||||||
throw new Error(errorMessage);
|
throw new Error(errorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addItems = async (
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
items: ITypeCount[],
|
||||||
|
inventoryChanges: IInventoryChanges = {}
|
||||||
|
): Promise<IInventoryChanges> => {
|
||||||
|
for (const item of items) {
|
||||||
|
const inventoryDelta = await addItem(inventory, item.ItemType, item.ItemCount);
|
||||||
|
combineInventoryChanges(inventoryChanges, inventoryDelta.InventoryChanges);
|
||||||
|
}
|
||||||
|
return inventoryChanges;
|
||||||
|
};
|
||||||
|
|
||||||
//TODO: maybe genericMethod for all the add methods, they share a lot of logic
|
//TODO: maybe genericMethod for all the add methods, they share a lot of logic
|
||||||
export const addSentinel = (
|
export const addSentinel = (
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
@ -37,10 +37,10 @@ export interface IInventoryDatabase
|
|||||||
> {
|
> {
|
||||||
accountOwnerId: Types.ObjectId;
|
accountOwnerId: Types.ObjectId;
|
||||||
Created: Date;
|
Created: Date;
|
||||||
TrainingDate: Date; // TrainingDate changed from IMongoDate to Date
|
TrainingDate: Date;
|
||||||
LoadOutPresets: Types.ObjectId; // LoadOutPresets changed from ILoadOutPresets to Types.ObjectId for population
|
LoadOutPresets: Types.ObjectId; // LoadOutPresets changed from ILoadOutPresets to Types.ObjectId for population
|
||||||
Mailbox: Types.ObjectId; // Mailbox changed from IMailbox to Types.ObjectId
|
Mailbox?: IMailboxDatabase;
|
||||||
GuildId?: Types.ObjectId; // GuildId changed from ?IOid to ?Types.ObjectId
|
GuildId?: Types.ObjectId;
|
||||||
PendingRecipes: IPendingRecipe[];
|
PendingRecipes: IPendingRecipe[];
|
||||||
QuestKeys: IQuestKeyDatabase[];
|
QuestKeys: IQuestKeyDatabase[];
|
||||||
BlessingCooldown: Date;
|
BlessingCooldown: Date;
|
||||||
@ -127,10 +127,14 @@ export interface IDuviriInfo {
|
|||||||
NumCompletions: number;
|
NumCompletions: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMailbox {
|
export interface IMailboxClient {
|
||||||
LastInboxId: IOid;
|
LastInboxId: IOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IMailboxDatabase {
|
||||||
|
LastInboxId: Types.ObjectId;
|
||||||
|
}
|
||||||
|
|
||||||
export type TSolarMapRegion =
|
export type TSolarMapRegion =
|
||||||
| "Earth"
|
| "Earth"
|
||||||
| "Ceres"
|
| "Ceres"
|
||||||
@ -202,7 +206,7 @@ export interface IInventoryClient extends IDailyAffiliations {
|
|||||||
KahlLoadOuts: IOperatorConfigClient[];
|
KahlLoadOuts: IOperatorConfigClient[];
|
||||||
|
|
||||||
DuviriInfo: IDuviriInfo;
|
DuviriInfo: IDuviriInfo;
|
||||||
Mailbox: IMailbox;
|
Mailbox?: IMailboxClient;
|
||||||
SubscribedToEmails: number;
|
SubscribedToEmails: number;
|
||||||
Created: IMongoDate;
|
Created: IMongoDate;
|
||||||
RewardSeed: number;
|
RewardSeed: number;
|
||||||
@ -238,7 +242,7 @@ export interface IInventoryClient extends IDailyAffiliations {
|
|||||||
ActiveQuest: string;
|
ActiveQuest: string;
|
||||||
FlavourItems: IFlavourItem[];
|
FlavourItems: IFlavourItem[];
|
||||||
LoadOutPresets: ILoadOutPresets;
|
LoadOutPresets: ILoadOutPresets;
|
||||||
CurrentLoadOutIds: IOid[]; // we store it in the database using this representation as well :/
|
CurrentLoadOutIds: IOid[]; //TODO: we store it in the database using this representation as well :/
|
||||||
Missions: IMission[];
|
Missions: IMission[];
|
||||||
RandomUpgradesIdentified?: number;
|
RandomUpgradesIdentified?: number;
|
||||||
LastRegionPlayed: TSolarMapRegion;
|
LastRegionPlayed: TSolarMapRegion;
|
||||||
|
@ -11,6 +11,29 @@ export interface IAccountAndLoginResponseCommons {
|
|||||||
Nonce: number;
|
Nonce: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IDatabaseAccount extends IAccountAndLoginResponseCommons {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
LastLoginDay?: number;
|
||||||
|
LatestEventMessageDate: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Includes virtual ID
|
||||||
|
export interface IDatabaseAccountJson extends IDatabaseAccount {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILoginRequest {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
time: number;
|
||||||
|
s: string;
|
||||||
|
lang: string;
|
||||||
|
date: number;
|
||||||
|
ClientType: string;
|
||||||
|
PS: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ILoginResponse extends IAccountAndLoginResponseCommons {
|
export interface ILoginResponse extends IAccountAndLoginResponseCommons {
|
||||||
id: string;
|
id: string;
|
||||||
Groups: IGroup[];
|
Groups: IGroup[];
|
||||||
@ -23,29 +46,7 @@ export interface ILoginResponse extends IAccountAndLoginResponseCommons {
|
|||||||
HUB: string;
|
HUB: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Includes virtual ID
|
|
||||||
export interface IDatabaseAccountJson extends IDatabaseAccount {
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IGroup {
|
export interface IGroup {
|
||||||
experiment: string;
|
experiment: string;
|
||||||
experimentGroup: string;
|
experimentGroup: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDatabaseAccount extends IAccountAndLoginResponseCommons {
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
LastLoginDay?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ILoginRequest {
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
time: number;
|
|
||||||
s: string;
|
|
||||||
lang: string;
|
|
||||||
date: number;
|
|
||||||
ClientType: string;
|
|
||||||
PS: string;
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
{
|
{
|
||||||
"Inbox": [
|
"Messages": [
|
||||||
|
{
|
||||||
|
"sub": "Welcome to Space Ninja Server",
|
||||||
|
"sndr": "/Lotus/Language/Bosses/Ordis",
|
||||||
|
"msg": "Enjoy your Space Ninja Experience",
|
||||||
|
"icon": "/Lotus/Interface/Icons/Npcs/Darvo.png",
|
||||||
|
"eventMessageDate": "2025-01-30T13:00:00.000Z",
|
||||||
|
"r": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"sub": "/Lotus/Language/Inbox/DarvoWeaponCraftingMessageBTitle",
|
"sub": "/Lotus/Language/Inbox/DarvoWeaponCraftingMessageBTitle",
|
||||||
"sndr": "/Lotus/Language/Bosses/Darvo",
|
"sndr": "/Lotus/Language/Bosses/Darvo",
|
||||||
@ -24,9 +32,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"highPriority": true,
|
"highPriority": true,
|
||||||
"messageId": "66d651800000000000000000",
|
"eventMessageDate": "2023-10-01T17:00:00.000Z",
|
||||||
"date": { "$date": { "$numberLong": "1725321600000" } },
|
"r": false
|
||||||
"r": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sub": "/Lotus/Language/G1Quests/Beginner_Growth_Inbox_Title",
|
"sub": "/Lotus/Language/G1Quests/Beginner_Growth_Inbox_Title",
|
||||||
@ -35,9 +42,8 @@
|
|||||||
"icon": "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
"icon": "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
"transmission": "/Lotus/Sounds/Dialog/VorsPrize/DLisetPostAssassinate110Lotus",
|
"transmission": "/Lotus/Sounds/Dialog/VorsPrize/DLisetPostAssassinate110Lotus",
|
||||||
"highPriority": true,
|
"highPriority": true,
|
||||||
"messageId": "66d651810000000000000000",
|
"eventMessageDate": "2023-09-01T17:00:00.000Z",
|
||||||
"date": { "$date": { "$numberLong": "1725321601000" } },
|
"r": false
|
||||||
"r": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user