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' ;
82import { 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' ;
175
186export const middlewareId = crypto . randomUUID ( ) ;
197
@@ -22,55 +10,85 @@ export const middlewareId = crypto.randomUUID();
2210 * @ignore
2311 */
2412export 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+ }
2622
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+ }
2854
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 ?? [ ] ;
3258 let missingUserPermissions : string [ ] = [ ] ;
3359
3460 if ( typeof userPermissionsRequired === 'string' ) {
3561 userPermissionsRequired = [ userPermissionsRequired ] ;
3662 }
3763
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 ?? [ ] ;
4068 let missingBotPermissions : string [ ] = [ ] ;
4169
4270 if ( typeof botPermissionsRequired === 'string' ) {
4371 botPermissionsRequired = [ botPermissionsRequired ] ;
4472 }
4573
46- if ( ! userPermissionsRequired ? .length && ! botPermissionsRequired ? .length ) {
74+ if ( ! userPermissionsRequired . length && ! botPermissionsRequired . length ) {
4775 return ;
4876 }
4977
50- if ( userPermissions && userPermissionsRequired ) {
78+ if ( userPermissionsRequired . length ) {
5179 for ( const permission of userPermissionsRequired ) {
52- const hasPermission = userPermissions . has ( permission ) ;
53-
80+ const hasPermission = userPermissions ?. has ( permission ) ;
5481 if ( ! hasPermission ) {
55- missingUserPermissions . push (
56- typeof permission === 'string'
57- ? permission
58- : findName ( PermissionFlagsBits , permission ) ,
59- ) ;
82+ missingUserPermissions . push ( permission ) ;
6083 }
6184 }
6285 }
6386
64- if ( botPermissions && botPermissionsRequired ) {
87+ if ( botPermissionsRequired . length ) {
6588 for ( const permission of botPermissionsRequired ) {
66- const hasPermission = botPermissions . has ( permission ) ;
67-
89+ const hasPermission = botPermissions ?. has ( permission ) ;
6890 if ( ! hasPermission ) {
69- missingBotPermissions . push (
70- typeof permission === 'string'
71- ? permission
72- : findName ( PermissionFlagsBits , permission ) ,
73- ) ;
91+ missingBotPermissions . push ( permission ) ;
7492 }
7593 }
7694 }
@@ -79,7 +97,7 @@ export async function beforeExecute(ctx: MiddlewareContext) {
7997 return ;
8098 }
8199
82- // Fix casing . e.g. KickMembers -> Kick Members
100+ // Fix permission string . e.g. KickMembers -> Kick Members
83101 const pattern = / ( [ a - z ] ) ( [ A - Z ] ) | ( [ A - Z ] + ) ( [ A - Z ] [ a - z ] ) / g;
84102
85103 missingUserPermissions = missingUserPermissions . map ( ( str ) =>
@@ -123,6 +141,23 @@ export async function beforeExecute(ctx: MiddlewareContext) {
123141 . setDescription ( embedDescription )
124142 . setColor ( 'Red' ) ;
125143
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
128163}
0 commit comments