added role reaction dynamic embed changes
This commit is contained in:
@@ -0,0 +1,522 @@
|
||||
const {
|
||||
EmbedBuilder
|
||||
} = require("discord.js");
|
||||
|
||||
const { mClient } = require("../index");
|
||||
|
||||
|
||||
const DATABASE =
|
||||
"neo-db";
|
||||
|
||||
const DUTY_COLLECTION =
|
||||
"items_duties";
|
||||
|
||||
const EVENT_COLLECTION =
|
||||
"items_events";
|
||||
|
||||
|
||||
/*
|
||||
* RAID SIGNUP EMOJIS
|
||||
*/
|
||||
|
||||
const RAID_EMOJIS = {
|
||||
Tank: {
|
||||
id:
|
||||
"1537931883369726042",
|
||||
|
||||
display:
|
||||
"<:TankRole:1537931883369726042>"
|
||||
},
|
||||
|
||||
Healer: {
|
||||
id:
|
||||
"1537931880756805704",
|
||||
|
||||
display:
|
||||
"<:HealerRole:1537931880756805704>"
|
||||
},
|
||||
|
||||
DPS: {
|
||||
id:
|
||||
"1537931878668050442",
|
||||
|
||||
display:
|
||||
"<:DPSRole:1537931878668050442>"
|
||||
},
|
||||
|
||||
Flex: {
|
||||
id:
|
||||
"1537948665606574210",
|
||||
|
||||
display:
|
||||
"<:AllRounderRole:1537948665606574210>"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MAIN REACTION HANDLER
|
||||
*
|
||||
* added = true
|
||||
* MessageReactionAdd
|
||||
*
|
||||
* added = false
|
||||
* MessageReactionRemove
|
||||
*/
|
||||
|
||||
async function handleRaidReaction(
|
||||
reaction,
|
||||
user,
|
||||
added
|
||||
) {
|
||||
|
||||
/*
|
||||
* Ignore bots.
|
||||
*
|
||||
* This prevents ShaiBot's own initial
|
||||
* signup reactions from being counted.
|
||||
*/
|
||||
|
||||
if (user.bot)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* Resolve partial reactions/messages.
|
||||
*/
|
||||
|
||||
if (reaction.partial) {
|
||||
try {
|
||||
await reaction.fetch();
|
||||
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Failed to fetch partial reaction:",
|
||||
error
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (reaction.message.partial) {
|
||||
try {
|
||||
await reaction.message.fetch();
|
||||
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Failed to fetch partial raid planner message:",
|
||||
error
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const message =
|
||||
reaction.message;
|
||||
|
||||
|
||||
/*
|
||||
* Raid planner messages always contain
|
||||
* an embed.
|
||||
*/
|
||||
|
||||
if (
|
||||
!message.embeds ||
|
||||
message.embeds.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const embed =
|
||||
message.embeds[0];
|
||||
|
||||
|
||||
/*
|
||||
* Footer format:
|
||||
*
|
||||
* raidPlanner:<raidId>
|
||||
*/
|
||||
|
||||
const footer =
|
||||
embed.footer?.text;
|
||||
|
||||
|
||||
if (
|
||||
!footer ||
|
||||
!footer.startsWith(
|
||||
"raidPlanner:"
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const [
|
||||
prefix,
|
||||
raidId
|
||||
] =
|
||||
footer.split(":");
|
||||
|
||||
|
||||
if (
|
||||
prefix !== "raidPlanner" ||
|
||||
!raidId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine which signup role
|
||||
* this reaction represents.
|
||||
*/
|
||||
|
||||
const role =
|
||||
getRoleFromEmoji(
|
||||
reaction.emoji
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Ignore unrelated reactions.
|
||||
*/
|
||||
|
||||
if (!role)
|
||||
return;
|
||||
|
||||
|
||||
const db =
|
||||
mClient.db(
|
||||
DATABASE
|
||||
);
|
||||
|
||||
|
||||
const events =
|
||||
db.collection(
|
||||
EVENT_COLLECTION
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Make sure event exists.
|
||||
*/
|
||||
|
||||
const raid =
|
||||
await events.findOne({
|
||||
raidId
|
||||
});
|
||||
|
||||
|
||||
if (!raid)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* REACTION ADDED
|
||||
*
|
||||
* Each role is independent.
|
||||
* Users may select multiple roles.
|
||||
*/
|
||||
|
||||
if (added) {
|
||||
await events.updateOne(
|
||||
{
|
||||
raidId
|
||||
},
|
||||
{
|
||||
$addToSet: {
|
||||
[`signups.${role}`]:
|
||||
user.id
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* REACTION REMOVED
|
||||
*
|
||||
* Remove only this role.
|
||||
*/
|
||||
|
||||
else {
|
||||
await events.updateOne(
|
||||
{
|
||||
raidId
|
||||
},
|
||||
{
|
||||
$pull: {
|
||||
[`signups.${role}`]:
|
||||
user.id
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rebuild planner from current Mongo state.
|
||||
*/
|
||||
|
||||
await updateRaidPlanner(
|
||||
message,
|
||||
raidId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* UPDATE RAID PLANNER EMBED
|
||||
*/
|
||||
|
||||
async function updateRaidPlanner(
|
||||
message,
|
||||
raidId
|
||||
) {
|
||||
const db =
|
||||
mClient.db(
|
||||
DATABASE
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Fetch raid state.
|
||||
*/
|
||||
|
||||
const raid =
|
||||
await db
|
||||
.collection(
|
||||
EVENT_COLLECTION
|
||||
)
|
||||
.findOne({
|
||||
raidId
|
||||
});
|
||||
|
||||
|
||||
if (!raid)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* Fetch duty.
|
||||
*/
|
||||
|
||||
const duty =
|
||||
await db
|
||||
.collection(
|
||||
DUTY_COLLECTION
|
||||
)
|
||||
.findOne({
|
||||
_id:
|
||||
raid.dutyId
|
||||
});
|
||||
|
||||
|
||||
if (!duty)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* Role counts.
|
||||
*/
|
||||
|
||||
const counts = {
|
||||
Tank:
|
||||
raid.signups?.Tank
|
||||
?.length
|
||||
?? 0,
|
||||
|
||||
Healer:
|
||||
raid.signups?.Healer
|
||||
?.length
|
||||
?? 0,
|
||||
|
||||
DPS:
|
||||
raid.signups?.DPS
|
||||
?.length
|
||||
?? 0,
|
||||
|
||||
Flex:
|
||||
raid.signups?.Flex
|
||||
?.length
|
||||
?? 0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Count UNIQUE participants.
|
||||
*
|
||||
* A user who reacts Tank + DPS + Flex
|
||||
* still counts as one participant.
|
||||
*/
|
||||
|
||||
const uniqueParticipants =
|
||||
new Set([
|
||||
...(
|
||||
raid.signups?.Tank
|
||||
?? []
|
||||
),
|
||||
|
||||
...(
|
||||
raid.signups?.Healer
|
||||
?? []
|
||||
),
|
||||
|
||||
...(
|
||||
raid.signups?.DPS
|
||||
?? []
|
||||
),
|
||||
|
||||
...(
|
||||
raid.signups?.Flex
|
||||
?? []
|
||||
)
|
||||
]).size;
|
||||
|
||||
|
||||
/*
|
||||
* Clone existing embed.
|
||||
*/
|
||||
|
||||
const oldEmbed =
|
||||
message.embeds[0];
|
||||
|
||||
|
||||
const updatedEmbed =
|
||||
EmbedBuilder.from(
|
||||
oldEmbed
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Replace only Party field.
|
||||
*/
|
||||
|
||||
const fields =
|
||||
oldEmbed.fields.map(
|
||||
field => {
|
||||
|
||||
if (
|
||||
field.name !==
|
||||
"Party"
|
||||
) {
|
||||
return {
|
||||
name:
|
||||
field.name,
|
||||
|
||||
value:
|
||||
field.value,
|
||||
|
||||
inline:
|
||||
field.inline
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
name:
|
||||
"Party",
|
||||
|
||||
value:
|
||||
buildPartyField(
|
||||
duty,
|
||||
counts,
|
||||
uniqueParticipants
|
||||
),
|
||||
|
||||
inline:
|
||||
false
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
updatedEmbed.setFields(
|
||||
fields
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Update message.
|
||||
*/
|
||||
|
||||
await message.edit({
|
||||
embeds: [
|
||||
updatedEmbed
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BUILD PARTY FIELD
|
||||
*/
|
||||
|
||||
function buildPartyField(
|
||||
duty,
|
||||
counts,
|
||||
uniqueParticipants
|
||||
) {
|
||||
return (
|
||||
`${RAID_EMOJIS.Tank.display} Tank **(${counts.Tank}/${duty.Party.Tanks})**\n` +
|
||||
`${RAID_EMOJIS.Healer.display} Healer **(${counts.Healer}/${duty.Party.Healers})**\n` +
|
||||
`${RAID_EMOJIS.DPS.display} DPS **(${counts.DPS}/${duty.Party.DPS})**\n` +
|
||||
`${RAID_EMOJIS.Flex.display} Flex **(${counts.Flex})**\n\n` +
|
||||
`**Participants: ${uniqueParticipants}/${duty.Party.Size}**`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EMOJI -> ROLE
|
||||
*/
|
||||
|
||||
function getRoleFromEmoji(
|
||||
emoji
|
||||
) {
|
||||
|
||||
if (
|
||||
emoji.id ===
|
||||
RAID_EMOJIS.Tank.id
|
||||
) {
|
||||
return "Tank";
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
emoji.id ===
|
||||
RAID_EMOJIS.Healer.id
|
||||
) {
|
||||
return "Healer";
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
emoji.id ===
|
||||
RAID_EMOJIS.DPS.id
|
||||
) {
|
||||
return "DPS";
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
emoji.id ===
|
||||
RAID_EMOJIS.Flex.id
|
||||
) {
|
||||
return "Flex";
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
handleRaidReaction,
|
||||
updateRaidPlanner
|
||||
};
|
||||
Reference in New Issue
Block a user