feat: alliance invites #1452
117
src/controllers/api/addToAllianceController.ts
Normal file
117
src/controllers/api/addToAllianceController.ts
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import { getJSONfromString, regexEscape } from "@/src/helpers/stringHelpers";
|
||||||
|
import { Alliance, AllianceMember, Guild, GuildMember } from "@/src/models/guildModel";
|
||||||
|
import { createMessage } from "@/src/services/inboxService";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
|
||||||
|
import { GuildPermission } from "@/src/types/guildTypes";
|
||||||
|
import { logger } from "@/src/utils/logger";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { ExportFlavour } from "warframe-public-export-plus";
|
||||||
|
|
||||||
|
export const addToAllianceController: RequestHandler = async (req, res) => {
|
||||||
|
// Check requester is a warlord in their guild
|
||||||
|
const account = await getAccountForRequest(req);
|
||||||
|
const guildMember = (await GuildMember.findOne({ accountId: account._id, status: 0 }))!;
|
||||||
|
if (guildMember.rank > 1) {
|
||||||
|
res.status(400).json({ Error: 104 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check guild has invite permissions in the alliance
|
||||||
|
const allianceMember = (await AllianceMember.findOne({
|
||||||
|
allianceId: req.query.allianceId,
|
||||||
|
guildId: guildMember.guildId
|
||||||
|
}))!;
|
||||||
|
if (!(allianceMember.Permissions & GuildPermission.Recruiter)) {
|
||||||
|
res.status(400).json({ Error: 104 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find clan to invite
|
||||||
|
const payload = getJSONfromString<IAddToAllianceRequest>(String(req.body));
|
||||||
|
const guilds = await Guild.find(
|
||||||
|
{
|
||||||
|
Name:
|
||||||
|
payload.clanName.indexOf("#") == -1
|
||||||
|
? new RegExp("^" + regexEscape(payload.clanName) + "#...$")
|
||||||
|
: payload.clanName
|
||||||
|
},
|
||||||
|
"Name"
|
||||||
|
);
|
||||||
|
if (guilds.length == 0) {
|
||||||
|
res.status(400).json({ Error: 101 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (guilds.length > 1) {
|
||||||
|
const choices: IGuildChoice[] = [];
|
||||||
|
for (const guild of guilds) {
|
||||||
|
choices.push({
|
||||||
|
OriginalPlatform: 0,
|
||||||
|
Name: guild.Name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
res.json(choices);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add clan as a pending alliance member
|
||||||
|
try {
|
||||||
|
await AllianceMember.insertOne({
|
||||||
|
allianceId: req.query.allianceId,
|
||||||
|
guildId: guilds[0]._id,
|
||||||
|
Pending: true,
|
||||||
|
Permissions: 0
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
logger.debug(`alliance invite failed due to ${String(e)}`);
|
||||||
|
res.status(400).json({ Error: 102 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send inbox message to founding warlord
|
||||||
|
// TOVERIFY: Should other warlords get this as well?
|
||||||
|
// TOVERIFY: Who/what should the sender be?
|
||||||
|
// TOVERIFY: Should this message be highPriority?
|
||||||
|
const invitedClanOwnerMember = (await GuildMember.findOne({ guildId: guilds[0]._id, rank: 0 }))!;
|
||||||
|
const senderInventory = await getInventory(account._id.toString(), "ActiveAvatarImageType");
|
||||||
|
const senderGuild = (await Guild.findById(allianceMember.guildId, "Name"))!;
|
||||||
|
const alliance = (await Alliance.findById(req.query.allianceId, "Name"))!;
|
||||||
|
await createMessage(invitedClanOwnerMember.accountId, [
|
||||||
|
{
|
||||||
|
sndr: getSuffixedName(account),
|
||||||
|
msg: "/Lotus/Language/Menu/Mailbox_AllianceInvite_Body",
|
||||||
|
arg: [
|
||||||
|
{
|
||||||
|
Key: "THEIR_CLAN",
|
||||||
|
Tag: senderGuild.Name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "CLAN",
|
||||||
|
Tag: guilds[0].Name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "ALLIANCE",
|
||||||
|
Tag: alliance.Name
|
||||||
|
}
|
||||||
|
],
|
||||||
|
sub: "/Lotus/Language/Menu/Mailbox_AllianceInvite_Title",
|
||||||
|
icon: ExportFlavour[senderInventory.ActiveAvatarImageType].icon,
|
||||||
|
contextInfo: alliance._id.toString(),
|
||||||
|
highPriority: true,
|
||||||
|
acceptAction: "ALLIANCE_INVITE",
|
||||||
|
declineAction: "ALLIANCE_INVITE",
|
||||||
|
hasAccountAction: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
res.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IAddToAllianceRequest {
|
||||||
|
clanName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IGuildChoice {
|
||||||
|
OriginalPlatform: number;
|
||||||
|
Name: string;
|
||||||
|
}
|
@ -88,7 +88,7 @@ export const addToGuildController: RequestHandler = async (req, res) => {
|
|||||||
RequestExpiry: new Date(Date.now() + 14 * 86400 * 1000) // TOVERIFY: I can't find any good information about this with regards to live, but 2 weeks seem reasonable.
|
RequestExpiry: new Date(Date.now() + 14 * 86400 * 1000) // TOVERIFY: I can't find any good information about this with regards to live, but 2 weeks seem reasonable.
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.debug(`alliance invite failed due to ${String(e)}`);
|
logger.debug(`guild invite failed due to ${String(e)}`);
|
||||||
res.status(400).send("Already requested");
|
res.status(400).send("Already requested");
|
||||||
}
|
}
|
||||||
res.end();
|
res.end();
|
||||||
|
37
src/controllers/api/confirmAllianceInvitationController.ts
Normal file
37
src/controllers/api/confirmAllianceInvitationController.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { Alliance, AllianceMember, Guild, GuildMember } from "@/src/models/guildModel";
|
||||||
|
import { getAllianceClient } from "@/src/services/guildService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const confirmAllianceInvitationController: RequestHandler = async (req, res) => {
|
||||||
|
// Check requester is a warlord in their guild
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const guildMember = (await GuildMember.findOne({ accountId, status: 0 }))!;
|
||||||
|
if (guildMember.rank > 1) {
|
||||||
|
res.status(400).json({ Error: 104 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allianceMember = await AllianceMember.findOne({
|
||||||
|
allianceId: req.query.allianceId,
|
||||||
|
guildId: guildMember.guildId
|
||||||
|
});
|
||||||
|
if (!allianceMember || !allianceMember.Pending) {
|
||||||
|
res.status(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allianceMember.Pending = false;
|
||||||
|
|
||||||
|
const guild = (await Guild.findById(guildMember.guildId))!;
|
||||||
|
guild.AllianceId = allianceMember.allianceId;
|
||||||
|
|
||||||
|
await Promise.all([allianceMember.save(), guild.save()]);
|
||||||
|
|
||||||
|
// Give client the new alliance data which uses "AllianceId" instead of "_id" in this response
|
||||||
|
const alliance = (await Alliance.findById(allianceMember.allianceId))!;
|
||||||
|
const { _id, ...rest } = await getAllianceClient(alliance, guild);
|
||||||
|
res.json({
|
||||||
|
AllianceId: _id,
|
||||||
|
...rest
|
||||||
|
});
|
||||||
|
};
|
17
src/controllers/api/declineAllianceInviteController.ts
Normal file
17
src/controllers/api/declineAllianceInviteController.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { AllianceMember, GuildMember } from "@/src/models/guildModel";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const declineAllianceInviteController: RequestHandler = async (req, res) => {
|
||||||
|
// Check requester is a warlord in their guild
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const guildMember = (await GuildMember.findOne({ accountId, status: 0 }))!;
|
||||||
|
if (guildMember.rank > 1) {
|
||||||
|
res.status(400).json({ Error: 104 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await AllianceMember.deleteOne({ allianceId: req.query.allianceId, guildId: guildMember.guildId });
|
||||||
|
|
||||||
|
res.end();
|
||||||
|
};
|
@ -26,3 +26,21 @@ export const getIndexAfter = (str: string, searchWord: string): number => {
|
|||||||
}
|
}
|
||||||
return index + searchWord.length;
|
return index + searchWord.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const regexEscape = (str: string): string => {
|
||||||
|
str = str.split(".").join("\\.");
|
||||||
|
str = str.split("\\").join("\\\\");
|
||||||
|
str = str.split("[").join("\\[");
|
||||||
|
str = str.split("]").join("\\]");
|
||||||
|
str = str.split("+").join("\\+");
|
||||||
|
str = str.split("*").join("\\*");
|
||||||
|
str = str.split("$").join("\\$");
|
||||||
|
str = str.split("^").join("\\^");
|
||||||
|
str = str.split("?").join("\\?");
|
||||||
|
str = str.split("|").join("\\|");
|
||||||
|
str = str.split("(").join("\\(");
|
||||||
|
str = str.split(")").join("\\)");
|
||||||
|
str = str.split("{").join("\\{");
|
||||||
|
str = str.split("}").join("\\}");
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
@ -265,10 +265,10 @@ allianceSchema.index({ Name: 1 }, { unique: true });
|
|||||||
export const Alliance = model<IAllianceDatabase>("Alliance", allianceSchema);
|
export const Alliance = model<IAllianceDatabase>("Alliance", allianceSchema);
|
||||||
|
|
||||||
const allianceMemberSchema = new Schema<IAllianceMemberDatabase>({
|
const allianceMemberSchema = new Schema<IAllianceMemberDatabase>({
|
||||||
allianceId: Schema.Types.ObjectId,
|
allianceId: { type: Schema.Types.ObjectId, required: true },
|
||||||
guildId: Schema.Types.ObjectId,
|
guildId: { type: Schema.Types.ObjectId, required: true },
|
||||||
Pending: Boolean,
|
Pending: { type: Boolean, required: true },
|
||||||
Permissions: Number
|
Permissions: { type: Number, required: true }
|
||||||
});
|
});
|
||||||
|
|
||||||
allianceMemberSchema.index({ allianceId: 1, guildId: 1 }, { unique: true });
|
allianceMemberSchema.index({ allianceId: 1, guildId: 1 }, { unique: true });
|
||||||
|
@ -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 { addToAllianceController } from "@/src/controllers/api/addToAllianceController";
|
||||||
import { addToGuildController } from "@/src/controllers/api/addToGuildController";
|
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";
|
||||||
@ -18,6 +19,7 @@ import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/cla
|
|||||||
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
|
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
|
||||||
import { clearNewEpisodeRewardController } from "@/src/controllers/api/clearNewEpisodeRewardController";
|
import { clearNewEpisodeRewardController } from "@/src/controllers/api/clearNewEpisodeRewardController";
|
||||||
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
|
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
|
||||||
|
import { confirmAllianceInvitationController } from "@/src/controllers/api/confirmAllianceInvitationController";
|
||||||
import { confirmGuildInvitationController } from "@/src/controllers/api/confirmGuildInvitationController";
|
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";
|
||||||
@ -27,6 +29,7 @@ import { createGuildController } from "@/src/controllers/api/createGuildControll
|
|||||||
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";
|
||||||
import { customObstacleCourseLeaderboardController } from "@/src/controllers/api/customObstacleCourseLeaderboardController";
|
import { customObstacleCourseLeaderboardController } from "@/src/controllers/api/customObstacleCourseLeaderboardController";
|
||||||
|
import { declineAllianceInviteController } from "@/src/controllers/api/declineAllianceInviteController";
|
||||||
import { declineGuildInviteController } from "@/src/controllers/api/declineGuildInviteController";
|
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";
|
||||||
@ -140,8 +143,10 @@ apiRouter.get("/cancelGuildAdvertisement.php", cancelGuildAdvertisementControlle
|
|||||||
apiRouter.get("/changeGuildRank.php", changeGuildRankController);
|
apiRouter.get("/changeGuildRank.php", changeGuildRankController);
|
||||||
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
|
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
|
||||||
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
|
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
|
||||||
|
apiRouter.get("/confirmAllianceInvitation.php", confirmAllianceInvitationController);
|
||||||
apiRouter.get("/confirmGuildInvitation.php", confirmGuildInvitationController);
|
apiRouter.get("/confirmGuildInvitation.php", confirmGuildInvitationController);
|
||||||
apiRouter.get("/credits.php", creditsController);
|
apiRouter.get("/credits.php", creditsController);
|
||||||
|
apiRouter.get("/declineAllianceInvite.php", declineAllianceInviteController);
|
||||||
apiRouter.get("/declineGuildInvite.php", declineGuildInviteController);
|
apiRouter.get("/declineGuildInvite.php", declineGuildInviteController);
|
||||||
apiRouter.get("/deleteSession.php", deleteSessionController);
|
apiRouter.get("/deleteSession.php", deleteSessionController);
|
||||||
apiRouter.get("/dojo", dojoController);
|
apiRouter.get("/dojo", dojoController);
|
||||||
@ -181,6 +186,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("/addToAlliance.php", addToAllianceController);
|
||||||
apiRouter.post("/addToGuild.php", addToGuildController);
|
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);
|
||||||
|
@ -315,8 +315,6 @@ export interface IAllianceMemberDatabase {
|
|||||||
Permissions: number;
|
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=1
|
||||||
// TODO: GET /api/divvyAllianceVault.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=663e9be9f741eeb5782f9df0&allianceId=000000000000000000000069&credits=0
|
// 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/removeFromAlliance.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=663e9be9f741eeb5782f9df0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user