From 54bea9ef14ed45c9dd84c018e4908e63457934c9 Mon Sep 17 00:00:00 2001 From: Dark <7890309+DarkView@users.noreply.github.com> Date: Tue, 16 Mar 2021 18:02:53 +0100 Subject: [PATCH] Allow users to be DM'd when they use reaction roles --- .../ReactionRoles/ReactionRolesPlugin.ts | 2 ++ backend/src/plugins/ReactionRoles/types.ts | 2 ++ .../util/addMemberPendingRoleChange.ts | 28 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts b/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts index 40c447df..e5acc9ac 100644 --- a/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts +++ b/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts @@ -17,6 +17,8 @@ const defaultOptions: PluginOptions = { config: { auto_refresh_interval: MIN_AUTO_REFRESH, remove_user_reactions: true, + dm_on_change: true, + change_message: "Your roles have been modified on {guildName}:\nRemoved: {removedRoles}\nAdded: {addedRoles}", can_manage: false, }, diff --git a/backend/src/plugins/ReactionRoles/types.ts b/backend/src/plugins/ReactionRoles/types.ts index 3212a33e..0f83a5d0 100644 --- a/backend/src/plugins/ReactionRoles/types.ts +++ b/backend/src/plugins/ReactionRoles/types.ts @@ -8,6 +8,8 @@ export const ConfigSchema = t.type({ auto_refresh_interval: t.number, remove_user_reactions: t.boolean, can_manage: t.boolean, + dm_on_change: t.boolean, + change_message: t.string, }); export type TConfigSchema = t.TypeOf; diff --git a/backend/src/plugins/ReactionRoles/util/addMemberPendingRoleChange.ts b/backend/src/plugins/ReactionRoles/util/addMemberPendingRoleChange.ts index 2b2dfd0d..3606d91e 100644 --- a/backend/src/plugins/ReactionRoles/util/addMemberPendingRoleChange.ts +++ b/backend/src/plugins/ReactionRoles/util/addMemberPendingRoleChange.ts @@ -2,6 +2,7 @@ import { GuildPluginData } from "knub"; import { ReactionRolesPluginType, RoleChangeMode, PendingMemberRoleChanges } from "../types"; import { resolveMember } from "../../../utils"; import { logger } from "../../../logger"; +import { renderTemplate } from "../../../templateFormatter"; const ROLE_CHANGE_BATCH_DEBOUNCE_TIME = 1500; @@ -22,6 +23,7 @@ export async function addMemberPendingRoleChange( const member = await resolveMember(pluginData.client, pluginData.guild, memberId); if (member) { + const oldRoles = member.roles; const newRoleIds = new Set(member.roles); for (const change of newPendingRoleChangeObj.changes) { if (change.mode === "+") newRoleIds.add(change.roleId); @@ -40,6 +42,32 @@ export async function addMemberPendingRoleChange( `Failed to apply role changes to ${member.username}#${member.discriminator} (${member.id}): ${e.message}`, ); } + + const cfg = pluginData.config.getForMember(member); + if (cfg.dm_on_change) { + const addedRoles: string[] = []; + const removedRoles: string[] = []; + for (const change of newPendingRoleChangeObj.changes) { + const roleName = pluginData.guild.roles.get(change.roleId)?.name ?? ""; + if (change.mode === "+" && !oldRoles.includes(change.roleId)) addedRoles.push(roleName); + else if (change.mode === "-" && oldRoles.includes(change.roleId)) removedRoles.push(roleName); + } + + if (addedRoles.length === 0 && removedRoles.length === 0) return; // Reaction that caused no change + + const dmMessage = await renderTemplate(cfg.change_message, { + guildName: pluginData.guild.name, + addedRoles: addedRoles.length >= 1 ? addedRoles.join(", ") : "None", + removedRoles: removedRoles.length >= 1 ? removedRoles.join(", ") : "None", + }); + + try { + const dms = await member.user.getDMChannel(); + await dms.createMessage(dmMessage); + } catch (e) { + // We are probably blocked or privacy is too high, ignore silently + } + } } lock.unlock(); },