返回提交历史
Added
src/controllers/api/addToGuildController.ts
+75
-0
Added
src/controllers/api/confirmGuildInvitationController.ts
+32
-0
Modified
src/controllers/api/createGuildController.ts
+10
-15
Added
src/controllers/api/declineGuildInviteController.ts
+14
-0
Modified
src/controllers/api/getGuildController.ts
+4
-66
Added
src/controllers/api/removeFromGuildController.ts
+45
-0
Modified
src/controllers/custom/deleteAccountController.ts
+3
-0
Modified
src/models/guildModel.ts
+14
-2
Modified
src/models/inboxModel.ts
+9
-1
Modified
src/models/inventoryModels/inventoryModel.ts
+1
-1
Modified
src/routes/api.ts
+8
-0
Modified
src/services/guildService.ts
+125
-2
Modified
src/types/guildTypes.ts
+35
-0
XFEstudio/SpaceNinjaServer
feat: clan members (#1143)
Now you can add/remove members and accept/decline invites. Closes #1110 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1143 Co-authored-by: Sainan <sainan@calamity.inc> Co-committed-by: Sainan <sainan@calamity.inc>
fae6615d
代码差异
13 个文件
+375
-87
@@ -0,0 +1,75 @@
1
import { Guild, GuildMember } from "@/src/models/guildModel";
2
import { Account } from "@/src/models/loginModel";
3
import { fillInInventoryDataForGuildMember } from "@/src/services/guildService";
4
import { createMessage } from "@/src/services/inboxService";
5
import { getInventory } from "@/src/services/inventoryService";
6
import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
7
import { IOid } from "@/src/types/commonTypes";
8
import { IGuildMemberClient } from "@/src/types/guildTypes";
9
import { RequestHandler } from "express";
10
import { ExportFlavour } from "warframe-public-export-plus";
11
12
export const addToGuildController: RequestHandler = async (req, res) => {
13
const payload = JSON.parse(String(req.body)) as IAddToGuildRequest;
14
15
const account = await Account.findOne({ DisplayName: payload.UserName });
16
if (!account) {
17
res.status(400).json("Username does not exist");
18
return;
19
}
20
21
const guild = (await Guild.findOne({ _id: payload.GuildId.$oid }, "Name"))!;
22
// TODO: Check sender is allowed to send invites for this guild.
23
24
if (
25
await GuildMember.exists({
26
accountId: account._id,
27
guildId: payload.GuildId.$oid
28
})
29
) {
30
res.status(400).json("User already invited to clan");
31
return;
32
}
33
34
await GuildMember.insertOne({
35
accountId: account._id,
36
guildId: payload.GuildId.$oid,
37
status: 2 // outgoing invite
38
});
39
40
const senderAccount = await getAccountForRequest(req);
41
const senderInventory = await getInventory(senderAccount._id.toString(), "ActiveAvatarImageType");
42
await createMessage(account._id.toString(), [
43
{
44
sndr: getSuffixedName(senderAccount),
45
msg: "/Lotus/Language/Menu/Mailbox_ClanInvite_Body",
46
arg: [
47
{
48
Key: "clan",
49
Tag: guild.Name + "#000"
50
}
51
],
52
sub: "/Lotus/Language/Menu/Mailbox_ClanInvite_Title",
53
icon: ExportFlavour[senderInventory.ActiveAvatarImageType].icon,
54
contextInfo: payload.GuildId.$oid,
55
highPriority: true,
56
acceptAction: "GUILD_INVITE",
57
declineAction: "GUILD_INVITE",
58
hasAccountAction: true
59
}
60
]);
61
62
const member: IGuildMemberClient = {
63
_id: { $oid: account._id.toString() },
64
DisplayName: account.DisplayName,
65
Rank: 7,
66
Status: 2
67
};
68
await fillInInventoryDataForGuildMember(member);
69
res.json({ NewMember: member });
70
};
71
72
interface IAddToGuildRequest {
73
UserName: string;
74
GuildId: IOid;
75
}
@@ -0,0 +1,32 @@
1
import { Guild, GuildMember } from "@/src/models/guildModel";
2
import { getGuildClient, updateInventoryForConfirmedGuildJoin } from "@/src/services/guildService";
3
import { getAccountIdForRequest } from "@/src/services/loginService";
4
import { RequestHandler } from "express";
5
import { Types } from "mongoose";
6
7
export const confirmGuildInvitationController: RequestHandler = async (req, res) => {
8
const accountId = await getAccountIdForRequest(req);
9
const guildMember = await GuildMember.findOne({
10
accountId: accountId,
11
guildId: req.query.clanId as string
12
});
13
if (guildMember) {
14
guildMember.status = 0;
15
await guildMember.save();
16
await updateInventoryForConfirmedGuildJoin(accountId, new Types.ObjectId(req.query.clanId as string));
17
const guild = (await Guild.findOne({ _id: req.query.clanId as string }))!;
18
res.json({
19
...(await getGuildClient(guild, accountId)),
20
InventoryChanges: {
21
Recipes: [
22
{
23
ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
24
ItemCount: 1
25
}
26
]
27
}
28
});
29
} else {
30
res.end();
31
}
32
};
@@ -1,8 +1,8 @@
1
1
import { RequestHandler } from "express";
2
2
import { getAccountIdForRequest } from "@/src/services/loginService";
3
3
import { getJSONfromString } from "@/src/helpers/stringHelpers";
4
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
5
import { Guild } from "@/src/models/guildModel";
4
import { Guild, GuildMember } from "@/src/models/guildModel";
5
import { updateInventoryForConfirmedGuildJoin } from "@/src/services/guildService";
6
6
7
7
export const createGuildController: RequestHandler = async (req, res) => {
8
8
const accountId = await getAccountIdForRequest(req);
@@ -14,20 +14,15 @@ export const createGuildController: RequestHandler = async (req, res) => {
14
14
});
15
15
await guild.save();
16
16
17
// Update inventory
18
const inventory = await Inventory.findOne({ accountOwnerId: accountId });
19
if (inventory) {
20
// Set GuildId
21
inventory.GuildId = guild._id;
22
23
// Give clan key (TODO: This should only be a blueprint)
24
inventory.LevelKeys.push({
25
ItemType: "/Lotus/Types/Keys/DojoKey",
26
ItemCount: 1
27
});
17
// Create guild member on database
18
await GuildMember.insertOne({
19
accountId: accountId,
20
guildId: guild._id,
21
status: 0,
22
rank: 0
23
});
28
24
29
await inventory.save();
30
}
25
await updateInventoryForConfirmedGuildJoin(accountId, guild._id);
31
26
32
27
res.json(guild);
33
28
};
@@ -0,0 +1,14 @@
1
import { GuildMember } from "@/src/models/guildModel";
2
import { getAccountForRequest } from "@/src/services/loginService";
3
import { RequestHandler } from "express";
4
5
export const declineGuildInviteController: RequestHandler = async (req, res) => {
6
const accountId = await getAccountForRequest(req);
7
8
await GuildMember.deleteOne({
9
accountId: accountId,
10
guildId: req.query.clanId as string
11
});
12
13
res.end();
14
};
@@ -1,18 +1,13 @@
1
1
import { RequestHandler } from "express";
2
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
3
2
import { Guild } from "@/src/models/guildModel";
4
3
import { getAccountIdForRequest } from "@/src/services/loginService";
5
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
6
import { getGuildVault } from "@/src/services/guildService";
7
4
import { logger } from "@/src/utils/logger";
5
import { getInventory } from "@/src/services/inventoryService";
6
import { getGuildClient } from "@/src/services/guildService";
8
7
9
8
const getGuildController: RequestHandler = async (req, res) => {
10
9
const accountId = await getAccountIdForRequest(req);
11
const inventory = await Inventory.findOne({ accountOwnerId: accountId });
12
if (!inventory) {
13
res.status(400).json({ error: "inventory was undefined" });
14
return;
15
}
10
const inventory = await getInventory(accountId);
16
11
if (inventory.GuildId) {
17
12
const guild = await Guild.findOne({ _id: inventory.GuildId });
18
13
if (guild) {
@@ -23,64 +18,7 @@ const getGuildController: RequestHandler = async (req, res) => {
23
18
guild.CeremonyResetDate = undefined;
24
19
await guild.save();
25
20
}
26
res.json({
27
_id: toOid(guild._id),
28
Name: guild.Name,
29
MOTD: guild.MOTD,
30
LongMOTD: guild.LongMOTD,
31
Members: [
32
{
33
_id: { $oid: req.query.accountId },
34
Rank: 0,
35
Status: 0
36
}
37
],
38
Ranks: [
39
{
40
Name: "/Lotus/Language/Game/Rank_Creator",
41
Permissions: 16351
42
},
43
{
44
Name: "/Lotus/Language/Game/Rank_Warlord",
45
Permissions: 14303
46
},
47
{
48
Name: "/Lotus/Language/Game/Rank_General",
49
Permissions: 4318
50
},
51
{
52
Name: "/Lotus/Language/Game/Rank_Officer",
53
Permissions: 4314
54
},
55
{
56
Name: "/Lotus/Language/Game/Rank_Leader",
57
Permissions: 4106
58
},
59
{
60
Name: "/Lotus/Language/Game/Rank_Sage",
61
Permissions: 4304
62
},
63
{
64
Name: "/Lotus/Language/Game/Rank_Soldier",
65
Permissions: 4098
66
},
67
{
68
Name: "/Lotus/Language/Game/Rank_Initiate",
69
Permissions: 4096
70
},
71
{
72
Name: "/Lotus/Language/Game/Rank_Utility",
73
Permissions: 4096
74
}
75
],
76
Tier: 1,
77
Vault: getGuildVault(guild),
78
Class: guild.Class,
79
XP: guild.XP,
80
IsContributor: !!guild.CeremonyContributors?.find(x => x.equals(accountId)),
81
NumContributors: guild.CeremonyContributors?.length ?? 0,
82
CeremonyResetDate: guild.CeremonyResetDate ? toMongoDate(guild.CeremonyResetDate) : undefined
83
});
21
res.json(await getGuildClient(guild, accountId));
84
22
return;
85
23
}
86
24
}
@@ -0,0 +1,45 @@
1
import { GuildMember } from "@/src/models/guildModel";
2
import { getGuildForRequest } from "@/src/services/guildService";
3
import { getInventory } from "@/src/services/inventoryService";
4
import { RequestHandler } from "express";
5
6
export const removeFromGuildController: RequestHandler = async (req, res) => {
7
const guild = await getGuildForRequest(req);
8
// TODO: Check permissions
9
const payload = JSON.parse(String(req.body)) as IRemoveFromGuildRequest;
10
11
const guildMember = (await GuildMember.findOne({ accountId: payload.userId, guildId: guild._id }))!;
12
if (guildMember.status == 0) {
13
const inventory = await getInventory(payload.userId);
14
inventory.GuildId = undefined;
15
16
// Remove clan key or blueprint from kicked member
17
const itemIndex = inventory.MiscItems.findIndex(x => x.ItemType == "/Lotus/Types/Keys/DojoKey");
18
if (itemIndex != -1) {
19
inventory.MiscItems.splice(itemIndex, 1);
20
} else {
21
const recipeIndex = inventory.Recipes.findIndex(x => x.ItemType == "/Lotus/Types/Keys/DojoKeyBlueprint");
22
if (recipeIndex != -1) {
23
inventory.Recipes.splice(itemIndex, 1);
24
}
25
}
26
27
await inventory.save();
28
29
// TODO: Handle clan leader kicking themselves (guild should be deleted in this case, I think)
30
} else if (guildMember.status == 2) {
31
// TODO: Maybe the inbox message for the sent invite should be deleted?
32
}
33
await GuildMember.deleteOne({ _id: guildMember._id });
34
35
res.json({
36
_id: payload.userId,
37
ItemToRemove: "/Lotus/Types/Keys/DojoKey",
38
RecipeToRemove: "/Lotus/Types/Keys/DojoKeyBlueprint"
39
});
40
};
41
42
interface IRemoveFromGuildRequest {
43
userId: string;
44
kicker?: string;
45
}
@@ -7,11 +7,14 @@ import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
7
7
import { PersonalRooms } from "@/src/models/personalRoomsModel";
8
8
import { Ship } from "@/src/models/shipModel";
9
9
import { Stats } from "@/src/models/statsModel";
10
import { GuildMember } from "@/src/models/guildModel";
10
11
11
12
export const deleteAccountController: RequestHandler = async (req, res) => {
12
13
const accountId = await getAccountIdForRequest(req);
14
// TODO: Handle the account being the creator of a guild
13
15
await Promise.all([
14
16
Account.deleteOne({ _id: accountId }),
17
GuildMember.deleteOne({ accountId: accountId }),
15
18
Inbox.deleteMany({ ownerId: accountId }),
16
19
Inventory.deleteOne({ accountOwnerId: accountId }),
17
20
Loadout.deleteOne({ loadoutOwnerId: accountId }),
@@ -4,7 +4,8 @@ import {
4
4
ITechProjectDatabase,
5
5
ITechProjectClient,
6
6
IDojoDecoDatabase,
7
ILongMOTD
7
ILongMOTD,
8
IGuildMemberDatabase
8
9
} from "@/src/types/guildTypes";
9
10
import { Document, Model, model, Schema, Types } from "mongoose";
10
11
import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel";
@@ -70,7 +71,7 @@ const longMOTDSchema = new Schema<ILongMOTD>(
70
71
71
72
const guildSchema = new Schema<IGuildDatabase>(
72
73
{
73
Name: { type: String, required: true },
74
Name: { type: String, required: true, unique: true },
74
75
MOTD: { type: String, default: "" },
75
76
LongMOTD: { type: longMOTDSchema, default: undefined },
76
77
DojoComponents: { type: [dojoComponentSchema], default: [] },
@@ -113,3 +114,14 @@ export type TGuildDatabaseDocument = Document<unknown, {}, IGuildDatabase> &
113
114
keyof GuildDocumentProps
114
115
> &
115
116
GuildDocumentProps;
117
118
const guildMemberSchema = new Schema<IGuildMemberDatabase>({
119
accountId: Types.ObjectId,
120
guildId: Types.ObjectId,
121
status: { type: Number, required: true },
122
rank: { type: Number, default: 7 }
123
});
124
125
guildMemberSchema.index({ accountId: 1, guildId: 1 }, { unique: true });
126
127
export const GuildMember = model<IGuildMemberDatabase>("GuildMember", guildMemberSchema);
@@ -32,6 +32,10 @@ export interface IMessage {
32
32
transmission?: string;
33
33
arg?: Arg[];
34
34
r?: boolean;
35
contextInfo?: string;
36
acceptAction?: string;
37
declineAction?: string;
38
hasAccountAction?: boolean;
35
39
}
36
40
37
41
export interface Arg {
@@ -100,7 +104,11 @@ const messageSchema = new Schema<IMessageDatabase>(
100
104
}
101
105
],
102
106
default: undefined
103
}
107
},
108
contextInfo: String,
109
acceptAction: String,
110
declineAction: String,
111
hasAccountAction: Boolean
104
112
},
105
113
{ timestamps: { createdAt: "date", updatedAt: false }, id: false }
106
114
);
@@ -1249,7 +1249,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1249
1249
Drones: [droneSchema],
1250
1250
1251
1251
//Active profile ico
1252
ActiveAvatarImageType: String,
1252
ActiveAvatarImageType: { type: String, default: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageDefault" },
1253
1253
1254
1254
// open location store like EidolonPlainsDiscoverable or OrbVallisCaveDiscoverable
1255
1255
DiscoveredMarkers: [Schema.Types.Mixed],
@@ -4,6 +4,7 @@ import { abortDojoComponentController } from "@/src/controllers/api/abortDojoCom
4
4
import { abortDojoComponentDestructionController } from "@/src/controllers/api/abortDojoComponentDestructionController";
5
5
import { activateRandomModController } from "@/src/controllers/api/activateRandomModController";
6
6
import { addFriendImageController } from "@/src/controllers/api/addFriendImageController";
7
import { addToGuildController } from "@/src/controllers/api/addToGuildController";
7
8
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
8
9
import { archonFusionController } from "@/src/controllers/api/archonFusionController";
9
10
import { artifactsController } from "@/src/controllers/api/artifactsController";
@@ -14,11 +15,13 @@ import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompl
14
15
import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/claimLibraryDailyTaskRewardController";
15
16
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
16
17
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
18
import { confirmGuildInvitationController } from "@/src/controllers/api/confirmGuildInvitationController";
17
19
import { contributeGuildClassController } from "@/src/controllers/api/contributeGuildClassController";
18
20
import { contributeToDojoComponentController } from "@/src/controllers/api/contributeToDojoComponentController";
19
21
import { contributeToVaultController } from "@/src/controllers/api/contributeToVaultController";
20
22
import { createGuildController } from "@/src/controllers/api/createGuildController";
21
23
import { creditsController } from "@/src/controllers/api/creditsController";
24
import { declineGuildInviteController } from "@/src/controllers/api/declineGuildInviteController";
22
25
import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
23
26
import { destroyDojoDecoController } from "@/src/controllers/api/destroyDojoDecoController";
24
27
import { dojoComponentRushController } from "@/src/controllers/api/dojoComponentRushController";
@@ -69,6 +72,7 @@ import { playerSkillsController } from "@/src/controllers/api/playerSkillsContro
69
72
import { projectionManagerController } from "@/src/controllers/api/projectionManagerController";
70
73
import { purchaseController } from "@/src/controllers/api/purchaseController";
71
74
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
75
import { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController";
72
76
import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
73
77
import { saveDialogueController } from "@/src/controllers/api/saveDialogueController";
74
78
import { saveLoadoutController } from "@/src/controllers/api/saveLoadout";
@@ -113,7 +117,9 @@ apiRouter.get("/abandonLibraryDailyTask.php", abandonLibraryDailyTaskController)
113
117
apiRouter.get("/abortDojoComponentDestruction.php", abortDojoComponentDestructionController);
114
118
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
115
119
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
120
apiRouter.get("/confirmGuildInvitation.php", confirmGuildInvitationController);
116
121
apiRouter.get("/credits.php", creditsController);
122
apiRouter.get("/declineGuildInvite.php", declineGuildInviteController);
117
123
apiRouter.get("/deleteSession.php", deleteSessionController);
118
124
apiRouter.get("/dojo", dojoController);
119
125
apiRouter.get("/drones.php", dronesController);
@@ -150,6 +156,7 @@ apiRouter.get("/updateSession.php", updateSessionGetController);
150
156
apiRouter.post("/abortDojoComponent.php", abortDojoComponentController);
151
157
apiRouter.post("/activateRandomMod.php", activateRandomModController);
152
158
apiRouter.post("/addFriendImage.php", addFriendImageController);
159
apiRouter.post("/addToGuild.php", addToGuildController);
153
160
apiRouter.post("/arcaneCommon.php", arcaneCommonController);
154
161
apiRouter.post("/archonFusion.php", archonFusionController);
155
162
apiRouter.post("/artifacts.php", artifactsController);
@@ -193,6 +200,7 @@ apiRouter.post("/placeDecoInComponent.php", placeDecoInComponentController);
193
200
apiRouter.post("/playerSkills.php", playerSkillsController);
194
201
apiRouter.post("/projectionManager.php", projectionManagerController);
195
202
apiRouter.post("/purchase.php", purchaseController);
203
apiRouter.post("/removeFromGuild.php", removeFromGuildController);
196
204
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
197
205
apiRouter.post("/saveDialogue.php", saveDialogueController);
198
206
apiRouter.post("/saveLoadout.php", saveLoadoutController);
@@ -1,19 +1,23 @@
1
1
import { Request } from "express";
2
2
import { getAccountIdForRequest } from "@/src/services/loginService";
3
import { getInventory } from "@/src/services/inventoryService";
4
import { Guild, TGuildDatabaseDocument } from "@/src/models/guildModel";
3
import { addRecipes, getInventory } from "@/src/services/inventoryService";
4
import { Guild, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
5
5
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
6
6
import {
7
7
IDojoClient,
8
8
IDojoComponentClient,
9
9
IDojoContributable,
10
10
IDojoDecoClient,
11
IGuildClient,
12
IGuildMemberClient,
11
13
IGuildVault
12
14
} from "@/src/types/guildTypes";
13
15
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
14
16
import { Types } from "mongoose";
15
17
import { ExportDojoRecipes, IDojoBuild } from "warframe-public-export-plus";
16
18
import { logger } from "../utils/logger";
19
import { config } from "./configService";
20
import { Account } from "../models/loginModel";
17
21
18
22
export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => {
19
23
const accountId = await getAccountIdForRequest(req);
@@ -36,6 +40,99 @@ export const getGuildForRequestEx = async (
36
40
return guild;
37
41
};
38
42
43
export const getGuildClient = async (guild: TGuildDatabaseDocument, accountId: string): Promise<IGuildClient> => {
44
const guildMembers = await GuildMember.find({ guildId: guild._id });
45
46
const members: IGuildMemberClient[] = [];
47
let missingEntry = true;
48
for (const guildMember of guildMembers) {
49
const member: IGuildMemberClient = {
50
_id: toOid(guildMember.accountId),
51
Rank: guildMember.rank,
52
Status: guildMember.status
53
};
54
if (guildMember.accountId.equals(accountId)) {
55
missingEntry = false;
56
} else {
57
member.DisplayName = (await Account.findOne(
58
{
59
_id: guildMember.accountId
60
},
61
"DisplayName"
62
))!.DisplayName;
63
await fillInInventoryDataForGuildMember(member);
64
}
65
members.push(member);
66
}
67
if (missingEntry) {
68
// Handle clans created prior to creation of the GuildMember model.
69
await GuildMember.insertOne({
70
accountId: accountId,
71
guildId: guild._id,
72
status: 0,
73
rank: 0
74
});
75
members.push({
76
_id: { $oid: accountId },
77
Status: 0,
78
Rank: 0
79
});
80
}
81
82
return {
83
_id: toOid(guild._id),
84
Name: guild.Name,
85
MOTD: guild.MOTD,
86
LongMOTD: guild.LongMOTD,
87
Members: members,
88
Ranks: [
89
{
90
Name: "/Lotus/Language/Game/Rank_Creator",
91
Permissions: 16351
92
},
93
{
94
Name: "/Lotus/Language/Game/Rank_Warlord",
95
Permissions: 14303
96
},
97
{
98
Name: "/Lotus/Language/Game/Rank_General",
99
Permissions: 4318
100
},
101
{
102
Name: "/Lotus/Language/Game/Rank_Officer",
103
Permissions: 4314
104
},
105
{
106
Name: "/Lotus/Language/Game/Rank_Leader",
107
Permissions: 4106
108
},
109
{
110
Name: "/Lotus/Language/Game/Rank_Sage",
111
Permissions: 4304
112
},
113
{
114
Name: "/Lotus/Language/Game/Rank_Soldier",
115
Permissions: 4098
116
},
117
{
118
Name: "/Lotus/Language/Game/Rank_Initiate",
119
Permissions: 4096
120
},
121
{
122
Name: "/Lotus/Language/Game/Rank_Utility",
123
Permissions: 4096
124
}
125
],
126
Tier: 1,
127
Vault: getGuildVault(guild),
128
Class: guild.Class,
129
XP: guild.XP,
130
IsContributor: !!guild.CeremonyContributors?.find(x => x.equals(accountId)),
131
NumContributors: guild.CeremonyContributors?.length ?? 0,
132
CeremonyResetDate: guild.CeremonyResetDate ? toMongoDate(guild.CeremonyResetDate) : undefined
133
};
134
};
135
39
136
export const getGuildVault = (guild: TGuildDatabaseDocument): IGuildVault => {
40
137
return {
41
138
DojoRefundRegularCredits: guild.VaultRegularCredits,
@@ -192,3 +289,29 @@ export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument,
192
289
}
193
290
}
194
291
};
292
293
export const fillInInventoryDataForGuildMember = async (member: IGuildMemberClient): Promise<void> => {
294
const inventory = await getInventory(member._id.$oid, "PlayerLevel ActiveAvatarImageType");
295
member.PlayerLevel = config.spoofMasteryRank == -1 ? inventory.PlayerLevel : config.spoofMasteryRank;
296
member.ActiveAvatarImageType = inventory.ActiveAvatarImageType;
297
};
298
299
export const updateInventoryForConfirmedGuildJoin = async (
300
accountId: string,
301
guildId: Types.ObjectId
302
): Promise<void> => {
303
const inventory = await getInventory(accountId);
304
305
// Set GuildId
306
inventory.GuildId = guildId;
307
308
// Give clan key blueprint
309
addRecipes(inventory, [
310
{
311
ItemType: "/Lotus/Types/Keys/DojoKeyBlueprint",
312
ItemCount: 1
313
}
314
]);
315
316
await inventory.save();
317
};