11import {
22 SlashCommandBuilder ,
33 ChatInputCommandInteraction ,
4- PermissionFlagsBits ,
54 ColorResolvable ,
5+ ContainerBuilder ,
6+ TextDisplayBuilder ,
7+ MessageFlags ,
68} from "discord.js" ;
79import { Command } from "../libs/loadCommands.js" ;
8- import { getBooster } from "../services/boosterService.js" ;
10+ import { ensureBoosterWhileBoosting , getBooster } from "../services/boosterService.js" ;
911import {
1012 createCustomRole ,
1113 updateCustomRole ,
1214 deleteCustomRole ,
1315} from "../services/roleService.js" ;
1416
17+ const ACCENT = 0xe642a4 ;
18+
19+ function componentsV2 ( lines : string [ ] ) {
20+ const container = new ContainerBuilder ( )
21+ . setAccentColor ( ACCENT )
22+ . addTextDisplayComponents ( ...lines . map ( ( content ) => new TextDisplayBuilder ( ) . setContent ( content ) ) ) ;
23+ return {
24+ flags : MessageFlags . Ephemeral | MessageFlags . IsComponentsV2 ,
25+ components : [ container ] ,
26+ } ;
27+ }
28+
1529const roleCommand : Command = {
1630 data : new SlashCommandBuilder ( )
1731 . setName ( "role" )
@@ -43,95 +57,126 @@ const roleCommand: Command = {
4357 ) ,
4458
4559 async execute ( interaction : ChatInputCommandInteraction ) : Promise < void > {
46- const record = await getBooster ( interaction . user . id , interaction ) ;
60+ const guild = interaction . guild ;
61+ if ( ! guild ) {
62+ await interaction . reply ( componentsV2 ( [ "This command can only be used in a server." ] ) ) ;
63+ return ;
64+ }
65+
66+ const member = await guild . members . fetch ( interaction . user . id ) ;
67+ const resolved = await getBooster ( interaction . user . id , interaction ) ;
4768
48- if ( ! record ?. data ?. active ) {
49- await interaction . reply ( {
50- content : "You must be an active booster to use this command." ,
51- ephemeral : true ,
52- } ) ;
69+ if ( ! resolved ?. success ) {
70+ await interaction . reply (
71+ componentsV2 ( [ "Could not load your guild data for this server." ] )
72+ ) ;
5373 return ;
5474 }
5575
76+ const nitroBoosting = member . premiumSince !== null ;
77+
78+ if ( ! nitroBoosting ) {
79+ await interaction . reply (
80+ componentsV2 ( [
81+ "**Uh oh!**" ,
82+ "You must be boosting this server with Nitro to use this command." ,
83+ ] )
84+ ) ;
85+ return ;
86+ }
87+
88+ const boosterRecord =
89+ resolved . data ??
90+ ( await ensureBoosterWhileBoosting (
91+ interaction . user . id ,
92+ guild . id ,
93+ guild . name ,
94+ guild . iconURL ( )
95+ ) ) ;
96+
5697 const sub = interaction . options . getSubcommand ( ) ;
57- const guild = interaction . guild ! ;
58- const member = await guild . members . fetch ( interaction . user . id ) ;
5998
6099 if ( sub === "create" ) {
61- if ( record . data . customRole ) {
62- await interaction . reply ( {
63- content : "You already have a custom role. Use /role edit to modify it." ,
64- ephemeral : true ,
65- } ) ;
100+ if ( boosterRecord . customRole ) {
101+ await interaction . reply (
102+ componentsV2 ( [
103+ "You already have a custom role." ,
104+ "Use `/role edit` to change it." ,
105+ ] )
106+ ) ;
66107 return ;
67108 }
68109
69110 const name = interaction . options . getString ( "name" , true ) ;
70111 const color = interaction . options . getString ( "color" , true ) ;
71112
72113 if ( ! / ^ # [ 0 - 9 a - f A - F ] { 6 } $ / . test ( color ) ) {
73- await interaction . reply ( {
74- content : "Invalid color. Please use a hex color like #ff0000." ,
75- ephemeral : true ,
76- } ) ;
114+ await interaction . reply (
115+ componentsV2 ( [
116+ "Invalid color." ,
117+ "Use a hex color like `#ff0000`." ,
118+ ] )
119+ ) ;
77120 return ;
78121 }
79122
80- await interaction . deferReply ( { ephemeral : true } ) ;
123+ await interaction . deferReply ( { flags : MessageFlags . Ephemeral } ) ;
81124
82125 const role = await createCustomRole ( guild , member , name , color as ColorResolvable ) ;
83126
84- await interaction . editReply ( `Custom role ${ role } created successfully.` ) ;
127+ await interaction . editReply (
128+ componentsV2 ( [ `**Custom role created!**` , `${ role } is ready to use.` ] )
129+ ) ;
85130 return ;
86131 }
87132
88133 if ( sub === "edit" ) {
89- if ( ! record . data . customRole ?. discordRoleId ) {
90- await interaction . reply ( {
91- content : "You do not have a custom role. Use /role create first." ,
92- ephemeral : true ,
93- } ) ;
134+ if ( ! boosterRecord . customRole ?. discordRoleId ) {
135+ await interaction . reply (
136+ componentsV2 ( [ "You don't have a custom role yet." , "Use `/role create` first." ] )
137+ ) ;
94138 return ;
95139 }
96140
97141 const name = interaction . options . getString ( "name" ) ?? undefined ;
98142 const color = ( interaction . options . getString ( "color" ) ?? undefined ) as ColorResolvable | undefined ;
99143
100144 if ( color && ! / ^ # [ 0 - 9 a - f A - F ] { 6 } $ / . test ( color as string ) ) {
101- await interaction . reply ( {
102- content : "Invalid color. Please use a hex color like #ff0000." ,
103- ephemeral : true ,
104- } ) ;
145+ await interaction . reply (
146+ componentsV2 ( [
147+ "Invalid color." ,
148+ "Use a hex color like `#ff0000`." ,
149+ ] )
150+ ) ;
105151 return ;
106152 }
107153
108- await interaction . deferReply ( { ephemeral : true } ) ;
154+ await interaction . deferReply ( { flags : MessageFlags . Ephemeral } ) ;
109155
110156 const role = await updateCustomRole ( guild , interaction . user . id , name , color ) ;
111157 if ( ! role ) {
112- await interaction . editReply ( "Failed to update role. It may have been deleted." ) ;
158+ await interaction . editReply (
159+ componentsV2 ( [ "Couldn't update that role." , "It may have been deleted manually." ] )
160+ ) ;
113161 return ;
114162 }
115163
116- await interaction . editReply ( ` Custom role updated successfully.` ) ;
164+ await interaction . editReply ( componentsV2 ( [ "** Custom role updated.**" ] ) ) ;
117165 return ;
118166 }
119167
120168 if ( sub === "delete" ) {
121- if ( ! record . data . customRole ?. discordRoleId ) {
122- await interaction . reply ( {
123- content : "You do not have a custom role." ,
124- ephemeral : true ,
125- } ) ;
169+ if ( ! boosterRecord . customRole ?. discordRoleId ) {
170+ await interaction . reply ( componentsV2 ( [ "You don't have a custom role to delete." ] ) ) ;
126171 return ;
127172 }
128173
129- await interaction . deferReply ( { ephemeral : true } ) ;
174+ await interaction . deferReply ( { flags : MessageFlags . Ephemeral } ) ;
130175 await deleteCustomRole ( guild , interaction . user . id ) ;
131- await interaction . editReply ( " Custom role deleted." ) ;
176+ await interaction . editReply ( componentsV2 ( [ "** Custom role deleted.**" ] ) ) ;
132177 return ;
133178 }
134179 } ,
135180} ;
136181
137- export default roleCommand ;
182+ export default roleCommand ;
0 commit comments