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.
- package/LICENSE +21 -0
- package/README.md +519 -0
- package/dist/Command.js +384 -0
- package/dist/CommandHandler.js +339 -0
- package/dist/FeatureHandler.js +89 -0
- package/dist/SlashCommands.js +220 -0
- package/dist/command-checks/channel-specific.js +30 -0
- package/dist/command-checks/guild-only-check.js +24 -0
- package/dist/command-checks/has-entitlement.js +52 -0
- package/dist/command-checks/has-permissions.js +39 -0
- package/dist/command-checks/has-roles.js +69 -0
- package/dist/command-checks/has-valid-arguments.js +54 -0
- package/dist/command-checks/in-cooldown.js +42 -0
- package/dist/command-checks/is-enabled.js +31 -0
- package/dist/command-checks/is-not-test-only.js +8 -0
- package/dist/command-checks/owner-only-check.js +22 -0
- package/dist/commands/channelonly.js +88 -0
- package/dist/commands/command.js +87 -0
- package/dist/commands/help/!ReactionListener.js +217 -0
- package/dist/commands/help/!get-first-embed.js +57 -0
- package/dist/commands/help/help.js +97 -0
- package/dist/commands/language.js +52 -0
- package/dist/commands/prefix.js +42 -0
- package/dist/commands/requiredrole.js +61 -0
- package/dist/commands/slash.js +102 -0
- package/dist/enums/CommandErrors.js +12 -0
- package/dist/enums/Events.js +9 -0
- package/dist/features/message-upsert.js +15 -0
- package/dist/get-all-files.js +25 -0
- package/dist/handlers/AutoModHandler.js +316 -0
- package/dist/handlers/ComponentHandler.js +110 -0
- package/dist/handlers/ContextMenuHandler.js +113 -0
- package/dist/handlers/EntitlementHandler.js +193 -0
- package/dist/handlers/ModalHandler.js +71 -0
- package/dist/handlers/PollHandler.js +230 -0
- package/dist/index.js +339 -0
- package/dist/message-handler.js +118 -0
- package/dist/models/channel-commands.js +49 -0
- package/dist/models/cooldown.js +51 -0
- package/dist/models/disabled-commands.js +45 -0
- package/dist/models/languages.js +46 -0
- package/dist/models/prefixes.js +46 -0
- package/dist/models/required-roles.js +49 -0
- package/dist/mongo.js +25 -0
- package/dist/permissions.js +39 -0
- package/dist/utils/ComponentBuilder.js +144 -0
- package/dist/utils/InteractionCollector.js +80 -0
- package/messages.json +391 -0
- package/package.json +72 -0
- 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;
|