2024-11-09 00:37:51 +00:00
const fs = require ( "fs" );
2025-09-20 23:09:22 +01:00
const { ApplicationCommandOptionType , ApplicationCommandType , EmbedBuilder , ActionRowBuilder , ButtonBuilder , ButtonStyle , ComponentType , MessageFlags } = require ( "discord.js" );
2024-11-09 00:37:51 +00:00
const yaml = require ( "js-yaml" );
2026-08-10 20:15:00 +01:00
const db = require ( "../../Structures/Database.js" );
2026-05-16 15:10:27 +01:00
const supportbot = require ( "../../Structures/ConfigStore" ). supportbot ;
const cmdconfig = require ( "../../Structures/ConfigStore" ). commands ;
const msgconfig = require ( "../../Structures/ConfigStore" ). messages ;
2024-11-09 00:37:51 +00:00
2025-09-20 23:09:22 +01:00
const Command = require ( "../../Structures/Command.js" );
2024-11-09 00:37:51 +00:00
// Function to chunk array into smaller arrays
function chunkArray ( arr , size ) {
const chunks = [];
for ( let i = 0 ; i < arr . length ; i += size ) {
chunks . push ( arr . slice ( i , i + size ));
}
return chunks ;
}
module . exports = new Command ({
name : cmdconfig . Mod . Command ,
2026-08-10 20:15:00 +01:00
description : cmdconfig . Mod . Description || "Moderation commands" ,
2024-11-09 00:37:51 +00:00
type : ApplicationCommandType . ChatInput ,
options : [
{
name : cmdconfig . Mod . TicketBlacklist . Command ,
2026-08-10 20:15:00 +01:00
description : cmdconfig . Mod . TicketBlacklist . Description || "Ticket Blacklist Commands" ,
2024-11-09 00:37:51 +00:00
type : ApplicationCommandOptionType . SubcommandGroup ,
options : [
{
name : cmdconfig . Mod . TicketBlacklist . Add . Command ,
2026-08-10 20:15:00 +01:00
description : msgconfig . Mod . TicketBlacklist . Add . Description || "Add a user to the blacklist" ,
2024-11-09 00:37:51 +00:00
type : ApplicationCommandOptionType . Subcommand ,
options : [
{
name : 'user' ,
2026-08-10 20:15:00 +01:00
description : 'The user to blacklist' ,
2024-11-09 00:37:51 +00:00
type : ApplicationCommandOptionType . User ,
required : true
},
{
2026-08-10 20:15:00 +01:00
name : 'reason' ,
description : 'Reason for blacklisting' ,
2024-11-09 00:37:51 +00:00
type : ApplicationCommandOptionType . String ,
required : false
}
]
},
{
name : cmdconfig . Mod . TicketBlacklist . Remove . Command ,
2026-08-10 20:15:00 +01:00
description : cmdconfig . Mod . TicketBlacklist . Remove . Description || "Remove a user from the blacklist" ,
2024-11-09 00:37:51 +00:00
type : ApplicationCommandOptionType . Subcommand ,
options : [
{
name : 'user' ,
2026-08-10 20:15:00 +01:00
description : 'The user to remove from the blacklist' ,
2024-11-09 00:37:51 +00:00
type : ApplicationCommandOptionType . User ,
required : true
},
{
name : 'reason' ,
2026-08-10 20:15:00 +01:00
description : 'Reason for unblacklisting' ,
2024-11-09 00:37:51 +00:00
type : ApplicationCommandOptionType . String ,
required : false
}
]
},
{
name : "view" ,
description : msgconfig . Mod . TicketBlacklist . View . Description || "View all blacklisted users" ,
2026-08-10 20:15:00 +01:00
type : ApplicationCommandOptionType . Subcommand
2024-11-09 00:37:51 +00:00
}
]
}
],
2026-08-28 17:48:09 +01:00
async run ( interaction ) {
2026-08-10 20:15:00 +01:00
const subcommandGroup = interaction . options . getSubcommandGroup ();
const subcommand = interaction . options . getSubcommand ();
2024-11-09 00:37:51 +00:00
const user = interaction . options . getUser ( 'user' );
const reason = interaction . options . getString ( 'reason' ) || "No reason provided" ;
try {
2026-08-10 20:15:00 +01:00
const blacklistedUsers = typeof db . getBlacklistedUsers === "function" ? db . getBlacklistedUsers () : [];
2024-11-09 00:37:51 +00:00
if ( subcommand === cmdconfig . Mod . TicketBlacklist . Add . Command ) {
2026-08-10 20:15:00 +01:00
if ( db . isUserBlacklisted && db . isUserBlacklisted ( user . id )) {
2024-11-09 00:37:51 +00:00
const alreadyBlacklistedEmbed = new EmbedBuilder ()
. setDescription ( msgconfig . Mod . TicketBlacklist . Add . AlreadyBlacklisted . replace ( "{userTag}" , user . tag ) || ":x: User is already blacklisted." )
. setColor ( supportbot . Embed . Colours . Warn );
2025-09-20 23:09:22 +01:00
return interaction . reply ({ embeds : [ alreadyBlacklistedEmbed ], flags : MessageFlags . Ephemeral });
2024-11-09 00:37:51 +00:00
}
2026-08-10 20:15:00 +01:00
if ( typeof db . addBlacklistedUser === "function" ) {
db . addBlacklistedUser ( user . id , reason , interaction . user . tag );
}
2024-11-09 00:37:51 +00:00
const successEmbed = new EmbedBuilder ()
. setDescription ( msgconfig . Mod . TicketBlacklist . Add . Success . replace ( "{userTag}" , user . tag ) || ":white_check_mark: User has been blacklisted." )
. setColor ( supportbot . Embed . Colours . Success );
const blacklistChannel = interaction . guild . channels . cache . get ( supportbot . Ticket . Log . TicketBlacklistLog );
if ( blacklistChannel ) {
const blacklistLogEmbed = new EmbedBuilder ()
. setTitle ( msgconfig . TicketBlacklistLog . Title || "Ticket Blacklist Log" )
. setColor ( msgconfig . TicketBlacklistLog . Colour || supportbot . Embed . Colours . Success )
. setFooter ({ text : supportbot . Embed . Footer , iconURL : interaction . user . displayAvatarURL () })
. setDescription ( `> **User:** ${ user . tag } (\` ${ user . id } \`)\n> **Actioned by:** <@ ${ interaction . user . id } >` )
2026-08-10 20:15:00 +01:00
. addFields ({ name : "Action" , value : "\`\`\`Added to blacklist\`\`\`" , inline : false })
2024-11-09 00:37:51 +00:00
. addFields ({ name : "Reason" , value : `\`\`\` ${ reason } \`\`\`` , inline : false });
blacklistChannel . send ({ embeds : [ blacklistLogEmbed ] });
}
return interaction . reply ({
embeds : [ successEmbed ],
2025-09-20 23:09:22 +01:00
flags : MessageFlags . Ephemeral
2024-11-09 00:37:51 +00:00
});
} else if ( subcommand === cmdconfig . Mod . TicketBlacklist . Remove . Command ) {
2026-08-10 20:15:00 +01:00
if ( db . isUserBlacklisted && ! db . isUserBlacklisted ( user . id )) {
2024-11-09 00:37:51 +00:00
const notBlacklistedEmbed = new EmbedBuilder ()
. setDescription ( msgconfig . Mod . TicketBlacklist . Remove . NotBlacklisted . replace ( "{userTag}" , user . tag ) || ":x: User is not blacklisted." )
. setColor ( supportbot . Embed . Colours . Warn );
2025-09-20 23:09:22 +01:00
return interaction . reply ({ embeds : [ notBlacklistedEmbed ], flags : MessageFlags . Ephemeral });
2024-11-09 00:37:51 +00:00
}
2026-08-10 20:15:00 +01:00
if ( typeof db . removeBlacklistedUser === "function" ) {
db . removeBlacklistedUser ( user . id );
}
2024-11-09 00:37:51 +00:00
const removedEmbed = new EmbedBuilder ()
. setDescription ( msgconfig . Mod . TicketBlacklist . Remove . Success . replace ( "{userTag}" , user . tag ) || ":white_check_mark: User has been removed from the blacklist." )
. setColor ( supportbot . Embed . Colours . Success );
const blacklistChannel = interaction . guild . channels . cache . get ( supportbot . Ticket . Log . TicketBlacklistLog );
if ( blacklistChannel ) {
const blacklistLogEmbed = new EmbedBuilder ()
. setTitle ( msgconfig . TicketBlacklistLog . Title || "Ticket Blacklist Log" )
. setColor ( msgconfig . TicketBlacklistLog . Colour || supportbot . Embed . Colours . Success )
. setFooter ({ text : supportbot . Embed . Footer , iconURL : interaction . user . displayAvatarURL () })
. setDescription ( `> **User:** ${ user . tag } (\` ${ user . id } \`)\n> **Actioned by:** <@ ${ interaction . user . id } >` )
. addFields ({ name : "Action" , value : "\`\`\`Removed from blacklist\`\`\`" , inline : false })
. addFields ({ name : "Reason" , value : `\`\`\` ${ reason } \`\`\`` , inline : false });
blacklistChannel . send ({ embeds : [ blacklistLogEmbed ] });
}
2025-09-20 23:09:22 +01:00
return interaction . reply ({ embeds : [ removedEmbed ], flags : MessageFlags . Ephemeral });
2024-11-09 00:37:51 +00:00
} else if ( subcommand === "view" ) {
if ( blacklistedUsers . length === 0 ) {
const noBlacklistedUsersEmbed = new EmbedBuilder ()
. setDescription ( msgconfig . Mod . TicketBlacklist . View . NoBlacklistedUsers || "No users are blacklisted." )
. setColor ( supportbot . Embed . Colours . Success );
2025-09-20 23:09:22 +01:00
return interaction . reply ({ embeds : [ noBlacklistedUsersEmbed ], flags : MessageFlags . Ephemeral });
2024-11-09 00:37:51 +00:00
}
const chunkedUsers = chunkArray ( blacklistedUsers , 5 );
let currentPage = 0 ;
const createEmbed = ( page ) => {
return new EmbedBuilder ()
. setTitle ( msgconfig . Mod . TicketBlacklist . View . EmbedTitle || "Blacklisted Users" )
. setDescription ( chunkedUsers [ page ]. map ( id => `<@ ${ id } >` ). join ( "\n" ))
. setColor ( supportbot . Embed . Colours . Success )
. setFooter ({ text : `Page ${ page + 1 } of ${ chunkedUsers . length } ` });
};
const buttons = new ActionRowBuilder ()
. addComponents (
new ButtonBuilder ()
. setCustomId ( 'previous' )
. setLabel ( 'Previous' )
. setStyle ( ButtonStyle . Secondary )
. setDisabled ( currentPage === 0 ),
new ButtonBuilder ()
. setCustomId ( 'next' )
. setLabel ( 'Next' )
. setStyle ( ButtonStyle . Secondary )
. setDisabled ( currentPage === chunkedUsers . length - 1 )
);
const response = await interaction . reply ({
embeds : [ createEmbed ( currentPage )],
components : chunkedUsers . length > 1 ? [ buttons ] : [],
2025-09-20 23:09:22 +01:00
flags : MessageFlags . Ephemeral
2024-11-09 00:37:51 +00:00
});
if ( chunkedUsers . length <= 1 ) return ;
const collector = response . createMessageComponentCollector ({
componentType : ComponentType . Button ,
time : 60000
});
collector . on ( 'collect' , async ( i ) => {
if ( i . user . id !== interaction . user . id ) {
return i . reply ({
content : 'You cannot use these buttons.' ,
2025-09-20 23:09:22 +01:00
flags : MessageFlags . Ephemeral
2024-11-09 00:37:51 +00:00
});
}
if ( i . customId === 'previous' && currentPage > 0 ) {
currentPage -- ;
} else if ( i . customId === 'next' && currentPage < chunkedUsers . length - 1 ) {
currentPage ++ ;
}
buttons . components [ 0 ]. setDisabled ( currentPage === 0 );
buttons . components [ 1 ]. setDisabled ( currentPage === chunkedUsers . length - 1 );
await i . update ({
embeds : [ createEmbed ( currentPage )],
components : [ buttons ]
});
});
collector . on ( 'end' , () => {
buttons . components . forEach ( button => button . setDisabled ( true ));
interaction . editReply ({
components : [ buttons ]
}). catch (() => {});
});
}
} catch ( error ) {
console . error ( "Error in mod command:" , error );
const errorEmbed = new EmbedBuilder ()
. setDescription ( msgconfig . Error . ActionFailed || "An error occurred while processing your request." )
. setColor ( supportbot . Embed . Colours . Warn );
2025-09-20 23:09:22 +01:00
interaction . reply ({ embeds : [ errorEmbed ], flags : MessageFlags . Ephemeral });
2024-11-09 00:37:51 +00:00
}
}
});