feat: gifting (#1344)
Reviewed-on: OpenWF/SpaceNinjaServer#1344 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
parent
a56ff89bb9
commit
36d2b2dda5
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 Settings");
|
||||
|
||||
// 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;
|
||||
}
|
@ -1,21 +1,24 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { Inbox } from "@/src/models/inboxModel";
|
||||
import {
|
||||
createMessage,
|
||||
createNewEventMessages,
|
||||
deleteAllMessagesRead,
|
||||
deleteMessageRead,
|
||||
getAllMessagesSorted,
|
||||
getMessage
|
||||
} from "@/src/services/inboxService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountForRequest, getAccountFromSuffixedName, getSuffixedName } from "@/src/services/loginService";
|
||||
import { addItems, combineInventoryChanges, getInventory } from "@/src/services/inventoryService";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { ExportGear } from "warframe-public-export-plus";
|
||||
import { ExportFlavour, ExportGear } from "warframe-public-export-plus";
|
||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||
|
||||
export const inboxController: RequestHandler = async (req, res) => {
|
||||
const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
|
||||
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const account = await getAccountForRequest(req);
|
||||
const accountId = account._id.toString();
|
||||
|
||||
if (deleteId) {
|
||||
if (deleteId === "DeleteAllRead") {
|
||||
@ -29,12 +32,12 @@ export const inboxController: RequestHandler = async (req, res) => {
|
||||
} else if (messageId) {
|
||||
const message = await getMessage(messageId as string);
|
||||
message.r = true;
|
||||
await message.save();
|
||||
|
||||
const attachmentItems = message.att;
|
||||
const attachmentCountedItems = message.countedAtt;
|
||||
|
||||
if (!attachmentItems && !attachmentCountedItems) {
|
||||
await message.save();
|
||||
|
||||
if (!attachmentItems && !attachmentCountedItems && !message.gifts) {
|
||||
res.status(200).end();
|
||||
return;
|
||||
}
|
||||
@ -54,9 +57,43 @@ export const inboxController: RequestHandler = async (req, res) => {
|
||||
if (attachmentCountedItems) {
|
||||
await addItems(inventory, attachmentCountedItems, inventoryChanges);
|
||||
}
|
||||
if (message.gifts) {
|
||||
const sender = await getAccountFromSuffixedName(message.sndr);
|
||||
const recipientName = getSuffixedName(account);
|
||||
const giftQuantity = message.arg!.find(x => x.Key == "GIFT_QUANTITY")!.Tag as number;
|
||||
for (const gift of message.gifts) {
|
||||
combineInventoryChanges(
|
||||
inventoryChanges,
|
||||
(await handleStoreItemAcquisition(gift.GiftType, inventory, giftQuantity)).InventoryChanges
|
||||
);
|
||||
if (sender) {
|
||||
await createMessage(sender._id.toString(), [
|
||||
{
|
||||
sndr: recipientName,
|
||||
msg: "/Lotus/Language/Menu/GiftReceivedConfirmationBody",
|
||||
arg: [
|
||||
{
|
||||
Key: "RECIPIENT_NAME",
|
||||
Tag: recipientName
|
||||
},
|
||||
{
|
||||
Key: "GIFT_TYPE",
|
||||
Tag: gift.GiftType
|
||||
},
|
||||
{
|
||||
Key: "GIFT_QUANTITY",
|
||||
Tag: giftQuantity
|
||||
}
|
||||
],
|
||||
sub: "/Lotus/Language/Menu/GiftReceivedConfirmationSubject",
|
||||
icon: ExportFlavour[inventory.ActiveAvatarImageType].icon,
|
||||
highPriority: true
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
await inventory.save();
|
||||
await message.save();
|
||||
|
||||
res.json({ InventoryChanges: inventoryChanges });
|
||||
} else if (latestClientMessageId) {
|
||||
await createNewEventMessages(req);
|
||||
|
@ -33,6 +33,7 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
||||
inventory[key] = 16000 + inventory.PlayerLevel * 500;
|
||||
}
|
||||
inventory.DailyFocus = 250000 + inventory.PlayerLevel * 5000;
|
||||
inventory.GiftsRemaining = Math.max(8, inventory.PlayerLevel);
|
||||
|
||||
inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask();
|
||||
|
||||
|
@ -31,6 +31,7 @@ export interface IMessage {
|
||||
countedAtt?: ITypeCount[];
|
||||
transmission?: string;
|
||||
arg?: Arg[];
|
||||
gifts?: IGift[];
|
||||
r?: boolean;
|
||||
contextInfo?: string;
|
||||
acceptAction?: string;
|
||||
@ -43,6 +44,10 @@ export interface Arg {
|
||||
Tag: string | number;
|
||||
}
|
||||
|
||||
export interface IGift {
|
||||
GiftType: string;
|
||||
}
|
||||
|
||||
//types are wrong
|
||||
// export interface IMessageDatabase {
|
||||
// _id: Types.ObjectId;
|
||||
@ -80,6 +85,14 @@ export interface Arg {
|
||||
// cinematic: string;
|
||||
// requiredLevel: string;
|
||||
// }
|
||||
|
||||
const giftSchema = new Schema<IGift>(
|
||||
{
|
||||
GiftType: String
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const messageSchema = new Schema<IMessageDatabase>(
|
||||
{
|
||||
ownerId: Schema.Types.ObjectId,
|
||||
@ -93,6 +106,7 @@ const messageSchema = new Schema<IMessageDatabase>(
|
||||
endDate: Date,
|
||||
r: Boolean,
|
||||
att: { type: [String], default: undefined },
|
||||
gifts: { type: [giftSchema], default: undefined },
|
||||
countedAtt: { type: [typeCountSchema], default: undefined },
|
||||
transmission: String,
|
||||
arg: {
|
||||
|
@ -51,6 +51,7 @@ import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSe
|
||||
import { getShipController } from "@/src/controllers/api/getShipController";
|
||||
import { getVendorInfoController } from "@/src/controllers/api/getVendorInfoController";
|
||||
import { getVoidProjectionRewardsController } from "@/src/controllers/api/getVoidProjectionRewardsController";
|
||||
import { giftingController } from "@/src/controllers/api/giftingController";
|
||||
import { gildWeaponController } from "@/src/controllers/api/gildWeaponController";
|
||||
import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
|
||||
import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController";
|
||||
@ -203,6 +204,7 @@ apiRouter.post("/getAlliance.php", getAllianceController);
|
||||
apiRouter.post("/getFriends.php", getFriendsController);
|
||||
apiRouter.post("/getGuildDojo.php", getGuildDojoController);
|
||||
apiRouter.post("/getVoidProjectionRewards.php", getVoidProjectionRewardsController);
|
||||
apiRouter.post("/gifting.php", giftingController);
|
||||
apiRouter.post("/gildWeapon.php", gildWeaponController);
|
||||
apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
|
||||
apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
|
||||
|
@ -100,3 +100,7 @@ export const getSuffixedName = (account: TAccountDocument): string => {
|
||||
const suffix = ((crc32.str(name.toLowerCase() + "595") >>> 0) + platform_magics[platformId]) % 1000;
|
||||
return name + "#" + suffix.toString().padStart(3, "0");
|
||||
};
|
||||
|
||||
export const getAccountFromSuffixedName = (name: string): Promise<TAccountDocument | null> => {
|
||||
return Account.findOne({ DisplayName: name.split("#")[0] });
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user