@@ -3,174 +3,127 @@ const { SlashCommandBuilder, EmbedBuilder, ButtonBuilder, ButtonStyle, ActionRow
33module . exports = {
44 data : new SlashCommandBuilder ( )
55 . setName ( 'mod-panel' )
6- . setDescription ( 'Moderate a member.' )
7- . setDefaultMemberPermissions ( PermissionFlagsBits . BanMembers )
8- . addUserOption ( option => option . setName ( "user" ) . setDescription ( "The user you want to moderate" ) . setRequired ( true ) )
9- . addStringOption ( option => option . setName ( 'reason' ) . setDescription ( 'Reason for moderating the member' ) . setRequired ( false ) )
10- . addIntegerOption ( option => option . setName ( 'time' ) . setDescription ( 'This is how long the user\'s punishment is going to last (in minutes). Default: 1 hour' ) . setRequired ( false ) ) ,
11- async execute ( interaction , client ) {
12- if ( ! interaction . member . permissions . has ( PermissionsBitField . Flags . Administrator ) ) return await interaction . reply ( { content : `${ client . config . noPerms } ` , flags : MessageFlags . Ephemeral } ) ;
6+ . setDescription ( 'Moderate a member with various punishment options.' )
7+ . setDefaultMemberPermissions ( PermissionFlagsBits . ModerateMembers )
8+ . addUserOption ( option => option . setName ( "user" ) . setDescription ( "The user you want to moderate" ) . setRequired ( true ) ) ,
9+
10+ async execute ( interaction , client ) {
11+ if ( ! interaction . member . permissions . has ( PermissionsBitField . Flags . ModerateMembers ) ) {
12+ return await interaction . reply ( {
13+ content : `${ client . config . noPerms } ` ,
14+ flags : MessageFlags . Ephemeral
15+ } ) ;
16+ }
1317
14- const target = await interaction . options . getUser ( `user` ) ;
15- const member = await interaction . options . getMember ( "user" )
16- const reason = await interaction . options . getString ( `reason` ) || "\`\`No reason given\`\`" ;
17- const length = await interaction . options . getInteger ( `time` ) || 60 ;
18- let guild = await interaction . guild . fetch ( ) ;
19-
20- const mod_panel = new EmbedBuilder ( )
21- . setAuthor ( { name : `${ client . user . username } Mod Panel` } )
22- . setTitle ( `> ${ client . config . modEmojiHard } Mod panel tool ${ client . config . arrowEmoji } ` )
23- . setThumbnail ( member . displayAvatarURL ( { size : 1024 , format : `png` , dynamic : true } ) )
24- . addFields ( { name : `Target:` , value : `> ${ target } ` , inline : true } )
25- . addFields ( { name : `Target ID:` , value : `> \`${ target . id } \`` , inline : true } )
26- . addFields ( { name : `Timeout Length:` , value : `> \`${ length } minute(s)\`` , inline : true } )
27- . addFields ( { name : `Reason for Punishment:` , value : `> \`${ reason } \`` , inline : false } )
28- . setFooter ( { text : `Mod panel ${ client . config . devBy } ` } )
29- . setTimestamp ( )
30- . setColor ( client . config . embedModHard )
31-
32- const row_1 = new ActionRowBuilder ( )
33- . addComponents (
34- new ButtonBuilder ( )
35- . setCustomId ( 'timeout' )
36- . setEmoji ( '⏳' )
37- . setLabel ( 'Timeout' )
38- . setStyle ( ButtonStyle . Secondary ) ,
39- new ButtonBuilder ( )
40- . setCustomId ( 'kick' )
41- . setEmoji ( '🦵' )
42- . setLabel ( 'Kick' )
43- . setStyle ( ButtonStyle . Primary ) ,
44- new ButtonBuilder ( )
45- . setCustomId ( 'ban' )
46- . setEmoji ( '🛠️' )
47- . setLabel ( 'Ban' )
48- . setStyle ( ButtonStyle . Danger ) ,
49- new ButtonBuilder ( )
50- . setLabel ( `Delete` )
51- . setCustomId ( `delete` )
52- . setEmoji ( '✖️' )
53- . setStyle ( ButtonStyle . Danger ) )
18+ const target = await interaction . options . getUser ( 'user' ) ;
19+ const member = await interaction . options . getMember ( 'user' ) ;
20+ const guild = interaction . guild ;
5421
55- const failEmbed = new EmbedBuilder ( )
56- . setColor ( client . config . embedModHard )
57- . setDescription ( `Failed to moderate **${ target } **.` )
58- . setFooter ( { text : `${ client . user . username } Moderation Tool ${ client . config . devBy } ` } )
22+ if ( ! member ) {
23+ return await interaction . reply ( {
24+ content : "This user is not a member of this server." ,
25+ flags : MessageFlags . Ephemeral
26+ } ) ;
27+ }
5928
60- const banEmbed = new EmbedBuilder ( )
61- . setColor ( client . config . embedModHard )
62- . setAuthor ( { name : `${ client . user . username } Moderation Tool` } )
63- . setTitle ( `> ${ client . config . modEmojiHard } You were **banned** from "${ guild . name } " ${ client . config . arrowEmoji } ` )
64- . addFields ( { name : 'Server' , value : `> ${ guild . name } ` , inline : true } )
65- . addFields ( { name : 'Reason' , value : `> ${ reason } ` , inline : true } )
66- . setFooter ( { text : `Banned from ${ guild . name } ${ client . config . devBy } ` } )
67- . setTimestamp ( )
68- . setThumbnail ( client . user . avatarURL ( ) )
29+ if ( interaction . member . id === member . id ) {
30+ return await interaction . reply ( {
31+ content : "You cannot moderate yourself." ,
32+ flags : MessageFlags . Ephemeral
33+ } ) ;
34+ }
6935
70- const timeoutEmbed = new EmbedBuilder ( )
71- . setColor ( client . config . embedModHard )
72- . setAuthor ( { name : `${ client . user . username } Moderation Tool` } )
73- . setTitle ( `> ${ client . config . modEmojiHard } You were **Timed-out** in "${ guild . name } " ${ client . config . arrowEmoji } ` )
74- . addFields ( { name : 'Server' , value : `> ${ guild . name } ` , inline : true } )
75- . addFields ( { name : 'Reason' , value : `> ${ reason } ` , inline : true } )
76- . addFields ( { name : 'Length' , value : `> ${ length } minute(s)` , inline : true } )
77- . setFooter ( { text : `Timed-out in ${ guild . name } ${ client . config . devBy } ` } )
78- . setTimestamp ( )
79- . setThumbnail ( client . user . avatarURL ( ) )
36+ if ( interaction . member . roles . highest . position <= member . roles . highest . position ) {
37+ return await interaction . reply ( {
38+ content : "You cannot moderate a member with the same or higher role than you." ,
39+ flags : MessageFlags . Ephemeral
40+ } ) ;
41+ }
42+
43+ if ( ! member . moderatable ) {
44+ return await interaction . reply ( {
45+ content : "I don't have permission to moderate this user. Their role may be higher than mine." ,
46+ flags : MessageFlags . Ephemeral
47+ } ) ;
48+ }
49+
50+ const panelId = Date . now ( ) . toString ( ) ;
8051
81- const kickEmbed = new EmbedBuilder ( )
82- . setColor ( client . config . embedModHard )
83- . setAuthor ( { name : `${ client . user . username } Moderation Tool` } )
84- . setTitle ( `> ${ client . config . modEmojiHard } You were **kicked** from "${ guild . name } " ${ client . config . arrowEmoji } ` )
85- . addFields ( { name : 'Server' , value : `> ${ guild . name } ` , inline : true } )
86- . addFields ( { name : 'Reason' , value : `> ${ reason } ` , inline : true } )
87- . setFooter ( { text : `Kicked from ${ guild . name } ${ client . config . devBy } ` } )
88- . setTimestamp ( )
89- . setThumbnail ( client . user . avatarURL ( ) )
52+ const mod_panel = new EmbedBuilder ( )
53+ . setAuthor ( { name : `${ client . user . username } Moderation Panel` } )
54+ . setTitle ( `> ${ client . config . modEmojiHard } Moderation Panel ${ client . config . arrowEmoji } ` )
55+ . setThumbnail ( member . displayAvatarURL ( { size : 1024 , format : 'png' , dynamic : true } ) )
56+ . addFields (
57+ { name : `Target User` , value : `> ${ target } (${ target . tag } )` , inline : true } ,
58+ { name : `Target ID` , value : `> \`${ target . id } \`` , inline : true } ,
59+ { name : `Instructions` , value : `> Select an action below. You will be prompted for additional details as needed.` }
60+ )
61+ . setFooter ( { text : `Moderation panel ${ client . config . devBy } • Panel ID: ${ panelId } ` } )
62+ . setTimestamp ( )
63+ . setColor ( client . config . embedModHard ) ;
9064
91- const banEmbed2 = new EmbedBuilder ( )
92- . setColor ( client . config . embedModHard )
93- . setAuthor ( { name : `${ client . user . username } Moderation Tool` } )
94- . setTitle ( `> ${ client . config . modEmojiHard } User was **\`BANNED\`** from "${ guild . name } " ${ client . config . arrowEmoji } ` )
95- . addFields ( { name : `Moderator:` , value : `${ interaction . user . tag } ` , inline : true } )
96- . addFields ( { name : `User:` , value : `${ target } ` , inline : true } )
97- . addFields ( { name : 'Reason' , value : `> ${ reason } ` , inline : true } )
98- . setFooter ( { text : `Banned from ${ guild . name } ${ client . config . devBy } ` } )
99- . setTimestamp ( )
100- . setThumbnail ( client . user . avatarURL ( ) )
65+ const actionButtons = new ActionRowBuilder ( )
66+ . addComponents (
67+ new ButtonBuilder ( )
68+ . setCustomId ( `modpanel_${ panelId } _${ interaction . user . id } _${ target . id } _timeout` )
69+ . setEmoji ( '⏳' )
70+ . setLabel ( 'Timeout' )
71+ . setStyle ( ButtonStyle . Secondary ) ,
72+ new ButtonBuilder ( )
73+ . setCustomId ( `modpanel_${ panelId } _${ interaction . user . id } _${ target . id } _kick` )
74+ . setEmoji ( '🦵' )
75+ . setLabel ( 'Kick' )
76+ . setStyle ( ButtonStyle . Primary ) ,
77+ new ButtonBuilder ( )
78+ . setCustomId ( `modpanel_${ panelId } _${ interaction . user . id } _${ target . id } _ban` )
79+ . setEmoji ( '🔨' )
80+ . setLabel ( 'Ban' )
81+ . setStyle ( ButtonStyle . Danger ) ,
82+ ) ;
83+
84+ const secondRow = new ActionRowBuilder ( )
85+ . addComponents (
86+ new ButtonBuilder ( )
87+ . setCustomId ( `modpanel_${ panelId } _${ interaction . user . id } _${ target . id } _softban` )
88+ . setEmoji ( '🧹' )
89+ . setLabel ( 'Soft Ban' )
90+ . setStyle ( ButtonStyle . Danger ) ,
91+ new ButtonBuilder ( )
92+ . setCustomId ( `modpanel_${ panelId } _${ interaction . user . id } _${ target . id } _delete` )
93+ . setEmoji ( '✖️' )
94+ . setLabel ( 'Cancel' )
95+ . setStyle ( ButtonStyle . Secondary ) ,
96+ ) ;
10197
102- const kickEmbed2 = new EmbedBuilder ( )
103- . setColor ( client . config . embedModHard )
104- . setAuthor ( { name : `${ client . user . username } Moderation Tool` } )
105- . setTitle ( `> ${ client . config . modEmojiHard } User was **\`KICKED\`** from "${ guild . name } " ${ client . config . arrowEmoji } ` )
106- . addFields ( { name : `Moderator:` , value : `${ interaction . user . tag } ` , inline : true } )
107- . addFields ( { name : `User:` , value : `${ target } ` , inline : true } )
108- . addFields ( { name : 'Reason' , value : `> ${ reason } ` , inline : true } )
109- . setFooter ( { text : `Kicked from ${ guild . name } ${ client . config . devBy } ` } )
110- . setTimestamp ( )
111- . setThumbnail ( client . user . avatarURL ( ) )
98+ if ( ! client . modPanels ) client . modPanels = new Map ( ) ;
11299
113- const timeoutEmbed2 = new EmbedBuilder ( )
114- . setColor ( client . config . embedModHard )
115- . setAuthor ( { name : `${ client . user . username } Moderation Tool` } )
116- . setTitle ( `> ${ client . config . modEmojiHard } User was **\`TIMED-OUT\`** from "${ guild . name } " ${ client . config . arrowEmoji } ` )
117- . addFields ( { name : `Moderator:` , value : `${ interaction . user . tag } ` , inline : true } )
118- . addFields ( { name : `User:` , value : `${ target } ` , inline : true } )
119- . addFields ( { name : 'Length' , value : `> ${ length } minute(s)` , inline : true } )
120- . addFields ( { name : 'Reason' , value : `> ${ reason } ` , inline : true } )
121- . setFooter ( { text : `Timed-out in ${ guild . name } ${ client . config . devBy } ` } )
122- . setTimestamp ( )
123- . setThumbnail ( client . user . avatarURL ( ) )
124-
125- const msg = await interaction . reply ( { embeds : [ mod_panel ] , components : [ row_1 ] } )
126-
127- collector = msg . createMessageComponentCollector ( )
128- collector . on ( 'collect' , async i => {
129- if ( i . customId == 'kick' ) {
130- if ( i . user . id !== interaction . user . id ) {
131- return await i . reply ( { content : `Only ${ interaction . user . tag } can interact with the buttons!` , flags : MessageFlags . Ephemeral } )
100+ client . modPanels . set ( panelId , {
101+ moderatorId : interaction . user . id ,
102+ moderatorTag : interaction . user . tag ,
103+ targetId : target . id ,
104+ targetTag : target . tag ,
105+ memberId : member . id ,
106+ guildId : guild . id ,
107+ guildName : guild . name ,
108+ messageId : null ,
109+ createdAt : Date . now ( ) ,
110+ expiryTimeout : setTimeout ( ( ) => {
111+ if ( client . modPanels . has ( panelId ) ) {
112+ client . modPanels . delete ( panelId ) ;
113+ client . logs . info ( `[MOD_PANEL] Panel ${ panelId } expired and was removed from cache` ) ;
132114 }
133- target . send ( { embeds : [ kickEmbed ] } ) . catch ( ( err ) => { return client . logs . error ( '[MOD_PANEL_KICK] Failed to DM user.' ) } ) ;
134- let kick = await guild . members . kick ( target ) . catch ( ( err ) => {
135- client . logs . error ( "Error with Kick command: " + err )
136- } )
137- await interaction . channel . send ( { embeds : [ kickEmbed2 ] } ) ;
138- if ( ! kick ) {
139- await interaction . reply ( { embeds : [ failEmbed ] , flags : MessageFlags . Ephemeral } )
140- }
141- }
142- if ( i . customId == 'timeout' ) {
143- if ( i . user . id !== interaction . user . id ) {
144- return await i . reply ( { content : `Only ${ interaction . user . tag } can interact with the buttons!` , flags : MessageFlags . Ephemeral } )
145- }
146- target . send ( { embeds : [ timeoutEmbed ] } ) . catch ( ( err ) => { return client . logs . error ( '[MOD_PANEL_TIMEOUT] Failed to DM user.' ) } ) ;
147- let timeout = await member . timeout ( length * 60000 ) . catch ( ( err ) => {
148- client . logs . error ( "Error with timeout command: " + err )
149- } )
150- await interaction . channel . send ( { embeds : [ timeoutEmbed2 ] } ) ;
151- if ( ! timeout ) {
152- await interaction . reply ( { embeds : [ failEmbed ] , flags : MessageFlags . Ephemeral } )
153- }
154- }
155- if ( i . customId == 'delete' ) {
156- if ( i . user . id !== interaction . user . id ) {
157- return await i . reply ( { content : `Only ${ interaction . user . tag } can interact with the buttons!` , flags : MessageFlags . Ephemeral } )
158- }
159- interaction . deleteReply ( ) ;
160- }
161- if ( i . customId == 'ban' ) {
162- if ( i . user . id !== interaction . user . id ) {
163- return await i . reply ( { content : `Only ${ interaction . user . tag } can interact with the buttons!` , flags : MessageFlags . Ephemeral } )
164- }
165- target . send ( { embeds : [ banEmbed ] } ) . catch ( ( err ) => { return client . logs . error ( '[MOD_PANEL_BAN] Failed to DM user.' ) } ) ;
166- await interaction . channel . send ( { embeds : [ banEmbed2 ] } ) ;
167- let ban = await guild . members . ban ( target , { reason : `${ reason } ` } ) . catch ( ( err ) => {
168- client . logs . error ( "Error with Ban command: " + err )
169- } )
170- if ( ! ban ) {
171- await interaction . reply ( { embeds : [ failEmbed ] , flags : MessageFlags . Ephemeral } )
172- }
173- }
174- } )
115+ } , 180000 )
116+ } ) ;
117+
118+ const response = await interaction . reply ( {
119+ embeds : [ mod_panel ] ,
120+ components : [ actionButtons , secondRow ]
121+ } ) . then ( ( ) => interaction . fetchReply ( ) ) ;
122+
123+ if ( client . modPanels . has ( panelId ) ) {
124+ const panelData = client . modPanels . get ( panelId ) ;
125+ panelData . messageId = response . id ;
126+ client . modPanels . set ( panelId , panelData ) ;
127+ }
175128 }
176- }
129+ } ;
0 commit comments