xernerx 2.5.0 → 2.6.2

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/main.js CHANGED
@@ -4,6 +4,7 @@ const { Client } = require('./models/Client.js'),
4
4
  { MessageCommand } = require('./models/commands/MessageCommand.js'),
5
5
  { InteractionCommand } = require('./models/commands/InteractionCommand.js'),
6
6
  { Event } = require('./models/commands/Event.js'),
7
+ { Inhibitor } = require('./models/commands/Inhibitor.js'),
7
8
  { LanguageHandler } = require('./models/handlers/LanguageHandler.js'),
8
9
  { ContextMenuCommand } = require('./models/commands/ContextMenuCommand.js'),
9
10
  pkg = require('./package.json'),
@@ -28,6 +29,8 @@ module.exports = {
28
29
  // Events
29
30
  Event,
30
31
 
32
+ Inhibitor,
33
+
31
34
  // Discord
32
35
  Discord,
33
36
  i18next,
package/models/Client.js CHANGED
@@ -1,88 +1,55 @@
1
1
  const Discord = require('discord.js');
2
2
  const { s } = require('@sapphire/shapeshift');
3
- const { color, config } = require('./utils/Functions.js');
3
+ const { color } = require('./utils/Functions.js');
4
4
  const { CommandHandler } = require('./handlers/CommandHandler.js');
5
5
  const { EventHandler } = require('./handlers/EventHandler.js');
6
6
  const { LanguageHandler } = require('./handlers/LanguageHandler.js');
7
- const Loader = require('./handlers/Loader.js');
7
+ const InhibitorHandler = require('./handlers/InhibitorHandler.js');
8
+ const Handler = require('./handlers/Handler.js');
8
9
 
9
- /**
10
- * @param {string} guildId - Test guild ID.
11
- * @param {boolean} global - Whether the bot should be globally or locally loaded.
12
- * @param {string[]} prefix - An array of prefix'.
13
- * @param {string[]} ownerId - An array of bot owners.
14
- * @param {boolean} ignoreOwner - Whether the bot should ignore owner privileges.
15
- * @param {number} defaultCooldown - A cooldown between each command in milliseconds.
16
- * @returns Discord client ready to login.
17
- */
18
10
  class Client extends Discord.Client {
19
- constructor(options = {}) {
11
+ constructor(options = {}, settings = {}, i18next = {}, config = {}) {
20
12
  super(options)
21
13
 
22
- s.object({
23
- // Required
24
- guildId: s.string,
25
- global: s.boolean,
14
+ this.client = new Discord.Client({ intents: options.intents });
26
15
 
27
- // optionals
28
- prefix: s.array(s.string).optional,
29
- ownerId: s.array(s.string).optional,
30
- ignoreOwner: s.boolean.optional,
31
- defaultCooldown: s.number.optional,
32
- cacheTime: s.number.optional,
33
- userPermissions: s.array(s.string).optional,
34
- clientPermissions: s.array(s.string).optional,
35
- defer: s.object({
36
- reply: s.boolean.optional,
37
- ephemeral: s.boolean.optional
38
- }).optional,
39
- }).parse(options)
16
+ this.client.settings = s.object({
17
+ guildId: s.string.default(undefined),
18
+ global: s.boolean.default(false),
19
+ prefix: s.array(s.string).default([]),
20
+ ownerId: s.array(s.string).default([]),
21
+ ignoreOwner: s.boolean.default(false),
22
+ defaultCooldown: s.number.default(0),
23
+ cacheTime: s.number.default(300000),
24
+ userPermissions: s.array(s.string).default([]),
25
+ clientPermissions: s.array(s.string).default([]),
26
+ logging: s.union(s.boolean, s.array(s.string)).default(false),
27
+ }).parse(settings);
40
28
 
41
- this.client = new Discord.Client({ intents: [options.intents || 0], partials: [options.partials] });
29
+ this.client.language = i18next;
42
30
 
43
- this.client.settings = {
44
- prefix: options.prefix || [],
31
+ this.client.color = color({ client: this.client, options: settings });
45
32
 
46
- ownerId: options.ownerId || [],
33
+ this.client.config = config;
47
34
 
48
- guildId: options.guildId || undefined,
35
+ this.client.data = {
36
+ messages: {},
49
37
 
50
- global: options.global || false,
51
-
52
- ignoreOwner: options.ignoreOwner || false,
53
-
54
- defaultCooldown: options.defaultCooldown || 0,
55
-
56
- logging: options.logging || undefined,
57
-
58
- cacheTime: options.cacheTime || 300000,
59
-
60
- userPermissions: options.userPermissions || [],
61
-
62
- clientPermissions: options.clientPermissions || [],
63
-
64
- defer: {
65
- reply: options?.defer?.reply === undefined ? null : options?.defer?.reply,
66
- ephemeral: options?.defer?.ephemeral === undefined ? null : options?.defer?.ephemeral
67
- },
68
- }
69
-
70
- this.client.language = options.language;
71
-
72
- this.client.color = color({ client: this.client, options: options });
73
-
74
- this.client.config = config({ client: this.client, options: options });
75
-
76
- this.client.messages = {};
38
+ cooldowns: {}
39
+ };
77
40
 
78
41
  this.client.modules = {
79
42
  commandHandler: new CommandHandler({ client: this.client }),
80
43
 
81
44
  eventHandler: new EventHandler({ client: this.client }),
82
45
 
83
- languageHandler: new LanguageHandler(this.client),
46
+ inhibitorHandler: new InhibitorHandler(this.client),
47
+
48
+ languageHandler: new LanguageHandler(this.client)
49
+ }
84
50
 
85
- loader: new Loader(this.client)
51
+ this.client.util = {
52
+ handler: new Handler(this.client)
86
53
  }
87
54
 
88
55
  return this.client;
@@ -0,0 +1,31 @@
1
+ const { s } = require('@sapphire/shapeshift')
2
+
3
+ /**
4
+ * @param {String} id - The id of the event. @required
5
+ * @param {object} options - of the event. @required
6
+ * @param {string} name - The name of the event. @required
7
+ * @param {boolean} once - Whether the event should be ran once or continuously.
8
+ */
9
+ class Inhibitor {
10
+ constructor(id, options = {}) {
11
+ s.object({
12
+ name: s.string,
13
+ type: s.string
14
+ }).parse(options)
15
+
16
+ this.id = id;
17
+
18
+ this.name = options.name;
19
+
20
+ this.type = options.type || undefined;
21
+
22
+ }
23
+
24
+ check(event) {
25
+ /*
26
+ * Make your custom event here.
27
+ */
28
+ }
29
+ }
30
+
31
+ module.exports = { Inhibitor };
@@ -17,6 +17,7 @@ class MessageCommand {
17
17
  name: s.string,
18
18
  aliases: s.array(s.string).optional,
19
19
  description: s.string,
20
+ prefix: s.array(s.string).optional,
20
21
  info: s.string.optional,
21
22
  owner: s.boolean.optional,
22
23
  admin: s.boolean.optional,
@@ -34,9 +35,13 @@ class MessageCommand {
34
35
 
35
36
  this.id = id;
36
37
 
38
+ this.name = options.name;
39
+
37
40
  this.aliases = [options.name, ...(options.aliases ? options.aliases : [])];
38
41
 
39
- this.type = options.type;
42
+ this.regex = options.regex instanceof RegExp ? String(options.regex) : undefined;
43
+
44
+ this.prefix = options.prefix || [];
40
45
 
41
46
  this.description = options.description || undefined;
42
47
 
@@ -3,6 +3,7 @@ const { interactionArgs } = require('./../utils/Arguments.js');
3
3
  const { InteractionType } = require('discord.js')
4
4
  const { commandValidation } = require('./../utils/CommandValidation.js');
5
5
  const { interactionUtil } = require('./../utils/Util.js');
6
+ const { inhibitorsValidation } = require('../utils/InhibitorsValidation.js');
6
7
  /**
7
8
  * @returns interaction command executor.
8
9
  */
@@ -16,12 +17,14 @@ class BuildInInteractionEvent extends Event {
16
17
  }
17
18
 
18
19
  async run(interaction) {
19
- await interactionUtil(interaction)
20
+ await interactionUtil(interaction);
20
21
 
21
22
  if (interaction.type == InteractionType.ApplicationCommand) {
22
23
  if (interaction.client.commands.interaction.has(interaction.commandName)) {
23
24
  let command = interaction.client.commands.interaction.get(interaction.commandName);
24
25
 
26
+ if (inhibitorsValidation(interaction, command)) return;
27
+
25
28
  await this.defer(interaction, command);
26
29
 
27
30
  command.client = interaction.client;
@@ -35,7 +38,9 @@ class BuildInInteractionEvent extends Event {
35
38
  if (commandValidation(interaction, command)) return;
36
39
 
37
40
  try {
38
- await command.exec(interaction, { group: group, subcommand: subcommand, args: args });
41
+ if (command.conditions) return command.conditions(interaction, { group, subcommand, args });
42
+
43
+ await command.exec(interaction, { group, subcommand, args });
39
44
 
40
45
  return interaction.client.emit('commandRun', interaction, "interaction", command)
41
46
  }
@@ -47,11 +52,15 @@ class BuildInInteractionEvent extends Event {
47
52
  if (interaction.client.commands.contextMenu.has(interaction.commandName)) {
48
53
  let command = interaction.client.commands.contextMenu.get(interaction.commandName);
49
54
 
55
+ if (inhibitorsValidation(interaction)) return;
56
+
50
57
  await this.defer(interaction, command);
51
58
 
52
59
  command.client = interaction.client;
53
60
 
54
61
  try {
62
+ if (command.conditions) return command.conditions(interaction);
63
+
55
64
  await command.exec(interaction);
56
65
 
57
66
  return interaction.client.emit('commandRun', interaction, 'contextMenu', command);
@@ -2,6 +2,7 @@ const { Event } = require('../commands/Event.js');
2
2
  const { messageArgs } = require("./../utils/Arguments.js");
3
3
  const { commandValidation } = require('./../utils/CommandValidation.js');
4
4
  const { messageUtil } = require('../utils/Util.js');
5
+ const { inhibitorsValidation } = require('../utils/InhibitorsValidation.js');
5
6
 
6
7
  /**
7
8
  * @returns message command executor.
@@ -17,33 +18,62 @@ class BuildInMessageEvent extends Event {
17
18
 
18
19
  async run(message) {
19
20
  if (!message.author.bot) {
21
+ await messageUtil(message, "create");
22
+
23
+ let commands = message.client.commands.message;
24
+
25
+ commands.filter(c => c.regex).map(async command => {
26
+ let regex = command.regex.split(/\//).slice(1);
27
+
28
+ regex = RegExp(...regex);
29
+
30
+ if (message.content.match(regex)) {
31
+ try {
32
+ if (command.conditions && (await command.conditions(message))) return;
33
+
34
+ return await command.exec(message);
35
+ }
36
+ catch (error) {
37
+ message.client.emit("error", message, error);
38
+ }
39
+ };
40
+ })
41
+
20
42
  if (message?.client?.settings?.prefix?.length <= 0) return;
21
43
 
22
- await messageUtil(message, "create");
44
+ commands.filter(c => !c.regex).map(async command => {
45
+ command?.prefix?.map(prefix => {
46
+ this.commandCheck(message, prefix, command);
47
+ })
23
48
 
24
- for (const prefix of message.client.settings.prefix) {
25
- if (!message.content.startsWith(prefix)) continue;
49
+ message.client.settings.prefix.map(prefix => {
50
+ this.commandCheck(message, prefix, command);
51
+ });
52
+ })
53
+ }
54
+ }
26
55
 
27
- let command = message.content.replace(prefix, "").split(/ +/).shift().toLowerCase();
56
+ async commandCheck(message, prefix, command) {
57
+ for (const alias of command.aliases) {
58
+ if (message.content.split(/ +/)[0] !== prefix + alias) continue;
28
59
 
29
- if (!message.client.commands.message.has(command) || command == '') return;
60
+ if (inhibitorsValidation(message, command)) break;
30
61
 
31
- command = message.client.commands.message.get(command);
62
+ const args = await messageArgs({ message: message, command: command });
32
63
 
33
- command.client = message.client;
64
+ if (commandValidation(message, command)) break;
34
65
 
35
- const args = await messageArgs({ message: message, command: command });
66
+ try {
67
+ if (command.conditions && (await command.conditions(message, args))) break;
36
68
 
37
- if (commandValidation(message, command)) return;
69
+ await command.exec(message, args);
38
70
 
39
- try {
40
- await command.exec(message, args);
71
+ return message.client.emit('commandRun', message, 'message', command);
72
+ }
73
+ catch (error) {
74
+ message.client.emit("error", message, error);
41
75
 
42
- return message.client.emit('commandRun', message, 'message', command);
43
- }
44
- catch (error) {
45
- message.client.emit("error", message, error);
46
- }
76
+ break;
47
77
  }
48
78
  }
49
79
  }
@@ -2,6 +2,7 @@ const { Event } = require('../commands/Event.js');
2
2
  const { messageArgs } = require("./../utils/Arguments.js");
3
3
  const { commandValidation } = require('./../utils/CommandValidation.js');
4
4
  const { messageUtil } = require('../utils/Util.js');
5
+ const { inhibitorsValidation } = require('../utils/InhibitorsValidation.js');
5
6
 
6
7
  /**
7
8
  * @returns message command executor.
@@ -16,37 +17,64 @@ class BuildInMessageUpdateEvent extends Event {
16
17
  }
17
18
 
18
19
  async run(oldMessage, newMessage) {
19
- if (newMessage?.client?.settings?.prefix?.length <= 0) return;
20
+ if (!oldMessage.author.bot && !newMessage.author.bot) {
21
+ await messageUtil(newMessage, "edit");
20
22
 
21
- await messageUtil(newMessage, "edit");
23
+ let commands = newMessage.client.commands.message;
22
24
 
23
- if (!oldMessage.author.bot && !newMessage.author.bot) {
25
+ commands.filter(c => c.regex).map(async command => {
26
+ let regex = command.regex.split(/\//).slice(1);
27
+
28
+ regex = RegExp(...regex);
24
29
 
25
- if (!newMessage.client.messages[newMessage.id] === undefined) return;
30
+ if (newMessage.content.match(regex)) {
31
+ try {
32
+ if (command.conditions && (await command.conditions(newMessage))) return;
26
33
 
27
- for (const prefix of newMessage.client.settings.prefix) {
28
- if (!newMessage.content.startsWith(prefix)) continue;
34
+ return await command.exec(newMessage);
35
+ }
36
+ catch (error) {
37
+ newMessage.client.emit("error", newMessage, error);
38
+ }
39
+ };
40
+ })
29
41
 
30
- let command = newMessage.content.replace(prefix, "").split(/ +/).shift().toLowerCase();
42
+ if (newMessage?.client?.settings?.prefix?.length <= 0) return;
31
43
 
32
- if (!newMessage.client.commands.message.has(command) || command === '') return;
44
+ if (!newMessage.client.data.messages[newMessage.id] === undefined) return;
33
45
 
34
- command = newMessage.client.commands.message.get(command);
46
+ commands.filter(c => !c.regex).map(async command => {
47
+ command?.prefix?.map(prefix => {
48
+ this.commandCheck(newMessage, prefix, command);
49
+ })
35
50
 
36
- command.client = newMessage.client;
51
+ newMessage.client.settings.prefix.map(prefix => {
52
+ this.commandCheck(newMessage, prefix, command);
53
+ });
54
+ })
55
+ }
56
+ }
37
57
 
38
- const args = await messageArgs({ message: newMessage, command: command });
58
+ async commandCheck(message, prefix, command) {
59
+ for (const alias of command.aliases) {
60
+ if (message.content.split(/ +/)[0] !== prefix + alias) continue;
39
61
 
40
- if (commandValidation(newMessage, command)) return;
62
+ if (inhibitorsValidation(message, command)) break;
41
63
 
42
- try {
43
- command.exec(newMessage, args);
64
+ const args = await messageArgs({ message: message, command: command });
44
65
 
45
- return newMessage.client.emit('commandRun', newMessage, 'message', command);
46
- }
47
- catch (error) {
48
- newMessage.client.emit("error", newMessage, error);
49
- }
66
+ if (commandValidation(message, command)) break;
67
+
68
+ try {
69
+ if (command.conditions && (await command.conditions(message, args))) break;
70
+
71
+ await command.exec(message, args);
72
+
73
+ return message.client.emit('commandRun', message, 'message', command);
74
+ }
75
+ catch (error) {
76
+ message.client.emit("error", message, error);
77
+ break;
50
78
  }
51
79
  }
52
80
  }
@@ -36,12 +36,20 @@ class BuildInReadyOnceEvent extends Event {
36
36
  loaded.push(event);
37
37
  }
38
38
 
39
+ for (const [id, inhibitor] of [...client.inhibitors]) {
40
+ inhibitor.runType = 'inhibitor';
41
+
42
+ loaded.push(inhibitor);
43
+ }
44
+
39
45
  console.table(loaded, client.settings.logging);
40
46
  }
41
47
  else {
42
48
  Object.entries(client.commands).map(([type, commands]) => {
43
49
  console.info(logStyle(`Loaded ${type} commands: ${commands.map(command => command?.data?.name || command?.name || command?.id).join(', ')}`, "text", "cyan"));
44
50
  })
51
+
52
+ // add events and inhibitors;
45
53
  }
46
54
  }
47
55
 
@@ -1,10 +1,5 @@
1
- const fs = require('fs');
2
1
  const Discord = require('discord.js');
3
- const { REST } = require('@discordjs/rest');
4
- const { Routes, GatewayVersion } = require('discord-api-types/v10');
5
- const { delay, logStyle } = require('dumfunctions')
6
- const paths = require("path");
7
- const Loader = require('./Loader.js');
2
+ const Handler = require('./Handler.js');
8
3
 
9
4
  /**
10
5
  * @param {object} client - The client.
@@ -15,8 +10,6 @@ class CommandHandler {
15
10
 
16
11
  this.client = client;
17
12
 
18
- this.commands = [];
19
-
20
13
  client.commands = {
21
14
  message: new Discord.Collection(),
22
15
 
@@ -25,7 +18,7 @@ class CommandHandler {
25
18
  contextMenu: new Discord.Collection()
26
19
  }
27
20
 
28
- this.load = new Loader(client);
21
+ this.load = new Handler(client);
29
22
  }
30
23
 
31
24
  loadAllInteractionCommands(path, logging = false) {
@@ -56,9 +56,11 @@ class EventHandler {
56
56
  }
57
57
 
58
58
  emitter(type) {
59
- if (type == 'client') return this.client;
60
- if (type == 'rest') return this.client.rest;
61
- else return eval(type)
59
+ const client = this.client;
60
+
61
+ if (type == 'client') return client;
62
+ if (type == 'rest') return client.rest;
63
+ else return eval(type);
62
64
  }
63
65
  }
64
66
 
@@ -0,0 +1,111 @@
1
+ const fs = require('fs');
2
+ const Discord = require('discord.js');
3
+ const { REST } = require('@discordjs/rest');
4
+ const { Routes, GatewayVersion } = require('discord-api-types/v10');
5
+ const { logStyle } = require('dumfunctions');
6
+ const { importCommands, reimportCommands } = require('../utils/CommandsUtil.js');
7
+ const { importInhibitors } = require('../utils/InhibitorsUtil.js');
8
+
9
+ module.exports = class Handler {
10
+ constructor(client) {
11
+ this.client = client;
12
+
13
+ this.commands = [];
14
+ }
15
+
16
+ loadAllInteractionCommands(path, logging = false) {
17
+ const files = this.#readdir(path);
18
+
19
+ importCommands(this.client, path, files, this.commands, 'interaction');
20
+
21
+ this.#deployCommands("interaction commands", logging);
22
+ }
23
+
24
+ reloadAllInteractionCommands() {
25
+ reimportCommands(this.client, this.commands, "interaction");
26
+
27
+ return this.#redeployCommands()
28
+ }
29
+
30
+ loadAllContextMenuCommands(path, logging = false) {
31
+ const files = this.#readdir(path);
32
+
33
+ importCommands(this.client, path, files, this.commands, 'contextMenu');
34
+
35
+ this.#deployCommands("context menu commands", logging);
36
+ }
37
+
38
+ reloadAllContextMenuCommands() {
39
+ reimportCommands(this.client, this.commands, "contextMenu");
40
+
41
+ return this.#redeployCommands()
42
+ }
43
+
44
+ loadAllMessageCommands(path) {
45
+ const files = this.#readdir(path);
46
+
47
+ importCommands(this.client, path, files, this.commands, 'message');
48
+ }
49
+
50
+ reloadAllMessageCommands() {
51
+ return reimportCommands(this.client, this.commands, "message");
52
+ }
53
+
54
+ loadAllInhibitors(path) {
55
+ const files = this.#readdir(path);
56
+
57
+ importInhibitors(this.client, path, files);
58
+ }
59
+
60
+ #deployCommands(type, logging = false) {
61
+ this.client.once('ready', async client => {
62
+ const rest = new REST({ version: GatewayVersion }).setToken(client.token);
63
+
64
+ try {
65
+ if (client.settings.global == true) {
66
+ if (logging || this.client.settings.logging) console.info(logStyle(`Loaded ${type} in ${(await client.guilds.fetch()).size} server(s) globally.`, 'text', 'purple'));
67
+ rest.put(Routes.applicationCommands(client.user.id), {
68
+ body: this.commands
69
+ })
70
+ }
71
+ else {
72
+ if (logging || this.client.settings.logging) console.info(logStyle(`Loaded ${type} locally.`, 'text', 'purple'));
73
+ rest.put(Routes.applicationGuildCommands(client.user.id, client.settings.guildId), {
74
+ body: this.commands
75
+ })
76
+ }
77
+ }
78
+ catch (e) {
79
+ throw new Error(e)
80
+ }
81
+ })
82
+ }
83
+
84
+ #redeployCommands() {
85
+ const rest = new REST({ version: GatewayVersion }).setToken(this.client.token);
86
+
87
+ (async () => {
88
+ try {
89
+ if (this.client.settings.global == true) {
90
+ rest.put(Routes.applicationCommands(this.client.user.id), {
91
+ body: this.commands
92
+ })
93
+ }
94
+ else {
95
+ rest.put(Routes.applicationGuildCommands(this.client.user.id, this.client.settings.guildId), {
96
+ body: this.commands
97
+ })
98
+ }
99
+ }
100
+ catch (e) {
101
+ throw new Error(e)
102
+ }
103
+ })();
104
+
105
+ return this.commands;
106
+ }
107
+
108
+ #readdir(path) {
109
+ return fs.readdirSync(path).filter(file => file.endsWith('.js'));
110
+ }
111
+ }
@@ -0,0 +1,16 @@
1
+ const Handler = require("./Handler");
2
+ const Discord = require('discord.js');
3
+
4
+ module.exports = class InhibitorHandler {
5
+ constructor(client) {
6
+ this.client = client;
7
+
8
+ client.inhibitors = new Discord.Collection();
9
+
10
+ this.load = new Handler(client);
11
+ }
12
+
13
+ loadAllInhibitors(path) {
14
+ this.load.loadAllInhibitors(path);
15
+ }
16
+ }
@@ -27,16 +27,26 @@ module.exports = new class Arguments {
27
27
  * @returns argument options without having to make them yourself.
28
28
  */
29
29
  async messageArgs({ message: message, command: command }) {
30
- let args = {}, separator = command.separator || ' ', i = 0;
30
+ let args = { flags: {} }, separator = command.separator || ' ', i = 0;
31
31
 
32
32
  if (!command.args) return;
33
33
 
34
- for (const argument of command.args) {
34
+ command.args.filter(c => c.type == "flag").map(flag => {
35
+ for (const flg of message.content.matchAll(flag.content)) {
36
+ if (flag.content == flg) {
37
+ message.content = message.content.replace(flag.content, "");
35
38
 
36
- let content = message.content.replace(new RegExp(`${separator}${separator}+`, "g"), separator).split(separator).slice(i + 1);
39
+ args.flags[flag.name] = true;
40
+ }
41
+ }
37
42
 
38
- if (content.join(separator) != '') {
43
+ if (!args.flags[flag.name]) args.flags[flag.name] = false;
44
+ })
39
45
 
46
+ for (const argument of command.args) {
47
+ let content = message.content.split(/ +/).slice(1).join(separator).replace(new RegExp(`${separator}${separator}+`, "g"), separator).split(separator).slice(i);
48
+
49
+ if (content.join(separator) != '' && argument.type !== "flag") {
40
50
  if (argument?.content?.includes(content[0])) {
41
51
  args[argument.name] = content[0];
42
52
  }
@@ -51,30 +61,39 @@ module.exports = new class Arguments {
51
61
 
52
62
  else if (argument.type == 'boolean') {
53
63
  if (content[0]?.toLowerCase() != 'true' && content[0]?.toLowerCase() != 'false') content[0] = undefined;
64
+
54
65
  args[argument.name] = content[0];
55
66
  }
56
67
 
57
68
  else if (argument.type == 'user') {
58
- let user;
59
- try { user = await message.client.users.fetch(content[0].replace(/<@!?|>/g, "")) } catch (e) { user = e }
69
+ let user = message.client.users.cache.find(u => u?.username?.toLowerCase()?.includes(content[0]));
70
+
71
+ try { user = await message.client.users.fetch(user?.id || content[0].replace(/<@!?|>/g, "")) } catch (e) { user = new Error("Invalid user snowflake ID") };
72
+
60
73
  args[argument.name] = user;
61
74
  }
62
75
 
63
76
  else if (argument.type == 'role') {
64
- let role;
65
- try { role = await message.guild.roles.fetch(content[0].replace(/<@&?|>/g, "")) } catch (e) { role = e }
77
+ let role = message.guild.roles.cache.find(r => r?.name?.toLowerCase()?.includes(content[0]));
78
+
79
+ try { role = await message.guild.roles.fetch(role?.id || content[0].replace(/<@&?|>/g, "")) } catch (e) { role = new Error("Invalid role snowflake ID") };
80
+
66
81
  args[argument.name] = role;
67
82
  }
68
83
 
69
84
  else if (argument.type == 'member') {
70
- let member;
71
- try { member = await message.guild.members.fetch(content[0].replace(/<@!?|>/g, "")) } catch (e) { member = e }
85
+ let member = message.guild.members.cache.find(m => m?.nickname?.toLowerCase()?.includes(content[0]) || m?.user?.username?.toLowerCase()?.includes(content[0]));
86
+
87
+ try { member = await message.guild.members.fetch(member?.id || content[0].replace(/<@!?|>/g, "")) } catch (e) { member = new Error("Invalid member snowflake ID") };
88
+
72
89
  args[argument.name] = member;
73
90
  }
74
91
 
75
92
  else if (argument.type == 'channel') {
76
- let channel;
77
- try { channel = await message.client.channels.fetch(content[0].replace(/<#|>/g, "")) } catch (e) { channel = e }
93
+ let channel = message.guild.channels.cache.find(c => c?.name?.toLowerCase()?.includes(content[0]));
94
+
95
+ try { channel = await message.client.channels.fetch(channel?.id || content[0].replace(/<#|>/g, "")) } catch (e) { channel = new Error("Invalid channel snowflake ID") }
96
+
78
97
  args[argument.name] = channel;
79
98
  }
80
99
 
@@ -88,12 +107,12 @@ module.exports = new class Arguments {
88
107
  else if (argument.prompt.send) return message.channel.send(argument.prompt.send);
89
108
  }
90
109
 
91
- else args[argument.name] = undefined;
110
+ else args[argument.name] = typeof argument.default == 'function' ? argument.default(message) : argument.default;
92
111
 
93
112
  i++
94
113
  }
95
114
 
96
- else args[argument.name] = undefined;
115
+ else args[argument.name] = typeof argument.default == 'function' ? argument.default(message) : argument.default;
97
116
  }
98
117
 
99
118
  return args;
@@ -1,8 +1,6 @@
1
1
  const Discord = require('discord.js');
2
2
  const { toPascalCase } = require('dumfunctions');
3
3
 
4
- const Cooldown = {};
5
-
6
4
  module.exports = new class CommandValidation {
7
5
  commandValidation(event, command, res = false) {
8
6
  function emit(reason, extra) {
@@ -11,16 +9,16 @@ module.exports = new class CommandValidation {
11
9
 
12
10
  if ((command?.ignoreOwner || event?.client?.settings?.ignoreOwner) && event?.client?.settings?.ownerId?.includes((event.user || event.author).id)) return res;
13
11
 
14
- if (Cooldown[(event.user || event.author).id]) {
12
+ if (event.client.data.cooldowns[(event.user || event.author).id]) {
15
13
  res = true;
16
- return emit("command on cooldown", (Cooldown[(event.user || event.author).id] - (event.editedTimestamp || event.createdTimestamp)));
14
+ return emit("command on cooldown", (event.client.data.cooldowns[(event.user || event.author).id] - (event.editedTimestamp || event.createdTimestamp)));
17
15
  }
18
16
 
19
- if (!Cooldown[(event.user || event.author).id]) {
20
- Cooldown[(event.user || event.author).id] = ((event.editedTimestamp || event.createdTimestamp) + (command.cooldown || event.client.settings.defaultCooldown || 0));
17
+ if (!event.client.data.cooldowns[(event.user || event.author).id]) {
18
+ event.client.data.cooldowns[(event.user || event.author).id] = ((event.editedTimestamp || event.createdTimestamp) + (command.cooldown || event.client.settings.defaultCooldown || 0));
21
19
 
22
20
  setTimeout(() => {
23
- delete Cooldown[(event.user || event.author).id]
21
+ delete event.client.data.cooldowns[(event.user || event.author).id]
24
22
  }, command.cooldown || event?.client?.settings?.defaultCooldown || 0);
25
23
  }
26
24
 
@@ -60,13 +58,13 @@ module.exports = new class CommandValidation {
60
58
  if (!event?.member?.permissions?.has(Discord.PermissionFlagsBits[toPascalCase(permission)])) missingPerms.push(toPascalCase(permission));
61
59
  }
62
60
 
63
- if (missingPerms.length >= 1) {
61
+ if (missingPerms?.length >= 1) {
64
62
  res = true;
65
63
  return emit("missing user permissions", missingPerms);
66
64
  }
67
65
  }
68
66
 
69
- if (event?.guild && command?.clientPermissions.length >= 1 || event.client.settings.clientPermissions.length >= 1) {
67
+ if (event?.guild && command?.clientPermissions?.length >= 1 || event?.client?.settings?.clientPermissions?.length >= 1) {
70
68
  let missingPerms = [];
71
69
 
72
70
  for (const permission of command?.clientPermissions) {
@@ -0,0 +1,70 @@
1
+ const { logStyle } = require("dumfunctions");
2
+
3
+ module.exports = new class CommandsUtil {
4
+ importCommands(client, path, files, commands, type) {
5
+ for (const file of files) {
6
+ try {
7
+ let filepath = `${require("path").resolve(path)}/${file}`;
8
+
9
+ let command = require(filepath);
10
+
11
+ command = new command;
12
+
13
+ command.filepath = filepath;
14
+
15
+ command.runType = type;
16
+
17
+ command.client = client;
18
+
19
+ if (type !== 'message') {
20
+ commands.push(command.data.toJSON());
21
+
22
+ client.commands[type].set(command.data.name, command);
23
+ }
24
+
25
+ if (type === 'message') {
26
+ client.commands[type].set(command.name, command);
27
+ }
28
+ }
29
+ catch (error) {
30
+ console.error(logStyle(`Couldn't load ${file} because of <${error.message}>!`, "text", "red"));
31
+ }
32
+ }
33
+
34
+ return commands;
35
+ }
36
+
37
+ reimportCommands(client, cmds, type) {
38
+ let commands = [];
39
+
40
+ client.commands[type].map(command => { if (!commands.includes(command.filepath)) commands.push(command.filepath) });
41
+
42
+ client.commands[type].sweep(() => true);
43
+
44
+ commands.map(path => {
45
+ delete require.cache[require.resolve(path)];
46
+
47
+ let command = require(path);
48
+
49
+ command = new command;
50
+
51
+ command.filepath = path;
52
+
53
+ command.runType = type;
54
+
55
+ command.client = client;
56
+
57
+ if (type !== 'message') {
58
+ cmds.push(command.data.toJSON());
59
+
60
+ client.commands[type].set(command.data.name, command);
61
+ }
62
+
63
+ if (type === 'message') {
64
+ client.commands[type].set(command.name, command);
65
+ }
66
+ })
67
+
68
+ return commands;
69
+ }
70
+ }
@@ -1,6 +1,7 @@
1
1
  const colors = require('../data/colors.json');
2
2
  const { EmbedBuilder, ActionRowBuilder, SelectMenuBuilder, Embed, ButtonBuilder, ButtonStyle } = require('discord.js');
3
3
  const opts = require('../data/options.json');
4
+ const { logStyle } = require('dumfunctions');
4
5
 
5
6
  function reply(interaction, text) {
6
7
  return (interaction.replied || interaction.deferred) ? interaction.editReply(text) : interaction.reply(text);
@@ -152,7 +153,7 @@ module.exports = new class Functions {
152
153
 
153
154
  else {
154
155
  commandInfo = {
155
- name: command?.data?.name || command?.id,
156
+ name: command?.data?.name || command?.name || command?.id,
156
157
  description: command?.data?.description || command?.description,
157
158
  category: command.category
158
159
  }
@@ -162,7 +163,7 @@ module.exports = new class Functions {
162
163
 
163
164
  else {
164
165
  commandInfo = {
165
- name: command?.data?.name || command?.id,
166
+ name: command?.data?.name || command?.name || command?.id,
166
167
  description: command?.data?.description || command?.description,
167
168
  category: command.category
168
169
  }
@@ -175,7 +176,7 @@ module.exports = new class Functions {
175
176
  return cmds;
176
177
  }
177
178
 
178
- if (!cmd) return [interaction?.commandName || interaction.content?.replace(interaction.client.settings.prefix.find(p => interaction.content.startsWith(p)), "").split(/ +/)[0], interaction?.options?._group, interaction?.options?._subcommand].join(' ').replace(/ +/g, " ").trim();
179
+ if (!cmd) return [interaction?.commandName || interaction.name || interaction.content?.replace(interaction.client.settings.prefix.find(p => interaction.content.startsWith(p)), "").split(/ +/)[0], interaction?.options?._group, interaction?.options?._subcommand].join(' ').replace(/ +/g, " ").trim();
179
180
  }
180
181
 
181
182
  buttonPaginator(interaction, embeds, options = {}) {
@@ -0,0 +1,24 @@
1
+ const { logStyle } = require('dumfunctions');
2
+
3
+ module.exports = new class InhibitorsUtil {
4
+ importInhibitors(client, path, files) {
5
+ for (const file of files) {
6
+ try {
7
+ let filepath = `${require("path").resolve(path)}/${file}`;
8
+
9
+ let inhibitor = require(filepath);
10
+
11
+ inhibitor = new inhibitor;
12
+
13
+ inhibitor.filepath = filepath;
14
+
15
+ inhibitor.client = client;
16
+
17
+ client.inhibitors.set(inhibitor.name, inhibitor);
18
+ }
19
+ catch (error) {
20
+ console.error(logStyle(`Couldn't load ${file} because of <${error.message}>!`, "text", "red"));
21
+ }
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,40 @@
1
+ module.exports = new class InhibitorValidation {
2
+ inhibitorsValidation(event, command) {
3
+ let inhibited = {};
4
+
5
+ if (event.client.inhibitors.has(command.runType)) {
6
+ let inhibitor = event.client.inhibitors.get(command.runType);
7
+
8
+ inhibited[command.runType] = inhibitor.check(event);
9
+ }
10
+
11
+ if (event.client.inhibitors.has("member")) {
12
+
13
+ let inhibitor = event.client.inhibitors.get("member");
14
+
15
+ inhibited["member"] = inhibitor.check(event, event.member);
16
+ }
17
+
18
+ if (event.client.inhibitors.has("guild")) {
19
+ let inhibitor = event.client.inhibitors.get("guild");
20
+
21
+ inhibited["guild"] = inhibitor.check(event, event.guild);
22
+ }
23
+
24
+ if (event.client.inhibitors.has("user")) {
25
+ let inhibitor = event.client.inhibitors.get("user");
26
+
27
+ inhibited["user"] = inhibitor.check(event, event.user || event.author);
28
+ }
29
+
30
+ if (event.client.inhibitors.has("channel")) {
31
+ let inhibitor = event.client.inhibitors.get("channel");
32
+
33
+ inhibited["channel"] = inhibitor.check(event);
34
+ }
35
+
36
+ for (const inhibit of Object.values(inhibited)) {
37
+ if (inhibit) return inhibited;
38
+ }
39
+ }
40
+ }
@@ -3,7 +3,7 @@ const { selectMenuPaginator, buttonPaginator, commandName, uptime, reply } = req
3
3
  module.exports = new class Util {
4
4
  async messageUtil(message, type) {
5
5
  setTimeout(() => {
6
- if (message.client.messages[message.id] === null || message.client.messages[message.id]) delete message.client.messages[message.id];
6
+ if (message.client.data.messages[message.id] === null || message.client.data.messages[message.id]) delete message.client.data.messages[message.id];
7
7
 
8
8
  if (message.channel.messages.cache.has(message.id)) message.channel.messages.cache.delete(message.id);
9
9
  }, message.client.settings.cacheTime);
@@ -16,12 +16,12 @@ module.exports = new class Util {
16
16
  }
17
17
 
18
18
  if (type == "create") {
19
- message.client.messages[message.id] = null;
19
+ message.client.data.messages[message.id] = null;
20
20
 
21
21
  message.util.send = async (e) => {
22
22
  const msg = await message.channel.send(e);
23
23
 
24
- message.client.messages[message.id] = msg.id;
24
+ message.client.data.messages[message.id] = msg.id;
25
25
 
26
26
  return msg;
27
27
  }
@@ -29,7 +29,7 @@ module.exports = new class Util {
29
29
  message.util.reply = async (e) => {
30
30
  const msg = await message.reply(e);
31
31
 
32
- message.client.messages[message.id] = msg.id;
32
+ message.client.data.messages[message.id] = msg.id;
33
33
 
34
34
  return msg;
35
35
  }
@@ -38,11 +38,11 @@ module.exports = new class Util {
38
38
  }
39
39
 
40
40
  if (type == 'edit') {
41
- if (message.client.messages[message.id] === null) {
41
+ if (message.client.data.messages[message.id] === null) {
42
42
  message.util.send = async (e) => {
43
43
  const msg = await message.channel.send(e);
44
44
 
45
- message.client.messages[message.id] = msg.id;
45
+ message.client.data.messages[message.id] = msg.id;
46
46
 
47
47
  return msg;
48
48
  }
@@ -50,7 +50,7 @@ module.exports = new class Util {
50
50
  message.util.reply = async (e) => {
51
51
  const msg = await message.reply(e);
52
52
 
53
- message.client.messages[message.id] = msg.id;
53
+ message.client.data.messages[message.id] = msg.id;
54
54
 
55
55
  return msg;
56
56
  }
@@ -58,8 +58,8 @@ module.exports = new class Util {
58
58
  return;
59
59
  }
60
60
 
61
- else if (message.client.messages[message.id] !== null) {
62
- const msg = await message.channel.messages.fetch(message.client.messages[message.id]);
61
+ else if (message.client.data.messages[message.id] !== null) {
62
+ const msg = await message.channel.messages.fetch(message.client.data.messages[message.id]);
63
63
 
64
64
  message.util.send = async (e) => {
65
65
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xernerx",
3
- "version": "2.5.0",
3
+ "version": "2.6.2",
4
4
  "description": "A bot framework for discord.js. [BETA]",
5
5
  "main": "main.js",
6
6
  "scripts": {
@@ -17,10 +17,10 @@
17
17
  },
18
18
  "homepage": "https://github.com/TheDummi/xernerx#readme",
19
19
  "dependencies": {
20
- "@discordjs/rest": "1.0.1",
20
+ "@discordjs/rest": "1.1.0",
21
21
  "@sapphire/shapeshift": "3.5.1",
22
- "discord-api-types": "^0.37.3",
23
- "discord.js": "^14.2.0",
22
+ "discord-api-types": "^0.37.5",
23
+ "discord.js": "^14.3.0",
24
24
  "dumfunctions": "^1.0.7",
25
25
  "i18next": "^21.9.1"
26
26
  },
@@ -1,218 +0,0 @@
1
- const fs = require('fs');
2
- const Discord = require('discord.js');
3
- const { REST } = require('@discordjs/rest');
4
- const { Routes, GatewayVersion } = require('discord-api-types/v10');
5
- const { logStyle } = require('dumfunctions');
6
-
7
- class Loader {
8
- constructor(client) {
9
- this.client = client;
10
-
11
- this.commands = [];
12
-
13
- client.commands = {
14
- message: new Discord.Collection(),
15
-
16
- interaction: new Discord.Collection(),
17
-
18
- contextMenu: new Discord.Collection()
19
- }
20
- }
21
-
22
- loadAllInteractionCommands(path, logging = false) {
23
- const commandFiles = fs.readdirSync(path).filter(file => file.endsWith('.js'))
24
-
25
- for (const file of commandFiles) {
26
- try {
27
- let filepath = `${require("path").resolve(path)}/${file}`
28
-
29
- let command = require(filepath);
30
-
31
- command = new command;
32
-
33
- command.filepath = filepath;
34
-
35
- this.commands.push(command.data.toJSON());
36
-
37
- this.client.commands.interaction.set(command.data.name, command);
38
- }
39
- catch (error) {
40
- console.error(logStyle(`Couldn't load ${file} because of <${error.message}>!`, "text", "red"));
41
- }
42
- }
43
-
44
- this.#deployCommands("interaction commands", logging);
45
- }
46
-
47
- reloadAllInteractionCommands() {
48
- let commands = this.client.commands.interaction.map(command => command.filepath);
49
-
50
- this.commands = [];
51
-
52
- this.client.commands.interaction.sweep(() => true);
53
-
54
- commands.map(path => {
55
- delete require.cache[require.resolve(path)];
56
-
57
- let command = require(path);
58
-
59
- command = new command;
60
-
61
- command.filepath = path;
62
-
63
- this.commands.push(command.data.toJSON());
64
-
65
- this.client.commands.interaction.set(command.data.name, command);
66
- })
67
-
68
- return this.#redeployCommands()
69
- }
70
-
71
- loadAllContextMenuCommands(path, logging = false) {
72
- const commandFiles = fs.readdirSync(path).filter(file => file.endsWith('.js'));
73
-
74
- for (const file of commandFiles) {
75
- try {
76
- let filepath = `${require("path").resolve(path)}/${file}`
77
-
78
- let command = require(filepath);
79
-
80
- command = new command;
81
-
82
- command.filepath = filepath;
83
-
84
- this.commands.push(command.data.toJSON());
85
-
86
- this.client.commands.contextMenu.set(command.data.name, command);
87
- }
88
- catch (error) {
89
- console.error(logStyle(`Couldn't load ${file} because of <${error.message}>!`, "text", "red"));
90
- }
91
- }
92
-
93
- this.#deployCommands("context menu commands", logging);
94
- }
95
-
96
- reloadAllContextMenuCommands() {
97
- let commands = this.client.commands.contextMenu.map(command => command.filepath);
98
-
99
- this.commands = [];
100
-
101
- this.client.commands.contextMenu.sweep(() => true);
102
-
103
- commands.map(path => {
104
- delete require.cache[require.resolve(path)];
105
-
106
- let command = require(path);
107
-
108
- command = new command;
109
-
110
- command.filepath = path;
111
-
112
- this.commands.push(command.data.toJSON());
113
-
114
- this.client.commands.contextMenu.set(command.data.name, command);
115
- })
116
-
117
- return this.#redeployCommands()
118
- }
119
-
120
- loadAllMessageCommands(path, logging = false) {
121
- const commandFiles = fs.readdirSync(path).filter(file => file.endsWith('.js'));
122
-
123
- for (const file of commandFiles) {
124
- try {
125
- let filepath = `${require("path").resolve(path)}/${file}`
126
-
127
- let command = require(filepath);
128
-
129
- command = new command;
130
-
131
- command.filepath = filepath;
132
-
133
- command.aliases.forEach((alias) => {
134
- if (this.client.commands.message.has(alias)) throw new Error('Cannot have duplicated aliases.');
135
-
136
- this.client.commands.message.set(alias, command);
137
- });
138
- }
139
- catch (error) {
140
- console.error(logStyle(`Couldn't load ${file} because of <${error.message}>!`, "text", "red"));
141
- }
142
- }
143
- }
144
-
145
- reloadAllMessageCommands() {
146
- let commands = this.client.commands.message.map(command => command.filepath);
147
-
148
- this.commands = [];
149
-
150
- this.client.commands.message.sweep(() => true);
151
-
152
- commands.map(path => {
153
- delete require.cache[require.resolve(path)];
154
-
155
- let command = require(path);
156
-
157
- command = new command;
158
-
159
- command.filepath = path;
160
-
161
- this.client.commands.message.set(command.id, command);
162
- })
163
-
164
- return this.#redeployCommands()
165
- }
166
-
167
- #deployCommands(type, logging = false) {
168
- this.client.once('ready', client => {
169
- const rest = new REST({ version: GatewayVersion }).setToken(client.token);
170
-
171
- (async () => {
172
- try {
173
- if (client.settings.global == true) {
174
- if (logging || this.client.settings.logging) console.info(logStyle(`Loaded ${type} in ${(await client.guilds.fetch()).size} server(s) globally.`, 'text', 'purple'));
175
- rest.put(Routes.applicationCommands(client.user.id), {
176
- body: this.commands
177
- })
178
- }
179
- else {
180
- if (logging || this.client.settings.logging) console.info(logStyle(`Loaded ${type} locally.`, 'text', 'purple'));
181
- rest.put(Routes.applicationGuildCommands(client.user.id, client.settings.guildId), {
182
- body: this.commands
183
- })
184
- }
185
- }
186
- catch (e) {
187
- throw new Error(e)
188
- }
189
- })();
190
- })
191
- }
192
-
193
- #redeployCommands() {
194
- const rest = new REST({ version: GatewayVersion }).setToken(this.client.token);
195
-
196
- (async () => {
197
- try {
198
- if (this.client.settings.global == true) {
199
- rest.put(Routes.applicationCommands(this.client.user.id), {
200
- body: this.commands
201
- })
202
- }
203
- else {
204
- rest.put(Routes.applicationGuildCommands(this.client.user.id, this.client.settings.guildId), {
205
- body: this.commands
206
- })
207
- }
208
- }
209
- catch (e) {
210
- throw new Error(e)
211
- }
212
- })();
213
-
214
- return this.commands;
215
- }
216
- }
217
-
218
- module.exports = Loader;