1
- import {
2
- EmbedBuilder ,
3
- PermissionFlags ,
4
- PermissionFlagsBits ,
5
- PermissionResolvable ,
6
- } from 'discord.js' ;
7
- import { MiddlewareContext } from '../commands/Context' ;
1
+ import { EmbedBuilder , MessageFlags } from 'discord.js' ;
8
2
import { getConfig } from '../../config/config' ;
9
-
10
- const findName = ( flags : PermissionFlags , flag : PermissionResolvable ) => {
11
- if ( typeof flag === 'string' ) return flag ;
12
-
13
- return (
14
- Object . entries ( flags ) . find ( ( [ _ , value ] ) => value === flag ) ?. [ 0 ] ?? `${ flag } `
15
- ) ;
16
- } ;
3
+ import { Logger } from '../../logger/Logger' ;
4
+ import { MiddlewareContext } from '../commands/Context' ;
17
5
18
6
export const middlewareId = crypto . randomUUID ( ) ;
19
7
@@ -22,55 +10,85 @@ export const middlewareId = crypto.randomUUID();
22
10
* @ignore
23
11
*/
24
12
export async function beforeExecute ( ctx : MiddlewareContext ) {
25
- if ( getConfig ( ) . disablePermissionsMiddleware ) return ;
13
+ if ( getConfig ( ) . disablePermissionsMiddleware ) {
14
+ return ;
15
+ }
16
+
17
+ const { interaction, message, command } = ctx ;
18
+
19
+ if ( interaction && ! interaction . isCommand ( ) ) {
20
+ return ;
21
+ }
26
22
27
- const { interaction, command } = ctx ;
23
+ if (
24
+ ( interaction && interaction . channel ?. isDMBased ( ) ) ||
25
+ ( message && message . channel ?. isDMBased ( ) )
26
+ ) {
27
+ const channel = interaction ?. channel ?? message ?. channel ;
28
+
29
+ const embed = new EmbedBuilder ( )
30
+ . setTitle ( ':x: Server-only command!' )
31
+ . setDescription ( 'This command can only be used in a server.' )
32
+ . setColor ( 'Red' ) ;
33
+
34
+ try {
35
+ if ( channel ?. isSendable ( ) ) {
36
+ if ( interaction && interaction . isRepliable ( ) ) {
37
+ await interaction . reply ( {
38
+ embeds : [ embed ] ,
39
+ flags : MessageFlags . Ephemeral ,
40
+ } ) ;
41
+ } else {
42
+ await message . reply ( { embeds : [ embed ] } ) ;
43
+ }
44
+ }
45
+ } catch ( error ) {
46
+ Logger . error (
47
+ `Could not send 'Server-only command' DM to user ${ interaction ?. user . id ?? message ?. author . id } for command ${ command . command . name } .` ,
48
+ error ,
49
+ ) ;
50
+ }
51
+
52
+ return ctx . cancel ( ) ; // Stop the command from executing
53
+ }
28
54
29
- if ( interaction . isAutocomplete ( ) ) return ;
30
- const userPermissions = interaction . memberPermissions ;
31
- let userPermissionsRequired = command . metadata ?. userPermissions ;
55
+ const userPermissions =
56
+ interaction ? .memberPermissions ?? message ?. member ?. permissions ;
57
+ let userPermissionsRequired = command . metadata ?. userPermissions ?? [ ] ;
32
58
let missingUserPermissions : string [ ] = [ ] ;
33
59
34
60
if ( typeof userPermissionsRequired === 'string' ) {
35
61
userPermissionsRequired = [ userPermissionsRequired ] ;
36
62
}
37
63
38
- const botPermissions = interaction . guild ?. members . me ?. permissions ;
39
- let botPermissionsRequired = command . metadata ?. botPermissions ;
64
+ const botPermissions =
65
+ interaction ?. guild ?. members . me ?. permissions ??
66
+ message ?. guild ?. members . me ?. permissions ;
67
+ let botPermissionsRequired = command . metadata ?. botPermissions ?? [ ] ;
40
68
let missingBotPermissions : string [ ] = [ ] ;
41
69
42
70
if ( typeof botPermissionsRequired === 'string' ) {
43
71
botPermissionsRequired = [ botPermissionsRequired ] ;
44
72
}
45
73
46
- if ( ! userPermissionsRequired ? .length && ! botPermissionsRequired ? .length ) {
74
+ if ( ! userPermissionsRequired . length && ! botPermissionsRequired . length ) {
47
75
return ;
48
76
}
49
77
50
- if ( userPermissions && userPermissionsRequired ) {
78
+ if ( userPermissionsRequired . length ) {
51
79
for ( const permission of userPermissionsRequired ) {
52
- const hasPermission = userPermissions . has ( permission ) ;
53
-
80
+ const hasPermission = userPermissions ?. has ( permission ) ;
54
81
if ( ! hasPermission ) {
55
- missingUserPermissions . push (
56
- typeof permission === 'string'
57
- ? permission
58
- : findName ( PermissionFlagsBits , permission ) ,
59
- ) ;
82
+ missingUserPermissions . push ( permission ) ;
60
83
}
61
84
}
62
85
}
63
86
64
- if ( botPermissions && botPermissionsRequired ) {
87
+ if ( botPermissionsRequired . length ) {
65
88
for ( const permission of botPermissionsRequired ) {
66
- const hasPermission = botPermissions . has ( permission ) ;
67
-
89
+ const hasPermission = botPermissions ?. has ( permission ) ;
68
90
if ( ! hasPermission ) {
69
- missingBotPermissions . push (
70
- typeof permission === 'string'
71
- ? permission
72
- : findName ( PermissionFlagsBits , permission ) ,
73
- ) ;
91
+ missingBotPermissions . push ( permission ) ;
74
92
}
75
93
}
76
94
}
@@ -79,7 +97,7 @@ export async function beforeExecute(ctx: MiddlewareContext) {
79
97
return ;
80
98
}
81
99
82
- // Fix casing . e.g. KickMembers -> Kick Members
100
+ // Fix permission string . e.g. KickMembers -> Kick Members
83
101
const pattern = / ( [ a - z ] ) ( [ A - Z ] ) | ( [ A - Z ] + ) ( [ A - Z ] [ a - z ] ) / g;
84
102
85
103
missingUserPermissions = missingUserPermissions . map ( ( str ) =>
@@ -123,6 +141,23 @@ export async function beforeExecute(ctx: MiddlewareContext) {
123
141
. setDescription ( embedDescription )
124
142
. setColor ( 'Red' ) ;
125
143
126
- await interaction . reply ( { embeds : [ embed ] , ephemeral : true } ) ;
127
- return true ;
144
+ try {
145
+ if ( interaction && interaction . isRepliable ( ) ) {
146
+ await interaction . reply ( {
147
+ embeds : [ embed ] ,
148
+ flags : MessageFlags . Ephemeral ,
149
+ } ) ;
150
+ } else if ( message && message . channel ?. isSendable ( ) ) {
151
+ await message . reply ( {
152
+ embeds : [ embed ] ,
153
+ } ) ;
154
+ }
155
+ } catch ( error ) {
156
+ Logger . error (
157
+ `Could not send 'Not enough permissions' reply to user ${ interaction ?. user . id ?? message ?. author . id } for command ${ command . command . name } .` ,
158
+ error ,
159
+ ) ;
160
+ }
161
+
162
+ return ctx . cancel ( ) ; // Stop the command from executing
128
163
}
0 commit comments