55 ContainerBuilder ,
66 TextDisplayBuilder ,
77 MessageFlags ,
8+ SeparatorSpacingSize ,
9+ ButtonBuilder ,
10+ ButtonStyle ,
811} from "discord.js" ;
912import {
1013 getBooster ,
@@ -14,54 +17,59 @@ import {
1417 getActiveBoosters ,
1518 getTotalBoosts ,
1619 registerBoost ,
20+ removeBoost ,
1721} from "../services/boosterService.js" ;
1822import { Command } from "../base/classes/command.js" ;
23+ import { logger } from "../libs/logger.js" ;
1924
2025export default new Command ( {
2126 info : new SlashCommandBuilder ( )
22- . setName ( "booster" )
27+ . setName ( "booster" )
2328 . setDescription ( "Booster management commands" )
2429 . setDefaultMemberPermissions ( PermissionFlagsBits . ManageGuild )
2530 . addSubcommand ( ( sub ) =>
2631 sub
2732 . setName ( "check" )
2833 . setDescription ( "Check booster info for a user" )
2934 . addUserOption ( ( opt ) =>
30- opt . setName ( "user" ) . setDescription ( "The user to check" ) . setRequired ( true )
31- )
35+ opt
36+ . setName ( "user" )
37+ . setDescription ( "The user to check" )
38+ . setRequired ( true ) ,
39+ ) ,
3240 )
3341 . addSubcommand ( ( sub ) =>
3442 sub
3543 . setName ( "add" )
3644 . setDescription ( "Add boost count to a user" )
3745 . addUserOption ( ( opt ) =>
38- opt . setName ( "user" ) . setDescription ( "The user" ) . setRequired ( true )
46+ opt . setName ( "user" ) . setDescription ( "The user" ) . setRequired ( true ) ,
3947 )
4048 . addIntegerOption ( ( opt ) =>
4149 opt
4250 . setName ( "amount" )
4351 . setDescription ( "Amount to add" )
4452 . setRequired ( true )
45- . setMinValue ( 1 )
46- )
53+ . setMinValue ( 1 ) ,
54+ ) ,
4755 )
4856 . addSubcommand ( ( sub ) =>
4957 sub
5058 . setName ( "remove" )
5159 . setDescription ( "Remove boost count from a user" )
5260 . addUserOption ( ( opt ) =>
53- opt . setName ( "user" ) . setDescription ( "The user" ) . setRequired ( true )
61+ opt . setName ( "user" ) . setDescription ( "The user" ) . setRequired ( true ) ,
5462 )
5563 . addIntegerOption ( ( opt ) =>
5664 opt
5765 . setName ( "amount" )
5866 . setDescription ( "Amount to remove" )
5967 . setRequired ( true )
60- . setMinValue ( 1 )
61- )
68+ . setMinValue ( 1 ) ,
69+ ) ,
6270 )
6371 . addSubcommand ( ( sub ) =>
64- sub . setName ( "stats" ) . setDescription ( "View server boost statistics" )
72+ sub . setName ( "stats" ) . setDescription ( "View server boost statistics" ) ,
6573 ) ,
6674 async execute ( interaction ) {
6775 const sub = interaction . options . getSubcommand ( ) ;
@@ -80,13 +88,18 @@ export default new Command({
8088 if ( sub === "check" ) {
8189 const user = interaction . options . getUser ( "user" , true ) ;
8290 const result = await getBooster ( user . id , interaction ) ;
83- const member = await discordGuild . members . fetch ( user . id ) . catch ( ( ) => null ) ;
91+ const member = await discordGuild . members
92+ . fetch ( user . id )
93+ . catch ( ( ) => null ) ;
8494 const isBoostingServer = member ?. premiumSince !== null ;
8595 const avatarUrl =
86- member ?. displayAvatarURL ( { size : 256 } ) ?? user . displayAvatarURL ( { size : 256 } ) ;
96+ member ?. displayAvatarURL ( { size : 256 } ) ??
97+ user . displayAvatarURL ( { size : 256 } ) ;
8798
8899 if ( ! result ?. success ) {
89- await interaction . editReply ( { content : "Could not load booster info for this server." } ) ;
100+ await interaction . editReply ( {
101+ content : "Could not load booster info for this server." ,
102+ } ) ;
90103 return ;
91104 }
92105
@@ -98,10 +111,14 @@ export default new Command({
98111 . setTitle ( `Here is the Booster Information for ${ user . id } !` )
99112 . setThumbnail ( avatarUrl )
100113 . addFields (
101- { name : "Status" , value : "🟢 Active (Nitro Boost)" , inline : true } ,
114+ {
115+ name : "Status" ,
116+ value : "🟢 Active (Nitro Boost)" ,
117+ inline : true ,
118+ } ,
102119 { name : "Discord boost" , value : discordBoost , inline : true } ,
103120 { name : "Custom Role" , value : "None" , inline : true } ,
104- { name : "User Ping" , value : `<@${ user . id } >` }
121+ { name : "User Ping" , value : `<@${ user . id } >` } ,
105122 )
106123 . setTimestamp ( ) ;
107124
@@ -113,7 +130,9 @@ export default new Command({
113130 . setAccentColor ( 0xe642a4 )
114131 . addTextDisplayComponents (
115132 new TextDisplayBuilder ( ) . setContent ( "**Uh oh!**" ) ,
116- new TextDisplayBuilder ( ) . setContent ( `It looks like ${ user } is not a Booster.` )
133+ new TextDisplayBuilder ( ) . setContent (
134+ `It looks like ${ user } is not a Booster.` ,
135+ ) ,
117136 ) ;
118137
119138 await interaction . editReply ( {
@@ -125,19 +144,75 @@ export default new Command({
125144
126145 const booster = result . data ;
127146
147+ if ( booster . boostCounts == 0 ) {
148+ try {
149+ await removeBoost ( booster . userId , interaction . guild . id ) ;
150+ } catch ( err ) {
151+ logger . error (
152+ `An error occured while removing ${ booster . userId } 's data: ${ err } ` ,
153+ ) ;
154+
155+ const supportButton = new ButtonBuilder ( )
156+ . setStyle ( ButtonStyle . Link )
157+ . setLabel ( "Our Support Server" )
158+ . setURL ( "https://discord.gg/NUtyKs7hA6" ) ;
159+
160+ const container = new ContainerBuilder ( )
161+ . setAccentColor ( 0xe642a4 )
162+ . addTextDisplayComponents (
163+ new TextDisplayBuilder ( ) . setContent ( "**Uh oh!**" ) ,
164+ new TextDisplayBuilder ( ) . setContent (
165+ `It looks like we ran into an issue\n-# If this issue is persistent, please consult your console logs if you're using a self-hosted version of Boostify, and create an issue on our [Repository](https://github.com/teamboostify/boostify/issues), or use our support server!.` ,
166+ ) ,
167+ )
168+ . addSeparatorComponents ( ( sep ) =>
169+ sep . setDivider ( true ) . setSpacing ( SeparatorSpacingSize . Small ) ,
170+ )
171+ . addActionRowComponents ( ( actrow ) =>
172+ actrow . addComponents ( supportButton ) ,
173+ ) ;
174+
175+ await interaction . editReply ( {
176+ flags : MessageFlags . Ephemeral | MessageFlags . IsComponentsV2 ,
177+ components : [ container ] ,
178+ } ) ;
179+ return ;
180+ }
181+ }
182+
183+ const premiumSince = member ?. premiumSince ;
184+ const isActiveBooster =
185+ booster . active && booster . boostCounts > 0 && ! ! premiumSince ;
186+
128187 const embed = new EmbedBuilder ( )
129188 . setColor ( booster . active ? 0xf47fff : 0x99aab5 )
130189 . setTitle ( `Booster Info: ${ user . username } ` )
131190 . setThumbnail ( avatarUrl )
132191 . addFields (
133- { name : "Status" , value : booster . active ? "🟢 Active" : "🔴 Inactive" , inline : true } ,
192+ {
193+ name : "Status" ,
194+ value : isActiveBooster ? "🟢 Active" : "🔴 Inactive" ,
195+ inline : true ,
196+ } ,
134197 {
135198 name : "Custom Role" ,
136- value : booster . customRole ? `<@&${ booster . customRole . discordRoleId } >` : "None" ,
199+ value : booster . customRole
200+ ? `<@&${ booster . customRole . discordRoleId } >`
201+ : "None" ,
202+ inline : true ,
203+ } ,
204+ {
205+ name : "Boosting since" ,
206+ value : premiumSince
207+ ? `<t:${ Math . floor ( premiumSince . getTime ( ) / 1000 ) } :D>`
208+ : "Not currently boosting" ,
209+ inline : true ,
210+ } ,
211+ {
212+ name : "Boosts Counts" ,
213+ value : booster . boostCounts . toString ( ) ,
137214 inline : true ,
138215 } ,
139- { name : "Boosting since" , value : `<t:${ Math . floor ( member ! . premiumSince ! . getTime ( ) / 1000 ) } :D>` , inline : true } ,
140- { name : "Boosts Counts" , value : booster . boostCounts . toString ( ) , inline : true }
141216 )
142217 . setTimestamp ( ) ;
143218
@@ -149,32 +224,42 @@ export default new Command({
149224 const user = interaction . options . getUser ( "user" , true ) ;
150225 const amount = interaction . options . getInteger ( "amount" , true ) ;
151226
152- const targetMember = await discordGuild . members . fetch ( user . id ) . catch ( ( ) => null ) ;
227+ const targetMember = await discordGuild . members
228+ . fetch ( user . id )
229+ . catch ( ( ) => null ) ;
153230 if ( ! targetMember ?. premiumSince ) {
154231 await interaction . editReply ( {
155232 content : `${ user } is not currently boosting this server with Nitro, so boosts can't be added for them.` ,
156233 } ) ;
157234 return ;
158235 }
159236
160- await registerBoost ( user . id , discordGuild . id , discordGuild . name , discordGuild . iconURL ( ) ) ;
237+ const registered = await registerBoost (
238+ user . id ,
239+ discordGuild . id ,
240+ discordGuild . name ,
241+ discordGuild . iconURL ( ) ,
242+ ) ;
161243
162- const updated = await addBoostCount ( user . id , discordGuild . id , amount ) ;
244+ const updated =
245+ amount > 1
246+ ? await addBoostCount ( user . id , discordGuild . id , amount - 1 )
247+ : registered ;
163248 if ( ! updated ) {
164- await interaction . editReply ( { content : "Failed to update boost count." } ) ;
249+ await interaction . editReply ( {
250+ content : "Failed to update boost count." ,
251+ } ) ;
165252 return ;
166253 }
167254
168255 const boostWord = amount === 1 ? "boost" : "boosts" ;
169256 const container = new ContainerBuilder ( )
170257 . setAccentColor ( 0xe642a4 )
171258 . addTextDisplayComponents (
259+ new TextDisplayBuilder ( ) . setContent ( `**Boost successfully added!**` ) ,
172260 new TextDisplayBuilder ( ) . setContent (
173- `**Boost successfully added!**`
261+ `We've successfully added ${ amount } ${ boostWord } to ${ user } 's profile.` ,
174262 ) ,
175- new TextDisplayBuilder ( ) . setContent (
176- `We've successfully added ${ amount } ${ boostWord } to ${ user } 's profile.`
177- )
178263 ) ;
179264
180265 await interaction . editReply ( {
@@ -190,7 +275,9 @@ export default new Command({
190275
191276 const updated = await removeBoostCount ( user . id , discordGuild . id , amount ) ;
192277 if ( ! updated ) {
193- await interaction . editReply ( { content : `No booster record found for ${ user . tag } .` } ) ;
278+ await interaction . editReply ( {
279+ content : `No booster record found for ${ user . tag } .` ,
280+ } ) ;
194281 return ;
195282 }
196283
@@ -211,14 +298,26 @@ export default new Command({
211298 . setColor ( 0xf47fff )
212299 . setTitle ( "Server Boost Statistics" )
213300 . addFields (
214- { name : "Current Boosters" , value : String ( activeBoosters . length ) , inline : true } ,
215- { name : "Total Boosts (All Time)" , value : String ( totalBoosts ) , inline : true } ,
216- { name : "Unique Boosters (All Time)" , value : String ( allBoosters . length ) , inline : true }
301+ {
302+ name : "Current Boosters" ,
303+ value : String ( activeBoosters . length ) ,
304+ inline : true ,
305+ } ,
306+ {
307+ name : "Total Boosts (All Time)" ,
308+ value : String ( totalBoosts ) ,
309+ inline : true ,
310+ } ,
311+ {
312+ name : "Unique Boosters (All Time)" ,
313+ value : String ( allBoosters . length ) ,
314+ inline : true ,
315+ } ,
217316 )
218317 . setTimestamp ( ) ;
219318
220319 await interaction . editReply ( { embeds : [ embed ] } ) ;
221320 return ;
222321 }
223322 } ,
224- } )
323+ } ) ;
0 commit comments