feat: clan members (#1143)
Now you can add/remove members and accept/decline invites. Closes #1110 Reviewed-on: #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