reciple 1.7.1-pre.0 → 2.0.0-pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  export * from './reciple/classes/RecipleClient';
2
2
  export * from './reciple/classes/RecipleConfig';
3
+ export * from './reciple/classes/MessageCommandOptionManager';
3
4
  export * from './reciple/classes/builders/InteractionCommandBuilder';
4
5
  export * from './reciple/classes/builders/MessageCommandBuilder';
5
6
  export * from './reciple/classes/builders/MessageCommandOptionBuilder';
6
- export * from './reciple/classes/builders/MessageCommandOptions';
7
- export * from './reciple/hasPermissions';
7
+ export * from './reciple/permissions';
8
8
  export * from './reciple/flags';
9
9
  export * from './reciple/isIgnoredChannel';
10
10
  export * from './reciple/logger';
package/bin/index.js CHANGED
@@ -16,11 +16,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./reciple/classes/RecipleClient"), exports);
18
18
  __exportStar(require("./reciple/classes/RecipleConfig"), exports);
19
+ __exportStar(require("./reciple/classes/MessageCommandOptionManager"), exports);
19
20
  __exportStar(require("./reciple/classes/builders/InteractionCommandBuilder"), exports);
20
21
  __exportStar(require("./reciple/classes/builders/MessageCommandBuilder"), exports);
21
22
  __exportStar(require("./reciple/classes/builders/MessageCommandOptionBuilder"), exports);
22
- __exportStar(require("./reciple/classes/builders/MessageCommandOptions"), exports);
23
- __exportStar(require("./reciple/hasPermissions"), exports);
23
+ __exportStar(require("./reciple/permissions"), exports);
24
24
  __exportStar(require("./reciple/flags"), exports);
25
25
  __exportStar(require("./reciple/isIgnoredChannel"), exports);
26
26
  __exportStar(require("./reciple/logger"), exports);
@@ -0,0 +1,21 @@
1
+ import { Guild, TextBasedChannel, User } from 'discord.js';
2
+ import { RecipleCommandBuilders } from '../modules';
3
+ export interface CooledDownUser {
4
+ user: User;
5
+ command: string;
6
+ type: RecipleCommandBuilders["builder"];
7
+ guild?: Guild | null;
8
+ channel?: TextBasedChannel;
9
+ expireTime: number;
10
+ }
11
+ export declare class CommandCooldownManager extends Array<CooledDownUser> {
12
+ /**
13
+ * Alias for `CommandCooldownManager#push()`
14
+ */
15
+ add(...options: CooledDownUser[]): number;
16
+ remove(options: Partial<CooledDownUser>, limit?: number): void;
17
+ isCooledDown(options: Partial<Omit<CooledDownUser, 'expireTime'>>): boolean;
18
+ clean(options?: Partial<Omit<CooledDownUser, 'expireTime'>>): void;
19
+ get(options: Partial<Omit<CooledDownUser, 'expireTime'>>): CooledDownUser | undefined;
20
+ static checkOptions(options: Partial<Omit<CooledDownUser, 'expireTime'>>, data: CooledDownUser): boolean;
21
+ }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CommandCooldownManager = void 0;
4
+ class CommandCooldownManager extends Array {
5
+ /**
6
+ * Alias for `CommandCooldownManager#push()`
7
+ */
8
+ add(...options) {
9
+ return this.push(...options);
10
+ }
11
+ remove(options, limit = 0) {
12
+ if (!Object.keys(options).length)
13
+ throw new TypeError('Provide atleast one option to remove cooldown data.');
14
+ let i = 0;
15
+ for (const index in this) {
16
+ if (!CommandCooldownManager.checkOptions(options, this[index]))
17
+ continue;
18
+ if (options.expireTime && this[index].expireTime > Date.now())
19
+ continue;
20
+ if (limit && i >= limit)
21
+ continue;
22
+ this.splice(Number(index));
23
+ i++;
24
+ }
25
+ }
26
+ isCooledDown(options) {
27
+ const data = this.get(options);
28
+ if (!data)
29
+ return false;
30
+ this.remove(Object.assign(Object.assign({}, data), { channel: undefined, guild: undefined, type: undefined, command: undefined }));
31
+ if (data.expireTime < Date.now())
32
+ return false;
33
+ return true;
34
+ }
35
+ clean(options) {
36
+ for (const index in this) {
37
+ if (options && !CommandCooldownManager.checkOptions(options, this[index]))
38
+ return;
39
+ if (this[index].expireTime > Date.now())
40
+ return;
41
+ this.slice(Number(index));
42
+ }
43
+ }
44
+ get(options) {
45
+ return this.find(data => CommandCooldownManager.checkOptions(options, data));
46
+ }
47
+ static checkOptions(options, data) {
48
+ var _a, _b;
49
+ if ((options === null || options === void 0 ? void 0 : options.user) && options.user.id !== data.user.id)
50
+ return false;
51
+ if ((options === null || options === void 0 ? void 0 : options.guild) && options.guild.id !== ((_a = data.guild) === null || _a === void 0 ? void 0 : _a.id))
52
+ return false;
53
+ if ((options === null || options === void 0 ? void 0 : options.channel) && options.channel.id !== ((_b = data.channel) === null || _b === void 0 ? void 0 : _b.id))
54
+ return false;
55
+ if ((options === null || options === void 0 ? void 0 : options.command) && options.command !== data.command)
56
+ return false;
57
+ if ((options === null || options === void 0 ? void 0 : options.type) && options.type !== data.type)
58
+ return false;
59
+ return true;
60
+ }
61
+ }
62
+ exports.CommandCooldownManager = CommandCooldownManager;
@@ -1,5 +1,5 @@
1
- import { MessageCommandValidatedOption } from './MessageCommandBuilder';
2
- export declare class MessageCommandOptions extends Array<MessageCommandValidatedOption> {
1
+ import { MessageCommandValidatedOption } from './builders/MessageCommandBuilder';
2
+ export declare class MessageCommandOptionManager extends Array<MessageCommandValidatedOption> {
3
3
  constructor(options: MessageCommandValidatedOption[]);
4
4
  /**
5
5
  * Get the option info
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MessageCommandOptions = void 0;
4
- class MessageCommandOptions extends Array {
3
+ exports.MessageCommandOptionManager = void 0;
4
+ class MessageCommandOptionManager extends Array {
5
5
  constructor(options) {
6
6
  super();
7
7
  this.push(...options);
@@ -20,4 +20,4 @@ class MessageCommandOptions extends Array {
20
20
  return (_a = option === null || option === void 0 ? void 0 : option.value) !== null && _a !== void 0 ? _a : null;
21
21
  }
22
22
  }
23
- exports.MessageCommandOptions = MessageCommandOptions;
23
+ exports.MessageCommandOptionManager = MessageCommandOptionManager;
@@ -1,10 +1,38 @@
1
- import { InteractionCommandBuilder, RecipleInteractionCommandExecute } from './builders/InteractionCommandBuilder';
2
- import { interactionCommandBuilders } from '../registerInteractionCommands';
3
- import { MessageCommandBuilder, RecipleMessageCommandExecute } from './builders/MessageCommandBuilder';
1
+ import { InteractionCommandBuilder, RecipleInteractionCommandExecuteData } from './builders/InteractionCommandBuilder';
2
+ import { InteractionBuilder } from '../registerInteractionCommands';
3
+ import { MessageCommandBuilder, RecipleMessageCommandExecuteData } from './builders/MessageCommandBuilder';
4
+ import { MessageCommandOptionManager } from './MessageCommandOptionManager';
4
5
  import { Logger as ILogger } from 'fallout-utility';
5
6
  import { Config } from './RecipleConfig';
7
+ import { CommandCooldownManager, CooledDownUser } from './CommandCooldownManager';
6
8
  import { ApplicationCommandDataResolvable, Awaitable, Client, ClientEvents, ClientOptions, CommandInteraction, Interaction, Message } from 'discord.js';
7
- import { recipleCommandBuilders, RecipleModule, RecipleScript } from '../modules';
9
+ import { RecipleCommandBuilders, RecipleModule, RecipleScript } from '../modules';
10
+ export declare type CommandHaltReason<Builder extends RecipleCommandBuilders> = RecipleHaltedCommandData<Builder>["reason"];
11
+ export declare type RecipleHaltedCommandData<Builder extends RecipleCommandBuilders> = CommandErrorData<Builder> | CommandCooldownData<Builder> | CommandInvalidArguments<Builder> | CommandMissingArguments<Builder> | CommandMissingMemberPermissions<Builder> | CommandMissingBotPermissions<Builder>;
12
+ export interface CommandHaltBaseData<Builder extends RecipleCommandBuilders> {
13
+ executeData: Builder extends InteractionCommandBuilder ? RecipleInteractionCommandExecuteData : RecipleMessageCommandExecuteData;
14
+ }
15
+ export interface CommandErrorData<Builder extends RecipleCommandBuilders> extends CommandHaltBaseData<Builder> {
16
+ reason: 'ERROR';
17
+ error: any;
18
+ }
19
+ export interface CommandCooldownData<Builder extends RecipleCommandBuilders> extends CommandHaltBaseData<Builder>, CooledDownUser {
20
+ reason: 'COOLDOWN';
21
+ }
22
+ export interface CommandInvalidArguments<Builder extends RecipleCommandBuilders> extends CommandHaltBaseData<Builder> {
23
+ reason: 'INVALID_ARGUMENTS';
24
+ invalidArguments: MessageCommandOptionManager;
25
+ }
26
+ export interface CommandMissingArguments<Builder extends RecipleCommandBuilders> extends CommandHaltBaseData<Builder> {
27
+ reason: 'MISSING_ARGUMENTS';
28
+ missingArguments: MessageCommandOptionManager;
29
+ }
30
+ export interface CommandMissingMemberPermissions<Builder extends RecipleCommandBuilders> extends CommandHaltBaseData<Builder> {
31
+ reason: 'MISSING_MEMBER_PERMISSIONS';
32
+ }
33
+ export interface CommandMissingBotPermissions<Builder extends RecipleCommandBuilders> extends CommandHaltBaseData<Builder> {
34
+ reason: 'MISSING_BOT_PERMISSIONS';
35
+ }
8
36
  export interface RecipleClientOptions extends ClientOptions {
9
37
  config?: Config;
10
38
  }
@@ -17,8 +45,8 @@ export interface RecipleClientCommands {
17
45
  };
18
46
  }
19
47
  export interface RecipleClientEvents extends ClientEvents {
20
- recipleMessageCommandCreate: [command: RecipleMessageCommandExecute];
21
- recipleInteractionCommandCreate: [command: RecipleInteractionCommandExecute];
48
+ recipleMessageCommandCreate: [executeData: RecipleMessageCommandExecuteData];
49
+ recipleInteractionCommandCreate: [executeData: RecipleInteractionCommandExecuteData];
22
50
  recipleReplyError: [error: unknown];
23
51
  }
24
52
  export interface RecipleClient<Ready extends boolean = boolean> extends Client<Ready> {
@@ -37,7 +65,8 @@ export interface RecipleClient<Ready extends boolean = boolean> extends Client<R
37
65
  export declare class RecipleClient<Ready extends boolean = boolean> extends Client<Ready> {
38
66
  config: Config;
39
67
  commands: RecipleClientCommands;
40
- otherApplicationCommandData: (interactionCommandBuilders | ApplicationCommandDataResolvable)[];
68
+ otherApplicationCommandData: (InteractionBuilder | ApplicationCommandDataResolvable)[];
69
+ commandCooldowns: CommandCooldownManager;
41
70
  modules: RecipleModule[];
42
71
  logger: ILogger;
43
72
  version: string;
@@ -57,7 +86,7 @@ export declare class RecipleClient<Ready extends boolean = boolean> extends Clie
57
86
  /**
58
87
  * Add interaction or message command to client
59
88
  */
60
- addCommand(command: recipleCommandBuilders): RecipleClient<Ready>;
89
+ addCommand(command: RecipleCommandBuilders): RecipleClient<Ready>;
61
90
  /**
62
91
  * Listed to command executions
63
92
  */
@@ -65,11 +94,11 @@ export declare class RecipleClient<Ready extends boolean = boolean> extends Clie
65
94
  /**
66
95
  * Execute a Message command
67
96
  */
68
- messageCommandExecute(message: Message, prefix?: string): Promise<void | RecipleMessageCommandExecute>;
97
+ messageCommandExecute(message: Message, prefix?: string): Promise<void | RecipleMessageCommandExecuteData>;
69
98
  /**
70
99
  * Execute an Interaction command
71
100
  */
72
- interactionCommandExecute(interaction: Interaction | CommandInteraction): Promise<void | RecipleInteractionCommandExecute>;
101
+ interactionCommandExecute(interaction: Interaction | CommandInteraction): Promise<void | RecipleInteractionCommandExecuteData>;
73
102
  /**
74
103
  * Get a message from config
75
104
  */
@@ -17,15 +17,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.RecipleClient = void 0;
19
19
  const registerInteractionCommands_1 = require("../registerInteractionCommands");
20
+ const MessageCommandOptionManager_1 = require("./MessageCommandOptionManager");
20
21
  const fallout_utility_1 = require("fallout-utility");
22
+ const RecipleConfig_1 = require("./RecipleConfig");
21
23
  const isIgnoredChannel_1 = require("../isIgnoredChannel");
22
- const hasPermissions_1 = require("../hasPermissions");
24
+ const CommandCooldownManager_1 = require("./CommandCooldownManager");
25
+ const permissions_1 = require("../permissions");
23
26
  const version_1 = require("../version");
24
27
  const logger_1 = require("../logger");
25
- const RecipleConfig_1 = require("./RecipleConfig");
26
28
  const discord_js_1 = require("discord.js");
27
29
  const modules_1 = require("../modules");
28
- const MessageCommandOptions_1 = require("./builders/MessageCommandOptions");
30
+ ;
29
31
  class RecipleClient extends discord_js_1.Client {
30
32
  constructor(options) {
31
33
  var _a, _b, _c;
@@ -33,6 +35,7 @@ class RecipleClient extends discord_js_1.Client {
33
35
  this.config = RecipleConfig_1.RecipleConfig.getDefaultConfig();
34
36
  this.commands = { MESSAGE_COMMANDS: {}, INTERACTION_COMMANDS: {} };
35
37
  this.otherApplicationCommandData = [];
38
+ this.commandCooldowns = new CommandCooldownManager_1.CommandCooldownManager();
36
39
  this.modules = [];
37
40
  this.version = version_1.version;
38
41
  this.logger = (0, logger_1.logger)(!!((_a = options.config) === null || _a === void 0 ? void 0 : _a.fileLogging.stringifyLoggedJSON), !!((_b = options.config) === null || _b === void 0 ? void 0 : _b.fileLogging.debugmode));
@@ -71,7 +74,7 @@ class RecipleClient extends discord_js_1.Client {
71
74
  this.logger.error(`Error loading ${(_a = module_.info.filename) !== null && _a !== void 0 ? _a : 'unknown module'}:`);
72
75
  this.logger.error(err);
73
76
  }
74
- this.modules = this.modules.filter((r, i) => i.toString() !== m.toString());
77
+ this.modules = this.modules.filter((_r, i) => i.toString() !== m.toString());
75
78
  });
76
79
  }
77
80
  if (typeof ((_b = module_.script) === null || _b === void 0 ? void 0 : _b.commands) !== 'undefined') {
@@ -155,36 +158,69 @@ class RecipleClient extends discord_js_1.Client {
155
158
  const command = this.findCommand(parseCommand.command, 'MESSAGE_COMMAND');
156
159
  if (!command)
157
160
  return;
158
- if ((0, hasPermissions_1.hasPermissions)(command.name, (_a = message.member) === null || _a === void 0 ? void 0 : _a.permissions, this.config.permissions.messageCommands, command)) {
161
+ const commandOptions = command.getCommandOptionValues(parseCommand);
162
+ const executeData = {
163
+ message: message,
164
+ options: new MessageCommandOptionManager_1.MessageCommandOptionManager(commandOptions),
165
+ command: parseCommand,
166
+ builder: command,
167
+ client: this
168
+ };
169
+ if ((0, permissions_1.userHasCommandPermissions)(command.name, (_a = message.member) === null || _a === void 0 ? void 0 : _a.permissions, this.config.permissions.messageCommands, command)) {
159
170
  if (!command.allowExecuteInDM && message.channel.type === 'DM'
160
171
  || !command.allowExecuteByBots
161
172
  && (message.author.bot || message.author.system)
162
173
  || (0, isIgnoredChannel_1.isIgnoredChannel)(message.channelId, this.config.ignoredChannels))
163
174
  return;
164
- const commandOptions = command.getCommandOptionValues(parseCommand);
165
175
  if (command.validateOptions) {
166
176
  if (commandOptions.some(o => o.invalid)) {
167
- yield message.reply(this.getMessage('invalidArguments', 'Invalid argument(s) given.')).catch(er => this.replyError(er));
177
+ if (!(command === null || command === void 0 ? void 0 : command.halt) || !(yield command.halt({ executeData, reason: 'INVALID_ARGUMENTS', invalidArguments: new MessageCommandOptionManager_1.MessageCommandOptionManager(executeData.options.filter(o => o.invalid)) }))) {
178
+ message.reply(this.getMessage('invalidArguments', 'Invalid argument(s) given.')).catch(er => this.replyError(er));
179
+ }
168
180
  return;
169
181
  }
170
182
  if (commandOptions.some(o => o.missing)) {
171
- yield message.reply(this.getMessage('notEnoughArguments', 'Not enough arguments.')).catch(er => this.replyError(er));
183
+ if (!command.halt || !(yield command.halt({ executeData, reason: 'MISSING_ARGUMENTS', missingArguments: new MessageCommandOptionManager_1.MessageCommandOptionManager(executeData.options.filter(o => o.missing)) }))) {
184
+ message.reply(this.getMessage('notEnoughArguments', 'Not enough arguments.')).catch(er => this.replyError(er));
185
+ }
172
186
  return;
173
187
  }
174
188
  }
175
- const options = {
176
- message: message,
177
- options: new MessageCommandOptions_1.MessageCommandOptions(commandOptions),
178
- command: parseCommand,
179
- builder: command,
180
- client: this
189
+ if (message.guild && !(0, permissions_1.botHasExecutePermissions)(message.guild, command.requiredBotPermissions)) {
190
+ if (!command.halt || !(yield command.halt({ executeData, reason: 'MISSING_BOT_PERMISSIONS' }))) {
191
+ message.reply(this.getMessage('insufficientBotPerms', 'Insufficient bot permissions.')).catch(er => this.replyError(er));
192
+ }
193
+ return;
194
+ }
195
+ const userCooldown = {
196
+ user: message.author,
197
+ command: command.name,
198
+ channel: message.channel,
199
+ guild: message.guild,
200
+ type: 'MESSAGE_COMMAND'
181
201
  };
182
- yield Promise.resolve(command.execute(options)).catch(err => this._commandExecuteError(err, options));
183
- this.emit('recipleMessageCommandCreate', options);
184
- return options;
202
+ if (command.cooldown && !this.commandCooldowns.isCooledDown(userCooldown)) {
203
+ this.commandCooldowns.add(Object.assign(Object.assign({}, userCooldown), { expireTime: Date.now() + command.cooldown }));
204
+ }
205
+ else if (command.cooldown) {
206
+ if (!command.halt || !(yield command.halt(Object.assign({ executeData, reason: 'COOLDOWN' }, this.commandCooldowns.get(userCooldown))))) {
207
+ yield message.reply(this.getMessage('cooldown', 'You cannot execute this command right now due to the cooldown.')).catch(er => this.replyError(er));
208
+ }
209
+ return;
210
+ }
211
+ try {
212
+ yield Promise.resolve(command.execute(executeData)).catch((err) => __awaiter(this, void 0, void 0, function* () { return !command.halt || !(yield command.halt({ executeData, reason: 'ERROR', error: err })) ? this._commandExecuteError(err, executeData) : void 0; }));
213
+ this.emit('recipleMessageCommandCreate', executeData);
214
+ return executeData;
215
+ }
216
+ catch (err) {
217
+ if (!command.halt || !(yield command.halt({ executeData, reason: 'ERROR', error: err }))) {
218
+ this._commandExecuteError(err, executeData);
219
+ }
220
+ }
185
221
  }
186
- else {
187
- yield message.reply(this.getMessage('noPermissions', 'You do not have permission to use this command.')).catch(er => this.replyError(er));
222
+ else if (!command.halt || !(yield command.halt({ executeData, reason: 'MISSING_MEMBER_PERMISSIONS' }))) {
223
+ message.reply(this.getMessage('noPermissions', 'You do not have permission to use this command.')).catch(er => this.replyError(er));
188
224
  }
189
225
  });
190
226
  }
@@ -192,27 +228,55 @@ class RecipleClient extends discord_js_1.Client {
192
228
  * Execute an Interaction command
193
229
  */
194
230
  interactionCommandExecute(interaction) {
195
- var _a;
231
+ var _a, _b;
196
232
  return __awaiter(this, void 0, void 0, function* () {
197
233
  if (!interaction || !interaction.isCommand() || !this.isReady())
198
234
  return;
199
235
  const command = this.findCommand(interaction.commandName, 'INTERACTION_COMMAND');
200
236
  if (!command)
201
237
  return;
202
- if ((0, hasPermissions_1.hasPermissions)(command.name, (_a = interaction.memberPermissions) !== null && _a !== void 0 ? _a : undefined, this.config.permissions.interactionCommands, command)) {
238
+ const executeData = {
239
+ interaction: interaction,
240
+ builder: command,
241
+ client: this
242
+ };
243
+ if ((0, permissions_1.userHasCommandPermissions)(command.name, (_a = interaction.memberPermissions) !== null && _a !== void 0 ? _a : undefined, this.config.permissions.interactionCommands, command)) {
203
244
  if (!command || (0, isIgnoredChannel_1.isIgnoredChannel)(interaction.channelId, this.config.ignoredChannels))
204
245
  return;
205
- const options = {
206
- interaction: interaction,
207
- command: command,
208
- builder: command,
209
- client: this
246
+ if (interaction.guild && (0, permissions_1.botHasExecutePermissions)(interaction.guild, command.requiredBotPermissions)) {
247
+ if (!command.halt || !(yield command.halt({ executeData, reason: 'MISSING_BOT_PERMISSIONS' }))) {
248
+ yield interaction.reply(this.getMessage('insufficientBotPerms', 'Insufficient bot permissions.')).catch(er => this.replyError(er));
249
+ }
250
+ return;
251
+ }
252
+ const userCooldown = {
253
+ user: interaction.user,
254
+ command: command.name,
255
+ channel: (_b = interaction.channel) !== null && _b !== void 0 ? _b : undefined,
256
+ guild: interaction.guild,
257
+ type: 'INTERACTION_COMMAND'
210
258
  };
211
- yield Promise.resolve(command.execute(options)).catch(err => this._commandExecuteError(err, options));
212
- this.emit('recipleInteractionCommandCreate', options);
213
- return options;
259
+ if (command.cooldown && !this.commandCooldowns.isCooledDown(userCooldown)) {
260
+ this.commandCooldowns.add(Object.assign(Object.assign({}, userCooldown), { expireTime: Date.now() + command.cooldown }));
261
+ }
262
+ else if (command.cooldown) {
263
+ if (!command.halt || !(yield command.halt(Object.assign({ executeData, reason: 'COOLDOWN' }, this.commandCooldowns.get(userCooldown))))) {
264
+ yield interaction.reply(this.getMessage('cooldown', 'You cannot execute this command right now due to the cooldown.')).catch(er => this.replyError(er));
265
+ }
266
+ return;
267
+ }
268
+ try {
269
+ yield Promise.resolve(command.execute(executeData)).catch((err) => __awaiter(this, void 0, void 0, function* () { return !command.halt || !(yield command.halt({ executeData, reason: 'ERROR', error: err })) ? this._commandExecuteError(err, executeData) : void 0; }));
270
+ this.emit('recipleInteractionCommandCreate', executeData);
271
+ return executeData;
272
+ }
273
+ catch (err) {
274
+ if (!command.halt || !(yield command.halt({ executeData, reason: 'ERROR', error: err }))) {
275
+ this._commandExecuteError(err, executeData);
276
+ }
277
+ }
214
278
  }
215
- else {
279
+ else if (!command.halt || !(yield command.halt({ executeData, reason: 'MISSING_MEMBER_PERMISSIONS' }))) {
216
280
  yield interaction.reply(this.getMessage('noPermissions', 'You do not have permission to use this command.')).catch(er => this.replyError(er));
217
281
  }
218
282
  });
@@ -1,7 +1,7 @@
1
- import { ClientOptions, PermissionFlags, PermissionString } from 'discord.js';
1
+ import { ClientOptions, PermissionResolvable } from 'discord.js';
2
2
  export interface ConfigCommandPermissions {
3
3
  command: string;
4
- permissions: (PermissionFlags | PermissionString)[];
4
+ permissions: PermissionResolvable[];
5
5
  }
6
6
  export interface Config {
7
7
  token: string;
@@ -11,12 +11,14 @@ export interface Config {
11
11
  enabled: boolean;
12
12
  replyOnError: boolean;
13
13
  allowCommandAlias: boolean;
14
+ enableCooldown: boolean;
14
15
  commandArgumentSeparator: string;
15
16
  };
16
17
  interactionCommand: {
17
18
  enabled: boolean;
18
19
  replyOnError: boolean;
19
20
  registerCommands: boolean;
21
+ enableCooldown: boolean;
20
22
  setRequiredPermissions: boolean;
21
23
  guilds: string[] | string;
22
24
  };
@@ -1,23 +1,34 @@
1
- import { CommandInteraction, PermissionFlags, PermissionString } from 'discord.js';
1
+ import { Awaitable, CommandInteraction, PermissionResolvable } from 'discord.js';
2
+ import { RecipleClient, RecipleHaltedCommandData } from '../RecipleClient';
2
3
  import { SlashCommandBuilder } from '@discordjs/builders';
3
- import { RecipleClient } from '../RecipleClient';
4
- export interface RecipleInteractionCommandExecute {
4
+ export interface RecipleInteractionCommandExecuteData {
5
5
  interaction: CommandInteraction;
6
- command: InteractionCommandBuilder;
7
6
  builder: InteractionCommandBuilder;
8
7
  client: RecipleClient<true>;
9
8
  }
10
9
  export declare class InteractionCommandBuilder extends SlashCommandBuilder {
11
10
  readonly builder = "INTERACTION_COMMAND";
12
- requiredPermissions: (PermissionFlags | PermissionString)[];
11
+ cooldown: number;
12
+ requiredBotPermissions: PermissionResolvable[];
13
+ RequiredUserPermissions: PermissionResolvable[];
13
14
  allowExecuteInDM: boolean;
14
- execute: (options: RecipleInteractionCommandExecute) => void;
15
+ halt?: (haltData: RecipleHaltedCommandData<InteractionCommandBuilder>) => Awaitable<boolean>;
16
+ execute: (executeData: RecipleInteractionCommandExecuteData) => Awaitable<void>;
15
17
  /**
16
- * Set required permissions before executing the command
18
+ * Sets the execute cooldown for this command.
19
+ * - `0` means no cooldown
17
20
  */
18
- setRequiredPermissions(requiredPermissions: (keyof PermissionFlags)[]): InteractionCommandBuilder;
21
+ setCooldown(cooldown: number): InteractionCommandBuilder;
22
+ /**
23
+ * Set required permissions to execute the command
24
+ */
25
+ setRequiredMemberPermissions(...permissions: PermissionResolvable[]): InteractionCommandBuilder;
26
+ /**
27
+ * Function when the command is interupted before execution
28
+ */
29
+ setHalt(halt?: (haltData: RecipleHaltedCommandData<InteractionCommandBuilder>) => Awaitable<boolean>): InteractionCommandBuilder;
19
30
  /**
20
31
  * Function when the command is executed
21
32
  */
22
- setExecute(execute: (options: RecipleInteractionCommandExecute) => void): InteractionCommandBuilder;
33
+ setExecute(execute: (executeData: RecipleInteractionCommandExecuteData) => void): InteractionCommandBuilder;
23
34
  }
@@ -6,17 +6,32 @@ class InteractionCommandBuilder extends builders_1.SlashCommandBuilder {
6
6
  constructor() {
7
7
  super(...arguments);
8
8
  this.builder = 'INTERACTION_COMMAND';
9
- this.requiredPermissions = [];
9
+ this.cooldown = 0;
10
+ this.requiredBotPermissions = [];
11
+ this.RequiredUserPermissions = [];
10
12
  this.allowExecuteInDM = true;
11
13
  this.execute = () => { };
12
14
  }
13
15
  /**
14
- * Set required permissions before executing the command
16
+ * Sets the execute cooldown for this command.
17
+ * - `0` means no cooldown
15
18
  */
16
- setRequiredPermissions(requiredPermissions) {
17
- if (!requiredPermissions || !Array.isArray(requiredPermissions))
18
- throw new Error('requiredPermissions must be an array.');
19
- this.requiredPermissions = requiredPermissions;
19
+ setCooldown(cooldown) {
20
+ this.cooldown = cooldown;
21
+ return this;
22
+ }
23
+ /**
24
+ * Set required permissions to execute the command
25
+ */
26
+ setRequiredMemberPermissions(...permissions) {
27
+ this.RequiredUserPermissions = permissions;
28
+ return this;
29
+ }
30
+ /**
31
+ * Function when the command is interupted before execution
32
+ */
33
+ setHalt(halt) {
34
+ this.halt = halt ? halt : undefined;
20
35
  return this;
21
36
  }
22
37
  /**
@@ -1,11 +1,11 @@
1
1
  import { MessageCommandOptionBuilder } from './MessageCommandOptionBuilder';
2
- import { Message, PermissionFlags, PermissionString } from 'discord.js';
2
+ import { RecipleClient, RecipleHaltedCommandData } from '../RecipleClient';
3
+ import { MessageCommandOptionManager } from '../MessageCommandOptionManager';
4
+ import { Awaitable, Message, PermissionResolvable } from 'discord.js';
3
5
  import { Command as CommandMessage } from 'fallout-utility';
4
- import { RecipleClient } from '../RecipleClient';
5
- import { MessageCommandOptions } from './MessageCommandOptions';
6
- export interface RecipleMessageCommandExecute {
6
+ export interface RecipleMessageCommandExecuteData {
7
7
  message: Message;
8
- options: MessageCommandOptions;
8
+ options: MessageCommandOptionManager;
9
9
  command: CommandMessage;
10
10
  builder: MessageCommandBuilder;
11
11
  client: RecipleClient<true>;
@@ -20,14 +20,17 @@ export interface MessageCommandValidatedOption {
20
20
  export declare class MessageCommandBuilder {
21
21
  readonly builder = "MESSAGE_COMMAND";
22
22
  name: string;
23
+ cooldown: number;
23
24
  description: string;
24
25
  aliases: string[];
25
26
  options: MessageCommandOptionBuilder[];
26
27
  validateOptions: boolean;
27
- requiredPermissions: (PermissionFlags | PermissionString)[];
28
+ requiredBotPermissions: PermissionResolvable[];
29
+ RequiredUserPermissions: PermissionResolvable[];
28
30
  allowExecuteInDM: boolean;
29
31
  allowExecuteByBots: boolean;
30
- execute: (options: RecipleMessageCommandExecute) => void;
32
+ halt?: (haltData: RecipleHaltedCommandData<MessageCommandBuilder>) => Awaitable<boolean>;
33
+ execute: (executeData: RecipleMessageCommandExecuteData) => void;
31
34
  /**
32
35
  * Sets the command name
33
36
  */
@@ -36,14 +39,23 @@ export declare class MessageCommandBuilder {
36
39
  * Sets the command description
37
40
  */
38
41
  setDescription(description: string): MessageCommandBuilder;
42
+ /**
43
+ * Sets the execute cooldown for this command.
44
+ * - `0` means no cooldown
45
+ */
46
+ setCooldown(cooldown: number): MessageCommandBuilder;
39
47
  /**
40
48
  * Add aliases to the command
41
49
  */
42
50
  addAliases(...aliases: string[]): MessageCommandBuilder;
43
51
  /**
44
- * Sets the default required permissions to execute this command
52
+ * Set required per
53
+ */
54
+ setRequiredBotPermissions(...permissions: PermissionResolvable[]): MessageCommandBuilder;
55
+ /**
56
+ * Set required user permissions to execute the command
45
57
  */
46
- setRequiredPermissions(permissions: (PermissionFlags | PermissionString)[]): MessageCommandBuilder;
58
+ setRequiredMemberPermissions(...permissions: PermissionResolvable[]): MessageCommandBuilder;
47
59
  /**
48
60
  * Set if command can be executed in dms
49
61
  */
@@ -52,10 +64,14 @@ export declare class MessageCommandBuilder {
52
64
  * Allow command to be executed by bots
53
65
  */
54
66
  setAllowExecuteByBots(allowExecuteByBots: boolean): MessageCommandBuilder;
67
+ /**
68
+ * Function when the command is interupted before execution
69
+ */
70
+ setHalt(halt?: (haltData: RecipleHaltedCommandData<MessageCommandBuilder>) => Awaitable<boolean>): MessageCommandBuilder;
55
71
  /**
56
72
  * Function when the command is executed
57
73
  */
58
- setExecute(execute: (options: RecipleMessageCommandExecute) => void): MessageCommandBuilder;
74
+ setExecute(execute: (executeData: RecipleMessageCommandExecuteData) => void): MessageCommandBuilder;
59
75
  /**
60
76
  * Add option to the command
61
77
  */
@@ -6,11 +6,13 @@ class MessageCommandBuilder {
6
6
  constructor() {
7
7
  this.builder = 'MESSAGE_COMMAND';
8
8
  this.name = '';
9
+ this.cooldown = 0;
9
10
  this.description = '';
10
11
  this.aliases = [];
11
12
  this.options = [];
12
13
  this.validateOptions = false;
13
- this.requiredPermissions = [];
14
+ this.requiredBotPermissions = [];
15
+ this.RequiredUserPermissions = [];
14
16
  this.allowExecuteInDM = true;
15
17
  this.allowExecuteByBots = false;
16
18
  this.execute = () => { };
@@ -33,6 +35,14 @@ class MessageCommandBuilder {
33
35
  this.description = description;
34
36
  return this;
35
37
  }
38
+ /**
39
+ * Sets the execute cooldown for this command.
40
+ * - `0` means no cooldown
41
+ */
42
+ setCooldown(cooldown) {
43
+ this.cooldown = cooldown;
44
+ return this;
45
+ }
36
46
  /**
37
47
  * Add aliases to the command
38
48
  */
@@ -47,12 +57,17 @@ class MessageCommandBuilder {
47
57
  return this;
48
58
  }
49
59
  /**
50
- * Sets the default required permissions to execute this command
60
+ * Set required per
61
+ */
62
+ setRequiredBotPermissions(...permissions) {
63
+ this.requiredBotPermissions = permissions;
64
+ return this;
65
+ }
66
+ /**
67
+ * Set required user permissions to execute the command
51
68
  */
52
- setRequiredPermissions(permissions) {
53
- if (!permissions || !Array.isArray(permissions))
54
- throw new TypeError('permissions must be an array.');
55
- this.requiredPermissions = permissions;
69
+ setRequiredMemberPermissions(...permissions) {
70
+ this.RequiredUserPermissions = permissions;
56
71
  return this;
57
72
  }
58
73
  /**
@@ -73,6 +88,13 @@ class MessageCommandBuilder {
73
88
  this.allowExecuteByBots = allowExecuteByBots;
74
89
  return this;
75
90
  }
91
+ /**
92
+ * Function when the command is interupted before execution
93
+ */
94
+ setHalt(halt) {
95
+ this.halt = halt ? halt : undefined;
96
+ return this;
97
+ }
76
98
  /**
77
99
  * Function when the command is executed
78
100
  */
@@ -1,15 +1,15 @@
1
- import { InteractionCommandBuilder, RecipleInteractionCommandExecute } from './classes/builders/InteractionCommandBuilder';
2
- import { MessageCommandBuilder, RecipleMessageCommandExecute } from './classes/builders/MessageCommandBuilder';
1
+ import { InteractionCommandBuilder, RecipleInteractionCommandExecuteData } from './classes/builders/InteractionCommandBuilder';
2
+ import { MessageCommandBuilder, RecipleMessageCommandExecuteData } from './classes/builders/MessageCommandBuilder';
3
3
  import { RecipleClient } from './classes/RecipleClient';
4
- export declare type recipleCommandBuilders = MessageCommandBuilder | InteractionCommandBuilder;
5
- export declare type recipleCommandBuildersExecute = RecipleInteractionCommandExecute | RecipleMessageCommandExecute;
6
- export declare type loadedModules = {
7
- commands: recipleCommandBuilders[];
4
+ export declare type RecipleCommandBuilders = MessageCommandBuilder | InteractionCommandBuilder;
5
+ export declare type RecipleCommandBuildersExecuteData = RecipleInteractionCommandExecuteData | RecipleMessageCommandExecuteData;
6
+ export declare type LoadedModules = {
7
+ commands: RecipleCommandBuilders[];
8
8
  modules: RecipleModule[];
9
9
  };
10
10
  export declare class RecipleScript {
11
11
  versions: string | string[];
12
- commands?: recipleCommandBuilders[];
12
+ commands?: RecipleCommandBuilders[];
13
13
  onLoad?(reciple: RecipleClient): void | Promise<void>;
14
14
  onStart(reciple: RecipleClient): boolean | Promise<boolean>;
15
15
  }
@@ -24,4 +24,4 @@ export interface RecipleModule {
24
24
  /**
25
25
  * Load modules from folder
26
26
  */
27
- export declare function loadModules(client: RecipleClient, folder?: string): Promise<loadedModules>;
27
+ export declare function loadModules(client: RecipleClient, folder?: string): Promise<LoadedModules>;
@@ -0,0 +1,8 @@
1
+ import { RecipleCommandBuilders } from './modules';
2
+ import { Config } from './classes/RecipleConfig';
3
+ import { Guild, PermissionResolvable, Permissions } from 'discord.js';
4
+ /**
5
+ * Check if the user has permissions to execute the given command name
6
+ */
7
+ export declare function userHasCommandPermissions(commandName: string, memberPermissions?: Permissions, configConmmandPermissions?: Config['permissions']['messageCommands'] | Config['permissions']['interactionCommands'], builder?: RecipleCommandBuilders): boolean;
8
+ export declare function botHasExecutePermissions(guild?: Guild, requiredPermissions?: PermissionResolvable[]): boolean;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.botHasExecutePermissions = exports.userHasCommandPermissions = void 0;
4
+ /**
5
+ * Check if the user has permissions to execute the given command name
6
+ */
7
+ function userHasCommandPermissions(commandName, memberPermissions, configConmmandPermissions, builder) {
8
+ var _a, _b;
9
+ if (!(configConmmandPermissions === null || configConmmandPermissions === void 0 ? void 0 : configConmmandPermissions.enabled))
10
+ return true;
11
+ const command = (_a = configConmmandPermissions.commands.find(c => c.command.toLowerCase() === commandName.toLowerCase())) !== null && _a !== void 0 ? _a : { permissions: (_b = builder === null || builder === void 0 ? void 0 : builder.RequiredUserPermissions) !== null && _b !== void 0 ? _b : [] };
12
+ if (!command.permissions.length)
13
+ return true;
14
+ return memberPermissions ? memberPermissions.has(command.permissions) : false;
15
+ }
16
+ exports.userHasCommandPermissions = userHasCommandPermissions;
17
+ function botHasExecutePermissions(guild, requiredPermissions) {
18
+ var _a;
19
+ if (!(requiredPermissions === null || requiredPermissions === void 0 ? void 0 : requiredPermissions.length))
20
+ return true;
21
+ return (guild === null || guild === void 0 ? void 0 : guild.me) ? (_a = guild.me) === null || _a === void 0 ? void 0 : _a.permissions.has(requiredPermissions) : false;
22
+ }
23
+ exports.botHasExecutePermissions = botHasExecutePermissions;
@@ -2,8 +2,8 @@ import { InteractionCommandBuilder } from './classes/builders/InteractionCommand
2
2
  import { ApplicationCommandDataResolvable } from 'discord.js';
3
3
  import { RecipleClient } from './classes/RecipleClient';
4
4
  import { ContextMenuCommandBuilder, SlashCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandOptionsOnlyBuilder, SlashCommandSubcommandGroupBuilder, SlashCommandSubcommandsOnlyBuilder } from '@discordjs/builders';
5
- export declare type interactionCommandBuilders = InteractionCommandBuilder | ContextMenuCommandBuilder | SlashCommandBuilder | SlashCommandSubcommandBuilder | SlashCommandOptionsOnlyBuilder | SlashCommandSubcommandGroupBuilder | SlashCommandSubcommandsOnlyBuilder;
5
+ export declare type InteractionBuilder = InteractionCommandBuilder | ContextMenuCommandBuilder | SlashCommandBuilder | SlashCommandSubcommandBuilder | SlashCommandOptionsOnlyBuilder | SlashCommandSubcommandGroupBuilder | SlashCommandSubcommandsOnlyBuilder;
6
6
  /**
7
7
  * Register interaction commands
8
8
  */
9
- export declare function registerInteractionCommands(client: RecipleClient, cmds?: (interactionCommandBuilders | ApplicationCommandDataResolvable)[], overwriteGuilds?: string | string[]): Promise<void>;
9
+ export declare function registerInteractionCommands(client: RecipleClient, cmds?: (InteractionBuilder | ApplicationCommandDataResolvable)[], overwriteGuilds?: string | string[]): Promise<void>;
@@ -24,8 +24,8 @@ function registerInteractionCommands(client, cmds, overwriteGuilds) {
24
24
  if ((cmd === null || cmd === void 0 ? void 0 : cmd.builder) === 'INTERACTION_COMMAND' && client.config.commands.interactionCommand.setRequiredPermissions) {
25
25
  const permissions = (_d = (((_a = client.config.permissions) === null || _a === void 0 ? void 0 : _a.interactionCommands.enabled) ?
26
26
  (_c = (_b = client.config.permissions) === null || _b === void 0 ? void 0 : _b.interactionCommands.commands.find(cmd_ => cmd_.command.toLowerCase() === cmd.name.toLowerCase())) === null || _c === void 0 ? void 0 : _c.permissions :
27
- undefined)) !== null && _d !== void 0 ? _d : cmd.requiredPermissions;
28
- cmd.setRequiredPermissions(permissions);
27
+ undefined)) !== null && _d !== void 0 ? _d : cmd.requiredBotPermissions;
28
+ cmd.setRequiredMemberPermissions(permissions);
29
29
  client.commands.INTERACTION_COMMANDS[cmd.name] = cmd;
30
30
  if (client.isClientLogsEnabled())
31
31
  client.logger.debug(`Set required permissions for ${cmd.name}`);
@@ -8,7 +8,7 @@ const semver_1 = __importDefault(require("semver"));
8
8
  /**
9
9
  * Current reciple version
10
10
  */
11
- exports.version = require('../../package.json').version;
11
+ exports.version = `${semver_1.default.coerce(require('../../package.json').version)}`;
12
12
  /**
13
13
  * Check if the version is valid
14
14
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reciple",
3
- "version": "1.7.1-pre.0",
3
+ "version": "2.0.0-pre.1",
4
4
  "description": "A Discord.js bot",
5
5
  "author": "FalloutStudios",
6
6
  "homepage": "https://falloutstudios.github.io/Reciple",
@@ -21,11 +21,11 @@
21
21
  ],
22
22
  "scripts": {
23
23
  "clean": "rm -rf bin",
24
- "build": "yarn run clean && npx tsc && yarn run reinstall && yarn run build:docs",
25
- "build:publish": "yarn run build && yarn publish",
26
- "build:pub-prerelease": "yarn run build && yarn publish --tag beta",
24
+ "build": "yarn run clean && npx tsc && yarn run reinstall",
25
+ "build:publish": "yarn run build && yarn publish && yarn run publish:docs",
26
+ "build:pub-prerelease": "yarn run build && yarn publish --tag pre",
27
27
  "reinstall": "npm un reciple -g && npm i ./ -g",
28
- "postpublish": "yarn run build:docs && yarn run update:docs",
28
+ "publish:docs": "yarn run build:docs && yarn run update:docs",
29
29
  "test": "yarn run build && yarn run test:start",
30
30
  "test:start": "cd test && npx reciple",
31
31
  "build:docs": "cd docs && yarn run build",
@@ -13,8 +13,10 @@ commands:
13
13
  enabled: true
14
14
  # reply when an error occured
15
15
  replyOnError: false
16
+ # Enable the use of command cooldowns
17
+ enableCooldown: false
16
18
  # Allow executing commands via aliases
17
- allowCommandAlias: false
19
+ allowCommandAlias: true
18
20
  # command argument separator
19
21
  commandArgumentSeparator: ' '
20
22
  interactionCommand:
@@ -22,6 +24,8 @@ commands:
22
24
  enabled: true
23
25
  # reply when an error occured
24
26
  replyOnError: false
27
+ # Enable the use of command cooldowns
28
+ enableCooldown: false
25
29
  # register interaction commands on bot ready
26
30
  registerCommands: true
27
31
  # set required permissions for interaction commands
@@ -1,7 +0,0 @@
1
- import { Permissions } from 'discord.js';
2
- import { recipleCommandBuilders } from './modules';
3
- import { Config } from './classes/RecipleConfig';
4
- /**
5
- * Check if the user has permissions to execute the given command name
6
- */
7
- export declare function hasPermissions(commandName: string, memberPermissions?: Permissions, configConmmandPermissions?: Config['permissions']['messageCommands'] | Config['permissions']['interactionCommands'], builder?: recipleCommandBuilders): boolean;
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasPermissions = void 0;
4
- /**
5
- * Check if the user has permissions to execute the given command name
6
- */
7
- function hasPermissions(commandName, memberPermissions, configConmmandPermissions, builder) {
8
- var _a, _b;
9
- if (!(configConmmandPermissions === null || configConmmandPermissions === void 0 ? void 0 : configConmmandPermissions.enabled))
10
- return true;
11
- const command = (_a = configConmmandPermissions.commands.find(c => c.command.toLowerCase() === commandName.toLowerCase())) !== null && _a !== void 0 ? _a : { permissions: (_b = builder === null || builder === void 0 ? void 0 : builder.requiredPermissions) !== null && _b !== void 0 ? _b : [] };
12
- if (!command.permissions.length)
13
- return true;
14
- return memberPermissions ? memberPermissions.has(command.permissions) : false;
15
- }
16
- exports.hasPermissions = hasPermissions;