spiralcord-full 2.3.1 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/spiral.js CHANGED
@@ -153,14 +153,23 @@ async function startBot(config) {
153
153
 
154
154
  program
155
155
  .command('run')
156
- .description('Start the bot runtime')
157
- .option('-R, --realtime', 'Start with auto-reload and REPL console')
156
+ .description('Start the bot runtime (with REPL console by default)')
157
+ .option('-N, --normal', 'Start without auto-reload or REPL console')
158
158
  .action(async (options) => {
159
159
  try {
160
160
  const config = await loadConfig();
161
161
  if (!config) return;
162
162
 
163
- if (options.realtime) {
163
+ if (options.normal) {
164
+ const runtime = await startBot(config);
165
+ console.log('Bot is running! Press Ctrl+C to stop.');
166
+
167
+ process.on('SIGINT', async () => {
168
+ console.log('\nShutting down...');
169
+ await runtime.stop();
170
+ process.exit(0);
171
+ });
172
+ } else {
164
173
  const chokidar = (() => {
165
174
  try {
166
175
  const resolved = require.resolve('chokidar', { paths: [process.cwd()] });
@@ -168,7 +177,7 @@ program
168
177
  } catch { return null; }
169
178
  })();
170
179
  if (!chokidar) {
171
- console.error('Error: "spiral run -R" requires chokidar. Run: npm install chokidar');
180
+ console.error('Error: "spiral run" requires chokidar. Run: npm install chokidar');
172
181
  process.exit(1);
173
182
  }
174
183
 
@@ -502,15 +511,6 @@ program
502
511
  if (runtime) await runtime.stop();
503
512
  process.exit(0);
504
513
  });
505
- } else {
506
- const runtime = await startBot(config);
507
- console.log('Bot is running! Press Ctrl+C to stop.');
508
-
509
- process.on('SIGINT', async () => {
510
- console.log('\nShutting down...');
511
- await runtime.stop();
512
- process.exit(0);
513
- });
514
514
  }
515
515
  } catch (error) {
516
516
  console.error('Failed to start bot:', error.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spiralcord-full",
3
- "version": "2.3.1",
3
+ "version": "2.5.1",
4
4
  "description": "Spiralcord Full - Discord Bot Runtime with Voice, Music, AI, Database & Image Support",
5
5
  "main": "src/index.js",
6
6
  "types": "src/types/index.d.ts",
@@ -24,8 +24,8 @@
24
24
  "database",
25
25
  "canvas"
26
26
  ],
27
- "author": "",
28
- "license": "MIT",
27
+ "author": "Isam Ahmed",
28
+ "license": "custom",
29
29
  "dependencies": {
30
30
  "commander": "^12.1.0",
31
31
  "discord.js": "^14.16.3",
@@ -13,7 +13,7 @@ class SpiralPluginManager extends EventEmitter {
13
13
  this.pluginAPIs = new Map();
14
14
  this.pluginConfigs = new Map();
15
15
  this.loadOrder = [];
16
- this.maxListeners = 50;
16
+ this.setMaxListeners(50);
17
17
  this._cache = new Map();
18
18
  this._hookCleanups = [];
19
19
  }
package/src/runtime.js CHANGED
@@ -137,16 +137,30 @@ class SpiralRuntime {
137
137
  const intents = this.config.intents || ['Guilds', 'GuildMessages', 'MessageContent'];
138
138
  const map = {
139
139
  'Guilds': GatewayIntentBits.Guilds,
140
- 'GuildMessages': GatewayIntentBits.GuildMessages,
141
- 'MessageContent': GatewayIntentBits.MessageContent,
142
140
  'GuildMembers': GatewayIntentBits.GuildMembers,
141
+ 'GuildModeration': GatewayIntentBits.GuildModeration,
142
+ 'GuildEmojisAndStickers': GatewayIntentBits.GuildEmojisAndStickers,
143
+ 'GuildIntegrations': GatewayIntentBits.GuildIntegrations,
144
+ 'GuildWebhooks': GatewayIntentBits.GuildWebhooks,
145
+ 'GuildInvites': GatewayIntentBits.GuildInvites,
143
146
  'GuildVoiceStates': GatewayIntentBits.GuildVoiceStates,
147
+ 'GuildPresences': GatewayIntentBits.GuildPresences,
148
+ 'GuildMessages': GatewayIntentBits.GuildMessages,
149
+ 'GuildMessageReactions': GatewayIntentBits.GuildMessageReactions,
150
+ 'GuildMessageTyping': GatewayIntentBits.GuildMessageTyping,
144
151
  'DirectMessages': GatewayIntentBits.DirectMessages,
145
- 'GuildPresences': GatewayIntentBits.GuildPresences
152
+ 'DirectMessageReactions': GatewayIntentBits.DirectMessageReactions,
153
+ 'DirectMessageTyping': GatewayIntentBits.DirectMessageTyping,
154
+ 'MessageContent': GatewayIntentBits.MessageContent,
155
+ 'GuildScheduledEvents': GatewayIntentBits.GuildScheduledEvents,
156
+ 'AutoModerationConfiguration': GatewayIntentBits.AutoModerationConfiguration,
157
+ 'AutoModerationExecution': GatewayIntentBits.AutoModerationExecution,
158
+ 'GuildMessagePolls': GatewayIntentBits.GuildMessagePolls,
159
+ 'UserThreads': GatewayIntentBits.UserThreads
146
160
  };
147
161
  return intents.map(i => {
148
162
  if (map[i] !== undefined) return map[i];
149
- console.warn(`[runtime] Unknown intent "${i}", defaulting to Guilds`);
163
+ console.warn(`[runtime] Unknown intent "${i}", skipping. Valid intents: ${Object.keys(map).join(', ')}`);
150
164
  return GatewayIntentBits.Guilds;
151
165
  });
152
166
  }
@@ -310,6 +324,48 @@ class SpiralRuntime {
310
324
  getPluginAPI(pluginName) {
311
325
  return this.pluginManager.getPluginAPI(pluginName);
312
326
  }
327
+
328
+ async registerSlashCommands(clientId, commands, options = {}) {
329
+ const { REST } = require('@discordjs/rest');
330
+ const { Routes } = require('discord-api-types/v10');
331
+
332
+ if (!clientId) throw new Error('[runtime] registerSlashCommands: clientId is required');
333
+
334
+ const token = this.config.token;
335
+ if (!token) throw new Error('[runtime] registerSlashCommands: no token in config');
336
+
337
+ const rest = new REST({ version: '10' }).setToken(token);
338
+
339
+ const body = commands.map(cmd => {
340
+ if (cmd.toJSON) return cmd.toJSON();
341
+ return cmd;
342
+ });
343
+
344
+ const BATCH_SIZE = 100;
345
+
346
+ if (this.config.perGuildSlash) {
347
+ const guilds = options.guilds || [...this.client.guilds.cache.values()];
348
+ console.log(`[runtime] Registering ${body.length} slash commands in ${guilds.length} guild(s)...`);
349
+
350
+ for (const guild of guilds) {
351
+ const guildId = guild.id || guild;
352
+ for (let i = 0; i < body.length; i += BATCH_SIZE) {
353
+ const batch = body.slice(i, i + BATCH_SIZE);
354
+ await rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: batch });
355
+ }
356
+ const name = guild.name || guildId;
357
+ console.log(`[runtime] Registered in ${name}`);
358
+ }
359
+ } else {
360
+ console.log(`[runtime] Registering ${body.length} slash commands globally...`);
361
+ for (let i = 0; i < body.length; i += BATCH_SIZE) {
362
+ const batch = body.slice(i, i + BATCH_SIZE);
363
+ await rest.put(Routes.applicationCommands(clientId), { body: batch });
364
+ }
365
+ }
366
+
367
+ console.log(`[runtime] Slash commands registered.`);
368
+ }
313
369
  }
314
370
 
315
371
  module.exports = SpiralRuntime;
@@ -5,6 +5,7 @@ export interface SpiralConfig {
5
5
  intents: string[];
6
6
  clientId: string;
7
7
  disabledCommands: string[];
8
+ perGuildSlash?: boolean;
8
9
  }
9
10
 
10
11
  export interface SpiralPluginManifest {
@@ -91,6 +92,7 @@ export interface SpiralRuntime {
91
92
  getAllCommands(): Map<string, any>;
92
93
  getPluginConfig(pluginName: string): SpiralPluginConfig;
93
94
  getPluginAPI(pluginName: string): Record<string, (...args: any[]) => any> | null;
95
+ registerSlashCommands(clientId: string, commands: any[], options?: { guilds?: any[] }): Promise<void>;
94
96
  emitHook(eventName: string, payload: any): Promise<void>;
95
97
  emitHookSerial(eventName: string, payload: any): Promise<void>;
96
98
  emitHookWithResult(eventName: string, payload: any): Promise<boolean>;