forked from OpenWF/SpaceNinjaServer
feat: create alliance (#1423)
Reviewed-on: OpenWF/SpaceNinjaServer#1423 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
parent
158310bda2
commit
24ed580a97
50
src/controllers/api/createAllianceController.ts
Normal file
50
src/controllers/api/createAllianceController.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
|
import { Alliance, AllianceMember, Guild, GuildMember } from "@/src/models/guildModel";
|
||||||
|
import { getAllianceClient } from "@/src/services/guildService";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { GuildPermission } from "@/src/types/guildTypes";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const createAllianceController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId, "GuildId");
|
||||||
|
const guild = (await Guild.findById(inventory.GuildId!, "Name Tier AllianceId"))!;
|
||||||
|
if (guild.AllianceId) {
|
||||||
|
res.status(400).send("Guild is already in an alliance").end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const guildMember = (await GuildMember.findOne({ guildId: guild._id, accountId }, "rank"))!;
|
||||||
|
if (guildMember.rank > 1) {
|
||||||
|
res.status(400).send("Invalid permission").end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = getJSONfromString<ICreateAllianceRequest>(String(req.body));
|
||||||
|
const alliance = new Alliance({ Name: data.allianceName });
|
||||||
|
try {
|
||||||
|
await alliance.save();
|
||||||
|
} catch (e) {
|
||||||
|
res.status(400).send("Alliance name already in use").end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
guild.AllianceId = alliance._id;
|
||||||
|
await Promise.all([
|
||||||
|
guild.save(),
|
||||||
|
AllianceMember.insertOne({
|
||||||
|
allianceId: alliance._id,
|
||||||
|
guildId: guild._id,
|
||||||
|
Pending: false,
|
||||||
|
Permissions:
|
||||||
|
GuildPermission.Ruler |
|
||||||
|
GuildPermission.Promoter |
|
||||||
|
GuildPermission.Recruiter |
|
||||||
|
GuildPermission.Treasurer |
|
||||||
|
GuildPermission.ChatModerator
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
res.json(await getAllianceClient(alliance, guild));
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ICreateAllianceRequest {
|
||||||
|
allianceName: string;
|
||||||
|
}
|
@ -1,7 +1,25 @@
|
|||||||
|
import { Alliance, Guild } from "@/src/models/guildModel";
|
||||||
|
import { getAllianceClient } from "@/src/services/guildService";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
const getAllianceController: RequestHandler = (_req, res) => {
|
export const getAllianceController: RequestHandler = async (req, res) => {
|
||||||
res.sendStatus(200);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId, "GuildId");
|
||||||
|
if (inventory.GuildId) {
|
||||||
|
const guild = (await Guild.findById(inventory.GuildId, "Name Tier AllianceId"))!;
|
||||||
|
if (guild.AllianceId) {
|
||||||
|
const alliance = (await Alliance.findById(guild.AllianceId))!;
|
||||||
|
res.json(await getAllianceClient(alliance, guild));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getAllianceController };
|
/*interface IGetAllianceRequest {
|
||||||
|
memberCount: number;
|
||||||
|
clanLeaderName: string;
|
||||||
|
clanLeaderId: string;
|
||||||
|
}*/
|
||||||
|
@ -5,7 +5,7 @@ import { logger } from "@/src/utils/logger";
|
|||||||
import { getInventory } from "@/src/services/inventoryService";
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
import { createUniqueClanName, getGuildClient } from "@/src/services/guildService";
|
import { createUniqueClanName, getGuildClient } from "@/src/services/guildService";
|
||||||
|
|
||||||
const getGuildController: RequestHandler = async (req, res) => {
|
export const getGuildController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const inventory = await getInventory(accountId, "GuildId");
|
const inventory = await getInventory(accountId, "GuildId");
|
||||||
if (inventory.GuildId) {
|
if (inventory.GuildId) {
|
||||||
@ -28,7 +28,5 @@ const getGuildController: RequestHandler = async (req, res) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.sendStatus(200);
|
res.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getGuildController };
|
|
||||||
|
@ -11,7 +11,9 @@ import {
|
|||||||
IGuildLogEntryRoster,
|
IGuildLogEntryRoster,
|
||||||
IGuildLogEntryContributable,
|
IGuildLogEntryContributable,
|
||||||
IDojoLeaderboardEntry,
|
IDojoLeaderboardEntry,
|
||||||
IGuildAdDatabase
|
IGuildAdDatabase,
|
||||||
|
IAllianceDatabase,
|
||||||
|
IAllianceMemberDatabase
|
||||||
} 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";
|
||||||
@ -167,6 +169,7 @@ const guildSchema = new Schema<IGuildDatabase>(
|
|||||||
TradeTax: { type: Number, default: 0 },
|
TradeTax: { type: Number, default: 0 },
|
||||||
Tier: { type: Number, default: 1 },
|
Tier: { type: Number, default: 1 },
|
||||||
Emblem: { type: Boolean },
|
Emblem: { type: Boolean },
|
||||||
|
AllianceId: { type: Types.ObjectId },
|
||||||
DojoComponents: { type: [dojoComponentSchema], default: [] },
|
DojoComponents: { type: [dojoComponentSchema], default: [] },
|
||||||
DojoCapacity: { type: Number, default: 100 },
|
DojoCapacity: { type: Number, default: 100 },
|
||||||
DojoEnergy: { type: Number, default: 5 },
|
DojoEnergy: { type: Number, default: 5 },
|
||||||
@ -246,3 +249,25 @@ guildAdSchema.index({ GuildId: 1 }, { unique: true });
|
|||||||
guildAdSchema.index({ Expiry: 1 }, { expireAfterSeconds: 0 });
|
guildAdSchema.index({ Expiry: 1 }, { expireAfterSeconds: 0 });
|
||||||
|
|
||||||
export const GuildAd = model<IGuildAdDatabase>("GuildAd", guildAdSchema);
|
export const GuildAd = model<IGuildAdDatabase>("GuildAd", guildAdSchema);
|
||||||
|
|
||||||
|
const allianceSchema = new Schema<IAllianceDatabase>({
|
||||||
|
Name: String,
|
||||||
|
MOTD: longMOTDSchema,
|
||||||
|
LongMOTD: longMOTDSchema,
|
||||||
|
Emblem: Boolean
|
||||||
|
});
|
||||||
|
|
||||||
|
allianceSchema.index({ Name: 1 }, { unique: true });
|
||||||
|
|
||||||
|
export const Alliance = model<IAllianceDatabase>("Alliance", allianceSchema);
|
||||||
|
|
||||||
|
const allianceMemberSchema = new Schema<IAllianceMemberDatabase>({
|
||||||
|
allianceId: Schema.Types.ObjectId,
|
||||||
|
guildId: Schema.Types.ObjectId,
|
||||||
|
Pending: Boolean,
|
||||||
|
Permissions: Number
|
||||||
|
});
|
||||||
|
|
||||||
|
guildMemberSchema.index({ allianceId: 1, guildId: 1 }, { unique: true });
|
||||||
|
|
||||||
|
export const AllianceMember = model<IAllianceMemberDatabase>("AllianceMember", allianceMemberSchema);
|
||||||
|
@ -22,6 +22,7 @@ import { confirmGuildInvitationController } from "@/src/controllers/api/confirmG
|
|||||||
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 { createAllianceController } from "@/src/controllers/api/createAllianceController";
|
||||||
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 { customizeGuildRanksController } from "@/src/controllers/api/customizeGuildRanksController";
|
import { customizeGuildRanksController } from "@/src/controllers/api/customizeGuildRanksController";
|
||||||
@ -193,6 +194,7 @@ apiRouter.post("/confirmGuildInvitation.php", confirmGuildInvitationController);
|
|||||||
apiRouter.post("/contributeGuildClass.php", contributeGuildClassController);
|
apiRouter.post("/contributeGuildClass.php", contributeGuildClassController);
|
||||||
apiRouter.post("/contributeToDojoComponent.php", contributeToDojoComponentController);
|
apiRouter.post("/contributeToDojoComponent.php", contributeToDojoComponentController);
|
||||||
apiRouter.post("/contributeToVault.php", contributeToVaultController);
|
apiRouter.post("/contributeToVault.php", contributeToVaultController);
|
||||||
|
apiRouter.post("/createAlliance.php", createAllianceController);
|
||||||
apiRouter.post("/createGuild.php", createGuildController);
|
apiRouter.post("/createGuild.php", createGuildController);
|
||||||
apiRouter.post("/customizeGuildRanks.php", customizeGuildRanksController);
|
apiRouter.post("/customizeGuildRanks.php", customizeGuildRanksController);
|
||||||
apiRouter.post("/customObstacleCourseLeaderboard.php", customObstacleCourseLeaderboardController);
|
apiRouter.post("/customObstacleCourseLeaderboard.php", customObstacleCourseLeaderboardController);
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
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 { getInventory } from "@/src/services/inventoryService";
|
||||||
import { Guild, GuildAd, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
|
import { AllianceMember, Guild, GuildAd, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
|
||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
import {
|
import {
|
||||||
GuildPermission,
|
GuildPermission,
|
||||||
|
IAllianceClient,
|
||||||
|
IAllianceDatabase,
|
||||||
|
IAllianceMemberClient,
|
||||||
IDojoClient,
|
IDojoClient,
|
||||||
IDojoComponentClient,
|
IDojoComponentClient,
|
||||||
IDojoComponentDatabase,
|
IDojoComponentDatabase,
|
||||||
@ -99,7 +102,8 @@ export const getGuildClient = async (guild: TGuildDatabaseDocument, accountId: s
|
|||||||
XP: guild.XP,
|
XP: guild.XP,
|
||||||
IsContributor: !!guild.CeremonyContributors?.find(x => x.equals(accountId)),
|
IsContributor: !!guild.CeremonyContributors?.find(x => x.equals(accountId)),
|
||||||
NumContributors: guild.CeremonyContributors?.length ?? 0,
|
NumContributors: guild.CeremonyContributors?.length ?? 0,
|
||||||
CeremonyResetDate: guild.CeremonyResetDate ? toMongoDate(guild.CeremonyResetDate) : undefined
|
CeremonyResetDate: guild.CeremonyResetDate ? toMongoDate(guild.CeremonyResetDate) : undefined,
|
||||||
|
AllianceId: guild.AllianceId ? toOid(guild.AllianceId) : undefined
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -549,4 +553,34 @@ export const deleteGuild = async (guildId: Types.ObjectId): Promise<void> => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await GuildAd.deleteOne({ GuildId: guildId });
|
await GuildAd.deleteOne({ GuildId: guildId });
|
||||||
|
|
||||||
|
await AllianceMember.deleteMany({ guildId });
|
||||||
|
|
||||||
|
// TODO: If this guild was the founding guild of an alliance (ruler permission), that would need to be forcefully deleted now as well.
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAllianceClient = async (
|
||||||
|
alliance: IAllianceDatabase,
|
||||||
|
guild: TGuildDatabaseDocument
|
||||||
|
): Promise<IAllianceClient> => {
|
||||||
|
const allianceMembers = await AllianceMember.find({ allianceId: alliance._id });
|
||||||
|
const clans: IAllianceMemberClient[] = [];
|
||||||
|
for (const allianceMember of allianceMembers) {
|
||||||
|
const memberGuild = allianceMember.guildId.equals(guild._id)
|
||||||
|
? guild
|
||||||
|
: (await Guild.findById(allianceMember.guildId))!;
|
||||||
|
clans.push({
|
||||||
|
_id: toOid(allianceMember.guildId),
|
||||||
|
Name: memberGuild.Name,
|
||||||
|
Tier: memberGuild.Tier,
|
||||||
|
Pending: allianceMember.Pending,
|
||||||
|
Permissions: allianceMember.Permissions,
|
||||||
|
MemberCount: await GuildMember.countDocuments({ guildId: memberGuild._id, status: 0 })
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
_id: toOid(alliance._id),
|
||||||
|
Name: alliance.Name,
|
||||||
|
Clans: clans
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,9 @@ export interface IGuildClient {
|
|||||||
IsContributor: boolean;
|
IsContributor: boolean;
|
||||||
NumContributors: number;
|
NumContributors: number;
|
||||||
CeremonyResetDate?: IMongoDate;
|
CeremonyResetDate?: IMongoDate;
|
||||||
|
CrossPlatformEnabled?: boolean;
|
||||||
|
AutoContributeFromVault?: boolean;
|
||||||
|
AllianceId?: IOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGuildDatabase {
|
export interface IGuildDatabase {
|
||||||
@ -29,6 +32,7 @@ export interface IGuildDatabase {
|
|||||||
TradeTax: number;
|
TradeTax: number;
|
||||||
Tier: number;
|
Tier: number;
|
||||||
Emblem?: boolean;
|
Emblem?: boolean;
|
||||||
|
AllianceId?: Types.ObjectId;
|
||||||
|
|
||||||
DojoComponents: IDojoComponentDatabase[];
|
DojoComponents: IDojoComponentDatabase[];
|
||||||
DojoCapacity: number;
|
DojoCapacity: number;
|
||||||
@ -60,21 +64,21 @@ export interface IGuildDatabase {
|
|||||||
export interface ILongMOTD {
|
export interface ILongMOTD {
|
||||||
message: string;
|
message: string;
|
||||||
authorName: string;
|
authorName: string;
|
||||||
//authorGuildName: "";
|
authorGuildName?: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 32 seems to be reserved
|
// 32 seems to be reserved
|
||||||
export enum GuildPermission {
|
export enum GuildPermission {
|
||||||
Ruler = 1, // Change clan hierarchy
|
Ruler = 1, // Clan: Change hierarchy. Alliance: Kick clans.
|
||||||
Advertiser = 8192,
|
Advertiser = 8192,
|
||||||
Recruiter = 2, // Invite members
|
Recruiter = 2, // Send invites (Clans & Alliances)
|
||||||
Regulator = 4, // Kick members
|
Regulator = 4, // Kick members
|
||||||
Promoter = 8, // Promote and demote members
|
Promoter = 8, // Clan: Promote and demote members. Alliance: Change clan permissions.
|
||||||
Architect = 16, // Create and destroy rooms
|
Architect = 16, // Create and destroy rooms
|
||||||
Decorator = 1024, // Create and destroy decos
|
Decorator = 1024, // Create and destroy decos
|
||||||
Treasurer = 64, // Contribute from vault and edit tax rate
|
Treasurer = 64, // Clan: Contribute from vault and edit tax rate. Alliance: Divvy vault.
|
||||||
Tech = 128, // Queue research
|
Tech = 128, // Queue research
|
||||||
ChatModerator = 512,
|
ChatModerator = 512, // (Clans & Alliances)
|
||||||
Herald = 2048, // Change MOTD
|
Herald = 2048, // Change MOTD
|
||||||
Fabricator = 4096 // Replicate research
|
Fabricator = 4096 // Replicate research
|
||||||
}
|
}
|
||||||
@ -268,3 +272,51 @@ export interface IGuildAdDatabase {
|
|||||||
RecruitMsg: string;
|
RecruitMsg: string;
|
||||||
Tier: number;
|
Tier: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IAllianceClient {
|
||||||
|
_id: IOid;
|
||||||
|
Name: string;
|
||||||
|
MOTD?: ILongMOTD;
|
||||||
|
LongMOTD?: ILongMOTD;
|
||||||
|
Emblem?: boolean;
|
||||||
|
CrossPlatformEnabled?: boolean;
|
||||||
|
Clans: IAllianceMemberClient[];
|
||||||
|
OriginalPlatform?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAllianceDatabase {
|
||||||
|
_id: Types.ObjectId;
|
||||||
|
Name: string;
|
||||||
|
MOTD?: ILongMOTD;
|
||||||
|
LongMOTD?: ILongMOTD;
|
||||||
|
Emblem?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAllianceMemberClient {
|
||||||
|
_id: IOid;
|
||||||
|
Name: string;
|
||||||
|
Tier: number;
|
||||||
|
Pending: boolean;
|
||||||
|
Emblem?: boolean;
|
||||||
|
Permissions: number;
|
||||||
|
MemberCount: number;
|
||||||
|
ClanLeader?: string;
|
||||||
|
ClanLeaderId?: IOid;
|
||||||
|
OriginalPlatform?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAllianceMemberDatabase {
|
||||||
|
allianceId: Types.ObjectId;
|
||||||
|
guildId: Types.ObjectId;
|
||||||
|
Pending: boolean;
|
||||||
|
Permissions: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Alliance chat permissions
|
||||||
|
// TODO: POST /api/addToAlliance.php: {"clanName":"abc"}
|
||||||
|
// TODO: GET /api/divvyAllianceVault.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=663e9be9f741eeb5782f9df0&allianceId=000000000000000000000069&credits=1
|
||||||
|
// TODO: GET /api/divvyAllianceVault.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=663e9be9f741eeb5782f9df0&allianceId=000000000000000000000069&credits=0
|
||||||
|
// TODO: GET /api/removeFromAlliance.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=663e9be9f741eeb5782f9df0
|
||||||
|
// TODO: GET /api/setAllianceGuildPermissions.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=000000000000000000000042&perms=2
|
||||||
|
// TODO: Handle alliance in contributeToVault
|
||||||
|
// TODO: Handle alliance in setGuildMotd
|
||||||
|
Loading…
x
Reference in New Issue
Block a user