spacecommands 1.0.0

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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +519 -0
  3. package/dist/Command.js +384 -0
  4. package/dist/CommandHandler.js +339 -0
  5. package/dist/FeatureHandler.js +89 -0
  6. package/dist/SlashCommands.js +220 -0
  7. package/dist/command-checks/channel-specific.js +30 -0
  8. package/dist/command-checks/guild-only-check.js +24 -0
  9. package/dist/command-checks/has-entitlement.js +52 -0
  10. package/dist/command-checks/has-permissions.js +39 -0
  11. package/dist/command-checks/has-roles.js +69 -0
  12. package/dist/command-checks/has-valid-arguments.js +54 -0
  13. package/dist/command-checks/in-cooldown.js +42 -0
  14. package/dist/command-checks/is-enabled.js +31 -0
  15. package/dist/command-checks/is-not-test-only.js +8 -0
  16. package/dist/command-checks/owner-only-check.js +22 -0
  17. package/dist/commands/channelonly.js +88 -0
  18. package/dist/commands/command.js +87 -0
  19. package/dist/commands/help/!ReactionListener.js +217 -0
  20. package/dist/commands/help/!get-first-embed.js +57 -0
  21. package/dist/commands/help/help.js +97 -0
  22. package/dist/commands/language.js +52 -0
  23. package/dist/commands/prefix.js +42 -0
  24. package/dist/commands/requiredrole.js +61 -0
  25. package/dist/commands/slash.js +102 -0
  26. package/dist/enums/CommandErrors.js +12 -0
  27. package/dist/enums/Events.js +9 -0
  28. package/dist/features/message-upsert.js +15 -0
  29. package/dist/get-all-files.js +25 -0
  30. package/dist/handlers/AutoModHandler.js +316 -0
  31. package/dist/handlers/ComponentHandler.js +110 -0
  32. package/dist/handlers/ContextMenuHandler.js +113 -0
  33. package/dist/handlers/EntitlementHandler.js +193 -0
  34. package/dist/handlers/ModalHandler.js +71 -0
  35. package/dist/handlers/PollHandler.js +230 -0
  36. package/dist/index.js +339 -0
  37. package/dist/message-handler.js +118 -0
  38. package/dist/models/channel-commands.js +49 -0
  39. package/dist/models/cooldown.js +51 -0
  40. package/dist/models/disabled-commands.js +45 -0
  41. package/dist/models/languages.js +46 -0
  42. package/dist/models/prefixes.js +46 -0
  43. package/dist/models/required-roles.js +49 -0
  44. package/dist/mongo.js +25 -0
  45. package/dist/permissions.js +39 -0
  46. package/dist/utils/ComponentBuilder.js +144 -0
  47. package/dist/utils/InteractionCollector.js +80 -0
  48. package/messages.json +391 -0
  49. package/package.json +72 -0
  50. package/typings.d.ts +276 -0
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const fs_1 = __importDefault(require("fs"));
6
+ const getAllFiles = (dir, extension) => {
7
+ const files = fs_1.default.readdirSync(dir, {
8
+ withFileTypes: true,
9
+ });
10
+ let jsFiles = [];
11
+ for (const file of files) {
12
+ if (file.isDirectory()) {
13
+ jsFiles = [...jsFiles, ...getAllFiles(`${dir}/${file.name}`, extension)];
14
+ }
15
+ else if (file.name.endsWith(extension || '.js') &&
16
+ !file.name.startsWith('!')) {
17
+ let fileName = file.name.replace(/\\/g, '/').split('/');
18
+ fileName = fileName[fileName.length - 1];
19
+ fileName = fileName.split('.')[0].toLowerCase();
20
+ jsFiles.push([`${dir}/${file.name}`, fileName]);
21
+ }
22
+ }
23
+ return jsFiles;
24
+ };
25
+ module.exports = getAllFiles;
@@ -0,0 +1,316 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const discord_js_1 = require("discord.js");
4
+ /**
5
+ * Handler for Discord AutoMod features
6
+ * Provides utilities for creating, managing, and listening to AutoMod rules and actions
7
+ */
8
+ class AutoModHandler {
9
+ _client;
10
+ _instance;
11
+ _actionHandlers = [];
12
+ _ruleCache = new Map(); // guildId -> ruleId -> rule
13
+ constructor(instance) {
14
+ this._instance = instance;
15
+ this._client = instance.client;
16
+ this.setUp();
17
+ }
18
+ setUp() {
19
+ // Listen for AutoMod action executions
20
+ this._client.on('autoModerationActionExecution', async (execution) => {
21
+ if (this._instance.debug) {
22
+ console.log(`SpaceCommands > AutoMod action executed in guild ${execution.guild.id}, rule: ${execution.ruleId}`);
23
+ }
24
+ await this.triggerActionHandlers(execution);
25
+ });
26
+ // Listen for AutoMod rule creation
27
+ this._client.on('autoModerationRuleCreate', (rule) => {
28
+ this.cacheRule(rule);
29
+ if (this._instance.debug) {
30
+ console.log(`SpaceCommands > AutoMod rule created: ${rule.name} (${rule.id}) in guild ${rule.guild.id}`);
31
+ }
32
+ });
33
+ // Listen for AutoMod rule updates
34
+ this._client.on('autoModerationRuleUpdate', (oldRule, newRule) => {
35
+ this.cacheRule(newRule);
36
+ if (this._instance.debug) {
37
+ console.log(`SpaceCommands > AutoMod rule updated: ${newRule.name} (${newRule.id}) in guild ${newRule.guild.id}`);
38
+ }
39
+ });
40
+ // Listen for AutoMod rule deletion
41
+ this._client.on('autoModerationRuleDelete', (rule) => {
42
+ this.uncacheRule(rule.guild.id, rule.id);
43
+ if (this._instance.debug) {
44
+ console.log(`SpaceCommands > AutoMod rule deleted: ${rule.name} (${rule.id}) in guild ${rule.guild.id}`);
45
+ }
46
+ });
47
+ }
48
+ /**
49
+ * Create an AutoMod rule in a guild
50
+ */
51
+ async createRule(guild, config) {
52
+ try {
53
+ const rule = await guild.autoModerationRules.create({
54
+ name: config.name,
55
+ eventType: config.eventType,
56
+ triggerType: config.triggerType,
57
+ triggerMetadata: config.triggerMetadata,
58
+ actions: config.actions,
59
+ enabled: config.enabled ?? true,
60
+ exemptRoles: config.exemptRoles,
61
+ exemptChannels: config.exemptChannels,
62
+ });
63
+ this.cacheRule(rule);
64
+ if (this._instance.debug) {
65
+ console.log(`SpaceCommands > Created AutoMod rule: ${rule.name} (${rule.id}) in guild ${guild.id}`);
66
+ }
67
+ return rule;
68
+ }
69
+ catch (error) {
70
+ console.error('SpaceCommands > Error creating AutoMod rule:', error);
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * Update an existing AutoMod rule
76
+ */
77
+ async updateRule(guild, ruleId, config) {
78
+ try {
79
+ const rule = await guild.autoModerationRules.edit(ruleId, {
80
+ name: config.name,
81
+ eventType: config.eventType,
82
+ triggerMetadata: config.triggerMetadata,
83
+ actions: config.actions,
84
+ enabled: config.enabled,
85
+ exemptRoles: config.exemptRoles,
86
+ exemptChannels: config.exemptChannels,
87
+ });
88
+ this.cacheRule(rule);
89
+ if (this._instance.debug) {
90
+ console.log(`SpaceCommands > Updated AutoMod rule: ${rule.name} (${rule.id}) in guild ${guild.id}`);
91
+ }
92
+ return rule;
93
+ }
94
+ catch (error) {
95
+ console.error('SpaceCommands > Error updating AutoMod rule:', error);
96
+ return null;
97
+ }
98
+ }
99
+ /**
100
+ * Delete an AutoMod rule
101
+ */
102
+ async deleteRule(guild, ruleId) {
103
+ try {
104
+ await guild.autoModerationRules.delete(ruleId);
105
+ this.uncacheRule(guild.id, ruleId);
106
+ if (this._instance.debug) {
107
+ console.log(`SpaceCommands > Deleted AutoMod rule: ${ruleId} in guild ${guild.id}`);
108
+ }
109
+ return true;
110
+ }
111
+ catch (error) {
112
+ console.error('SpaceCommands > Error deleting AutoMod rule:', error);
113
+ return false;
114
+ }
115
+ }
116
+ /**
117
+ * Fetch all AutoMod rules for a guild
118
+ */
119
+ async fetchGuildRules(guild, useCache = true) {
120
+ try {
121
+ const rules = await guild.autoModerationRules.fetch();
122
+ if (useCache) {
123
+ // Update cache
124
+ for (const rule of rules.values()) {
125
+ this.cacheRule(rule);
126
+ }
127
+ }
128
+ return rules;
129
+ }
130
+ catch (error) {
131
+ console.error('SpaceCommands > Error fetching AutoMod rules:', error);
132
+ return new discord_js_1.Collection();
133
+ }
134
+ }
135
+ /**
136
+ * Fetch a specific AutoMod rule
137
+ */
138
+ async fetchRule(guild, ruleId, useCache = true) {
139
+ try {
140
+ // Check cache first
141
+ if (useCache) {
142
+ const cachedRule = this.getCachedRule(guild.id, ruleId);
143
+ if (cachedRule)
144
+ return cachedRule;
145
+ }
146
+ const rule = await guild.autoModerationRules.fetch(ruleId);
147
+ if (useCache) {
148
+ this.cacheRule(rule);
149
+ }
150
+ return rule;
151
+ }
152
+ catch (error) {
153
+ console.error('SpaceCommands > Error fetching AutoMod rule:', error);
154
+ return null;
155
+ }
156
+ }
157
+ /**
158
+ * Register a handler for AutoMod action executions
159
+ */
160
+ registerActionHandler(handler) {
161
+ this._actionHandlers.push(handler);
162
+ if (this._instance.debug) {
163
+ console.log(`SpaceCommands > Registered AutoMod action handler${handler.ruleId ? ` for rule: ${handler.ruleId}` : ''}`);
164
+ }
165
+ return this;
166
+ }
167
+ /**
168
+ * Trigger all matching action handlers
169
+ */
170
+ async triggerActionHandlers(execution) {
171
+ for (const handler of this._actionHandlers) {
172
+ let matches = false;
173
+ if (!handler.ruleId) {
174
+ // Handler for all rules
175
+ matches = true;
176
+ }
177
+ else if (typeof handler.ruleId === 'string') {
178
+ matches = handler.ruleId === execution.ruleId;
179
+ }
180
+ else {
181
+ matches = handler.ruleId.test(execution.ruleId);
182
+ }
183
+ if (matches) {
184
+ try {
185
+ await handler.callback(execution, this._instance);
186
+ }
187
+ catch (error) {
188
+ console.error('SpaceCommands > Error executing AutoMod action handler:', error);
189
+ }
190
+ }
191
+ }
192
+ }
193
+ /**
194
+ * Cache a rule
195
+ */
196
+ cacheRule(rule) {
197
+ const guildId = rule.guild.id;
198
+ if (!this._ruleCache.has(guildId)) {
199
+ this._ruleCache.set(guildId, new Map());
200
+ }
201
+ this._ruleCache.get(guildId).set(rule.id, rule);
202
+ }
203
+ /**
204
+ * Remove a rule from cache
205
+ */
206
+ uncacheRule(guildId, ruleId) {
207
+ if (this._ruleCache.has(guildId)) {
208
+ this._ruleCache.get(guildId).delete(ruleId);
209
+ }
210
+ }
211
+ /**
212
+ * Get a cached rule
213
+ */
214
+ getCachedRule(guildId, ruleId) {
215
+ return this._ruleCache.get(guildId)?.get(ruleId) || null;
216
+ }
217
+ /**
218
+ * Clear the rule cache for a guild
219
+ */
220
+ clearGuildCache(guildId) {
221
+ this._ruleCache.delete(guildId);
222
+ }
223
+ /**
224
+ * Clear all rule caches
225
+ */
226
+ clearAllCaches() {
227
+ this._ruleCache.clear();
228
+ }
229
+ /**
230
+ * Helper: Create a keyword filter rule
231
+ */
232
+ async createKeywordRule(guild, name, keywords, actions, options) {
233
+ return this.createRule(guild, {
234
+ name,
235
+ eventType: discord_js_1.AutoModerationRuleEventType.MessageSend,
236
+ triggerType: discord_js_1.AutoModerationRuleTriggerType.Keyword,
237
+ triggerMetadata: {
238
+ keywordFilter: keywords,
239
+ allowList: options?.allowList,
240
+ },
241
+ actions,
242
+ enabled: options?.enabled,
243
+ exemptRoles: options?.exemptRoles,
244
+ exemptChannels: options?.exemptChannels,
245
+ });
246
+ }
247
+ /**
248
+ * Helper: Create a spam rule
249
+ */
250
+ async createSpamRule(guild, name, actions, options) {
251
+ return this.createRule(guild, {
252
+ name,
253
+ eventType: discord_js_1.AutoModerationRuleEventType.MessageSend,
254
+ triggerType: discord_js_1.AutoModerationRuleTriggerType.Spam,
255
+ actions,
256
+ enabled: options?.enabled,
257
+ exemptRoles: options?.exemptRoles,
258
+ exemptChannels: options?.exemptChannels,
259
+ });
260
+ }
261
+ /**
262
+ * Helper: Create a mention spam rule
263
+ */
264
+ async createMentionSpamRule(guild, name, mentionLimit, actions, options) {
265
+ return this.createRule(guild, {
266
+ name,
267
+ eventType: discord_js_1.AutoModerationRuleEventType.MessageSend,
268
+ triggerType: discord_js_1.AutoModerationRuleTriggerType.MentionSpam,
269
+ triggerMetadata: {
270
+ mentionTotalLimit: mentionLimit,
271
+ mentionRaidProtectionEnabled: options?.raidProtection ?? false,
272
+ },
273
+ actions,
274
+ enabled: options?.enabled,
275
+ exemptRoles: options?.exemptRoles,
276
+ exemptChannels: options?.exemptChannels,
277
+ });
278
+ }
279
+ /**
280
+ * Helper: Create a regex pattern rule
281
+ */
282
+ async createRegexRule(guild, name, patterns, actions, options) {
283
+ return this.createRule(guild, {
284
+ name,
285
+ eventType: discord_js_1.AutoModerationRuleEventType.MessageSend,
286
+ triggerType: discord_js_1.AutoModerationRuleTriggerType.Keyword,
287
+ triggerMetadata: {
288
+ regexPatterns: patterns,
289
+ allowList: options?.allowList,
290
+ },
291
+ actions,
292
+ enabled: options?.enabled,
293
+ exemptRoles: options?.exemptRoles,
294
+ exemptChannels: options?.exemptChannels,
295
+ });
296
+ }
297
+ /**
298
+ * Helper: Create preset keyword rule (profanity, slurs, etc.)
299
+ */
300
+ async createPresetRule(guild, name, presets, actions, options) {
301
+ return this.createRule(guild, {
302
+ name,
303
+ eventType: discord_js_1.AutoModerationRuleEventType.MessageSend,
304
+ triggerType: discord_js_1.AutoModerationRuleTriggerType.KeywordPreset,
305
+ triggerMetadata: {
306
+ presets,
307
+ allowList: options?.allowList,
308
+ },
309
+ actions,
310
+ enabled: options?.enabled,
311
+ exemptRoles: options?.exemptRoles,
312
+ exemptChannels: options?.exemptChannels,
313
+ });
314
+ }
315
+ }
316
+ exports.default = AutoModHandler;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const get_all_files_1 = __importDefault(require("../get-all-files"));
7
+ class ComponentHandler {
8
+ _client;
9
+ _instance;
10
+ _buttonHandlers = new Map();
11
+ _selectMenuHandlers = new Map();
12
+ constructor(instance, componentsDir, typeScript = false) {
13
+ this._instance = instance;
14
+ this._client = instance.client;
15
+ this.setUp(componentsDir, typeScript);
16
+ }
17
+ async setUp(componentsDir, typeScript = false) {
18
+ // Listen for component interactions
19
+ this._client.on('interactionCreate', async (interaction) => {
20
+ if (!interaction.isButton() && !interaction.isAnySelectMenu()) {
21
+ return;
22
+ }
23
+ const customId = interaction.customId;
24
+ if (interaction.isButton()) {
25
+ await this.handleButton(interaction, customId);
26
+ }
27
+ else if (interaction.isAnySelectMenu()) {
28
+ await this.handleSelectMenu(interaction, customId);
29
+ }
30
+ });
31
+ // Load custom component handlers if directory provided
32
+ if (componentsDir) {
33
+ await this.loadComponentHandlers(componentsDir, typeScript);
34
+ }
35
+ }
36
+ async loadComponentHandlers(dir, typeScript) {
37
+ const files = (0, get_all_files_1.default)(dir, typeScript ? '.ts' : '');
38
+ for (const [file, fileName] of files) {
39
+ const handler = require(file);
40
+ const config = handler.default || handler;
41
+ if (config.type === 'button') {
42
+ this.registerButtonHandler(config);
43
+ }
44
+ else if (config.type === 'selectMenu') {
45
+ this.registerSelectMenuHandler(config);
46
+ }
47
+ }
48
+ }
49
+ registerButtonHandler(handler) {
50
+ const key = typeof handler.customId === 'string'
51
+ ? handler.customId
52
+ : handler.customId.source;
53
+ this._buttonHandlers.set(key, handler);
54
+ }
55
+ registerSelectMenuHandler(handler) {
56
+ const key = typeof handler.customId === 'string'
57
+ ? handler.customId
58
+ : handler.customId.source;
59
+ this._selectMenuHandlers.set(key, handler);
60
+ }
61
+ async handleButton(interaction, customId) {
62
+ for (const [key, handler] of this._buttonHandlers.entries()) {
63
+ const regex = handler.customId instanceof RegExp ? handler.customId : null;
64
+ if ((regex && regex.test(customId)) ||
65
+ (!regex && handler.customId === customId)) {
66
+ try {
67
+ await handler.callback(interaction, this._instance);
68
+ }
69
+ catch (error) {
70
+ console.error(`SpaceCommands > Error handling button "${customId}":`, error);
71
+ if (!interaction.replied && !interaction.deferred) {
72
+ await interaction.reply({
73
+ content: 'An error occurred while processing this button.',
74
+ ephemeral: true,
75
+ });
76
+ }
77
+ }
78
+ return;
79
+ }
80
+ }
81
+ }
82
+ async handleSelectMenu(interaction, customId) {
83
+ for (const [key, handler] of this._selectMenuHandlers.entries()) {
84
+ const regex = handler.customId instanceof RegExp ? handler.customId : null;
85
+ if ((regex && regex.test(customId)) ||
86
+ (!regex && handler.customId === customId)) {
87
+ try {
88
+ await handler.callback(interaction, this._instance);
89
+ }
90
+ catch (error) {
91
+ console.error(`SpaceCommands > Error handling select menu "${customId}":`, error);
92
+ if (!interaction.replied && !interaction.deferred) {
93
+ await interaction.reply({
94
+ content: 'An error occurred while processing this menu.',
95
+ ephemeral: true,
96
+ });
97
+ }
98
+ }
99
+ return;
100
+ }
101
+ }
102
+ }
103
+ get buttonHandlers() {
104
+ return this._buttonHandlers;
105
+ }
106
+ get selectMenuHandlers() {
107
+ return this._selectMenuHandlers;
108
+ }
109
+ }
110
+ exports.default = ComponentHandler;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const discord_js_1 = require("discord.js");
7
+ const get_all_files_1 = __importDefault(require("../get-all-files"));
8
+ class ContextMenuHandler {
9
+ _client;
10
+ _instance;
11
+ _contextMenus = new Map();
12
+ constructor(instance, contextMenusDir, typeScript = false) {
13
+ this._instance = instance;
14
+ this._client = instance.client;
15
+ this.setUp(contextMenusDir, typeScript);
16
+ }
17
+ async setUp(contextMenusDir, typeScript = false) {
18
+ // Listen for context menu interactions
19
+ this._client.on('interactionCreate', async (interaction) => {
20
+ if (!interaction.isContextMenuCommand()) {
21
+ return;
22
+ }
23
+ const commandName = interaction.commandName;
24
+ await this.handleContextMenu(interaction, commandName);
25
+ });
26
+ // Load custom context menu commands if directory provided
27
+ if (contextMenusDir) {
28
+ await this.loadContextMenus(contextMenusDir, typeScript);
29
+ }
30
+ }
31
+ async loadContextMenus(dir, typeScript) {
32
+ const files = (0, get_all_files_1.default)(dir, typeScript ? '.ts' : '');
33
+ for (const [file, fileName] of files) {
34
+ const command = require(file);
35
+ const config = command.default || command;
36
+ if (config.type && config.callback) {
37
+ await this.registerContextMenu(config);
38
+ }
39
+ }
40
+ }
41
+ async registerContextMenu(command) {
42
+ this._contextMenus.set(command.name, command);
43
+ // Register with Discord
44
+ const contextMenuCommand = new discord_js_1.ContextMenuCommandBuilder()
45
+ .setName(command.name)
46
+ .setType(command.type);
47
+ if (command.testOnly && this._instance.testServers.length) {
48
+ // Register to test servers only
49
+ for (const guildId of this._instance.testServers) {
50
+ const guild = this._client.guilds.cache.get(guildId);
51
+ if (guild) {
52
+ await guild.commands.create(contextMenuCommand.toJSON());
53
+ }
54
+ }
55
+ }
56
+ else {
57
+ // Register globally
58
+ await this._client.application?.commands.create(contextMenuCommand.toJSON());
59
+ }
60
+ console.log(`SpaceCommands > Registered context menu command: ${command.name}`);
61
+ }
62
+ async handleContextMenu(interaction, commandName) {
63
+ const command = this._contextMenus.get(commandName);
64
+ if (!command) {
65
+ return;
66
+ }
67
+ // Check owner-only
68
+ if (command.ownerOnly &&
69
+ !this._instance.botOwner.includes(interaction.user.id)) {
70
+ await interaction.reply({
71
+ content: 'This command is only available to bot owners.',
72
+ ephemeral: true,
73
+ });
74
+ return;
75
+ }
76
+ // Check guild-only
77
+ if (command.guildOnly && !interaction.guild) {
78
+ await interaction.reply({
79
+ content: 'This command can only be used in servers.',
80
+ ephemeral: true,
81
+ });
82
+ return;
83
+ }
84
+ // Check permissions
85
+ if (command.permissions && interaction.guild && interaction.member) {
86
+ const member = interaction.member;
87
+ const hasPermission = command.permissions.every((perm) => member.permissions.has(perm));
88
+ if (!hasPermission) {
89
+ await interaction.reply({
90
+ content: 'You do not have permission to use this command.',
91
+ ephemeral: true,
92
+ });
93
+ return;
94
+ }
95
+ }
96
+ try {
97
+ await command.callback(interaction, this._instance);
98
+ }
99
+ catch (error) {
100
+ console.error(`SpaceCommands > Error handling context menu "${commandName}":`, error);
101
+ if (!interaction.replied && !interaction.deferred) {
102
+ await interaction.reply({
103
+ content: 'An error occurred while executing this command.',
104
+ ephemeral: true,
105
+ });
106
+ }
107
+ }
108
+ }
109
+ get contextMenus() {
110
+ return this._contextMenus;
111
+ }
112
+ }
113
+ exports.default = ContextMenuHandler;