feat: gifting #1344
							
								
								
									
										92
									
								
								src/controllers/api/giftingController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/controllers/api/giftingController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
 | 
					import { Account } from "@/src/models/loginModel";
 | 
				
			||||||
 | 
					import { createMessage } from "@/src/services/inboxService";
 | 
				
			||||||
 | 
					import { getInventory, updateCurrency } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
 | 
				
			||||||
 | 
					import { IOid } from "@/src/types/commonTypes";
 | 
				
			||||||
 | 
					import { IPurchaseParams } from "@/src/types/purchaseTypes";
 | 
				
			||||||
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					import { ExportFlavour } from "warframe-public-export-plus";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const giftingController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const data = getJSONfromString<IGiftingRequest>(String(req.body));
 | 
				
			||||||
 | 
					    if (data.PurchaseParams.Source != 0 || !data.PurchaseParams.UsePremium) {
 | 
				
			||||||
 | 
					        throw new Error(`unexpected purchase params in gifting request: ${String(req.body)}`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const account = await Account.findOne(
 | 
				
			||||||
 | 
					        data.RecipientId ? { _id: data.RecipientId.$oid } : { DisplayName: data.Recipient }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    if (!account) {
 | 
				
			||||||
 | 
					        res.status(400).send("9").end();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const inventory = await getInventory(account._id.toString(), "Suits");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Cannot gift items to players that have not completed the tutorial.
 | 
				
			||||||
 | 
					    if (inventory.Suits.length == 0) {
 | 
				
			||||||
 | 
					        res.status(400).send("14").end();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Cannot gift to players who have gifting disabled.
 | 
				
			||||||
 | 
					    // TODO: Also consider GIFT_MODE_FRIENDS once friends are implemented
 | 
				
			||||||
 | 
					    if (inventory.Settings?.GiftMode == "GIFT_MODE_NONE") {
 | 
				
			||||||
 | 
					        res.status(400).send("17").end();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: Cannot gift items with mastery requirement to players who are too low level. (Code 2)
 | 
				
			||||||
 | 
					    // TODO: Cannot gift archwing items to players that have not completed the archwing quest. (Code 7)
 | 
				
			||||||
 | 
					    // TODO: Cannot gift necramechs to players that have not completed heart of deimos. (Code 20)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const senderAccount = await getAccountForRequest(req);
 | 
				
			||||||
 | 
					    const senderInventory = await getInventory(
 | 
				
			||||||
 | 
					        senderAccount._id.toString(),
 | 
				
			||||||
 | 
					        "PremiumCredits PremiumCreditsFree ActiveAvatarImageType GiftsRemaining"
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (senderInventory.GiftsRemaining == 0) {
 | 
				
			||||||
 | 
					        res.status(400).send("10").end();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    senderInventory.GiftsRemaining -= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    updateCurrency(senderInventory, data.PurchaseParams.ExpectedPrice, true);
 | 
				
			||||||
 | 
					    await senderInventory.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const senderName = getSuffixedName(senderAccount);
 | 
				
			||||||
 | 
					    await createMessage(account._id.toString(), [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sndr: senderName,
 | 
				
			||||||
 | 
					            msg: data.Message || "/Lotus/Language/Menu/GiftReceivedBody_NoCustomMessage",
 | 
				
			||||||
 | 
					            arg: [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Key: "GIFTER_NAME",
 | 
				
			||||||
 | 
					                    Tag: senderName
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Key: "GIFT_QUANTITY",
 | 
				
			||||||
 | 
					                    Tag: data.PurchaseParams.Quantity
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            sub: "/Lotus/Language/Menu/GiftReceivedSubject",
 | 
				
			||||||
 | 
					            icon: ExportFlavour[senderInventory.ActiveAvatarImageType].icon,
 | 
				
			||||||
 | 
					            gifts: [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    GiftType: data.PurchaseParams.StoreItem
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    res.end();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IGiftingRequest {
 | 
				
			||||||
 | 
					    PurchaseParams: IPurchaseParams;
 | 
				
			||||||
 | 
					    Message?: string;
 | 
				
			||||||
 | 
					    Recipient?: string;
 | 
				
			||||||
 | 
					    RecipientId?: IOid;
 | 
				
			||||||
 | 
					    buildLabel: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -8,9 +8,10 @@ import {
 | 
				
			|||||||
    getMessage
 | 
					    getMessage
 | 
				
			||||||
} from "@/src/services/inboxService";
 | 
					} from "@/src/services/inboxService";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { addItems, getInventory } from "@/src/services/inventoryService";
 | 
					import { addItems, combineInventoryChanges, getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { ExportGear } from "warframe-public-export-plus";
 | 
					import { ExportGear } from "warframe-public-export-plus";
 | 
				
			||||||
 | 
					import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const inboxController: RequestHandler = async (req, res) => {
 | 
					export const inboxController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
 | 
					    const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
 | 
				
			||||||
@ -29,12 +30,12 @@ export const inboxController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
    } else if (messageId) {
 | 
					    } else if (messageId) {
 | 
				
			||||||
        const message = await getMessage(messageId as string);
 | 
					        const message = await getMessage(messageId as string);
 | 
				
			||||||
        message.r = true;
 | 
					        message.r = true;
 | 
				
			||||||
 | 
					        await message.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const attachmentItems = message.att;
 | 
					        const attachmentItems = message.att;
 | 
				
			||||||
        const attachmentCountedItems = message.countedAtt;
 | 
					        const attachmentCountedItems = message.countedAtt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!attachmentItems && !attachmentCountedItems) {
 | 
					        if (!attachmentItems && !attachmentCountedItems && !message.gifts) {
 | 
				
			||||||
            await message.save();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            res.status(200).end();
 | 
					            res.status(200).end();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -54,9 +55,21 @@ export const inboxController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        if (attachmentCountedItems) {
 | 
					        if (attachmentCountedItems) {
 | 
				
			||||||
            await addItems(inventory, attachmentCountedItems, inventoryChanges);
 | 
					            await addItems(inventory, attachmentCountedItems, inventoryChanges);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (message.gifts) {
 | 
				
			||||||
 | 
					            for (const gift of message.gifts) {
 | 
				
			||||||
 | 
					                combineInventoryChanges(
 | 
				
			||||||
 | 
					                    inventoryChanges,
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        await handleStoreItemAcquisition(
 | 
				
			||||||
 | 
					                            gift.GiftType,
 | 
				
			||||||
 | 
					                            inventory,
 | 
				
			||||||
 | 
					                            message.arg!.find(x => x.Key == "GIFT_QUANTITY")!.Tag as number
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    ).InventoryChanges
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        await inventory.save();
 | 
					        await inventory.save();
 | 
				
			||||||
        await message.save();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        res.json({ InventoryChanges: inventoryChanges });
 | 
					        res.json({ InventoryChanges: inventoryChanges });
 | 
				
			||||||
    } else if (latestClientMessageId) {
 | 
					    } else if (latestClientMessageId) {
 | 
				
			||||||
        await createNewEventMessages(req);
 | 
					        await createNewEventMessages(req);
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@ export const inventoryController: RequestHandler = async (request, response) =>
 | 
				
			|||||||
            inventory[key] = 16000 + inventory.PlayerLevel * 500;
 | 
					            inventory[key] = 16000 + inventory.PlayerLevel * 500;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        inventory.DailyFocus = 250000 + inventory.PlayerLevel * 5000;
 | 
					        inventory.DailyFocus = 250000 + inventory.PlayerLevel * 5000;
 | 
				
			||||||
 | 
					        inventory.GiftsRemaining = Math.max(8, inventory.PlayerLevel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask();
 | 
					        inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,6 +31,7 @@ export interface IMessage {
 | 
				
			|||||||
    countedAtt?: ITypeCount[];
 | 
					    countedAtt?: ITypeCount[];
 | 
				
			||||||
    transmission?: string;
 | 
					    transmission?: string;
 | 
				
			||||||
    arg?: Arg[];
 | 
					    arg?: Arg[];
 | 
				
			||||||
 | 
					    gifts?: IGift[];
 | 
				
			||||||
    r?: boolean;
 | 
					    r?: boolean;
 | 
				
			||||||
    contextInfo?: string;
 | 
					    contextInfo?: string;
 | 
				
			||||||
    acceptAction?: string;
 | 
					    acceptAction?: string;
 | 
				
			||||||
@ -43,6 +44,10 @@ export interface Arg {
 | 
				
			|||||||
    Tag: string | number;
 | 
					    Tag: string | number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IGift {
 | 
				
			||||||
 | 
					    GiftType: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//types are wrong
 | 
					//types are wrong
 | 
				
			||||||
// export interface IMessageDatabase {
 | 
					// export interface IMessageDatabase {
 | 
				
			||||||
//     _id: Types.ObjectId;
 | 
					//     _id: Types.ObjectId;
 | 
				
			||||||
@ -80,6 +85,14 @@ export interface Arg {
 | 
				
			|||||||
//     cinematic: string;
 | 
					//     cinematic: string;
 | 
				
			||||||
//     requiredLevel: string;
 | 
					//     requiredLevel: string;
 | 
				
			||||||
// }
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const giftSchema = new Schema<IGift>(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        GiftType: String
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    { _id: false }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messageSchema = new Schema<IMessageDatabase>(
 | 
					const messageSchema = new Schema<IMessageDatabase>(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ownerId: Schema.Types.ObjectId,
 | 
					        ownerId: Schema.Types.ObjectId,
 | 
				
			||||||
@ -93,6 +106,7 @@ const messageSchema = new Schema<IMessageDatabase>(
 | 
				
			|||||||
        endDate: Date,
 | 
					        endDate: Date,
 | 
				
			||||||
        r: Boolean,
 | 
					        r: Boolean,
 | 
				
			||||||
        att: { type: [String], default: undefined },
 | 
					        att: { type: [String], default: undefined },
 | 
				
			||||||
 | 
					        gifts: { type: [giftSchema], default: undefined },
 | 
				
			||||||
        countedAtt: { type: [typeCountSchema], default: undefined },
 | 
					        countedAtt: { type: [typeCountSchema], default: undefined },
 | 
				
			||||||
        transmission: String,
 | 
					        transmission: String,
 | 
				
			||||||
        arg: {
 | 
					        arg: {
 | 
				
			||||||
 | 
				
			|||||||
@ -51,6 +51,7 @@ import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSe
 | 
				
			|||||||
import { getShipController } from "@/src/controllers/api/getShipController";
 | 
					import { getShipController } from "@/src/controllers/api/getShipController";
 | 
				
			||||||
import { getVendorInfoController } from "@/src/controllers/api/getVendorInfoController";
 | 
					import { getVendorInfoController } from "@/src/controllers/api/getVendorInfoController";
 | 
				
			||||||
import { getVoidProjectionRewardsController } from "@/src/controllers/api/getVoidProjectionRewardsController";
 | 
					import { getVoidProjectionRewardsController } from "@/src/controllers/api/getVoidProjectionRewardsController";
 | 
				
			||||||
 | 
					import { giftingController } from "@/src/controllers/api/giftingController";
 | 
				
			||||||
import { gildWeaponController } from "@/src/controllers/api/gildWeaponController";
 | 
					import { gildWeaponController } from "@/src/controllers/api/gildWeaponController";
 | 
				
			||||||
import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
 | 
					import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
 | 
				
			||||||
import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController";
 | 
					import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController";
 | 
				
			||||||
@ -203,6 +204,7 @@ apiRouter.post("/getAlliance.php", getAllianceController);
 | 
				
			|||||||
apiRouter.post("/getFriends.php", getFriendsController);
 | 
					apiRouter.post("/getFriends.php", getFriendsController);
 | 
				
			||||||
apiRouter.post("/getGuildDojo.php", getGuildDojoController);
 | 
					apiRouter.post("/getGuildDojo.php", getGuildDojoController);
 | 
				
			||||||
apiRouter.post("/getVoidProjectionRewards.php", getVoidProjectionRewardsController);
 | 
					apiRouter.post("/getVoidProjectionRewards.php", getVoidProjectionRewardsController);
 | 
				
			||||||
 | 
					apiRouter.post("/gifting.php", giftingController);
 | 
				
			||||||
apiRouter.post("/gildWeapon.php", gildWeaponController);
 | 
					apiRouter.post("/gildWeapon.php", gildWeaponController);
 | 
				
			||||||
apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
 | 
					apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
 | 
				
			||||||
apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
 | 
					apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user