xernerx 2.0.3 → 2.0.4

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
@@ -6,10 +6,10 @@ const { Client } = require('./models/Client.js'),
6
6
  { Event } = require('./models/commands/Event.js'),
7
7
  { LanguageHandler } = require('./models/handlers/LanguageHandler.js'),
8
8
  { ContextMenuCommand } = require('./models/commands/ContextMenuCommand.js'),
9
- Discord = require('discord.js'),
10
9
  pkg = require('./package.json'),
11
10
  Dumfunctions = require('dumfunctions'),
12
- { reply, selectMenuPaginator, buttonPaginator, commandName } = require('dumdiscord.js');
11
+ { reply, selectMenuPaginator, buttonPaginator, commandName } = require('dumdiscord.js'),
12
+ Discord = require('discord.js');
13
13
 
14
14
  module.exports = {
15
15
  // Client
@@ -39,5 +39,5 @@ module.exports = {
39
39
  commandName,
40
40
 
41
41
  // Details
42
- version: pkg.version
42
+ version: pkg.version,
43
43
  }
package/models/Client.js CHANGED
@@ -1,6 +1,9 @@
1
1
  const Discord = require('discord.js');
2
2
  const { s } = require('@sapphire/shapeshift');
3
3
  const { color, config } = require('./data/Functions.js');
4
+ const { CommandHandler } = require('./handlers/CommandHandler.js');
5
+ const { EventHandler } = require('./handlers/EventHandler.js');
6
+ const { LanguageHandler } = require('./handlers/LanguageHandler.js');
4
7
 
5
8
  /**
6
9
  * @param {string} guildId - Test guild ID.
@@ -27,32 +30,48 @@ class Client extends Discord.Client {
27
30
  defaultCooldown: s.number.optional,
28
31
  logging: s.boolean.optional,
29
32
  cacheTime: s.number.optional,
30
- dummi: s.boolean.optional
33
+ dummi: s.boolean.optional,
34
+ userPermissions: s.array(s.string).optional,
35
+ clientPermissions: s.array(s.string).optional
31
36
  }).parse(options)
32
37
 
33
38
  this.client = new Discord.Client({ intents: [options.intents], partials: [options.partials] });
34
39
 
35
- this.client.messages = {};
40
+ this.client.settings = {
41
+ prefix: options.prefix,
42
+
43
+ ownerId: options.ownerId,
44
+
45
+ guildId: options.guildId,
46
+
47
+ global: options.global || false,
36
48
 
37
- this.client.prefix = options.prefix;
49
+ ignoreOwner: options.ignoreOwner || false,
38
50
 
39
- this.client.ownerId = options.ownerId;
51
+ defaultCooldown: options.defaultCooldown || 0,
40
52
 
41
- this.client.guildId = options.guildId;
53
+ logging: options.logging || false,
42
54
 
43
- this.client.global = options.global || false;
55
+ cacheTime: options.cacheTime || 300000,
44
56
 
45
- this.client.ignoreOwner = options.ignoreOwner || false;
57
+ userPermissions: options.userPermissions || [],
46
58
 
47
- this.client.defaultCooldown = options.defaultCooldown || 0;
59
+ clientPermissions: options.clientPermissions || []
60
+ }
48
61
 
49
62
  this.client.color = color({ client: this.client, options: options });
50
63
 
51
64
  this.client.config = config({ client: this.client, options: options });
52
65
 
53
- this.client.logging = options.logging || false;
66
+ this.client.messages = {};
67
+
68
+ this.client.modules = {
69
+ commandHandler: new CommandHandler({ client: this.client }),
70
+
71
+ eventHandler: new EventHandler({ client: this.client }),
54
72
 
55
- this.client.cacheTime = options.cacheTime || 300000;
73
+ // languageHandler: new LanguageHandler({ client: this.client })
74
+ }
56
75
 
57
76
  return this.client;
58
77
  }
@@ -16,21 +16,33 @@ class ContextMenuCommand {
16
16
  admin: s.boolean.optional,
17
17
  info: s.string.optional,
18
18
  category: s.string.optional,
19
+ channels: s.array(s.string).optional,
20
+ guilds: s.array(s.string).optional,
21
+ userPermissions: s.array(s.string).optional,
22
+ clientPermissions: s.array(s.string).optional
19
23
  }).parse(options)
20
24
 
21
25
  this.data = new Builders.ContextMenuCommandBuilder()
22
26
  .setName(options.name)
23
27
  .setType(this.types(options.type))
24
28
 
25
- this.inVoice = options.inVoice;
29
+ this.inVoice = options.inVoice || false;
26
30
 
27
- this.category = options.category;
31
+ this.category = options.category || undefined;
28
32
 
29
- this.owner = options.owner;
33
+ this.owner = options.owner || false;
30
34
 
31
- this.admin = options.admin;
35
+ this.admin = options.admin || false;
32
36
 
33
- this.info = options.info;
37
+ this.info = options.info || undefined;
38
+
39
+ this.channels = options.channels || [];
40
+
41
+ this.guilds = options.guilds || [];
42
+
43
+ this.userPermissions = options.userPermissions || [];
44
+
45
+ this.clientPermissions = options.clientPermissions || [];
34
46
 
35
47
  this.config = options.config;
36
48
  }
@@ -23,7 +23,11 @@ class InteractionCommand {
23
23
  category: s.string.optional,
24
24
  cooldown: s.number.optional,
25
25
  ignoreOwner: s.boolean.optional,
26
- inVoice: s.boolean.optional
26
+ inVoice: s.boolean.optional,
27
+ channels: s.array(s.string).optional,
28
+ guilds: s.array(s.string).optional,
29
+ userPermissions: s.array(s.string).optional,
30
+ clientPermissions: s.array(s.string).optional
27
31
  }).parse(options);
28
32
 
29
33
  this.data = new SlashCommandBuilder()
@@ -50,19 +54,27 @@ class InteractionCommand {
50
54
 
51
55
  this.admin = options.admin || false;
52
56
 
53
- this.channel = options.channel;
57
+ this.channel = options.channel || undefined;
54
58
 
55
- this.category = options.category;
59
+ this.category = options.category || undefined;
56
60
 
57
61
  this.config = options.config;
58
62
 
59
- this.cooldown = options.cooldown;
63
+ this.cooldown = options.cooldown || 0;
60
64
 
61
65
  this.ignoreOwner = options.ignoreOwner || false;
62
66
 
63
67
  this.inVoice = options.inVoice || false;
64
68
 
65
- this.info = options.info;
69
+ this.info = options.info || undefined;
70
+
71
+ this.channels = options.channels || [];
72
+
73
+ this.guilds = options.guilds || [];
74
+
75
+ this.userPermissions = options.userPermissions || [];
76
+
77
+ this.clientPermissions = options.clientPermissions || [];
66
78
  }
67
79
 
68
80
  exec(interaction) {
@@ -25,7 +25,11 @@ class MessageCommand {
25
25
  category: s.string.optional,
26
26
  cooldown: s.number.optional,
27
27
  ignoreOwner: s.boolean.optional,
28
- inVoice: s.boolean.optional
28
+ inVoice: s.boolean.optional,
29
+ channels: s.array(s.string).optional,
30
+ guilds: s.array(s.string).optional,
31
+ userPermissions: s.array(s.string).optional,
32
+ clientPermissions: s.array(s.string).optional
29
33
  }).parse(options);
30
34
 
31
35
  this.id = id;
@@ -34,29 +38,37 @@ class MessageCommand {
34
38
 
35
39
  this.type = options.type;
36
40
 
37
- this.description = options.description;
41
+ this.description = options.description || undefined;
38
42
 
39
- this.owner = options.owner;
43
+ this.owner = options.owner || undefined;
40
44
 
41
- this.admin = options.admin;
45
+ this.admin = options.admin || undefined;
42
46
 
43
- this.channel = options.channel;
47
+ this.channel = options.channel || undefined;
44
48
 
45
- this.separator = options.separator;
49
+ this.separator = options.separator || ' '
46
50
 
47
51
  this.args = options.args;
48
52
 
49
- this.category = options.category;
53
+ this.category = options.category || undefined;
50
54
 
51
55
  this.config = options.config;
52
56
 
53
- this.cooldown = options.cooldown;
57
+ this.cooldown = options.cooldown || 0;
54
58
 
55
59
  this.ignoreOwner = options.ignoreOwner || false;
56
60
 
57
61
  this.inVoice = options.inVoice || false;
58
62
 
59
- this.info = options.info;
63
+ this.info = options.info || undefined;
64
+
65
+ this.channels = options.channels || [];
66
+
67
+ this.guilds = options.guilds || [];
68
+
69
+ this.userPermissions = options.userPermissions || [];
70
+
71
+ this.clientPermissions = options.clientPermissions || [];
60
72
  }
61
73
 
62
74
  exec(message) {
@@ -0,0 +1,95 @@
1
+ const Discord = require('discord.js');
2
+ const { toPascalCase } = require('dumfunctions');
3
+
4
+ const Cooldown = {};
5
+
6
+ module.exports = function commandValidation(event, command, res = false) {
7
+ function emit(reason, extra) {
8
+ return event.client.emit('commandBlocked', event, reason, extra);
9
+ }
10
+ if ((command.ignoreOwner || event.client.ignoreOwner) && event.client.ownerId.includes((event.user || event.author).id)) return res;
11
+
12
+ if (Cooldown[(event.user || event.author).id]) {
13
+ res = true;
14
+ return emit("command on cooldown", (Cooldown[(event.user || event.author).id] - event.createdTimestamp));
15
+ }
16
+
17
+ if (!Cooldown[(event.user || event.author).id]) {
18
+ Cooldown[(event.user || event.author).id] = (event.createdTimestamp + (command.cooldown || event.client.settings.defaultCooldown || 0));
19
+
20
+ setTimeout(() => {
21
+ delete Cooldown[(event.user || event.author).id]
22
+ }, command.cooldown || event.client.settings.defaultCooldown || 0)
23
+ }
24
+
25
+ if (command?.owner && event?.client?.ownerId != undefined && !event?.client?.ownerId?.includes((event.user || event.author).id)) {
26
+ res = true;
27
+ return emit("missing ownership", client.ownerId)
28
+ }
29
+
30
+ if (command?.admin && event?.member?.permissions?.has(Discord.PermissionFlagsBits.Administrator) == false) {
31
+ res = true;
32
+ return emit("missing admin permission", "Administrator")
33
+ }
34
+
35
+ if (command?.channel == "guild" && event?.channel?.type != "GUILD_TEXT") {
36
+ res = true
37
+ return emit("not a guild channel");
38
+ }
39
+
40
+ if (command?.channel == "dm" && event?.type != null) {
41
+ res = true;
42
+ return emit("not a dm channel");
43
+ }
44
+
45
+ if (command?.inVoice && !event?.member?.voice?.channelId) {
46
+ res = true;
47
+ return emit("not a in a voice channel");
48
+ }
49
+
50
+ if (event?.guild && command?.userPermissions.length >= 1 || event?.client?.settings?.userPermissions.length >= 1) {
51
+ let missingPerms = [];
52
+
53
+ for (const permission of command.userPermissions) {
54
+ if (!event?.member?.permissions?.has(Discord.PermissionFlagsBits[toPascalCase(permission)])) missingPerms.push(toPascalCase(permission));
55
+ }
56
+
57
+ for (const permission of event.client.settings.userPermissions) {
58
+ if (!event?.member?.permissions?.has(Discord.PermissionFlagsBits[toPascalCase(permission)])) missingPerms.push(toPascalCase(permission));
59
+ }
60
+
61
+ if (missingPerms.length >= 1) {
62
+ res = true;
63
+ return emit("missing user permissions", missingPerms);
64
+ }
65
+ }
66
+
67
+ if (event?.guild && command?.clientPermissions.length >= 1 || event.client.settings.clientPermissions.length >= 1) {
68
+ let missingPerms = [];
69
+
70
+ for (const permission of command.clientPermissions) {
71
+ if (!event?.guild?.members?.me?.permissions?.has(Discord.PermissionFlagsBits[toPascalCase(permission)])) missingPerms.push(toPascalCase(permission));
72
+ }
73
+
74
+ for (const permission of event.client.settings.clientPermissions) {
75
+ if (!event?.guild?.members?.me?.permissions?.has(Discord.PermissionFlagsBits[toPascalCase(permission)])) missingPerms.push(toPascalCase(permission));
76
+ }
77
+
78
+ if (missingPerms.length >= 1) {
79
+ res = true;
80
+ return emit("missing client permissions", missingPerms);
81
+ }
82
+ }
83
+
84
+ if (command.guilds.length >= 1 && !command?.guilds?.includes(event.guild)) {
85
+ res = true;
86
+ return emit('not in a specified guild', command.guilds);
87
+ }
88
+
89
+ if (command.channels.length >= 1 && !command?.channels?.includes(event.channel.id)) {
90
+ res = true;
91
+ return emit('not in a specified channel', command.channels);
92
+ }
93
+
94
+ return res;
95
+ }
@@ -1,12 +1,9 @@
1
- const { Message } = require('discord.js');
2
1
  const colors = require('./colors.json');
3
2
 
4
- const Cooldown = new Set();
5
3
  /**
6
4
  * @param {object} Functions - Build in functions of the bot hidden away in the handlers/setters.
7
5
  */
8
6
  class Functions {
9
-
10
7
  /**
11
8
  *
12
9
  * @param {object} client - Client object.
@@ -143,55 +140,12 @@ class Functions {
143
140
  return args;
144
141
  }
145
142
 
146
- access(event, command, res = false) {
147
- if ((command.ignoreOwner || event.client.ignoreOwner) && event.client.ownerId.includes((event.user || event.author).id)) return res;
148
-
149
- if (Cooldown.has((event.user || event.author).id)) {
150
- res = false
151
- return event.client.emit('commandBlocked', event, "command is on cooldown");
152
- }
153
-
154
- if (!Cooldown.has((event.user || event.author).id)) {
155
- Cooldown.add((event.user || event.author).id);
156
-
157
- setTimeout(() => {
158
- Cooldown.delete((event.user || event.author).id);
159
- }, command.cooldown || event.client.defaultCooldown || 0)
160
- }
161
-
162
- if (command.owner && event?.client?.ownerId != undefined && !event?.client?.ownerId?.includes((event.user || event.author).id)) {
163
- res = true;
164
- return event.client.emit('commandBlocked', event, "missing ownership")
165
- }
166
-
167
- if (command.admin && event?.member?.permissions?.has(Discord.Permissions.FLAGS.ADMINISTRATOR) == false) {
168
- res = true;
169
- return event.client.emit('commandBlocked', event, "missing admin permission")
170
- }
171
-
172
- if (command?.channel == "guild" && event?.channel?.type != "GUILD_TEXT") {
173
- res = true
174
- return event.client.emit('commandBlocked', event, "not a guild channel");
175
- }
176
-
177
- if (command?.channel == "dm" && event?.type != null) {
178
- res = true;
179
- return event.client.emit('commandBlocked', event, "not a dm channel");
180
- }
181
-
182
- if (command.inVoice && !event?.member?.voice?.channelId) {
183
- res = true;
184
- return event.client.emit('commandBlocked', event, "not a in a voice channel");
185
- }
186
-
187
- return res;
188
- }
189
-
190
143
  async messageEdit(message, type) {
191
144
  setTimeout(() => {
192
145
  if (message.client.messages[message.id] === null || message.client.messages[message.id]) delete message.client.messages[message.id];
193
- if (message.channel.messages.cache.has(message.id)) message.channel.messages.cache.delete(message.id)
194
- }, message.client.cacheTime)
146
+
147
+ if (message.channel.messages.cache.has(message.id)) message.channel.messages.cache.delete(message.id);
148
+ }, message.client.settings.cacheTime);
195
149
 
196
150
  message.util = {};
197
151
 
@@ -1,6 +1,7 @@
1
1
  const { Event } = require('../commands/Event.js');
2
- const { interactionArgs, access } = require('./../data/Functions.js');
2
+ const { interactionArgs } = require('./../data/Functions.js');
3
3
  const { InteractionType } = require('discord.js')
4
+ const commandValidation = require('./../data/CommandValidation.js');
4
5
  /**
5
6
  * @returns interaction command executor.
6
7
  */
@@ -26,7 +27,14 @@ class BuildInInteractionEvent extends Event {
26
27
 
27
28
  const args = interactionArgs(interaction).options;
28
29
 
29
- if (access(interaction, command)) return;
30
+ if (commandValidation(interaction, command)) return;
31
+
32
+ interaction.util = {}
33
+
34
+ interaction.util.reply = (text) => {
35
+ if (interaction.replied || interaction.deferred) return interaction.editReply(text);
36
+ else return interaction.reply(text);
37
+ }
30
38
 
31
39
  try {
32
40
  await command.exec(interaction, { group: group, subcommand: subcommand, args: args });
@@ -1,5 +1,6 @@
1
1
  const { Event } = require('../commands/Event.js');
2
- const { messageArgs, access, messageEdit } = require("./../data/Functions.js");
2
+ const { messageArgs, messageEdit } = require("./../data/Functions.js");
3
+ const commandValidation = require('./../data/CommandValidation.js');
3
4
 
4
5
  /**
5
6
  * @returns message command executor.
@@ -18,7 +19,7 @@ class BuildInMessageEvent extends Event {
18
19
 
19
20
  await messageEdit(message, "create");
20
21
 
21
- for (const prefix of message.client.prefix) {
22
+ for (const prefix of message.client.settings.prefix) {
22
23
  if (!message.content.startsWith(prefix)) continue;
23
24
 
24
25
  let command = message.content.replace(prefix, "").split(/ +/).shift().toLowerCase();
@@ -31,7 +32,7 @@ class BuildInMessageEvent extends Event {
31
32
 
32
33
  const args = await messageArgs({ message: message, command: command });
33
34
 
34
- if (access(message, command)) return;
35
+ if (commandValidation(message, command)) return;
35
36
 
36
37
  try {
37
38
  await command.exec(message, args);
@@ -1,5 +1,6 @@
1
1
  const { Event } = require('../commands/Event.js');
2
- const { messageArgs, access, messageEdit } = require("./../data/Functions.js");
2
+ const { messageArgs, messageEdit } = require("./../data/Functions.js");
3
+ const commandValidation = require('./../data/CommandValidation.js');
3
4
 
4
5
  /**
5
6
  * @returns message command executor.
@@ -21,7 +22,7 @@ class BuildInMessageUpdateEvent extends Event {
21
22
 
22
23
  if (!newMessage.client.messages[newMessage.id] == undefined) return;
23
24
 
24
- for (const prefix of newMessage.client.prefix) {
25
+ for (const prefix of newMessage.client.settings.prefix) {
25
26
  if (!newMessage.content.startsWith(prefix)) continue;
26
27
 
27
28
  let command = newMessage.content.replace(prefix, "").split(/ +/).shift().toLowerCase();
@@ -34,7 +35,7 @@ class BuildInMessageUpdateEvent extends Event {
34
35
 
35
36
  const args = await messageArgs({ message: newMessage, command: command });
36
37
 
37
- if (access(newMessage, command)) return;
38
+ if (commandValidation(newMessage, command)) return;
38
39
 
39
40
  try {
40
41
  command.exec(newMessage, args);
@@ -8,7 +8,6 @@ class BuildInReadyOnceEvent extends Event {
8
8
  constructor() {
9
9
  super('ready', {
10
10
  name: 'ready',
11
- type: 'client',
12
11
  once: true,
13
12
  })
14
13
  }
@@ -23,16 +23,20 @@ class CommandHandler {
23
23
  client.contextMenuCommands = new Discord.Collection();
24
24
  }
25
25
 
26
- loadInteractionCommands(path, logging = false) {
26
+ loadAllInteractionCommands(path, logging = false) {
27
27
  let commands = [];
28
28
 
29
29
  const commandFiles = fs.readdirSync(path).filter(file => file.endsWith('.js'))
30
30
 
31
31
  for (const file of commandFiles) {
32
- let command = require(`${require("path").resolve(path)}/${file}`);
32
+ let filepath = `${require("path").resolve(path)}/${file}`
33
+
34
+ let command = require(filepath);
33
35
 
34
36
  command = new command;
35
37
 
38
+ command.filepath = filepath;
39
+
36
40
  this.commands.push(command.data.toJSON());
37
41
 
38
42
  commands.push(command.data.name);
@@ -45,16 +49,20 @@ class CommandHandler {
45
49
  if (logging || this.client.logging) console.info(logStyle(`Loading interaction commands: ${commands.join(', ')}`, "text", "yellow"));
46
50
  }
47
51
 
48
- loadContextMenuCommands(path, logging = false) {
52
+ loadAllContextMenuCommands(path, logging = false) {
49
53
  let commands = [];
50
54
 
51
55
  const commandFiles = fs.readdirSync(path).filter(file => file.endsWith('.js'));
52
56
 
53
57
  for (const file of commandFiles) {
54
- let command = require(`${require("path").resolve(path)}/${file}`);
58
+ let filepath = `${require("path").resolve(path)}/${file}`
59
+
60
+ let command = require(filepath);
55
61
 
56
62
  command = new command;
57
63
 
64
+ command.filepath = filepath;
65
+
58
66
  this.commands.push(command.data.toJSON());
59
67
 
60
68
  commands.push(command.data.name);
@@ -67,16 +75,20 @@ class CommandHandler {
67
75
  if (logging || this.client.logging) console.info(logStyle(`Loading context menu commands: ${commands.join(', ')}`, 'text', 'yellow'));
68
76
  }
69
77
 
70
- loadMessageCommands(path, logging = false) {
78
+ loadAllMessageCommands(path, logging = false) {
71
79
  let commands = [];
72
80
 
73
81
  const commandFiles = fs.readdirSync(path).filter(file => file.endsWith('.js'));
74
82
 
75
83
  for (const file of commandFiles) {
76
- let command = require(`${require("path").resolve(path)}/${file}`);
84
+ let filepath = `${require("path").resolve(path)}/${file}`
85
+
86
+ let command = require(filepath);
77
87
 
78
88
  command = new command;
79
89
 
90
+ command.filepath = filepath;
91
+
80
92
  command.aliases.forEach((alias) => {
81
93
  if (this.client.messageCommands.has(alias)) throw new Error('Cannot have duplicated aliases.');
82
94
 
@@ -103,7 +115,7 @@ class CommandHandler {
103
115
  }
104
116
  else {
105
117
  if (logging || this.client.logging) console.info(logStyle(`Loaded ${type} locally.`, 'text', 'purple'));
106
- rest.put(Routes.applicationGuildCommands(client.user.id, client.guildId), {
118
+ rest.put(Routes.applicationGuildCommands(client.user.id, client.settings.guildId), {
107
119
  body: this.commands
108
120
  })
109
121
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xernerx",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "A bot framework for discord.js. [BETA]",
5
5
  "main": "main.js",
6
6
  "scripts": {
@@ -22,7 +22,7 @@
22
22
  "discord-api-types": "^0.36.3",
23
23
  "discord.js": "^14.0.3",
24
24
  "dumdiscord.js": "^1.0.5",
25
- "dumfunctions": "^1.0.5",
25
+ "dumfunctions": "^1.0.6",
26
26
  "i18next": "^21.8.14"
27
27
  },
28
28
  "packageManager": "npm@8.5.5"