@@ -3,6 +3,10 @@ import {
33 SlashCommandBuilder ,
44 EmbedBuilder ,
55 GuildMember ,
6+ ActionRowBuilder ,
7+ ButtonBuilder ,
8+ ButtonStyle ,
9+ ComponentType ,
610 MessageFlags ,
711} from "discord.js" ;
812import { LinkLogger } from "../utils/linkLogger.js" ;
@@ -69,39 +73,45 @@ export async function execute(
6973 {
7074 name : "📜 CONFIRMATION REQUIRED" ,
7175 value :
72- "React with 🖋️ within 1 minute to proceed with the severance ritual." ,
76+ "Click the button below within 60 seconds to proceed with the severance ritual." ,
7377 inline : false ,
7478 } ,
7579 )
76- . setFooter ( { text : "This confirmation will expire in 60 seconds" } )
80+ . setFooter ( { text : "This confirmation expires in 60 seconds" } )
7781 . setTimestamp ( ) ;
7882
79- const confirmationMessage = await interaction . reply ( {
80- embeds : [ confirmationEmbed ] ,
81- flags : MessageFlags . Ephemeral ,
82- } ) ;
83+ const confirmButton = new ButtonBuilder ( )
84+ . setCustomId ( "confirm_severance" )
85+ . setLabel ( "Sever the Link" )
86+ . setEmoji ( "♠️" )
87+ . setStyle ( ButtonStyle . Danger ) ;
8388
84- const message = await confirmationMessage . fetch ( ) ;
89+ const cancelButton = new ButtonBuilder ( )
90+ . setCustomId ( "cancel_severance" )
91+ . setLabel ( "Cancel" )
92+ . setEmoji ( "❌" )
93+ . setStyle ( ButtonStyle . Secondary ) ;
8594
86- try {
87- await message . react ( "🖋️" ) ;
88- } catch ( error ) {
89- console . error ( "Failed to add reaction:" , error ) ;
90- }
95+ const row = new ActionRowBuilder < ButtonBuilder > ( ) . addComponents (
96+ cancelButton ,
97+ confirmButton ,
98+ ) ;
9199
92- const filter = ( reaction : any , user : any ) => {
93- return reaction . emoji . name === "🖋️" && user . id === interaction . user . id ;
94- } ;
100+ const response = await interaction . reply ( {
101+ embeds : [ confirmationEmbed ] ,
102+ components : [ row ] ,
103+ flags : MessageFlags . Ephemeral ,
104+ } ) ;
95105
96106 try {
97- const collected = await message . awaitReactions ( {
98- filter,
99- max : 1 ,
107+ const confirmation = await response . awaitMessageComponent ( {
108+ filter : ( i ) => i . user . id === interaction . user . id ,
109+ componentType : ComponentType . Button ,
100110 time : 60000 ,
101- errors : [ "time" ] ,
102111 } ) ;
103112
104- if ( collected . size > 0 ) {
113+ if ( confirmation . customId === "confirm_severance" ) {
114+ await confirmation . deferUpdate ( ) ;
105115 await LinkLogger . removeLink ( targetUser . id ) ;
106116
107117 if ( targetMember ) {
@@ -111,14 +121,11 @@ export async function execute(
111121 TOP_CONTRIBUTORS_ROLE_ID ,
112122 ...FANDOM_ROLE_IDS ,
113123 ...EDIT_COUNT_ROLE_IDS ,
114- ] ;
115- const rolesToRemoveFiltered = rolesToRemove . filter ( ( roleId ) =>
116- targetMember . roles . cache . has ( roleId ) ,
117- ) ;
124+ ] . filter ( ( roleId ) => targetMember . roles . cache . has ( roleId ) ) ;
118125
119- if ( rolesToRemoveFiltered . length > 0 ) {
126+ if ( rolesToRemove . length > 0 ) {
120127 try {
121- await targetMember . roles . remove ( rolesToRemoveFiltered ) ;
128+ await targetMember . roles . remove ( rolesToRemove ) ;
122129 } catch ( roleError ) {
123130 console . error ( "Failed to remove roles during unlink:" , roleError ) ;
124131 }
@@ -134,51 +141,50 @@ export async function execute(
134141 . addFields (
135142 {
136143 name : "EXECUTOR OF SEVERANCE" ,
137- value : ` ${ executor . user . tag } ` ,
144+ value : executor . user . tag ,
138145 inline : true ,
139146 } ,
140147 {
141- name : "SEVERED LINKING " ,
148+ name : "SEVERED LINK " ,
142149 value : `Discord: ${ targetUser . tag } \nFandom: ${ existingLink . fandomUsername } ` ,
143150 inline : true ,
144151 } ,
145152 {
146153 name : "ROLES REMOVED" ,
147154 value : targetMember
148- ? "All linked and Fandom specific roles have been stripped."
149- : "User not in server - roles could not be removed ." ,
155+ ? "All linked and Fandom- specific roles have been stripped."
156+ : "User not in server — roles could not be modified ." ,
150157 inline : false ,
151158 } ,
152159 )
153160 . setTimestamp ( ) ;
154161
155- await interaction . followUp ( { embeds : [ successEmbed ] } ) ;
162+ await interaction . editReply ( {
163+ embeds : [ successEmbed ] ,
164+ components : [ ] ,
165+ } ) ;
156166
157167 try {
158168 await targetUser . send (
159- `**THY LINK HATH BEEN SEVERED!\n\nThy connection to the Fandom alter "${ existingLink . fandomUsername } " has been severed by ${ executor . user . tag } .\n\nTo restore thy link, thou must use the /link command again and verify thy identity anew.** ` ,
169+ `**THY LINK HATH BEEN SEVERED!** \n\nThy connection to the Fandom alter "${ existingLink . fandomUsername } " has been severed by ** ${ executor . user . tag } ** .\n\nTo restore thy link, thou must use the /link command again and verify thy identity anew.` ,
160170 ) ;
161171 } catch ( dmError ) {
162- console . log ( "Failed to send DM to unlinked user:" , dmError ) ;
172+ console . log ( `Could not DM ${ targetUser . tag } :` , dmError ) ;
163173 }
174+ } else if ( confirmation . customId === "cancel_severance" ) {
175+ await confirmation . update ( {
176+ content :
177+ "**THE SEVERANCE RITUAL HATH BEEN CANCELED. THE LINK REMAINS INTACT.**" ,
178+ embeds : [ ] ,
179+ components : [ ] ,
180+ } ) ;
164181 }
165182 } catch ( error ) {
166- const timeoutEmbed = new EmbedBuilder ( )
167- . setColor ( "#808080" )
168- . setTitle ( "⏰ SEVERANCE RITUAL EXPIRED" )
169- . setDescription (
170- "**THE SEVERANCE CONFIRMATION HAS EXPIRED. NO CHANGES WERE MADE.**" ,
171- )
172- . addFields ( {
173- name : "TO RETRY" ,
174- value :
175- "Run the `/removelink` command again to restart the severance process." ,
176- inline : false ,
177- } ) ;
178-
179- await interaction . followUp ( {
180- embeds : [ timeoutEmbed ] ,
181- flags : MessageFlags . Ephemeral ,
183+ await interaction . editReply ( {
184+ content :
185+ "**⏰ THE SEVERANCE RITUAL HAS EXPIRED. NO CHANGES WERE MADE.**" ,
186+ embeds : [ ] ,
187+ components : [ ] ,
182188 } ) ;
183189 }
184190 } catch ( error ) {
0 commit comments