forked from OpenWF/SpaceNinjaServer
		
	chore: handle account switching guilds (#1398)
Plus some additional inventory cleanup when a guild is being deleted forcefully. 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
							
								
									9e0dd3e0a5
								
							
						
					
					
						commit
						42e08faaaf
					
				@ -1,23 +1,47 @@
 | 
				
			|||||||
import { Guild, GuildMember } from "@/src/models/guildModel";
 | 
					import { Guild, GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
import { getGuildClient, updateInventoryForConfirmedGuildJoin } from "@/src/services/guildService";
 | 
					import { deleteGuild, getGuildClient, removeDojoKeyItems } from "@/src/services/guildService";
 | 
				
			||||||
 | 
					import { addRecipes, combineInventoryChanges, getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
 | 
					import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
 | 
				
			||||||
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
import { Types } from "mongoose";
 | 
					import { Types } from "mongoose";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const confirmGuildInvitationController: RequestHandler = async (req, res) => {
 | 
					export const confirmGuildInvitationController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const account = await getAccountForRequest(req);
 | 
					    const account = await getAccountForRequest(req);
 | 
				
			||||||
    const guildMember = await GuildMember.findOne({
 | 
					    const invitedGuildMember = await GuildMember.findOne({
 | 
				
			||||||
        accountId: account._id,
 | 
					        accountId: account._id,
 | 
				
			||||||
        guildId: req.query.clanId as string
 | 
					        guildId: req.query.clanId as string
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    if (guildMember) {
 | 
					    if (invitedGuildMember) {
 | 
				
			||||||
        guildMember.status = 0;
 | 
					        let inventoryChanges: IInventoryChanges = {};
 | 
				
			||||||
        await guildMember.save();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await updateInventoryForConfirmedGuildJoin(
 | 
					        // If this account is already in a guild, we need to do cleanup first.
 | 
				
			||||||
            account._id.toString(),
 | 
					        const guildMember = await GuildMember.findOneAndDelete({ accountId: account._id, status: 0 });
 | 
				
			||||||
            new Types.ObjectId(req.query.clanId as string)
 | 
					        if (guildMember) {
 | 
				
			||||||
        );
 | 
					            const inventory = await getInventory(account._id.toString(), "LevelKeys Recipes");
 | 
				
			||||||
 | 
					            inventoryChanges = removeDojoKeyItems(inventory);
 | 
				
			||||||
 | 
					            await inventory.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (guildMember.rank == 0) {
 | 
				
			||||||
 | 
					                await deleteGuild(guildMember.guildId);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Now that we're sure this account is not in a guild right now, we can just proceed with the normal updates.
 | 
				
			||||||
 | 
					        invitedGuildMember.status = 0;
 | 
				
			||||||
 | 
					        await invitedGuildMember.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const inventory = await getInventory(account._id.toString(), "GuildId LevelKeys Recipes");
 | 
				
			||||||
 | 
					        inventory.GuildId = new Types.ObjectId(req.query.clanId as string);
 | 
				
			||||||
 | 
					        const recipeChanges = [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
 | 
				
			||||||
 | 
					                ItemCount: 1
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					        addRecipes(inventory, recipeChanges);
 | 
				
			||||||
 | 
					        combineInventoryChanges(inventoryChanges, { Recipes: recipeChanges });
 | 
				
			||||||
 | 
					        await inventory.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const guild = (await Guild.findById(req.query.clanId as string))!;
 | 
					        const guild = (await Guild.findById(req.query.clanId as string))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -31,14 +55,7 @@ export const confirmGuildInvitationController: RequestHandler = async (req, res)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        res.json({
 | 
					        res.json({
 | 
				
			||||||
            ...(await getGuildClient(guild, account._id.toString())),
 | 
					            ...(await getGuildClient(guild, account._id.toString())),
 | 
				
			||||||
            InventoryChanges: {
 | 
					            InventoryChanges: inventoryChanges
 | 
				
			||||||
                Recipes: [
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
 | 
					 | 
				
			||||||
                        ItemCount: 1
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                ]
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        res.end();
 | 
					        res.end();
 | 
				
			||||||
 | 
				
			|||||||
@ -2,11 +2,8 @@ import { RequestHandler } from "express";
 | 
				
			|||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
					import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
import { Guild, GuildMember } from "@/src/models/guildModel";
 | 
					import { Guild, GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
import {
 | 
					import { createUniqueClanName, getGuildClient } from "@/src/services/guildService";
 | 
				
			||||||
    createUniqueClanName,
 | 
					import { addRecipes, getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
    getGuildClient,
 | 
					 | 
				
			||||||
    updateInventoryForConfirmedGuildJoin
 | 
					 | 
				
			||||||
} from "@/src/services/guildService";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const createGuildController: RequestHandler = async (req, res) => {
 | 
					export const createGuildController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
@ -26,7 +23,15 @@ export const createGuildController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        rank: 0
 | 
					        rank: 0
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await updateInventoryForConfirmedGuildJoin(accountId, guild._id);
 | 
					    const inventory = await getInventory(accountId, "GuildId Recipes");
 | 
				
			||||||
 | 
					    inventory.GuildId = guild._id;
 | 
				
			||||||
 | 
					    addRecipes(inventory, [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
 | 
				
			||||||
 | 
					            ItemCount: 1
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    await inventory.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    res.json({
 | 
					    res.json({
 | 
				
			||||||
        ...(await getGuildClient(guild, accountId)),
 | 
					        ...(await getGuildClient(guild, accountId)),
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { GuildMember } from "@/src/models/guildModel";
 | 
					import { GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
import { Inbox } from "@/src/models/inboxModel";
 | 
					import { Inbox } from "@/src/models/inboxModel";
 | 
				
			||||||
import { Account } from "@/src/models/loginModel";
 | 
					import { Account } from "@/src/models/loginModel";
 | 
				
			||||||
import { deleteGuild, getGuildForRequest, hasGuildPermission } from "@/src/services/guildService";
 | 
					import { deleteGuild, getGuildForRequest, hasGuildPermission, removeDojoKeyItems } from "@/src/services/guildService";
 | 
				
			||||||
import { getInventory } from "@/src/services/inventoryService";
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
 | 
					import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
 | 
				
			||||||
import { GuildPermission } from "@/src/types/guildTypes";
 | 
					import { GuildPermission } from "@/src/types/guildTypes";
 | 
				
			||||||
@ -22,22 +22,9 @@ export const removeFromGuildController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        await deleteGuild(guild._id);
 | 
					        await deleteGuild(guild._id);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        if (guildMember.status == 0) {
 | 
					        if (guildMember.status == 0) {
 | 
				
			||||||
            const inventory = await getInventory(payload.userId);
 | 
					            const inventory = await getInventory(payload.userId, "GuildId LevelKeys Recipes");
 | 
				
			||||||
            inventory.GuildId = undefined;
 | 
					            inventory.GuildId = undefined;
 | 
				
			||||||
 | 
					            removeDojoKeyItems(inventory);
 | 
				
			||||||
            // Remove clan key or blueprint from kicked member
 | 
					 | 
				
			||||||
            const itemIndex = inventory.LevelKeys.findIndex(x => x.ItemType == "/Lotus/Types/Keys/DojoKey");
 | 
					 | 
				
			||||||
            if (itemIndex != -1) {
 | 
					 | 
				
			||||||
                inventory.LevelKeys.splice(itemIndex, 1);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                const recipeIndex = inventory.Recipes.findIndex(
 | 
					 | 
				
			||||||
                    x => x.ItemType == "/Lotus/Types/Keys/DojoKeyBlueprint"
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
                if (recipeIndex != -1) {
 | 
					 | 
				
			||||||
                    inventory.Recipes.splice(recipeIndex, 1);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            await inventory.save();
 | 
					            await inventory.save();
 | 
				
			||||||
        } else if (guildMember.status == 2) {
 | 
					        } else if (guildMember.status == 2) {
 | 
				
			||||||
            // Delete the inbox message for the invite
 | 
					            // Delete the inbox message for the invite
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { Request } from "express";
 | 
					import { Request } from "express";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { addRecipes, getInventory } from "@/src/services/inventoryService";
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { Guild, GuildAd, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
 | 
					import { Guild, GuildAd, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
 | 
				
			||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
					import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -25,6 +25,7 @@ import { Account } from "../models/loginModel";
 | 
				
			|||||||
import { getRandomInt } from "./rngService";
 | 
					import { getRandomInt } from "./rngService";
 | 
				
			||||||
import { Inbox } from "../models/inboxModel";
 | 
					import { Inbox } from "../models/inboxModel";
 | 
				
			||||||
import { ITypeCount } from "../types/inventoryTypes/inventoryTypes";
 | 
					import { ITypeCount } from "../types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
 | 
					import { IInventoryChanges } from "../types/purchaseTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => {
 | 
					export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
@ -350,26 +351,6 @@ export const fillInInventoryDataForGuildMember = async (member: IGuildMemberClie
 | 
				
			|||||||
    member.ActiveAvatarImageType = inventory.ActiveAvatarImageType;
 | 
					    member.ActiveAvatarImageType = inventory.ActiveAvatarImageType;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const updateInventoryForConfirmedGuildJoin = async (
 | 
					 | 
				
			||||||
    accountId: string,
 | 
					 | 
				
			||||||
    guildId: Types.ObjectId
 | 
					 | 
				
			||||||
): Promise<void> => {
 | 
					 | 
				
			||||||
    const inventory = await getInventory(accountId, "GuildId Recipes");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Set GuildId
 | 
					 | 
				
			||||||
    inventory.GuildId = guildId;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Give clan key blueprint
 | 
					 | 
				
			||||||
    addRecipes(inventory, [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
 | 
					 | 
				
			||||||
            ItemCount: 1
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    ]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await inventory.save();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const createUniqueClanName = async (name: string): Promise<string> => {
 | 
					export const createUniqueClanName = async (name: string): Promise<string> => {
 | 
				
			||||||
    const initialDiscriminator = getRandomInt(0, 999);
 | 
					    const initialDiscriminator = getRandomInt(0, 999);
 | 
				
			||||||
    let discriminator = initialDiscriminator;
 | 
					    let discriminator = initialDiscriminator;
 | 
				
			||||||
@ -518,8 +499,45 @@ const setGuildTier = async (guild: TGuildDatabaseDocument, newTier: number): Pro
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const removeDojoKeyItems = (inventory: TInventoryDatabaseDocument): IInventoryChanges => {
 | 
				
			||||||
 | 
					    const inventoryChanges: IInventoryChanges = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const itemIndex = inventory.LevelKeys.findIndex(x => x.ItemType == "/Lotus/Types/Keys/DojoKey");
 | 
				
			||||||
 | 
					    if (itemIndex != -1) {
 | 
				
			||||||
 | 
					        inventoryChanges.LevelKeys = [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ItemType: "/Lotus/Types/Keys/DojoKey",
 | 
				
			||||||
 | 
					                ItemCount: inventory.LevelKeys[itemIndex].ItemCount * -1
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					        inventory.LevelKeys.splice(itemIndex, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const recipeIndex = inventory.Recipes.findIndex(x => x.ItemType == "/Lotus/Types/Keys/DojoKeyBlueprint");
 | 
				
			||||||
 | 
					    if (recipeIndex != -1) {
 | 
				
			||||||
 | 
					        inventoryChanges.Recipes = [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
 | 
				
			||||||
 | 
					                ItemCount: inventory.Recipes[recipeIndex].ItemCount * -1
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					        inventory.Recipes.splice(recipeIndex, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return inventoryChanges;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const deleteGuild = async (guildId: Types.ObjectId): Promise<void> => {
 | 
					export const deleteGuild = async (guildId: Types.ObjectId): Promise<void> => {
 | 
				
			||||||
    await Guild.deleteOne({ _id: guildId });
 | 
					    await Guild.deleteOne({ _id: guildId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const guildMembers = await GuildMember.find({ guildId, status: 0 }, "accountId");
 | 
				
			||||||
 | 
					    for (const member of guildMembers) {
 | 
				
			||||||
 | 
					        const inventory = await getInventory(member.accountId.toString(), "GuildId LevelKeys Recipes");
 | 
				
			||||||
 | 
					        inventory.GuildId = undefined;
 | 
				
			||||||
 | 
					        removeDojoKeyItems(inventory);
 | 
				
			||||||
 | 
					        await inventory.save();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await GuildMember.deleteMany({ guildId });
 | 
					    await GuildMember.deleteMany({ guildId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If guild sent any invites, delete those inbox messages as well.
 | 
					    // If guild sent any invites, delete those inbox messages as well.
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user