testing inbox
This commit is contained in:
		
							parent
							
								
									57061073be
								
							
						
					
					
						commit
						506aae1ed6
					
				@ -26,7 +26,10 @@
 | 
				
			|||||||
        "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",
 | 
				
			||||||
 | 
					        "@typescript-eslint/return-await": "error"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "parser": "@typescript-eslint/parser",
 | 
					    "parser": "@typescript-eslint/parser",
 | 
				
			||||||
    "parserOptions": {
 | 
					    "parserOptions": {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,76 @@
 | 
				
			|||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
import inbox from "@/static/fixed_responses/inbox.json";
 | 
					import { Inbox } from "@/src/models/inboxModel";
 | 
				
			||||||
 | 
					import { createNewEventMessages, 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 Inbox.deleteMany({ ownerId: accountId, r: true });
 | 
				
			||||||
 | 
					            res.status(200).end();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await Inbox.findOneAndDelete({ _id: deleteId, r: true });
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					        res.json({ Inbox: messages });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
export { inboxController };
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -252,6 +252,8 @@ export const inventoryController: RequestHandler = async (request, response) =>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    inventoryResponse.LastInventorySync = toOid(new Types.ObjectId());
 | 
					    inventoryResponse.LastInventorySync = toOid(new Types.ObjectId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inventoryResponse.Mailbox = { LastInboxId: { $oid: "679be1b66e1affa6d05e75d7" } };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    response.json(inventoryResponse);
 | 
					    response.json(inventoryResponse);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										127
									
								
								src/models/inboxModel.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/models/inboxModel.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,127 @@
 | 
				
			|||||||
 | 
					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: [String],
 | 
				
			||||||
 | 
					        countedAtt: [typeCountSchema],
 | 
				
			||||||
 | 
					        transmission: String,
 | 
				
			||||||
 | 
					        arg: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Key: String,
 | 
				
			||||||
 | 
					                Tag: String,
 | 
				
			||||||
 | 
					                _id: false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    { 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");
 | 
				
			||||||
@ -7,7 +7,7 @@ import {
 | 
				
			|||||||
    IBooster,
 | 
					    IBooster,
 | 
				
			||||||
    IInventoryClient,
 | 
					    IInventoryClient,
 | 
				
			||||||
    ISlots,
 | 
					    ISlots,
 | 
				
			||||||
    IMailbox,
 | 
					    IMailboxDatabase,
 | 
				
			||||||
    IDuviriInfo,
 | 
					    IDuviriInfo,
 | 
				
			||||||
    IPendingRecipe as IPendingRecipeDatabase,
 | 
					    IPendingRecipe as IPendingRecipeDatabase,
 | 
				
			||||||
    IPendingRecipeResponse,
 | 
					    IPendingRecipeResponse,
 | 
				
			||||||
@ -53,7 +53,8 @@ import {
 | 
				
			|||||||
    IUpgradeDatabase,
 | 
					    IUpgradeDatabase,
 | 
				
			||||||
    ICrewShipDatabase,
 | 
					    ICrewShipDatabase,
 | 
				
			||||||
    ICrewShipMemberDatabase,
 | 
					    ICrewShipMemberDatabase,
 | 
				
			||||||
    ICrewShipMemberClient
 | 
					    ICrewShipMemberClient,
 | 
				
			||||||
 | 
					    IMailboxClient
 | 
				
			||||||
} from "../../types/inventoryTypes/inventoryTypes";
 | 
					} from "../../types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
import { IOid } from "../../types/commonTypes";
 | 
					import { IOid } from "../../types/commonTypes";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -343,13 +344,9 @@ 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 }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
@ -357,8 +354,7 @@ const MailboxSchema = new Schema<IMailbox>(
 | 
				
			|||||||
MailboxSchema.set("toJSON", {
 | 
					MailboxSchema.set("toJSON", {
 | 
				
			||||||
    transform(_document, returnedObject) {
 | 
					    transform(_document, returnedObject) {
 | 
				
			||||||
        delete returnedObject.__v;
 | 
					        delete returnedObject.__v;
 | 
				
			||||||
        //TODO: there is a lot of any here
 | 
					        (returnedObject as IMailboxClient).LastInboxId = toOid(returnedObject.LastInboxId);
 | 
				
			||||||
        returnedObject.LastInboxId = toOid(returnedObject.LastInboxId as Types.ObjectId);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										72
									
								
								src/services/inboxService.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/services/inboxService.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					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 { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getAllMessagesSorted = async (accountId: string): Promise<IMessageDatabase[]> => {
 | 
				
			||||||
 | 
					    const inbox = await Inbox.find({ ownerId: accountId }).sort({ date: -1 });
 | 
				
			||||||
 | 
					    return inbox.map(message => message.toJSON());
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 deleteMessage = async (messageId: string): Promise<void> => {
 | 
				
			||||||
 | 
					    await Inbox.findOneAndDelete({ _id: messageId });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const deleteAllMessages = 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? send message
 | 
				
			||||||
 | 
					    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 newEventMessagesSorted = newEventMessages.sort(
 | 
				
			||||||
 | 
					        (a, b) => new Date(a.eventMessageDate).getTime() - new Date(b.eventMessageDate).getTime()
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    const savedEventMessages = await createMessage(account._id.toString(), newEventMessages);
 | 
				
			||||||
 | 
					    logger.debug("created event messages", savedEventMessages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const latestEventMessage = savedEventMessages.reduce((prev, current) =>
 | 
				
			||||||
 | 
					        prev.date > current.date ? prev : current
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    account.LatestEventMessageDate = latestEventMessage.date;
 | 
				
			||||||
 | 
					    await account.save();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const createMessage = async (accountId: string, message: IMessageCreationTemplate[]) => {
 | 
				
			||||||
 | 
					    //TODO: createmany
 | 
				
			||||||
 | 
					    const savedMessages = [];
 | 
				
			||||||
 | 
					    for (const msg of message) {
 | 
				
			||||||
 | 
					        const savedMessage = await Inbox.create({
 | 
				
			||||||
 | 
					            ...msg,
 | 
				
			||||||
 | 
					            ownerId: accountId
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        savedMessages.push(savedMessage);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return savedMessages;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IMessageCreationTemplate extends Omit<IMessageDatabase, "_id" | "date" | "ownerId"> {
 | 
				
			||||||
 | 
					    ownerId?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -470,6 +470,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;
 | 
				
			||||||
@ -107,10 +107,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"
 | 
				
			||||||
@ -172,7 +176,7 @@ export interface IInventoryClient extends IDailyAffiliations {
 | 
				
			|||||||
    DrifterMelee: IEquipmentDatabase[];
 | 
					    DrifterMelee: IEquipmentDatabase[];
 | 
				
			||||||
    DrifterGuns: IEquipmentDatabase[];
 | 
					    DrifterGuns: IEquipmentDatabase[];
 | 
				
			||||||
    DuviriInfo: IDuviriInfo;
 | 
					    DuviriInfo: IDuviriInfo;
 | 
				
			||||||
    Mailbox: IMailbox;
 | 
					    Mailbox?: IMailboxClient;
 | 
				
			||||||
    KahlLoadOuts: IEquipmentDatabase[];
 | 
					    KahlLoadOuts: IEquipmentDatabase[];
 | 
				
			||||||
    SubscribedToEmails: number;
 | 
					    SubscribedToEmails: number;
 | 
				
			||||||
    Created: IMongoDate;
 | 
					    Created: IMongoDate;
 | 
				
			||||||
@ -210,7 +214,7 @@ export interface IInventoryClient extends IDailyAffiliations {
 | 
				
			|||||||
    FlavourItems: IFlavourItem[];
 | 
					    FlavourItems: IFlavourItem[];
 | 
				
			||||||
    Scoops: IEquipmentDatabase[];
 | 
					    Scoops: IEquipmentDatabase[];
 | 
				
			||||||
    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