forked from OpenWF/SpaceNinjaServer
		
	feat: clan members (#1143)
Now you can add/remove members and accept/decline invites. Closes #1110 Reviewed-on: OpenWF/SpaceNinjaServer#1143 Co-authored-by: Sainan <sainan@calamity.inc> Co-committed-by: Sainan <sainan@calamity.inc>
This commit is contained in:
		
							parent
							
								
									00f6a8bd6d
								
							
						
					
					
						commit
						fae6615df4
					
				
							
								
								
									
										75
									
								
								src/controllers/api/addToGuildController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/controllers/api/addToGuildController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					import { Guild, GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
 | 
					import { Account } from "@/src/models/loginModel";
 | 
				
			||||||
 | 
					import { fillInInventoryDataForGuildMember } from "@/src/services/guildService";
 | 
				
			||||||
 | 
					import { createMessage } from "@/src/services/inboxService";
 | 
				
			||||||
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
 | 
				
			||||||
 | 
					import { IOid } from "@/src/types/commonTypes";
 | 
				
			||||||
 | 
					import { IGuildMemberClient } from "@/src/types/guildTypes";
 | 
				
			||||||
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					import { ExportFlavour } from "warframe-public-export-plus";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const addToGuildController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const payload = JSON.parse(String(req.body)) as IAddToGuildRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const account = await Account.findOne({ DisplayName: payload.UserName });
 | 
				
			||||||
 | 
					    if (!account) {
 | 
				
			||||||
 | 
					        res.status(400).json("Username does not exist");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const guild = (await Guild.findOne({ _id: payload.GuildId.$oid }, "Name"))!;
 | 
				
			||||||
 | 
					    // TODO: Check sender is allowed to send invites for this guild.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (
 | 
				
			||||||
 | 
					        await GuildMember.exists({
 | 
				
			||||||
 | 
					            accountId: account._id,
 | 
				
			||||||
 | 
					            guildId: payload.GuildId.$oid
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        res.status(400).json("User already invited to clan");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await GuildMember.insertOne({
 | 
				
			||||||
 | 
					        accountId: account._id,
 | 
				
			||||||
 | 
					        guildId: payload.GuildId.$oid,
 | 
				
			||||||
 | 
					        status: 2 // outgoing invite
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const senderAccount = await getAccountForRequest(req);
 | 
				
			||||||
 | 
					    const senderInventory = await getInventory(senderAccount._id.toString(), "ActiveAvatarImageType");
 | 
				
			||||||
 | 
					    await createMessage(account._id.toString(), [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sndr: getSuffixedName(senderAccount),
 | 
				
			||||||
 | 
					            msg: "/Lotus/Language/Menu/Mailbox_ClanInvite_Body",
 | 
				
			||||||
 | 
					            arg: [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Key: "clan",
 | 
				
			||||||
 | 
					                    Tag: guild.Name + "#000"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            sub: "/Lotus/Language/Menu/Mailbox_ClanInvite_Title",
 | 
				
			||||||
 | 
					            icon: ExportFlavour[senderInventory.ActiveAvatarImageType].icon,
 | 
				
			||||||
 | 
					            contextInfo: payload.GuildId.$oid,
 | 
				
			||||||
 | 
					            highPriority: true,
 | 
				
			||||||
 | 
					            acceptAction: "GUILD_INVITE",
 | 
				
			||||||
 | 
					            declineAction: "GUILD_INVITE",
 | 
				
			||||||
 | 
					            hasAccountAction: true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const member: IGuildMemberClient = {
 | 
				
			||||||
 | 
					        _id: { $oid: account._id.toString() },
 | 
				
			||||||
 | 
					        DisplayName: account.DisplayName,
 | 
				
			||||||
 | 
					        Rank: 7,
 | 
				
			||||||
 | 
					        Status: 2
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    await fillInInventoryDataForGuildMember(member);
 | 
				
			||||||
 | 
					    res.json({ NewMember: member });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IAddToGuildRequest {
 | 
				
			||||||
 | 
					    UserName: string;
 | 
				
			||||||
 | 
					    GuildId: IOid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								src/controllers/api/confirmGuildInvitationController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/controllers/api/confirmGuildInvitationController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					import { Guild, GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
 | 
					import { getGuildClient, updateInventoryForConfirmedGuildJoin } from "@/src/services/guildService";
 | 
				
			||||||
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					import { Types } from "mongoose";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const confirmGuildInvitationController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
 | 
					    const guildMember = await GuildMember.findOne({
 | 
				
			||||||
 | 
					        accountId: accountId,
 | 
				
			||||||
 | 
					        guildId: req.query.clanId as string
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    if (guildMember) {
 | 
				
			||||||
 | 
					        guildMember.status = 0;
 | 
				
			||||||
 | 
					        await guildMember.save();
 | 
				
			||||||
 | 
					        await updateInventoryForConfirmedGuildJoin(accountId, new Types.ObjectId(req.query.clanId as string));
 | 
				
			||||||
 | 
					        const guild = (await Guild.findOne({ _id: req.query.clanId as string }))!;
 | 
				
			||||||
 | 
					        res.json({
 | 
				
			||||||
 | 
					            ...(await getGuildClient(guild, accountId)),
 | 
				
			||||||
 | 
					            InventoryChanges: {
 | 
				
			||||||
 | 
					                Recipes: [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
 | 
				
			||||||
 | 
					                        ItemCount: 1
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        res.end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
import { RequestHandler } from "express";
 | 
					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 { Inventory } from "@/src/models/inventoryModels/inventoryModel";
 | 
					import { Guild, GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
import { Guild } from "@/src/models/guildModel";
 | 
					import { 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);
 | 
				
			||||||
@ -14,20 +14,15 @@ export const createGuildController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
    await guild.save();
 | 
					    await guild.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Update inventory
 | 
					    // Create guild member on database
 | 
				
			||||||
    const inventory = await Inventory.findOne({ accountOwnerId: accountId });
 | 
					    await GuildMember.insertOne({
 | 
				
			||||||
    if (inventory) {
 | 
					        accountId: accountId,
 | 
				
			||||||
        // Set GuildId
 | 
					        guildId: guild._id,
 | 
				
			||||||
        inventory.GuildId = guild._id;
 | 
					        status: 0,
 | 
				
			||||||
 | 
					        rank: 0
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Give clan key (TODO: This should only be a blueprint)
 | 
					    await updateInventoryForConfirmedGuildJoin(accountId, guild._id);
 | 
				
			||||||
        inventory.LevelKeys.push({
 | 
					 | 
				
			||||||
            ItemType: "/Lotus/Types/Keys/DojoKey",
 | 
					 | 
				
			||||||
            ItemCount: 1
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        await inventory.save();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    res.json(guild);
 | 
					    res.json(guild);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								src/controllers/api/declineGuildInviteController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/controllers/api/declineGuildInviteController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import { GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
 | 
					import { getAccountForRequest } from "@/src/services/loginService";
 | 
				
			||||||
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const declineGuildInviteController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const accountId = await getAccountForRequest(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await GuildMember.deleteOne({
 | 
				
			||||||
 | 
					        accountId: accountId,
 | 
				
			||||||
 | 
					        guildId: req.query.clanId as string
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    res.end();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -1,18 +1,13 @@
 | 
				
			|||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
 | 
					 | 
				
			||||||
import { Guild } from "@/src/models/guildModel";
 | 
					import { Guild } from "@/src/models/guildModel";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
					 | 
				
			||||||
import { getGuildVault } from "@/src/services/guildService";
 | 
					 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					import { getGuildClient } from "@/src/services/guildService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getGuildController: RequestHandler = async (req, res) => {
 | 
					const getGuildController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
    const inventory = await Inventory.findOne({ accountOwnerId: accountId });
 | 
					    const inventory = await getInventory(accountId);
 | 
				
			||||||
    if (!inventory) {
 | 
					 | 
				
			||||||
        res.status(400).json({ error: "inventory was undefined" });
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (inventory.GuildId) {
 | 
					    if (inventory.GuildId) {
 | 
				
			||||||
        const guild = await Guild.findOne({ _id: inventory.GuildId });
 | 
					        const guild = await Guild.findOne({ _id: inventory.GuildId });
 | 
				
			||||||
        if (guild) {
 | 
					        if (guild) {
 | 
				
			||||||
@ -23,64 +18,7 @@ const getGuildController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
                guild.CeremonyResetDate = undefined;
 | 
					                guild.CeremonyResetDate = undefined;
 | 
				
			||||||
                await guild.save();
 | 
					                await guild.save();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            res.json({
 | 
					            res.json(await getGuildClient(guild, accountId));
 | 
				
			||||||
                _id: toOid(guild._id),
 | 
					 | 
				
			||||||
                Name: guild.Name,
 | 
					 | 
				
			||||||
                MOTD: guild.MOTD,
 | 
					 | 
				
			||||||
                LongMOTD: guild.LongMOTD,
 | 
					 | 
				
			||||||
                Members: [
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        _id: { $oid: req.query.accountId },
 | 
					 | 
				
			||||||
                        Rank: 0,
 | 
					 | 
				
			||||||
                        Status: 0
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                ],
 | 
					 | 
				
			||||||
                Ranks: [
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_Creator",
 | 
					 | 
				
			||||||
                        Permissions: 16351
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_Warlord",
 | 
					 | 
				
			||||||
                        Permissions: 14303
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_General",
 | 
					 | 
				
			||||||
                        Permissions: 4318
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_Officer",
 | 
					 | 
				
			||||||
                        Permissions: 4314
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_Leader",
 | 
					 | 
				
			||||||
                        Permissions: 4106
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_Sage",
 | 
					 | 
				
			||||||
                        Permissions: 4304
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_Soldier",
 | 
					 | 
				
			||||||
                        Permissions: 4098
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_Initiate",
 | 
					 | 
				
			||||||
                        Permissions: 4096
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Name: "/Lotus/Language/Game/Rank_Utility",
 | 
					 | 
				
			||||||
                        Permissions: 4096
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                ],
 | 
					 | 
				
			||||||
                Tier: 1,
 | 
					 | 
				
			||||||
                Vault: getGuildVault(guild),
 | 
					 | 
				
			||||||
                Class: guild.Class,
 | 
					 | 
				
			||||||
                XP: guild.XP,
 | 
					 | 
				
			||||||
                IsContributor: !!guild.CeremonyContributors?.find(x => x.equals(accountId)),
 | 
					 | 
				
			||||||
                NumContributors: guild.CeremonyContributors?.length ?? 0,
 | 
					 | 
				
			||||||
                CeremonyResetDate: guild.CeremonyResetDate ? toMongoDate(guild.CeremonyResetDate) : undefined
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										45
									
								
								src/controllers/api/removeFromGuildController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/controllers/api/removeFromGuildController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					import { GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
 | 
					import { getGuildForRequest } from "@/src/services/guildService";
 | 
				
			||||||
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const removeFromGuildController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const guild = await getGuildForRequest(req);
 | 
				
			||||||
 | 
					    // TODO: Check permissions
 | 
				
			||||||
 | 
					    const payload = JSON.parse(String(req.body)) as IRemoveFromGuildRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const guildMember = (await GuildMember.findOne({ accountId: payload.userId, guildId: guild._id }))!;
 | 
				
			||||||
 | 
					    if (guildMember.status == 0) {
 | 
				
			||||||
 | 
					        const inventory = await getInventory(payload.userId);
 | 
				
			||||||
 | 
					        inventory.GuildId = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Remove clan key or blueprint from kicked member
 | 
				
			||||||
 | 
					        const itemIndex = inventory.MiscItems.findIndex(x => x.ItemType == "/Lotus/Types/Keys/DojoKey");
 | 
				
			||||||
 | 
					        if (itemIndex != -1) {
 | 
				
			||||||
 | 
					            inventory.MiscItems.splice(itemIndex, 1);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            const recipeIndex = inventory.Recipes.findIndex(x => x.ItemType == "/Lotus/Types/Keys/DojoKeyBlueprint");
 | 
				
			||||||
 | 
					            if (recipeIndex != -1) {
 | 
				
			||||||
 | 
					                inventory.Recipes.splice(itemIndex, 1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await inventory.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO: Handle clan leader kicking themselves (guild should be deleted in this case, I think)
 | 
				
			||||||
 | 
					    } else if (guildMember.status == 2) {
 | 
				
			||||||
 | 
					        // TODO: Maybe the inbox message for the sent invite should be deleted?
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    await GuildMember.deleteOne({ _id: guildMember._id });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    res.json({
 | 
				
			||||||
 | 
					        _id: payload.userId,
 | 
				
			||||||
 | 
					        ItemToRemove: "/Lotus/Types/Keys/DojoKey",
 | 
				
			||||||
 | 
					        RecipeToRemove: "/Lotus/Types/Keys/DojoKeyBlueprint"
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IRemoveFromGuildRequest {
 | 
				
			||||||
 | 
					    userId: string;
 | 
				
			||||||
 | 
					    kicker?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -7,11 +7,14 @@ import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
 | 
				
			|||||||
import { PersonalRooms } from "@/src/models/personalRoomsModel";
 | 
					import { PersonalRooms } from "@/src/models/personalRoomsModel";
 | 
				
			||||||
import { Ship } from "@/src/models/shipModel";
 | 
					import { Ship } from "@/src/models/shipModel";
 | 
				
			||||||
import { Stats } from "@/src/models/statsModel";
 | 
					import { Stats } from "@/src/models/statsModel";
 | 
				
			||||||
 | 
					import { GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const deleteAccountController: RequestHandler = async (req, res) => {
 | 
					export const deleteAccountController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
 | 
					    // TODO: Handle the account being the creator of a guild
 | 
				
			||||||
    await Promise.all([
 | 
					    await Promise.all([
 | 
				
			||||||
        Account.deleteOne({ _id: accountId }),
 | 
					        Account.deleteOne({ _id: accountId }),
 | 
				
			||||||
 | 
					        GuildMember.deleteOne({ accountId: accountId }),
 | 
				
			||||||
        Inbox.deleteMany({ ownerId: accountId }),
 | 
					        Inbox.deleteMany({ ownerId: accountId }),
 | 
				
			||||||
        Inventory.deleteOne({ accountOwnerId: accountId }),
 | 
					        Inventory.deleteOne({ accountOwnerId: accountId }),
 | 
				
			||||||
        Loadout.deleteOne({ loadoutOwnerId: accountId }),
 | 
					        Loadout.deleteOne({ loadoutOwnerId: accountId }),
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,8 @@ import {
 | 
				
			|||||||
    ITechProjectDatabase,
 | 
					    ITechProjectDatabase,
 | 
				
			||||||
    ITechProjectClient,
 | 
					    ITechProjectClient,
 | 
				
			||||||
    IDojoDecoDatabase,
 | 
					    IDojoDecoDatabase,
 | 
				
			||||||
    ILongMOTD
 | 
					    ILongMOTD,
 | 
				
			||||||
 | 
					    IGuildMemberDatabase
 | 
				
			||||||
} from "@/src/types/guildTypes";
 | 
					} from "@/src/types/guildTypes";
 | 
				
			||||||
import { Document, Model, model, Schema, Types } from "mongoose";
 | 
					import { Document, Model, model, Schema, Types } from "mongoose";
 | 
				
			||||||
import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel";
 | 
					import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel";
 | 
				
			||||||
@ -70,7 +71,7 @@ const longMOTDSchema = new Schema<ILongMOTD>(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const guildSchema = new Schema<IGuildDatabase>(
 | 
					const guildSchema = new Schema<IGuildDatabase>(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Name: { type: String, required: true },
 | 
					        Name: { type: String, required: true, unique: true },
 | 
				
			||||||
        MOTD: { type: String, default: "" },
 | 
					        MOTD: { type: String, default: "" },
 | 
				
			||||||
        LongMOTD: { type: longMOTDSchema, default: undefined },
 | 
					        LongMOTD: { type: longMOTDSchema, default: undefined },
 | 
				
			||||||
        DojoComponents: { type: [dojoComponentSchema], default: [] },
 | 
					        DojoComponents: { type: [dojoComponentSchema], default: [] },
 | 
				
			||||||
@ -113,3 +114,14 @@ export type TGuildDatabaseDocument = Document<unknown, {}, IGuildDatabase> &
 | 
				
			|||||||
        keyof GuildDocumentProps
 | 
					        keyof GuildDocumentProps
 | 
				
			||||||
    > &
 | 
					    > &
 | 
				
			||||||
    GuildDocumentProps;
 | 
					    GuildDocumentProps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const guildMemberSchema = new Schema<IGuildMemberDatabase>({
 | 
				
			||||||
 | 
					    accountId: Types.ObjectId,
 | 
				
			||||||
 | 
					    guildId: Types.ObjectId,
 | 
				
			||||||
 | 
					    status: { type: Number, required: true },
 | 
				
			||||||
 | 
					    rank: { type: Number, default: 7 }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					guildMemberSchema.index({ accountId: 1, guildId: 1 }, { unique: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const GuildMember = model<IGuildMemberDatabase>("GuildMember", guildMemberSchema);
 | 
				
			||||||
 | 
				
			|||||||
@ -32,6 +32,10 @@ export interface IMessage {
 | 
				
			|||||||
    transmission?: string;
 | 
					    transmission?: string;
 | 
				
			||||||
    arg?: Arg[];
 | 
					    arg?: Arg[];
 | 
				
			||||||
    r?: boolean;
 | 
					    r?: boolean;
 | 
				
			||||||
 | 
					    contextInfo?: string;
 | 
				
			||||||
 | 
					    acceptAction?: string;
 | 
				
			||||||
 | 
					    declineAction?: string;
 | 
				
			||||||
 | 
					    hasAccountAction?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface Arg {
 | 
					export interface Arg {
 | 
				
			||||||
@ -100,7 +104,11 @@ const messageSchema = new Schema<IMessageDatabase>(
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            default: undefined
 | 
					            default: undefined
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        contextInfo: String,
 | 
				
			||||||
 | 
					        acceptAction: String,
 | 
				
			||||||
 | 
					        declineAction: String,
 | 
				
			||||||
 | 
					        hasAccountAction: Boolean
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    { timestamps: { createdAt: "date", updatedAt: false }, id: false }
 | 
					    { timestamps: { createdAt: "date", updatedAt: false }, id: false }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
				
			|||||||
@ -1249,7 +1249,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        Drones: [droneSchema],
 | 
					        Drones: [droneSchema],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Active profile ico
 | 
					        //Active profile ico
 | 
				
			||||||
        ActiveAvatarImageType: String,
 | 
					        ActiveAvatarImageType: { type: String, default: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageDefault" },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // open location store like EidolonPlainsDiscoverable or OrbVallisCaveDiscoverable
 | 
					        // open location store like EidolonPlainsDiscoverable or OrbVallisCaveDiscoverable
 | 
				
			||||||
        DiscoveredMarkers: [Schema.Types.Mixed],
 | 
					        DiscoveredMarkers: [Schema.Types.Mixed],
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ import { abortDojoComponentController } from "@/src/controllers/api/abortDojoCom
 | 
				
			|||||||
import { abortDojoComponentDestructionController } from "@/src/controllers/api/abortDojoComponentDestructionController";
 | 
					import { abortDojoComponentDestructionController } from "@/src/controllers/api/abortDojoComponentDestructionController";
 | 
				
			||||||
import { activateRandomModController } from "@/src/controllers/api/activateRandomModController";
 | 
					import { activateRandomModController } from "@/src/controllers/api/activateRandomModController";
 | 
				
			||||||
import { addFriendImageController } from "@/src/controllers/api/addFriendImageController";
 | 
					import { addFriendImageController } from "@/src/controllers/api/addFriendImageController";
 | 
				
			||||||
 | 
					import { addToGuildController } from "@/src/controllers/api/addToGuildController";
 | 
				
			||||||
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
 | 
					import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
 | 
				
			||||||
import { archonFusionController } from "@/src/controllers/api/archonFusionController";
 | 
					import { archonFusionController } from "@/src/controllers/api/archonFusionController";
 | 
				
			||||||
import { artifactsController } from "@/src/controllers/api/artifactsController";
 | 
					import { artifactsController } from "@/src/controllers/api/artifactsController";
 | 
				
			||||||
@ -14,11 +15,13 @@ import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompl
 | 
				
			|||||||
import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/claimLibraryDailyTaskRewardController";
 | 
					import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/claimLibraryDailyTaskRewardController";
 | 
				
			||||||
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
 | 
					import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
 | 
				
			||||||
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
 | 
					import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
 | 
				
			||||||
 | 
					import { confirmGuildInvitationController } from "@/src/controllers/api/confirmGuildInvitationController";
 | 
				
			||||||
import { contributeGuildClassController } from "@/src/controllers/api/contributeGuildClassController";
 | 
					import { contributeGuildClassController } from "@/src/controllers/api/contributeGuildClassController";
 | 
				
			||||||
import { contributeToDojoComponentController } from "@/src/controllers/api/contributeToDojoComponentController";
 | 
					import { contributeToDojoComponentController } from "@/src/controllers/api/contributeToDojoComponentController";
 | 
				
			||||||
import { contributeToVaultController } from "@/src/controllers/api/contributeToVaultController";
 | 
					import { contributeToVaultController } from "@/src/controllers/api/contributeToVaultController";
 | 
				
			||||||
import { createGuildController } from "@/src/controllers/api/createGuildController";
 | 
					import { createGuildController } from "@/src/controllers/api/createGuildController";
 | 
				
			||||||
import { creditsController } from "@/src/controllers/api/creditsController";
 | 
					import { creditsController } from "@/src/controllers/api/creditsController";
 | 
				
			||||||
 | 
					import { declineGuildInviteController } from "@/src/controllers/api/declineGuildInviteController";
 | 
				
			||||||
import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
 | 
					import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
 | 
				
			||||||
import { destroyDojoDecoController } from "@/src/controllers/api/destroyDojoDecoController";
 | 
					import { destroyDojoDecoController } from "@/src/controllers/api/destroyDojoDecoController";
 | 
				
			||||||
import { dojoComponentRushController } from "@/src/controllers/api/dojoComponentRushController";
 | 
					import { dojoComponentRushController } from "@/src/controllers/api/dojoComponentRushController";
 | 
				
			||||||
@ -69,6 +72,7 @@ import { playerSkillsController } from "@/src/controllers/api/playerSkillsContro
 | 
				
			|||||||
import { projectionManagerController } from "@/src/controllers/api/projectionManagerController";
 | 
					import { projectionManagerController } from "@/src/controllers/api/projectionManagerController";
 | 
				
			||||||
import { purchaseController } from "@/src/controllers/api/purchaseController";
 | 
					import { purchaseController } from "@/src/controllers/api/purchaseController";
 | 
				
			||||||
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
 | 
					import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
 | 
				
			||||||
 | 
					import { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController";
 | 
				
			||||||
import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
 | 
					import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
 | 
				
			||||||
import { saveDialogueController } from "@/src/controllers/api/saveDialogueController";
 | 
					import { saveDialogueController } from "@/src/controllers/api/saveDialogueController";
 | 
				
			||||||
import { saveLoadoutController } from "@/src/controllers/api/saveLoadout";
 | 
					import { saveLoadoutController } from "@/src/controllers/api/saveLoadout";
 | 
				
			||||||
@ -113,7 +117,9 @@ apiRouter.get("/abandonLibraryDailyTask.php", abandonLibraryDailyTaskController)
 | 
				
			|||||||
apiRouter.get("/abortDojoComponentDestruction.php", abortDojoComponentDestructionController);
 | 
					apiRouter.get("/abortDojoComponentDestruction.php", abortDojoComponentDestructionController);
 | 
				
			||||||
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
 | 
					apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
 | 
				
			||||||
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
 | 
					apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
 | 
				
			||||||
 | 
					apiRouter.get("/confirmGuildInvitation.php", confirmGuildInvitationController);
 | 
				
			||||||
apiRouter.get("/credits.php", creditsController);
 | 
					apiRouter.get("/credits.php", creditsController);
 | 
				
			||||||
 | 
					apiRouter.get("/declineGuildInvite.php", declineGuildInviteController);
 | 
				
			||||||
apiRouter.get("/deleteSession.php", deleteSessionController);
 | 
					apiRouter.get("/deleteSession.php", deleteSessionController);
 | 
				
			||||||
apiRouter.get("/dojo", dojoController);
 | 
					apiRouter.get("/dojo", dojoController);
 | 
				
			||||||
apiRouter.get("/drones.php", dronesController);
 | 
					apiRouter.get("/drones.php", dronesController);
 | 
				
			||||||
@ -150,6 +156,7 @@ apiRouter.get("/updateSession.php", updateSessionGetController);
 | 
				
			|||||||
apiRouter.post("/abortDojoComponent.php", abortDojoComponentController);
 | 
					apiRouter.post("/abortDojoComponent.php", abortDojoComponentController);
 | 
				
			||||||
apiRouter.post("/activateRandomMod.php", activateRandomModController);
 | 
					apiRouter.post("/activateRandomMod.php", activateRandomModController);
 | 
				
			||||||
apiRouter.post("/addFriendImage.php", addFriendImageController);
 | 
					apiRouter.post("/addFriendImage.php", addFriendImageController);
 | 
				
			||||||
 | 
					apiRouter.post("/addToGuild.php", addToGuildController);
 | 
				
			||||||
apiRouter.post("/arcaneCommon.php", arcaneCommonController);
 | 
					apiRouter.post("/arcaneCommon.php", arcaneCommonController);
 | 
				
			||||||
apiRouter.post("/archonFusion.php", archonFusionController);
 | 
					apiRouter.post("/archonFusion.php", archonFusionController);
 | 
				
			||||||
apiRouter.post("/artifacts.php", artifactsController);
 | 
					apiRouter.post("/artifacts.php", artifactsController);
 | 
				
			||||||
@ -193,6 +200,7 @@ apiRouter.post("/placeDecoInComponent.php", placeDecoInComponentController);
 | 
				
			|||||||
apiRouter.post("/playerSkills.php", playerSkillsController);
 | 
					apiRouter.post("/playerSkills.php", playerSkillsController);
 | 
				
			||||||
apiRouter.post("/projectionManager.php", projectionManagerController);
 | 
					apiRouter.post("/projectionManager.php", projectionManagerController);
 | 
				
			||||||
apiRouter.post("/purchase.php", purchaseController);
 | 
					apiRouter.post("/purchase.php", purchaseController);
 | 
				
			||||||
 | 
					apiRouter.post("/removeFromGuild.php", removeFromGuildController);
 | 
				
			||||||
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
 | 
					apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
 | 
				
			||||||
apiRouter.post("/saveDialogue.php", saveDialogueController);
 | 
					apiRouter.post("/saveDialogue.php", saveDialogueController);
 | 
				
			||||||
apiRouter.post("/saveLoadout.php", saveLoadoutController);
 | 
					apiRouter.post("/saveLoadout.php", saveLoadoutController);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,19 +1,23 @@
 | 
				
			|||||||
import { Request } from "express";
 | 
					import { Request } from "express";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { getInventory } from "@/src/services/inventoryService";
 | 
					import { addRecipes, getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { Guild, TGuildDatabaseDocument } from "@/src/models/guildModel";
 | 
					import { Guild, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
 | 
				
			||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
					import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    IDojoClient,
 | 
					    IDojoClient,
 | 
				
			||||||
    IDojoComponentClient,
 | 
					    IDojoComponentClient,
 | 
				
			||||||
    IDojoContributable,
 | 
					    IDojoContributable,
 | 
				
			||||||
    IDojoDecoClient,
 | 
					    IDojoDecoClient,
 | 
				
			||||||
 | 
					    IGuildClient,
 | 
				
			||||||
 | 
					    IGuildMemberClient,
 | 
				
			||||||
    IGuildVault
 | 
					    IGuildVault
 | 
				
			||||||
} from "@/src/types/guildTypes";
 | 
					} from "@/src/types/guildTypes";
 | 
				
			||||||
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
					import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
import { Types } from "mongoose";
 | 
					import { Types } from "mongoose";
 | 
				
			||||||
import { ExportDojoRecipes, IDojoBuild } from "warframe-public-export-plus";
 | 
					import { ExportDojoRecipes, IDojoBuild } from "warframe-public-export-plus";
 | 
				
			||||||
import { logger } from "../utils/logger";
 | 
					import { logger } from "../utils/logger";
 | 
				
			||||||
 | 
					import { config } from "./configService";
 | 
				
			||||||
 | 
					import { Account } from "../models/loginModel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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);
 | 
				
			||||||
@ -36,6 +40,99 @@ export const getGuildForRequestEx = async (
 | 
				
			|||||||
    return guild;
 | 
					    return guild;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getGuildClient = async (guild: TGuildDatabaseDocument, accountId: string): Promise<IGuildClient> => {
 | 
				
			||||||
 | 
					    const guildMembers = await GuildMember.find({ guildId: guild._id });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const members: IGuildMemberClient[] = [];
 | 
				
			||||||
 | 
					    let missingEntry = true;
 | 
				
			||||||
 | 
					    for (const guildMember of guildMembers) {
 | 
				
			||||||
 | 
					        const member: IGuildMemberClient = {
 | 
				
			||||||
 | 
					            _id: toOid(guildMember.accountId),
 | 
				
			||||||
 | 
					            Rank: guildMember.rank,
 | 
				
			||||||
 | 
					            Status: guildMember.status
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        if (guildMember.accountId.equals(accountId)) {
 | 
				
			||||||
 | 
					            missingEntry = false;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            member.DisplayName = (await Account.findOne(
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    _id: guildMember.accountId
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "DisplayName"
 | 
				
			||||||
 | 
					            ))!.DisplayName;
 | 
				
			||||||
 | 
					            await fillInInventoryDataForGuildMember(member);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        members.push(member);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (missingEntry) {
 | 
				
			||||||
 | 
					        // Handle clans created prior to creation of the GuildMember model.
 | 
				
			||||||
 | 
					        await GuildMember.insertOne({
 | 
				
			||||||
 | 
					            accountId: accountId,
 | 
				
			||||||
 | 
					            guildId: guild._id,
 | 
				
			||||||
 | 
					            status: 0,
 | 
				
			||||||
 | 
					            rank: 0
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        members.push({
 | 
				
			||||||
 | 
					            _id: { $oid: accountId },
 | 
				
			||||||
 | 
					            Status: 0,
 | 
				
			||||||
 | 
					            Rank: 0
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        _id: toOid(guild._id),
 | 
				
			||||||
 | 
					        Name: guild.Name,
 | 
				
			||||||
 | 
					        MOTD: guild.MOTD,
 | 
				
			||||||
 | 
					        LongMOTD: guild.LongMOTD,
 | 
				
			||||||
 | 
					        Members: members,
 | 
				
			||||||
 | 
					        Ranks: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_Creator",
 | 
				
			||||||
 | 
					                Permissions: 16351
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_Warlord",
 | 
				
			||||||
 | 
					                Permissions: 14303
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_General",
 | 
				
			||||||
 | 
					                Permissions: 4318
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_Officer",
 | 
				
			||||||
 | 
					                Permissions: 4314
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_Leader",
 | 
				
			||||||
 | 
					                Permissions: 4106
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_Sage",
 | 
				
			||||||
 | 
					                Permissions: 4304
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_Soldier",
 | 
				
			||||||
 | 
					                Permissions: 4098
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_Initiate",
 | 
				
			||||||
 | 
					                Permissions: 4096
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Name: "/Lotus/Language/Game/Rank_Utility",
 | 
				
			||||||
 | 
					                Permissions: 4096
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        Tier: 1,
 | 
				
			||||||
 | 
					        Vault: getGuildVault(guild),
 | 
				
			||||||
 | 
					        Class: guild.Class,
 | 
				
			||||||
 | 
					        XP: guild.XP,
 | 
				
			||||||
 | 
					        IsContributor: !!guild.CeremonyContributors?.find(x => x.equals(accountId)),
 | 
				
			||||||
 | 
					        NumContributors: guild.CeremonyContributors?.length ?? 0,
 | 
				
			||||||
 | 
					        CeremonyResetDate: guild.CeremonyResetDate ? toMongoDate(guild.CeremonyResetDate) : undefined
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getGuildVault = (guild: TGuildDatabaseDocument): IGuildVault => {
 | 
					export const getGuildVault = (guild: TGuildDatabaseDocument): IGuildVault => {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
        DojoRefundRegularCredits: guild.VaultRegularCredits,
 | 
					        DojoRefundRegularCredits: guild.VaultRegularCredits,
 | 
				
			||||||
@ -192,3 +289,29 @@ export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const fillInInventoryDataForGuildMember = async (member: IGuildMemberClient): Promise<void> => {
 | 
				
			||||||
 | 
					    const inventory = await getInventory(member._id.$oid, "PlayerLevel ActiveAvatarImageType");
 | 
				
			||||||
 | 
					    member.PlayerLevel = config.spoofMasteryRank == -1 ? inventory.PlayerLevel : config.spoofMasteryRank;
 | 
				
			||||||
 | 
					    member.ActiveAvatarImageType = inventory.ActiveAvatarImageType;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const updateInventoryForConfirmedGuildJoin = async (
 | 
				
			||||||
 | 
					    accountId: string,
 | 
				
			||||||
 | 
					    guildId: Types.ObjectId
 | 
				
			||||||
 | 
					): Promise<void> => {
 | 
				
			||||||
 | 
					    const inventory = await getInventory(accountId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Set GuildId
 | 
				
			||||||
 | 
					    inventory.GuildId = guildId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Give clan key blueprint
 | 
				
			||||||
 | 
					    addRecipes(inventory, [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
 | 
				
			||||||
 | 
					            ItemCount: 1
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await inventory.save();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,25 @@ import { Types } from "mongoose";
 | 
				
			|||||||
import { IOid, IMongoDate } from "@/src/types/commonTypes";
 | 
					import { IOid, IMongoDate } from "@/src/types/commonTypes";
 | 
				
			||||||
import { IFusionTreasure, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
					import { IFusionTreasure, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IGuildClient {
 | 
				
			||||||
 | 
					    _id: IOid;
 | 
				
			||||||
 | 
					    Name: string;
 | 
				
			||||||
 | 
					    MOTD: string;
 | 
				
			||||||
 | 
					    LongMOTD?: ILongMOTD;
 | 
				
			||||||
 | 
					    Members: IGuildMemberClient[];
 | 
				
			||||||
 | 
					    Ranks: {
 | 
				
			||||||
 | 
					        Name: string;
 | 
				
			||||||
 | 
					        Permissions: number;
 | 
				
			||||||
 | 
					    }[];
 | 
				
			||||||
 | 
					    Tier: number;
 | 
				
			||||||
 | 
					    Vault: IGuildVault;
 | 
				
			||||||
 | 
					    Class: number;
 | 
				
			||||||
 | 
					    XP: number;
 | 
				
			||||||
 | 
					    IsContributor: boolean;
 | 
				
			||||||
 | 
					    NumContributors: number;
 | 
				
			||||||
 | 
					    CeremonyResetDate?: IMongoDate;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IGuildDatabase {
 | 
					export interface IGuildDatabase {
 | 
				
			||||||
    _id: Types.ObjectId;
 | 
					    _id: Types.ObjectId;
 | 
				
			||||||
    Name: string;
 | 
					    Name: string;
 | 
				
			||||||
@ -35,6 +54,22 @@ export interface ILongMOTD {
 | 
				
			|||||||
    //authorGuildName: "";
 | 
					    //authorGuildName: "";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IGuildMemberDatabase {
 | 
				
			||||||
 | 
					    accountId: Types.ObjectId;
 | 
				
			||||||
 | 
					    guildId: Types.ObjectId;
 | 
				
			||||||
 | 
					    status: number;
 | 
				
			||||||
 | 
					    rank: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IGuildMemberClient {
 | 
				
			||||||
 | 
					    _id: IOid;
 | 
				
			||||||
 | 
					    Status: number;
 | 
				
			||||||
 | 
					    Rank: number;
 | 
				
			||||||
 | 
					    DisplayName?: string;
 | 
				
			||||||
 | 
					    ActiveAvatarImageType?: string;
 | 
				
			||||||
 | 
					    PlayerLevel?: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IGuildVault {
 | 
					export interface IGuildVault {
 | 
				
			||||||
    DojoRefundRegularCredits?: number;
 | 
					    DojoRefundRegularCredits?: number;
 | 
				
			||||||
    DojoRefundMiscItems?: IMiscItem[];
 | 
					    DojoRefundMiscItems?: IMiscItem[];
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user