diff --git a/locales/en.json b/locales/en.json index 24e2998..d360c78 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1013,8 +1013,11 @@ "field-wl-users": "Whitelisted Users", "list-none": "None are configured.", "modal-title": "Confirm data deletion for this user", + "fallback-modal-title": "Confirm data deletion", "modal-label": "Confirm data deletion by typing this phrase:", + "fallback-modal-label": "Confirm by typing this phrase:", "modal-phrase": "I understand that the data of this user will be deleted and that this action cannot be undone.", + "fallback-modal-phrase": "I confirm the data deletion of this user with risks.", "modal-failed": "The phrase you entered is incorrect. Data deletion cancelled.", "field-quick-history": "Quick history view (Last %w weeks)", "field-quick-desc": "Pings history amount: %p\nModeration actions amount: %m", @@ -1165,8 +1168,10 @@ "succ-ac-end": "✅ Activity check ended manually.", "err-gen-no-user": "❌ Could not find that user.", "del-conf-phrase": "I understand that this will delete the specified data for this user and it cannot be undone.", + "fallback-conf-phrase": "I confirm the data deletion with risks.", "mod-del-title": "Confirm Data Deletion", "mod-del-lbl": "Type confirmation phrase:", + "fallback-del-lbl": "Confirm with phrase:", "del-all-title": "Confirm total data deletion", "del-all-desc": "You are about to delete ALL data for this user. Reminder that this ***cannot be undone***. This is the last chance to back out. If you are sure, click the button below.\nThis action will automatically cancel in 30 seconds.", "btn-conf-del": "Confirm deletion", diff --git a/modules/ping-protection/commands/ping-protection.js b/modules/ping-protection/commands/ping-protection.js index 0d47c21..5a0f8e3 100644 --- a/modules/ping-protection/commands/ping-protection.js +++ b/modules/ping-protection/commands/ping-protection.js @@ -44,15 +44,10 @@ module.exports.subcommands = { 'protected': async function (interaction) { await listHandler(interaction, 'protected'); }, - 'list': { - 'protected': async function (interaction) { - await listHandler(interaction, 'protected'); - }, - 'whitelisted': async function (interaction) { - await listHandler(interaction, 'whitelisted'); - } + 'whitelisted': async function (interaction) { + await listHandler(interaction, 'whitelisted'); } -}; +}}; // Handles list subcommands async function listHandler(interaction, type) { diff --git a/modules/ping-protection/events/interactionCreate.js b/modules/ping-protection/events/interactionCreate.js index f483e26..b181e73 100644 --- a/modules/ping-protection/events/interactionCreate.js +++ b/modules/ping-protection/events/interactionCreate.js @@ -100,17 +100,33 @@ module.exports.run = async function (client, interaction) { }); } + // Checks to ensure modal content fits Discord limits + let modalTitle = localize('ping-protection', 'modal-title'); + if (modalTitle.length > 45) { + modalTitle = localize('ping-protection', 'fallback-modal-title'); + } + + let modalLabel = localize('ping-protection', 'modal-label'); + if (modalLabel.length > 45) { + modalLabel = localize('ping-protection', 'fallback-modal-label'); + } + + let confirmationPhrase = localize('ping-protection', 'modal-phrase'); + if (confirmationPhrase.length > 100) { + confirmationPhrase = localize('ping-protection', 'fallback-modal-phrase'); + } + const modal = new ModalBuilder() .setCustomId(`ping-protection_del-confirm_${targetId}_${selection}`) - .setTitle(localize('ping-protection', 'modal-title')); + .setTitle(modalTitle); modal.addComponents( new ActionRowBuilder().addComponents( new TextInputBuilder() .setCustomId('confirm') - .setLabel(localize('ping-protection', 'modal-label')) + .setLabel(modalLabel) .setStyle(TextInputStyle.Paragraph) - .setPlaceholder(localize('ping-protection', 'modal-phrase')) + .setPlaceholder(confirmationPhrase) .setRequired(true) ) ); @@ -130,7 +146,11 @@ module.exports.run = async function (client, interaction) { const targetId = parts[2]; const selection = parts.slice(3).join('_'); - const confirmPhrase = localize('ping-protection', 'modal-phrase'); + let confirmPhrase = localize('ping-protection', 'modal-phrase'); + if (confirmPhrase.length > 100) { + confirmPhrase = localize('ping-protection', 'fallback-modal-phrase'); + } + if (interaction.fields.getTextInputValue('confirm').trim() !== confirmPhrase) { return interaction.reply({ content: localize('ping-protection', 'modal-failed'), diff --git a/modules/staff-management-system/commands/duty.js b/modules/staff-management-system/commands/duty.js index 45e4a42..ce3aa26 100644 --- a/modules/staff-management-system/commands/duty.js +++ b/modules/staff-management-system/commands/duty.js @@ -1025,8 +1025,16 @@ async function handleDutyAdminVoidAll(client, interaction) { const permCheck = checkDutyAdminPermission(client, interaction); if (permCheck) return permCheck; + let confirmPhrase = localize('staff-management-system', 'del-conf-phrase'); + if (confirmPhrase.length > 100) { + confirmPhrase = localize('staff-management-system', 'fallback-conf-phrase'); + } + let delModalLabel = localize('staff-management-system', 'mod-del-lbl'); + if (delModalLabel.length > 45) { + delModalLabel = localize('staff-management-system', 'fallback-del-lbl'); + } + const targetUserId = interaction.customId.split('_')[2]; - const confirmPhrase = localize('staff-management-system', 'del-conf-phrase'); const modal = new ModalBuilder() .setCustomId(`duty-mgmt_admin-voidall-submit_${targetUserId}`) .setTitle(localize('staff-management-system', 'mod-v-all-title')); @@ -1035,8 +1043,8 @@ async function handleDutyAdminVoidAll(client, interaction) { new ActionRowBuilder().addComponents( new TextInputBuilder() .setCustomId('confirm') - .setLabel(localize('staff-management-system', 'mod-del-lbl')) - .setStyle(TextInputStyle.Short) + .setLabel(delModalLabel) + .setStyle(TextInputStyle.Paragraph) .setPlaceholder(confirmPhrase) .setRequired(true) ) @@ -1049,7 +1057,10 @@ async function handleDutyAdminVoidAllSubmit(client, interaction) { if (permCheck) return permCheck; const targetUserId = interaction.customId.split('_')[2]; - const confirmPhrase = localize('staff-management-system', 'del-conf-phrase'); + let confirmPhrase = localize('staff-management-system', 'del-conf-phrase'); + if (confirmPhrase.length > 100) { + confirmPhrase = localize('staff-management-system', 'fallback-conf-phrase'); + } if (interaction.fields.getTextInputValue('confirm').trim() !== confirmPhrase) { return interaction.reply({ diff --git a/modules/staff-management-system/commands/staff-management.js b/modules/staff-management-system/commands/staff-management.js index e667ee1..f064a46 100644 --- a/modules/staff-management-system/commands/staff-management.js +++ b/modules/staff-management-system/commands/staff-management.js @@ -138,10 +138,6 @@ async function handleProfileView(client, interaction, targetUser) { }; let embedTemplate = config.profileEmbedMessage; - if (typeof embedTemplate === 'string') { - try { embedTemplate = JSON.parse(embedTemplate); } catch (e) {} - } - let msgOpts = await embedTypeV2(embedTemplate, placeholders); if (!msgOpts) { diff --git a/modules/staff-management-system/configs/reviews.json b/modules/staff-management-system/configs/reviews.json index 6065550..a31bb24 100644 --- a/modules/staff-management-system/configs/reviews.json +++ b/modules/staff-management-system/configs/reviews.json @@ -21,7 +21,8 @@ "humanName": "Enable Reviews System", "description": "Enabling this unlocks the staff review system, allowing users to submit ratings with feedback for staff members.", "type": "boolean", - "default": true + "default": true, + "elementToggle": true }, { "name": "reviewLogChannel", diff --git a/modules/staff-management-system/events/botReady.js b/modules/staff-management-system/events/botReady.js index 6d2405a..787be60 100644 --- a/modules/staff-management-system/events/botReady.js +++ b/modules/staff-management-system/events/botReady.js @@ -140,7 +140,6 @@ async function checkExpiredSuspensions(client, guild) { try { let rolesToRestore = []; - if (profile?.suspendedRoles) { try { const parsed = JSON.parse(profile.suspendedRoles); @@ -151,7 +150,7 @@ async function checkExpiredSuspensions(client, guild) { ); } } - + if (member) { if (rolesToRestore.length > 0) { await member.roles.add(rolesToRestore).catch(e => { diff --git a/modules/staff-management-system/events/interactionCreate.js b/modules/staff-management-system/events/interactionCreate.js index 804f740..cea2316 100644 --- a/modules/staff-management-system/events/interactionCreate.js +++ b/modules/staff-management-system/events/interactionCreate.js @@ -163,15 +163,24 @@ module.exports.run = async (client, interaction) => { return interaction.update(payload); } - const confirmPhrase = localize('staff-management-system', 'del-conf-phrase'); + let confirmPhrase = localize('staff-management-system', 'del-conf-phrase'); + if (confirmPhrase.length > 100) { + confirmPhrase = localize('staff-management-system', 'fallback-conf-phrase'); + } + let delModalLabel = localize('staff-management-system', 'mod-del-lbl'); + if (delModalLabel.length > 45) { + delModalLabel = localize('staff-management-system', 'fallback-del-lbl'); + } + const delModalTitle = localize('staff-management-system', 'mod-del-title'); + const modal = new ModalBuilder() .setCustomId(`staff-mgmt_del-confirm_${targetId}_${selection}`) - .setTitle(localize('staff-management-system', 'mod-del-title')); + .setTitle(delModalTitle); modal.addComponents( new ActionRowBuilder().addComponents( new TextInputBuilder() .setCustomId('confirm') - .setLabel(localize('staff-management-system', 'mod-del-lbl')) + .setLabel(delModalLabel) .setStyle(TextInputStyle.Paragraph) .setPlaceholder(confirmPhrase) .setRequired(true) @@ -195,7 +204,10 @@ module.exports.run = async (client, interaction) => { const targetId = parts[2]; const selection = parts.slice(3).join('_'); - const confirmPhrase = localize('staff-management-system', 'del-conf-phrase'); + let confirmPhrase = localize('staff-management-system', 'del-conf-phrase'); + if (confirmPhrase.length > 100) { + confirmPhrase = localize('staff-management-system', 'fallback-conf-phrase'); + } if (interaction.fields.getTextInputValue('confirm').trim() !== confirmPhrase) { return interaction.editReply({ diff --git a/modules/staff-management-system/module.json b/modules/staff-management-system/module.json index 0d5c061..77348f9 100644 --- a/modules/staff-management-system/module.json +++ b/modules/staff-management-system/module.json @@ -21,7 +21,7 @@ "configs/activity-checks.json" ], "tags": [ - "moderation" + "administration" ], "humanReadableName": "Staff Management System", "description": "A powerful, highly customizable staff management system designed to track activity, moderate personnel, and maintain detailed staff records seamlessly." diff --git a/modules/staff-management-system/staff-management.js b/modules/staff-management-system/staff-management.js index 3538e88..9e79df6 100644 --- a/modules/staff-management-system/staff-management.js +++ b/modules/staff-management-system/staff-management.js @@ -119,17 +119,18 @@ async function issueInfraction(client, interaction, targetMember, type, reason, content: localize('staff-management-system', 'err-feat-disabled', {feature: 'Infractions'}) }); + const generalConfig = getConfig(client, 'configuration'); + const canInfract = checkStaffPermissions(interaction.member, generalConfig, 'supervisor'); + if (!canInfract) return interaction.editReply({ + content: localize('staff-management-system', 'err-gen-no-perm') + }); + if (targetMember.id === interaction.user.id) { return interaction.editReply({ content: localize('staff-management-system', 'err-self-infract') }); } - const canInfract = checkStaffPermissions(interaction.member, config, 'staff'); - if (!canInfract) return interaction.editReply({ - content: localize('staff-management-system', 'err-gen-no-perm') - }); - if (type.toLowerCase() === 'suspension') { return interaction.editReply({ content: localize('staff-management-system', 'err-use-susp') @@ -179,14 +180,6 @@ async function issueInfraction(client, interaction, targetMember, type, reason, const channel = await interaction.guild.channels.fetch(channelId).catch(() => null); if (channel) { let template = config.infractionMessage; - if (typeof template === 'string') { - try { - template = JSON.parse(template); - } catch (e) { - } - } else if (typeof template === 'object') { - template = JSON.parse(JSON.stringify(template)); - } if (template && template.embeds && !template._schema) template._schema = 'v3'; let msgOpts = await embedTypeV2(template, placeholders); @@ -205,15 +198,6 @@ async function issueInfraction(client, interaction, targetMember, type, reason, if (config.dmInfractedUser && config.infractionDmMessage) { let dmTemplate = config.infractionDmMessage; - if (typeof dmTemplate === 'string') { - try { - dmTemplate = JSON.parse(dmTemplate); - } catch (e) { - } - } else if (typeof dmTemplate === 'object') { - dmTemplate = JSON.parse(JSON.stringify(dmTemplate)); - } - if (dmTemplate && dmTemplate.embeds && !dmTemplate._schema) dmTemplate._schema = 'v3'; const dmOpts = await embedTypeV2(dmTemplate, placeholders); if (dmOpts?.content?.trim() === '') delete dmOpts.content; @@ -257,17 +241,18 @@ async function issueSuspension(client, interaction, targetMember, durationInput, }) }); + const generalConfig = getConfig(client, 'configuration'); + const canSuspend = checkStaffPermissions(interaction.member, generalConfig, 'supervisor'); + if (!canSuspend) return interaction.editReply({ + content: localize('staff-management-system', 'err-gen-no-perm') + }); + if (targetMember.id === interaction.user.id) { return interaction.editReply({ content: localize('staff-management-system', 'err-self-infract') }); } - const canSuspend = checkStaffPermissions(interaction.member, config, 'staff'); - if (!canSuspend) return interaction.editReply({ - content: localize('staff-management-system', 'err-gen-no-perm') - }); - const durationDays = parseDurationToDays(durationInput); if (!durationDays) return interaction.editReply({ @@ -329,14 +314,6 @@ async function issueSuspension(client, interaction, targetMember, durationInput, const channel = await interaction.guild.channels.fetch(channelId).catch(() => null); if (channel) { let template = config.suspensionMessage; - if (typeof template === 'string') { - try { - template = JSON.parse(template); - } catch (e) { - } - } else if (typeof template === 'object') { - template = JSON.parse(JSON.stringify(template)); - } if (template && template.embeds && !template._schema) template._schema = 'v3'; let msgOpts = await embedTypeV2(template, placeholders); @@ -355,14 +332,6 @@ async function issueSuspension(client, interaction, targetMember, durationInput, if (config.dmInfractedUser && config.suspensionDmMessage) { let dmTemplate = config.suspensionDmMessage; - if (typeof dmTemplate === 'string') { - try { - dmTemplate = JSON.parse(dmTemplate); - } catch (e) { - } - } else if (typeof dmTemplate === 'object') { - dmTemplate = JSON.parse(JSON.stringify(dmTemplate)); - } if (dmTemplate && dmTemplate.embeds && !dmTemplate._schema) dmTemplate._schema = 'v3'; const dmOpts = await embedTypeV2(dmTemplate, placeholders); @@ -455,7 +424,7 @@ async function voidInfraction(client, interaction, reference) { const rolesToRestore = JSON.parse(profile.suspendedRoles || '[]'); if (rolesToRestore.length > 0) await member.roles.add(rolesToRestore); if (config.suspensionRole) await member.roles.remove(config.suspensionRole); - await profile.update({ isSuspended: false, suspendedRoles: '[]' }); + await profile.update({ isSuspended: false, suspendedRoles: JSON.stringify([]) }); } catch (e) { return interaction.editReply({ content: localize('staff-management-system', 'succ-void-fail', {caseId: record.caseId}) @@ -543,6 +512,12 @@ async function promoteUser(client, interaction, targetMember, newRole, reason) { content: localize('staff-management-system', 'err-feat-disabled', {feature: 'Promotions'}) }); + const generalConfig = getConfig(client, 'configuration'); + const canPromote = checkStaffPermissions(interaction.member, generalConfig, 'supervisor'); + if (!canPromote) return interaction.editReply({ + content: localize('staff-management-system', 'err-gen-no-perm') + }); + if (targetMember.id === interaction.user.id) { return interaction.editReply({ content: localize('staff-management-system', 'err-self-promo') @@ -602,13 +577,6 @@ async function promoteUser(client, interaction, targetMember, newRole, reason) { const channel = await interaction.guild.channels.fetch(targetChannelId).catch(() => null); if (channel) { let embedTemplate = config.promotionMessage; - if (typeof embedTemplate === 'string') { - try { - embedTemplate = JSON.parse(embedTemplate); - } - catch (e) {} } else if (typeof embedTemplate === 'object') { - embedTemplate = JSON.parse(JSON.stringify(embedTemplate)); - } if (embedTemplate && embedTemplate.embeds && !embedTemplate._schema) embedTemplate._schema = 'v3'; let msgOpts = await embedTypeV2(embedTemplate, placeholders); @@ -635,14 +603,6 @@ async function promoteUser(client, interaction, targetMember, newRole, reason) { if (config.dmPromotedUser && config.promotionDmMessage) { let dmTemplate = config.promotionDmMessage; - if (typeof dmTemplate === 'string') { - try { - dmTemplate = JSON.parse(dmTemplate); - } catch (e) { - } - } else if (typeof dmTemplate === 'object') { - dmTemplate = JSON.parse(JSON.stringify(dmTemplate)); - } if (dmTemplate && dmTemplate.embeds && !dmTemplate._schema) dmTemplate._schema = 'v3'; const dmOpts = await embedTypeV2(dmTemplate, placeholders);