1
+ // we need to await in a loop as we're rate-limited anyway
2
+ /* eslint-disable no-await-in-loop */
1
3
/* eslint-disable @typescript-eslint/no-non-null-assertion */
2
4
import type {
3
5
ApplicationCommand ,
@@ -7,12 +9,15 @@ import type {
7
9
Guild ,
8
10
GuildApplicationCommandManager ,
9
11
GuildResolvable ,
12
+ ApplicationCommandType ,
10
13
} from 'discord.js' ;
11
14
import { Collection } from 'discord.js' ;
15
+ import { ApplicationCommandTypes } from 'discord.js/typings/enums' ;
12
16
import { filter } from 'domyno' ;
13
17
import { isEqual } from 'lodash-es' ;
14
18
15
19
import type { CommandDataWithHandler } from '../../types' ;
20
+ import { commands } from '../modules/modmail' ;
16
21
import { asyncCatch } from '../utils/asyncCatch.js' ;
17
22
import { map , mapʹ } from '../utils/map.js' ;
18
23
import { merge } from '../utils/merge.js' ;
@@ -46,6 +51,7 @@ export const guildCommands = new Map(
46
51
shitpostInteraction ,
47
52
npmInteraction ,
48
53
whynoInteraction ,
54
+ ...commands ,
49
55
// warn // Not used atm
50
56
] . map ( command => [ command . name , command ] )
51
57
) ; // placeholder for now
@@ -58,16 +64,22 @@ export const applicationCommands = new Collection<
58
64
const getRelevantCmdProperties = ( {
59
65
description,
60
66
name,
67
+ type = ApplicationCommandTypes . CHAT_INPUT ,
61
68
options,
69
+ defaultPermission = true ,
62
70
} : {
63
- description : string ;
71
+ type ?: ApplicationCommandTypes | ApplicationCommandType ;
72
+ description ?: string ;
64
73
name : string ;
65
74
options ?: unknown [ ] ;
75
+ defaultPermission ?: boolean ;
66
76
} ) : ApplicationCommandData => {
67
77
const relevantData = {
78
+ type : _normalizeType ( type ) ,
68
79
description,
69
80
name,
70
81
options,
82
+ defaultPermission,
71
83
} as unknown as ApplicationCommandData ;
72
84
return stripNullish ( normalizeApplicationCommandData ( relevantData ) ) ;
73
85
} ;
@@ -92,7 +104,7 @@ export const registerCommands = async (client: Client): Promise<void> => {
92
104
client . on (
93
105
'interactionCreate' ,
94
106
asyncCatch ( async interaction => {
95
- if ( ! interaction . isCommand ( ) ) {
107
+ if ( ! interaction . isCommand ( ) && ! interaction . isContextMenu ( ) ) {
96
108
return ;
97
109
}
98
110
@@ -123,13 +135,13 @@ export const registerCommands = async (client: Client): Promise<void> => {
123
135
124
136
for ( const { onAttach } of applicationCommands . values ( ) ) {
125
137
// We're attaching these so it's fine
126
-
138
+
127
139
onAttach ?.( client ) ;
128
140
}
129
141
130
142
for ( const { onAttach } of guildCommands . values ( ) ) {
131
143
// We're attaching these so it's fine
132
-
144
+
133
145
onAttach ?.( client ) ;
134
146
}
135
147
@@ -161,6 +173,25 @@ export const registerCommands = async (client: Client): Promise<void> => {
161
173
// })
162
174
} ;
163
175
176
+ function _normalizeType (
177
+ type : ApplicationCommandType | ApplicationCommandTypes
178
+ ) {
179
+ if ( typeof type === 'number' ) {
180
+ return type ;
181
+ }
182
+
183
+ switch ( type ) {
184
+ case 'MESSAGE' :
185
+ return ApplicationCommandTypes . MESSAGE ;
186
+ case 'USER' :
187
+ return ApplicationCommandTypes . USER ;
188
+ case 'CHAT_INPUT' :
189
+ default :
190
+ return ApplicationCommandTypes . CHAT_INPUT ;
191
+ }
192
+ }
193
+
194
+ const interactionTypes = new Set ( [ 'CHAT_INPUT' , 'USER' , 'MESSAGE' ] )
164
195
async function addCommands (
165
196
serverCommands : Collection <
166
197
string ,
@@ -169,25 +200,22 @@ async function addCommands(
169
200
commandDescriptions : Map < string , CommandDataWithHandler > ,
170
201
commandManager : ApplicationCommandManager | GuildApplicationCommandManager
171
202
) {
172
- const discordChatInputCommandsById = serverCommands . filter (
173
- x => x . type === 'CHAT_INPUT'
203
+ const discordInteractionsById = serverCommands . filter (
204
+ x => interactionTypes . has ( x . type )
174
205
) ;
175
206
176
207
const discordCommands = new Collection (
177
- discordChatInputCommandsById . map ( value => [ value . name , value ] )
208
+ discordInteractionsById . map ( value => [ value . name , value ] )
178
209
) ;
179
210
180
- const validCommands = pipe <
181
- Iterable < [ string , CommandDataWithHandler ] > ,
182
- Iterable < string >
183
- > ( [
211
+ const validCommands = pipe ( [
184
212
filter < [ string , CommandDataWithHandler ] > (
185
- ( [ key , val ] : [ string , CommandDataWithHandler ] ) =>
213
+ ( [ , val ] : [ string , CommandDataWithHandler ] ) =>
186
214
'guild' in commandManager && val . guildValidate
187
215
? val . guildValidate ( commandManager . guild )
188
216
: true
189
217
) ,
190
- map ( ( [ key ] ) => key ) ,
218
+ map ( ( [ key ] ) : string => key ) ,
191
219
] ) ;
192
220
193
221
const newCommands = difference (
@@ -218,9 +246,7 @@ async function addCommands(
218
246
}
219
247
220
248
function getDestination (
221
- commandManager :
222
- | ApplicationCommandManager
223
- | GuildApplicationCommandManager
249
+ commandManager : ApplicationCommandManager | GuildApplicationCommandManager
224
250
) {
225
251
return 'guild' in commandManager
226
252
? `Guild: ${ commandManager . guild . name } `
@@ -236,10 +262,13 @@ function createNewCommands(
236
262
const command = cmdDescriptions . get ( name ) ;
237
263
// this is always true
238
264
if ( command ) {
239
- const { onAttach, handler, ...rest } = command ;
265
+ const { onAttach, handler, managePermissions , ...rest } = command ;
240
266
console . info ( `Adding Command ${ name } for ${ destination } ` ) ;
241
267
242
- return cmdMgr . create ( rest ) ;
268
+ const guildCmd = await cmdMgr . create ( rest ) ;
269
+ const { permissions, guild } = guildCmd ;
270
+
271
+ await managePermissions ?.( guild , permissions ) ;
243
272
}
244
273
} ) ;
245
274
}
@@ -250,11 +279,11 @@ function editExistingCommands(
250
279
existingCommands : Map < string , ApplicationCommand >
251
280
) {
252
281
const destination = getDestination ( cmdMgr ) ;
253
- return map ( ( name : string ) => {
282
+ return map ( async ( name : string ) => {
254
283
const cmd = cmdDescriptions . get ( name ) ;
255
284
const existing = existingCommands . get ( name ) ;
256
285
257
- const { onAttach, handler, ...command } = cmd ;
286
+ const { onAttach, handler, managePermissions , ...command } = cmd ;
258
287
259
288
if (
260
289
! isEqual (
@@ -263,8 +292,18 @@ function editExistingCommands(
263
292
)
264
293
) {
265
294
console . info ( `Updating ${ name } for ${ destination } ` ) ;
295
+ console . log (
296
+ getRelevantCmdProperties ( cmd ) ,
297
+ getRelevantCmdProperties ( existing ) )
266
298
267
- return cmdMgr . edit ( existing . id , command ) ;
299
+ await cmdMgr . edit ( existing . id , command ) ;
300
+ }
301
+
302
+ try {
303
+ const { permissions, guild } = existing ;
304
+ await managePermissions ?.( guild , permissions ) ;
305
+ } catch ( error ) {
306
+ console . log ( { error } ) ;
268
307
}
269
308
} ) ;
270
309
}
@@ -278,6 +317,6 @@ function deleteRemovedCommands(
278
317
const existing = existingCommands . get ( name ) ! ;
279
318
console . warn ( `Deleting ${ name } from ${ destination } ` ) ;
280
319
281
- return cmdMgr . delete ( existing . id ) ;
320
+ await cmdMgr . delete ( existing . id ) ;
282
321
} ) ;
283
322
}
0 commit comments