Files
MultiRoombaRover/server/src/services/discordBotService/integrations/dmModeration.js
T
2026-05-01 01:50:35 -04:00

152 lines
5.9 KiB
JavaScript

// Discord DM Moderation Integrations
// Purpose: Sends verification/private-access DMs and resolves reactions.
// Scope: Handles moderation request workflows tied to Discord DMs.
function createDmModerationHandlers(deps) {
const {
logger,
client,
lockdownAdminIds,
attachDmMessage,
getRequestByMessageId,
approveRequest,
denyRequest,
attachPrivateAccessDmMessage,
getPrivateAccessRequestByMessageId,
approvePrivateAccessRequest,
denyPrivateAccessRequest,
isLockdownAdminUser,
sanitizeMentions,
} = deps;
const APPROVE = '✅';
const DENY = '❌';
async function sendVerificationRequestDms(event) {
const payload = event?.payload || {};
const requestId = payload.id;
if (!requestId) return;
const createdAt = payload.createdAt ? new Date(payload.createdAt).toLocaleString() : 'unknown';
const content = [
'**Verification Request**',
`Request ID: \`${requestId}\``,
`Nickname: ${sanitizeMentions(payload.nickname || 'unknown')}`,
`Identity key: \`${String(payload.cookieUserId || 'unknown')}\``,
`IP: \`${String(payload.ip || 'unknown')}\``,
`Created: ${createdAt}`,
'',
`React with ${APPROVE} to approve or ${DENY} to deny.`,
].join('\n');
await Promise.all(Array.from(lockdownAdminIds).map(async (adminId) => {
try {
const user = await client.users.fetch(String(adminId));
if (!user) return;
const dm = await user.createDM();
const message = await dm.send({ content, allowedMentions: { parse: [] } });
try { await message.react(APPROVE); await message.react(DENY); } catch {}
attachDmMessage(requestId, message.id, adminId);
} catch (err) {
logger.warn('Failed to DM lockdown admin for verification request', { requestId, adminId, error: err.message });
}
}));
}
async function sendPrivateRoverAccessRequestDms(event) {
const payload = event?.payload || {};
const requestId = payload.id;
if (!requestId) return;
const requester = payload?.requester || {};
const createdAt = payload.createdAt ? new Date(payload.createdAt).toLocaleString() : 'unknown';
const content = [
'**Private Rover Access Request**',
`Request ID: \`${requestId}\``,
`Rover: ${sanitizeMentions(payload.roverName || payload.roverId || 'unknown')} (\`${String(payload.roverId || 'unknown')}\`)`,
`Requester: ${sanitizeMentions(requester.nickname || requester.socketId || 'unknown')}`,
`Role: \`${String(requester.role || 'unknown')}\``,
`Verified: \`${requester.isVerified ? 'yes' : 'no'}\``,
`Identity key: \`${String(requester.cookieUserId || 'unknown')}\``,
`IP: \`${String(requester.ip || 'unknown')}\``,
`Created: ${createdAt}`,
'',
`React with ${APPROVE} to approve or ${DENY} to deny.`,
].join('\n');
await Promise.all(Array.from(lockdownAdminIds).map(async (adminId) => {
try {
const user = await client.users.fetch(String(adminId));
if (!user) return;
const dm = await user.createDM();
const message = await dm.send({ content, allowedMentions: { parse: [] } });
try { await message.react(APPROVE); await message.react(DENY); } catch {}
attachPrivateAccessDmMessage(requestId, message.id, adminId);
} catch (err) {
logger.warn('Failed to DM lockdown admin for private rover access request', { requestId, adminId, error: err.message });
}
}));
}
async function handleVerificationReaction(reaction, user) {
if (!reaction || !user || user.bot || !isLockdownAdminUser(user.id)) return;
const emoji = reaction.emoji?.name;
if (emoji !== APPROVE && emoji !== DENY) return;
if (reaction.message?.partial || reaction.partial) {
try { await reaction.fetch(); } catch { return; }
}
const linked = getRequestByMessageId(reaction.message?.id);
if (!linked?.request || linked.request.status !== 'pending') return;
if (emoji === APPROVE) {
approveRequest(linked.request.id, user.id);
await reaction.message.reply({
content: `Approved request \`${linked.request.id}\`.`,
allowedMentions: { parse: [] },
});
} else {
denyRequest(linked.request.id, user.id);
await reaction.message.reply({
content: `Denied request \`${linked.request.id}\`.`,
allowedMentions: { parse: [] },
});
}
try {
await reaction.message.reactions.removeAll();
} catch {}
}
async function handlePrivateAccessReaction(reaction, user) {
if (!reaction || !user || user.bot || !isLockdownAdminUser(user.id)) return;
const emoji = reaction.emoji?.name;
if (emoji !== APPROVE && emoji !== DENY) return;
if (reaction.message?.partial || reaction.partial) {
try { await reaction.fetch(); } catch { return; }
}
const linked = getPrivateAccessRequestByMessageId(reaction.message?.id);
if (!linked?.request || linked.request.status !== 'pending') return;
if (emoji === APPROVE) {
const { assignedSocketId } = approvePrivateAccessRequest(linked.request.id, user.id);
const assignmentNote = assignedSocketId
? ` Granted and assigned to socket \`${assignedSocketId}\`.`
: ' Granted.';
await reaction.message.reply({
content: `Approved private access request \`${linked.request.id}\`.${assignmentNote}`,
allowedMentions: { parse: [] },
});
} else {
denyPrivateAccessRequest(linked.request.id, user.id);
await reaction.message.reply({
content: `Denied private access request \`${linked.request.id}\`.`,
allowedMentions: { parse: [] },
});
}
try {
await reaction.message.reactions.removeAll();
} catch {}
}
return {
sendVerificationRequestDms,
sendPrivateRoverAccessRequestDms,
handleVerificationReaction,
handlePrivateAccessReaction,
};
}
module.exports = { createDmModerationHandlers };