forked from AlexzanderFlores/WOKCommands
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCommandHandler.ts
253 lines (211 loc) · 7.49 KB
/
CommandHandler.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
import { Client, Guild } from 'discord.js'
import fs from 'fs'
import WOKCommands from '.'
import Command from './Command'
import getAllFiles from './get-all-files'
import ICommand from './interfaces/ICommand'
import disabledCommands from './modles/disabled-commands'
import permissions from './permissions'
class CommandHandler {
private _commands: Map<String, Command> = new Map()
private _disabled: Map<String, String[]> = new Map() // <GuildID, Command Name>
constructor(instance: WOKCommands, client: Client, dir: string) {
if (dir) {
if (fs.existsSync(dir)) {
const files = getAllFiles(dir)
const amount = files.length
if (amount > 0) {
this.fetchDisabledCommands()
console.log(
`WOKCommands > Loaded ${amount} command${amount === 1 ? '' : 's'}.`
)
for (const [file, fileName] of files) {
this.registerCommand(instance, client, file, fileName)
}
client.on('message', (message) => {
const guild: Guild | null = message.guild
let content: string = message.content
const prefix = instance.getPrefix(guild)
if (content.startsWith(prefix)) {
// Remove the prefix
content = content.substring(prefix.length)
const args = content.split(/ /g)
// Remove the "command", leaving just the arguments
const firstElement = args.shift()
if (firstElement) {
// Ensure the user input is lower case because it is stored as lower case in the map
const name = firstElement.toLowerCase()
const command = this._commands.get(name)
if (command) {
if (guild) {
const isDisabled = instance.commandHandler.isCommandDisabled(
guild.id,
command.names[0]
)
if (isDisabled) {
message.reply(
'That command is currently disabled in this server'
)
return
}
}
const { member } = message
const {
minArgs,
maxArgs,
expectedArgs,
requiredPermissions = [],
} = command
let { syntaxError = instance.syntaxError } = command
for (const perm of requiredPermissions) {
// @ts-ignore
if (!member?.hasPermission(perm)) {
message.reply(
`You must have the "${perm}" permission in order to use this command.`
)
return
}
}
// Are the proper number of arguments provided?
if (
(minArgs !== undefined && args.length < minArgs) ||
(maxArgs !== undefined &&
maxArgs !== -1 &&
args.length > maxArgs)
) {
// Replace {PREFIX} with the actual prefix
if (syntaxError) {
syntaxError = syntaxError.replace(/{PREFIX}/g, prefix)
}
// Replace {COMMAND} with the name of the command that was ran
syntaxError = syntaxError.replace(/{COMMAND}/g, name)
// Replace {ARGUMENTS} with the expectedArgs property from the command
// If one was not provided then replace {ARGUMENTS} with an empty string
syntaxError = syntaxError.replace(
/ {ARGUMENTS}/g,
expectedArgs ? ` ${expectedArgs}` : ''
)
// Reply with the local or global syntax error
message.reply(syntaxError)
return
}
command.execute(message, args)
}
}
}
})
}
} else {
throw new Error(`Commands directory "${dir}" doesn't exist!`)
}
}
}
public registerCommand(
instance: WOKCommands,
client: Client,
file: string,
fileName: string
) {
const configuration = require(file)
const {
name = fileName,
commands,
aliases,
callback,
execute,
run,
description,
requiredPermissions,
} = configuration
let callbackCounter = 0
if (callback) ++callbackCounter
if (execute) ++callbackCounter
if (run) ++callbackCounter
if (callbackCounter > 1) {
throw new Error(
'Commands can have "callback", "execute", or "run" functions, but not multiple.'
)
}
let names = commands || aliases || []
if (!name && (!names || names.length === 0)) {
throw new Error(
`Command located at "${file}" does not have a name, commands array, or aliases array set. Please set at lease one property to specify the command name.`
)
}
if (typeof names === 'string') {
names = [names]
}
if (name && !names.includes(name.toLowerCase())) {
names.unshift(name.toLowerCase())
}
if (requiredPermissions) {
for (const perm of requiredPermissions) {
if (!permissions.includes(perm)) {
throw new Error(
`Command located at "${file}" has an invalid permission node: "${perm}". Permissions must be all upper case and be one of the following: "${[
...permissions,
].join('", "')}"`
)
}
}
}
if (!description) {
console.warn(
`WOKCommands > Command "${names[0]}" does not have a "description" property.`
)
}
const hasCallback = callback || execute || run
if (hasCallback) {
const command = new Command(
instance,
client,
names,
callback || execute || run,
configuration
)
for (const name of names) {
// Ensure the alias is lower case because we read as lower case later on
this._commands.set(name.toLowerCase(), command)
}
}
}
public get commands(): ICommand[] {
const results: { names: string[]; description: string }[] = []
this._commands.forEach(({ names, description = '' }) => {
results.push({
names: [...names],
description,
})
})
return results
}
public async fetchDisabledCommands() {
const results: any[] = await disabledCommands.find({})
for (const result of results) {
const { guildId, command } = result
const array = this._disabled.get(guildId) || []
array.push(command)
this._disabled.set(guildId, array)
}
console.log(this._disabled)
}
public disableCommand(guildId: string, command: string) {
const array = this._disabled.get(guildId) || []
if (array && !array.includes(command)) {
array.push(command)
this._disabled.set(guildId, array)
}
}
public enableCommand(guildId: string, command: string) {
const array = this._disabled.get(guildId) || []
const index = array ? array.indexOf(command) : -1
if (array && index >= 0) {
array.splice(index, 1)
}
}
public isCommandDisabled(guildId: string, command: string): boolean {
const array = this._disabled.get(guildId)
return (array && array.includes(command)) || false
}
}
export = CommandHandler