@spatulox/simplediscordbot 1.1.0 → 1.2.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/dist/index.d.mts CHANGED
@@ -341,6 +341,7 @@ declare abstract class BasicUserManager {
341
341
  }
342
342
 
343
343
  declare class GuildUserManager extends BasicUserManager {
344
+ static find(userId: string, guild: Guild | string): Promise<GuildMember | null>;
344
345
  static rename(member: GuildMember, nickname: string, maxAttempts?: number): Promise<boolean>;
345
346
  /**
346
347
  * Check if user is banned from guild
@@ -528,7 +529,7 @@ declare class GuildManager {
528
529
  static readonly channel: typeof GuildChannelList;
529
530
  static readonly invite: typeof InviteManager;
530
531
  static list(): Guild[];
531
- static find(guild_id: string): Promise<Guild | null>;
532
+ static find(guild_id: string): Promise<Guild>;
532
533
  /**
533
534
  * Search channel by ID (TextChannel, DMChannel, ThreadChannel)
534
535
  */
@@ -553,20 +554,60 @@ declare class UserManager extends BasicUserManager {
553
554
  static find(userId: string): Promise<User | null>;
554
555
  }
555
556
 
557
+ declare enum ModalFieldType {
558
+ SHORT = 0,
559
+ LONG = 1,
560
+ NUMBER = 2,
561
+ DATE = 3,
562
+ PHONE = 4
563
+ }
564
+ interface ModalField {
565
+ type: ModalFieldType;
566
+ label: string;
567
+ placeholder?: string;
568
+ required?: boolean;
569
+ }
556
570
  declare class ModalManager {
557
571
  /**
558
- * Load modal from JSON file and return ModalBuilder
572
+ * Creates base Modal - SIMPLE API !
573
+ */
574
+ static create(modalTitle: string, customId: string): ModalBuilder;
575
+ /**
576
+ * Individual field creator
577
+ */
578
+ private static _createField;
579
+ /**
580
+ * Simple modal with ONE field - DIRECT ModalBuilder return !
581
+ */
582
+ static simple(customId: string, modalTitle: string | null, field: ModalField): ModalBuilder;
583
+ /**
584
+ * Title + Description modal preset
559
585
  */
560
- static load(filename: string): Promise<ModalBuilder | false>;
586
+ static titleDescription(customId: string, modalTitle: string, title: Omit<ModalField, "type">, description: Omit<ModalField, "type">): ModalBuilder;
561
587
  /**
562
- * List all modal files
588
+ * Date modal preset
563
589
  */
564
- static list(): Promise<string[] | false>;
565
- private static jsonToBuilder;
566
- private static fieldJsonToInput;
590
+ static date(customId: string, modalTitle?: string, inputLabel?: string): ModalBuilder;
591
+ /**
592
+ * Number modal preset
593
+ */
594
+ static number(customId: string, modalTitle?: string, inputLabel?: string): ModalBuilder;
595
+ /**
596
+ * Number modal preset
597
+ */
598
+ static phone(customId: string, modalTitle?: string, inputLabel?: string): ModalBuilder;
599
+ /**
600
+ * Add field to existing modal (Fluent API)
601
+ */
602
+ static add(modal: ModalBuilder, field: ModalField[]): ModalBuilder;
603
+ static add(modal: ModalBuilder, field: ModalField): ModalBuilder;
567
604
  static parseNumber(value: string): number | null;
568
605
  static parsePhone(value: string): string | null;
569
606
  static parseDate(value: string): Date | null;
607
+ /**
608
+ * Transform modal to interaction.showModal() format
609
+ */
610
+ static toInteraction(modal: ModalBuilder): ModalBuilder;
570
611
  }
571
612
 
572
613
  type SelectMenuCreateOption = {
package/dist/index.d.ts CHANGED
@@ -341,6 +341,7 @@ declare abstract class BasicUserManager {
341
341
  }
342
342
 
343
343
  declare class GuildUserManager extends BasicUserManager {
344
+ static find(userId: string, guild: Guild | string): Promise<GuildMember | null>;
344
345
  static rename(member: GuildMember, nickname: string, maxAttempts?: number): Promise<boolean>;
345
346
  /**
346
347
  * Check if user is banned from guild
@@ -528,7 +529,7 @@ declare class GuildManager {
528
529
  static readonly channel: typeof GuildChannelList;
529
530
  static readonly invite: typeof InviteManager;
530
531
  static list(): Guild[];
531
- static find(guild_id: string): Promise<Guild | null>;
532
+ static find(guild_id: string): Promise<Guild>;
532
533
  /**
533
534
  * Search channel by ID (TextChannel, DMChannel, ThreadChannel)
534
535
  */
@@ -553,20 +554,60 @@ declare class UserManager extends BasicUserManager {
553
554
  static find(userId: string): Promise<User | null>;
554
555
  }
555
556
 
557
+ declare enum ModalFieldType {
558
+ SHORT = 0,
559
+ LONG = 1,
560
+ NUMBER = 2,
561
+ DATE = 3,
562
+ PHONE = 4
563
+ }
564
+ interface ModalField {
565
+ type: ModalFieldType;
566
+ label: string;
567
+ placeholder?: string;
568
+ required?: boolean;
569
+ }
556
570
  declare class ModalManager {
557
571
  /**
558
- * Load modal from JSON file and return ModalBuilder
572
+ * Creates base Modal - SIMPLE API !
573
+ */
574
+ static create(modalTitle: string, customId: string): ModalBuilder;
575
+ /**
576
+ * Individual field creator
577
+ */
578
+ private static _createField;
579
+ /**
580
+ * Simple modal with ONE field - DIRECT ModalBuilder return !
581
+ */
582
+ static simple(customId: string, modalTitle: string | null, field: ModalField): ModalBuilder;
583
+ /**
584
+ * Title + Description modal preset
559
585
  */
560
- static load(filename: string): Promise<ModalBuilder | false>;
586
+ static titleDescription(customId: string, modalTitle: string, title: Omit<ModalField, "type">, description: Omit<ModalField, "type">): ModalBuilder;
561
587
  /**
562
- * List all modal files
588
+ * Date modal preset
563
589
  */
564
- static list(): Promise<string[] | false>;
565
- private static jsonToBuilder;
566
- private static fieldJsonToInput;
590
+ static date(customId: string, modalTitle?: string, inputLabel?: string): ModalBuilder;
591
+ /**
592
+ * Number modal preset
593
+ */
594
+ static number(customId: string, modalTitle?: string, inputLabel?: string): ModalBuilder;
595
+ /**
596
+ * Number modal preset
597
+ */
598
+ static phone(customId: string, modalTitle?: string, inputLabel?: string): ModalBuilder;
599
+ /**
600
+ * Add field to existing modal (Fluent API)
601
+ */
602
+ static add(modal: ModalBuilder, field: ModalField[]): ModalBuilder;
603
+ static add(modal: ModalBuilder, field: ModalField): ModalBuilder;
567
604
  static parseNumber(value: string): number | null;
568
605
  static parsePhone(value: string): string | null;
569
606
  static parseDate(value: string): Date | null;
607
+ /**
608
+ * Transform modal to interaction.showModal() format
609
+ */
610
+ static toInteraction(modal: ModalBuilder): ModalBuilder;
570
611
  }
571
612
 
572
613
  type SelectMenuCreateOption = {
package/dist/index.js CHANGED
@@ -1559,7 +1559,7 @@ var ReactionManager = class {
1559
1559
  };
1560
1560
 
1561
1561
  // src/manager/guild/GuildManager.ts
1562
- var import_discord13 = require("discord.js");
1562
+ var import_discord14 = require("discord.js");
1563
1563
 
1564
1564
  // src/manager/direct/BasicUserManager.ts
1565
1565
  var import_discord8 = require("discord.js");
@@ -1634,9 +1634,22 @@ var BasicUserManager = class {
1634
1634
  };
1635
1635
 
1636
1636
  // src/manager/guild/GuildUserManager.ts
1637
+ var import_discord9 = require("discord.js");
1637
1638
  var import_promises2 = require("timers/promises");
1638
1639
  var MAX_NICKNAME_LENGTH = 32;
1639
1640
  var GuildUserManager = class extends BasicUserManager {
1641
+ static async find(userId, guild) {
1642
+ try {
1643
+ if (guild instanceof import_discord9.Guild) {
1644
+ return await guild.members.fetch(userId);
1645
+ } else {
1646
+ return await (await GuildManager.find(guild)).members.fetch(userId);
1647
+ }
1648
+ } catch (error) {
1649
+ Log.error(`UserManager: Member ${userId} not found`);
1650
+ return null;
1651
+ }
1652
+ }
1640
1653
  static async rename(member, nickname, maxAttempts = 3) {
1641
1654
  if (nickname.length > MAX_NICKNAME_LENGTH) {
1642
1655
  nickname = nickname.slice(0, MAX_NICKNAME_LENGTH);
@@ -1925,15 +1938,15 @@ var RoleManager = class {
1925
1938
  };
1926
1939
 
1927
1940
  // src/manager/guild/ChannelManager/ForumChannelManager.ts
1928
- var import_discord9 = require("discord.js");
1941
+ var import_discord10 = require("discord.js");
1929
1942
  var ForumChannelManager = class extends GuildChannelManager {
1930
1943
  static async findInGuild(guildId, channelId) {
1931
1944
  const channel = await super.findInGuild(guildId, channelId);
1932
- return channel instanceof import_discord9.ForumChannel ? channel : null;
1945
+ return channel instanceof import_discord10.ForumChannel ? channel : null;
1933
1946
  }
1934
1947
  static async find(channelId) {
1935
1948
  const channel = await super.find(channelId);
1936
- return channel instanceof import_discord9.ForumChannel ? channel : null;
1949
+ return channel instanceof import_discord10.ForumChannel ? channel : null;
1937
1950
  }
1938
1951
  static findAll(guildId) {
1939
1952
  const guild = Bot.client.guilds.cache.get(guildId);
@@ -1941,27 +1954,27 @@ var ForumChannelManager = class extends GuildChannelManager {
1941
1954
  Log.warn(`Guild ${guildId} not found`);
1942
1955
  return [];
1943
1956
  }
1944
- return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord9.ForumChannel);
1957
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord10.ForumChannel);
1945
1958
  }
1946
1959
  static async create(guildId, name, options) {
1947
1960
  return await super._create(guildId, {
1948
1961
  name,
1949
- type: import_discord9.ChannelType.GuildForum,
1962
+ type: import_discord10.ChannelType.GuildForum,
1950
1963
  ...options
1951
1964
  });
1952
1965
  }
1953
1966
  };
1954
1967
 
1955
1968
  // src/manager/guild/ChannelManager/NewsChannelManager.ts
1956
- var import_discord10 = require("discord.js");
1969
+ var import_discord11 = require("discord.js");
1957
1970
  var NewsChannelManager = class extends GuildChannelManager {
1958
1971
  static async findInGuild(guildId, channelId) {
1959
1972
  const channel = await super.findInGuild(guildId, channelId);
1960
- return channel instanceof import_discord10.NewsChannel ? channel : null;
1973
+ return channel instanceof import_discord11.NewsChannel ? channel : null;
1961
1974
  }
1962
1975
  static async find(channelId) {
1963
1976
  const channel = await super.find(channelId);
1964
- return channel instanceof import_discord10.NewsChannel ? channel : null;
1977
+ return channel instanceof import_discord11.NewsChannel ? channel : null;
1965
1978
  }
1966
1979
  static findAll(guildId) {
1967
1980
  const guild = Bot.client.guilds.cache.get(guildId);
@@ -1969,27 +1982,27 @@ var NewsChannelManager = class extends GuildChannelManager {
1969
1982
  Log.warn(`Guild ${guildId} not found`);
1970
1983
  return [];
1971
1984
  }
1972
- return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord10.NewsChannel);
1985
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord11.NewsChannel);
1973
1986
  }
1974
1987
  static async create(guildId, name, options) {
1975
1988
  return await super._create(guildId, {
1976
1989
  name,
1977
- type: import_discord10.ChannelType.GuildAnnouncement,
1990
+ type: import_discord11.ChannelType.GuildAnnouncement,
1978
1991
  ...options
1979
1992
  });
1980
1993
  }
1981
1994
  };
1982
1995
 
1983
1996
  // src/manager/guild/ChannelManager/StageChannelManager.ts
1984
- var import_discord11 = require("discord.js");
1997
+ var import_discord12 = require("discord.js");
1985
1998
  var StageChannelManager = class extends GuildChannelManager {
1986
1999
  static async findInGuild(guildId, channelId) {
1987
2000
  const channel = await super.findInGuild(guildId, channelId);
1988
- return channel instanceof import_discord11.StageChannel ? channel : null;
2001
+ return channel instanceof import_discord12.StageChannel ? channel : null;
1989
2002
  }
1990
2003
  static async find(channelId) {
1991
2004
  const channel = await super.find(channelId);
1992
- return channel instanceof import_discord11.StageChannel ? channel : null;
2005
+ return channel instanceof import_discord12.StageChannel ? channel : null;
1993
2006
  }
1994
2007
  static findAll(guildId) {
1995
2008
  const guild = Bot.client.guilds.cache.get(guildId);
@@ -1997,12 +2010,12 @@ var StageChannelManager = class extends GuildChannelManager {
1997
2010
  Log.warn(`Guild ${guildId} not found`);
1998
2011
  return [];
1999
2012
  }
2000
- return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord11.StageChannel);
2013
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord12.StageChannel);
2001
2014
  }
2002
2015
  static async create(guildId, name, options) {
2003
2016
  return await super._create(guildId, {
2004
2017
  name,
2005
- type: import_discord11.ChannelType.GuildStageVoice,
2018
+ type: import_discord12.ChannelType.GuildStageVoice,
2006
2019
  ...options
2007
2020
  });
2008
2021
  }
@@ -2050,7 +2063,7 @@ var ThreadChannelManager = class {
2050
2063
  };
2051
2064
 
2052
2065
  // src/manager/guild/ChannelManager/GuildVoiceChannelManager.ts
2053
- var import_discord12 = require("discord.js");
2066
+ var import_discord13 = require("discord.js");
2054
2067
  var GuildVoiceChannelManager = class extends GuildChannelManager {
2055
2068
  static async findInGuild(guildId, channelId) {
2056
2069
  const channel = await super.findInGuild(guildId, channelId);
@@ -2066,12 +2079,12 @@ var GuildVoiceChannelManager = class extends GuildChannelManager {
2066
2079
  Log.warn(`Guild ${guildId} not found`);
2067
2080
  return [];
2068
2081
  }
2069
- return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord12.VoiceChannel);
2082
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord13.VoiceChannel);
2070
2083
  }
2071
2084
  static async create(guildId, name, options) {
2072
2085
  return await super._create(guildId, {
2073
2086
  name,
2074
- type: import_discord12.ChannelType.GuildVoice,
2087
+ type: import_discord13.ChannelType.GuildVoice,
2075
2088
  ...options
2076
2089
  });
2077
2090
  }
@@ -2132,7 +2145,7 @@ var InviteManager = class {
2132
2145
  */
2133
2146
  static async list(guildId) {
2134
2147
  try {
2135
- const guild = Bot.client.guilds.cache.get(guildId);
2148
+ const guild = await GuildManager.find(guildId);
2136
2149
  if (!guild) {
2137
2150
  throw new Error(`Guild ${guildId} not found`);
2138
2151
  }
@@ -2153,14 +2166,7 @@ var GuildManager = class {
2153
2166
  return Array.from(Bot.client.guilds.cache.values());
2154
2167
  }
2155
2168
  static async find(guild_id) {
2156
- try {
2157
- const cached = Bot.client.guilds.cache.get(guild_id);
2158
- if (cached) return cached;
2159
- return await Bot.client.guilds.fetch(guild_id);
2160
- } catch (error) {
2161
- Log.error(`GuildManager: Guild ${guild_id} : ${error} `);
2162
- return null;
2163
- }
2169
+ return await Bot.client.guilds.fetch(guild_id);
2164
2170
  }
2165
2171
  /**
2166
2172
  * Search channel by ID (TextChannel, DMChannel, ThreadChannel)
@@ -2199,7 +2205,7 @@ var GuildManager = class {
2199
2205
  */
2200
2206
  static async fetchAllMembers(guildId, MAX_ATTEMPTS = 3, RETRY_DELAY = Time.minute.MIN_05.toMilliseconds()) {
2201
2207
  let guild;
2202
- if (guildId instanceof import_discord13.Guild) {
2208
+ if (guildId instanceof import_discord14.Guild) {
2203
2209
  guild = guildId;
2204
2210
  } else {
2205
2211
  let tmp = Bot.client.guilds.cache.get(guildId);
@@ -2252,10 +2258,10 @@ var GuildManager = class {
2252
2258
  if (!toChannel) {
2253
2259
  throw new Error(`To channel ${toChannelId} not found`);
2254
2260
  }
2255
- if (!(fromChannel instanceof import_discord13.VoiceChannel || fromChannel instanceof import_discord13.StageChannel)) {
2261
+ if (!(fromChannel instanceof import_discord14.VoiceChannel || fromChannel instanceof import_discord14.StageChannel)) {
2256
2262
  throw new Error(`From channel ${fromChannelId} is not a voice/stage channel`);
2257
2263
  }
2258
- if (!(toChannel instanceof import_discord13.VoiceChannel || toChannel instanceof import_discord13.StageChannel)) {
2264
+ if (!(toChannel instanceof import_discord14.VoiceChannel || toChannel instanceof import_discord14.StageChannel)) {
2259
2265
  throw new Error(`To channel ${toChannelId} is not a voice/stage channel`);
2260
2266
  }
2261
2267
  if (member.voice.channelId !== fromChannelId) {
@@ -2292,62 +2298,112 @@ var UserManager = class extends BasicUserManager {
2292
2298
  };
2293
2299
 
2294
2300
  // src/manager/interactions/ModalManager.ts
2295
- var import_discord14 = require("discord.js");
2296
- var ModalManager = class _ModalManager {
2301
+ var import_discord15 = require("discord.js");
2302
+ var ModalManager = class {
2297
2303
  /**
2298
- * Load modal from JSON file and return ModalBuilder
2304
+ * Creates base Modal - SIMPLE API !
2299
2305
  */
2300
- static async load(filename) {
2301
- try {
2302
- const file = await FileManager.readJsonFile(`./handlers/${"modals" /* MODAL */}/${filename}`);
2303
- if (!file) return false;
2304
- return _ModalManager.jsonToBuilder(file);
2305
- } catch {
2306
- return false;
2307
- }
2306
+ static create(modalTitle, customId) {
2307
+ return new import_discord15.ModalBuilder().setTitle(modalTitle).setCustomId(customId);
2308
2308
  }
2309
2309
  /**
2310
- * List all modal files
2310
+ * Individual field creator
2311
2311
  */
2312
- static async list() {
2313
- try {
2314
- const files = await FileManager.listJsonFiles(`./handlers/${"modals" /* MODAL */}`);
2315
- return files || [];
2316
- } catch {
2317
- return false;
2318
- }
2312
+ static _createField(opt) {
2313
+ const builder = new import_discord15.TextInputBuilder().setCustomId(opt.customId).setRequired(opt.required ?? false);
2314
+ if (opt.placeholder) {
2315
+ builder.setPlaceholder(opt.placeholder);
2316
+ } else {
2317
+ builder.setPlaceholder(`Enter ${opt.label.toLowerCase()}`);
2318
+ }
2319
+ switch (opt.type) {
2320
+ case 0 /* SHORT */:
2321
+ builder.setStyle(import_discord15.TextInputStyle.Short).setMaxLength(4e3);
2322
+ break;
2323
+ case 1 /* LONG */:
2324
+ builder.setStyle(import_discord15.TextInputStyle.Paragraph).setMaxLength(4e3);
2325
+ break;
2326
+ case 2 /* NUMBER */:
2327
+ builder.setStyle(import_discord15.TextInputStyle.Short).setMaxLength(10);
2328
+ break;
2329
+ case 3 /* DATE */:
2330
+ builder.setStyle(import_discord15.TextInputStyle.Short).setMaxLength(10);
2331
+ break;
2332
+ case 4 /* PHONE */:
2333
+ builder.setStyle(import_discord15.TextInputStyle.Short).setMaxLength(20);
2334
+ break;
2335
+ }
2336
+ return new import_discord15.LabelBuilder().setLabel(opt.label).setTextInputComponent(builder);
2337
+ }
2338
+ /**
2339
+ * Simple modal with ONE field - DIRECT ModalBuilder return !
2340
+ */
2341
+ static simple(customId, modalTitle, field) {
2342
+ const modal = this.create(modalTitle ?? Bot.config?.botName ?? "Bot", customId);
2343
+ const opt = {
2344
+ ...field,
2345
+ customId: `${customId}_input`,
2346
+ placeholder: field.placeholder ?? `Enter ${field.label.toLowerCase()}`
2347
+ };
2348
+ modal.addLabelComponents(this._createField(opt));
2349
+ return modal;
2319
2350
  }
2320
- static jsonToBuilder(json) {
2321
- const modal = new import_discord14.ModalBuilder().setCustomId(json.customId).setTitle(json.title.slice(0, 45));
2322
- const actionRows = [];
2323
- for (const fieldJson of json.fields) {
2324
- const input = this.fieldJsonToInput(fieldJson);
2325
- const row = new import_discord14.ActionRowBuilder().addComponents(input);
2326
- actionRows.push(row);
2327
- }
2328
- return modal.addComponents(...actionRows);
2351
+ /**
2352
+ * Title + Description modal preset
2353
+ */
2354
+ static titleDescription(customId, modalTitle, title, description) {
2355
+ const modal = this.create(modalTitle, customId);
2356
+ const titleField = {
2357
+ customId: `${customId}_title`,
2358
+ label: title.label,
2359
+ placeholder: title.placeholder ?? `Enter ${title.label.toLowerCase()}`,
2360
+ type: 0 /* SHORT */,
2361
+ required: title.required
2362
+ };
2363
+ const descField = {
2364
+ customId: `${customId}_desc`,
2365
+ label: description.label,
2366
+ placeholder: description.placeholder ?? `Enter ${description.label.toLowerCase()}`,
2367
+ type: 1 /* LONG */,
2368
+ required: description.required
2369
+ };
2370
+ modal.addLabelComponents(this._createField(titleField));
2371
+ modal.addLabelComponents(this._createField(descField));
2372
+ return modal;
2329
2373
  }
2330
- static fieldJsonToInput(fieldJson) {
2331
- const input = new import_discord14.TextInputBuilder().setCustomId(fieldJson.customId).setLabel(fieldJson.title.slice(0, 45)).setPlaceholder(fieldJson.placeholder || "Enter value...").setRequired(fieldJson.required !== false).setMinLength(fieldJson.minLength || 0).setMaxLength(fieldJson.maxLength || 400);
2332
- const style = fieldJson.style;
2333
- if (typeof style === "number") {
2334
- input.setStyle(style);
2335
- } else {
2336
- switch (style) {
2337
- case "Number":
2338
- case "Phone":
2339
- case "Date":
2340
- input.setStyle(import_discord14.TextInputStyle.Short);
2341
- input.setPlaceholder(
2342
- style === "Number" ? "123" : style === "Phone" ? "+33 6 12 34 56 78" : "2024-02-05"
2343
- );
2344
- break;
2345
- default:
2346
- input.setStyle(import_discord14.TextInputStyle.Short);
2374
+ /**
2375
+ * Date modal preset
2376
+ */
2377
+ static date(customId, modalTitle = "Select Date", inputLabel = "Date") {
2378
+ return this.simple(`${customId}_date`, modalTitle, { label: inputLabel, type: 3 /* DATE */, placeholder: "YYYY-MM-DD or DD/MM/YYYY" });
2379
+ }
2380
+ /**
2381
+ * Number modal preset
2382
+ */
2383
+ static number(customId, modalTitle = "Enter a Number", inputLabel = "Number") {
2384
+ return this.simple(`${customId}_number`, modalTitle, { label: inputLabel, type: 2 /* NUMBER */, placeholder: "Enter a number" });
2385
+ }
2386
+ /**
2387
+ * Number modal preset
2388
+ */
2389
+ static phone(customId, modalTitle = "Enter a Phone number", inputLabel = "Phone number") {
2390
+ return this.simple(`${customId}_phone_number`, modalTitle, { label: inputLabel, type: 4 /* PHONE */, placeholder: "Enter a phone number" });
2391
+ }
2392
+ static add(modal, field) {
2393
+ if (Array.isArray(field)) {
2394
+ for (const f of field) {
2395
+ this.add(modal, f);
2347
2396
  }
2397
+ return modal;
2348
2398
  }
2349
- return input;
2399
+ const opt = {
2400
+ ...field,
2401
+ customId: `${modal.data.custom_id}_${field.label}`
2402
+ };
2403
+ modal.addLabelComponents(this._createField(opt));
2404
+ return modal;
2350
2405
  }
2406
+ // Keep your existing parse methods
2351
2407
  static parseNumber(value) {
2352
2408
  if (!/^\d+$/.test(value)) return null;
2353
2409
  const num = parseInt(value);
@@ -2376,16 +2432,22 @@ var ModalManager = class _ModalManager {
2376
2432
  }
2377
2433
  return null;
2378
2434
  }
2435
+ /**
2436
+ * Transform modal to interaction.showModal() format
2437
+ */
2438
+ static toInteraction(modal) {
2439
+ return modal;
2440
+ }
2379
2441
  };
2380
2442
 
2381
2443
  // src/manager/interactions/SelectMenuManager.ts
2382
- var import_discord15 = require("discord.js");
2444
+ var import_discord16 = require("discord.js");
2383
2445
  var SelectMenuManager = class {
2384
2446
  /**
2385
2447
  * Creates base StringSelectMenu - SIMPLE API !
2386
2448
  */
2387
2449
  static create(customId, placeholder = "Select an option...") {
2388
- return new import_discord15.StringSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(1);
2450
+ return new import_discord16.StringSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(1);
2389
2451
  }
2390
2452
  /**
2391
2453
  * Quick StringSelectMenu
@@ -2403,10 +2465,10 @@ var SelectMenuManager = class {
2403
2465
  * Pagination menu
2404
2466
  */
2405
2467
  static paginated(customId, options, pageSize = 25) {
2406
- const row = new import_discord15.ActionRowBuilder();
2468
+ const row = new import_discord16.ActionRowBuilder();
2407
2469
  for (let i = 0; i < options.length; i += pageSize) {
2408
2470
  const pageOptions = options.slice(i, i + pageSize);
2409
- const menu = new import_discord15.StringSelectMenuBuilder().setCustomId(`${customId}_page_${Math.floor(i / pageSize)}`).setPlaceholder(`Page ${Math.floor(i / pageSize) + 1}`).addOptions(pageOptions.map((opt) => {
2471
+ const menu = new import_discord16.StringSelectMenuBuilder().setCustomId(`${customId}_page_${Math.floor(i / pageSize)}`).setPlaceholder(`Page ${Math.floor(i / pageSize) + 1}`).addOptions(pageOptions.map((opt) => {
2410
2472
  return this.option(opt);
2411
2473
  }));
2412
2474
  row.addComponents(menu);
@@ -2417,25 +2479,25 @@ var SelectMenuManager = class {
2417
2479
  * User Select Menu (Components V2)
2418
2480
  */
2419
2481
  static users(customId, placeholder = "Select users...") {
2420
- return new import_discord15.UserSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2482
+ return new import_discord16.UserSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2421
2483
  }
2422
2484
  /**
2423
2485
  * Role Select Menu (Components V2)
2424
2486
  */
2425
2487
  static roles(customId, placeholder = "Select roles...") {
2426
- return new import_discord15.RoleSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2488
+ return new import_discord16.RoleSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2427
2489
  }
2428
2490
  /**
2429
2491
  * Mentionable Select Menu (Components V2)
2430
2492
  */
2431
2493
  static mentionables(customId, placeholder = "Select users/roles...") {
2432
- return new import_discord15.MentionableSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2494
+ return new import_discord16.MentionableSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2433
2495
  }
2434
2496
  /**
2435
2497
  * Channel Select Menu (Components V2)
2436
2498
  */
2437
2499
  static channels(customId, placeholder = "Select channels...", channelTypes = []) {
2438
- return new import_discord15.ChannelSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25).setChannelTypes(...channelTypes);
2500
+ return new import_discord16.ChannelSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25).setChannelTypes(...channelTypes);
2439
2501
  }
2440
2502
  static option(option) {
2441
2503
  if (Array.isArray(option)) {
@@ -2444,7 +2506,7 @@ var SelectMenuManager = class {
2444
2506
  return this._createOption(option);
2445
2507
  }
2446
2508
  static _createOption(option) {
2447
- const builder = new import_discord15.StringSelectMenuOptionBuilder().setLabel(option.label).setValue(option.value);
2509
+ const builder = new import_discord16.StringSelectMenuOptionBuilder().setLabel(option.label).setValue(option.value);
2448
2510
  option.description && builder.setDescription(option.description);
2449
2511
  option.emoji && builder.setEmoji(option.emoji);
2450
2512
  return builder;
@@ -2465,7 +2527,7 @@ var SelectMenuManager = class {
2465
2527
  * ActionRow
2466
2528
  */
2467
2529
  static row(component) {
2468
- return new import_discord15.ActionRowBuilder().addComponents(component);
2530
+ return new import_discord16.ActionRowBuilder().addComponents(component);
2469
2531
  }
2470
2532
  /**
2471
2533
  * Rows multiples (5 max)
@@ -2518,7 +2580,7 @@ var SimpleMutex = class {
2518
2580
  // package.json
2519
2581
  var package_default = {
2520
2582
  name: "@spatulox/simplediscordbot",
2521
- version: "1.0.42",
2583
+ version: "1.1.1",
2522
2584
  author: "Spatulox",
2523
2585
  description: "Simple discord bot framework to set up a bot under 30 secondes",
2524
2586
  exports: {
package/dist/index.mjs CHANGED
@@ -1520,7 +1520,11 @@ var ReactionManager = class {
1520
1520
  };
1521
1521
 
1522
1522
  // src/manager/guild/GuildManager.ts
1523
- import { Guild as Guild2, StageChannel as StageChannel2, VoiceChannel as VoiceChannel2 } from "discord.js";
1523
+ import {
1524
+ Guild as Guild3,
1525
+ VoiceChannel as VoiceChannel2,
1526
+ StageChannel as StageChannel2
1527
+ } from "discord.js";
1524
1528
 
1525
1529
  // src/manager/direct/BasicUserManager.ts
1526
1530
  import { GuildMember as GuildMember2 } from "discord.js";
@@ -1595,9 +1599,22 @@ var BasicUserManager = class {
1595
1599
  };
1596
1600
 
1597
1601
  // src/manager/guild/GuildUserManager.ts
1602
+ import { Guild as Guild2 } from "discord.js";
1598
1603
  import { setTimeout as setTimeout2 } from "timers/promises";
1599
1604
  var MAX_NICKNAME_LENGTH = 32;
1600
1605
  var GuildUserManager = class extends BasicUserManager {
1606
+ static async find(userId, guild) {
1607
+ try {
1608
+ if (guild instanceof Guild2) {
1609
+ return await guild.members.fetch(userId);
1610
+ } else {
1611
+ return await (await GuildManager.find(guild)).members.fetch(userId);
1612
+ }
1613
+ } catch (error) {
1614
+ Log.error(`UserManager: Member ${userId} not found`);
1615
+ return null;
1616
+ }
1617
+ }
1601
1618
  static async rename(member, nickname, maxAttempts = 3) {
1602
1619
  if (nickname.length > MAX_NICKNAME_LENGTH) {
1603
1620
  nickname = nickname.slice(0, MAX_NICKNAME_LENGTH);
@@ -2093,7 +2110,7 @@ var InviteManager = class {
2093
2110
  */
2094
2111
  static async list(guildId) {
2095
2112
  try {
2096
- const guild = Bot.client.guilds.cache.get(guildId);
2113
+ const guild = await GuildManager.find(guildId);
2097
2114
  if (!guild) {
2098
2115
  throw new Error(`Guild ${guildId} not found`);
2099
2116
  }
@@ -2114,14 +2131,7 @@ var GuildManager = class {
2114
2131
  return Array.from(Bot.client.guilds.cache.values());
2115
2132
  }
2116
2133
  static async find(guild_id) {
2117
- try {
2118
- const cached = Bot.client.guilds.cache.get(guild_id);
2119
- if (cached) return cached;
2120
- return await Bot.client.guilds.fetch(guild_id);
2121
- } catch (error) {
2122
- Log.error(`GuildManager: Guild ${guild_id} : ${error} `);
2123
- return null;
2124
- }
2134
+ return await Bot.client.guilds.fetch(guild_id);
2125
2135
  }
2126
2136
  /**
2127
2137
  * Search channel by ID (TextChannel, DMChannel, ThreadChannel)
@@ -2160,7 +2170,7 @@ var GuildManager = class {
2160
2170
  */
2161
2171
  static async fetchAllMembers(guildId, MAX_ATTEMPTS = 3, RETRY_DELAY = Time.minute.MIN_05.toMilliseconds()) {
2162
2172
  let guild;
2163
- if (guildId instanceof Guild2) {
2173
+ if (guildId instanceof Guild3) {
2164
2174
  guild = guildId;
2165
2175
  } else {
2166
2176
  let tmp = Bot.client.guilds.cache.get(guildId);
@@ -2254,66 +2264,116 @@ var UserManager = class extends BasicUserManager {
2254
2264
 
2255
2265
  // src/manager/interactions/ModalManager.ts
2256
2266
  import {
2257
- ActionRowBuilder as ActionRowBuilder3,
2258
2267
  ModalBuilder,
2259
2268
  TextInputBuilder,
2260
- TextInputStyle
2269
+ TextInputStyle,
2270
+ LabelBuilder
2261
2271
  } from "discord.js";
2262
- var ModalManager = class _ModalManager {
2272
+ var ModalManager = class {
2263
2273
  /**
2264
- * Load modal from JSON file and return ModalBuilder
2274
+ * Creates base Modal - SIMPLE API !
2265
2275
  */
2266
- static async load(filename) {
2267
- try {
2268
- const file = await FileManager.readJsonFile(`./handlers/${"modals" /* MODAL */}/${filename}`);
2269
- if (!file) return false;
2270
- return _ModalManager.jsonToBuilder(file);
2271
- } catch {
2272
- return false;
2273
- }
2276
+ static create(modalTitle, customId) {
2277
+ return new ModalBuilder().setTitle(modalTitle).setCustomId(customId);
2274
2278
  }
2275
2279
  /**
2276
- * List all modal files
2280
+ * Individual field creator
2277
2281
  */
2278
- static async list() {
2279
- try {
2280
- const files = await FileManager.listJsonFiles(`./handlers/${"modals" /* MODAL */}`);
2281
- return files || [];
2282
- } catch {
2283
- return false;
2284
- }
2282
+ static _createField(opt) {
2283
+ const builder = new TextInputBuilder().setCustomId(opt.customId).setRequired(opt.required ?? false);
2284
+ if (opt.placeholder) {
2285
+ builder.setPlaceholder(opt.placeholder);
2286
+ } else {
2287
+ builder.setPlaceholder(`Enter ${opt.label.toLowerCase()}`);
2288
+ }
2289
+ switch (opt.type) {
2290
+ case 0 /* SHORT */:
2291
+ builder.setStyle(TextInputStyle.Short).setMaxLength(4e3);
2292
+ break;
2293
+ case 1 /* LONG */:
2294
+ builder.setStyle(TextInputStyle.Paragraph).setMaxLength(4e3);
2295
+ break;
2296
+ case 2 /* NUMBER */:
2297
+ builder.setStyle(TextInputStyle.Short).setMaxLength(10);
2298
+ break;
2299
+ case 3 /* DATE */:
2300
+ builder.setStyle(TextInputStyle.Short).setMaxLength(10);
2301
+ break;
2302
+ case 4 /* PHONE */:
2303
+ builder.setStyle(TextInputStyle.Short).setMaxLength(20);
2304
+ break;
2305
+ }
2306
+ return new LabelBuilder().setLabel(opt.label).setTextInputComponent(builder);
2307
+ }
2308
+ /**
2309
+ * Simple modal with ONE field - DIRECT ModalBuilder return !
2310
+ */
2311
+ static simple(customId, modalTitle, field) {
2312
+ const modal = this.create(modalTitle ?? Bot.config?.botName ?? "Bot", customId);
2313
+ const opt = {
2314
+ ...field,
2315
+ customId: `${customId}_input`,
2316
+ placeholder: field.placeholder ?? `Enter ${field.label.toLowerCase()}`
2317
+ };
2318
+ modal.addLabelComponents(this._createField(opt));
2319
+ return modal;
2285
2320
  }
2286
- static jsonToBuilder(json) {
2287
- const modal = new ModalBuilder().setCustomId(json.customId).setTitle(json.title.slice(0, 45));
2288
- const actionRows = [];
2289
- for (const fieldJson of json.fields) {
2290
- const input = this.fieldJsonToInput(fieldJson);
2291
- const row = new ActionRowBuilder3().addComponents(input);
2292
- actionRows.push(row);
2293
- }
2294
- return modal.addComponents(...actionRows);
2321
+ /**
2322
+ * Title + Description modal preset
2323
+ */
2324
+ static titleDescription(customId, modalTitle, title, description) {
2325
+ const modal = this.create(modalTitle, customId);
2326
+ const titleField = {
2327
+ customId: `${customId}_title`,
2328
+ label: title.label,
2329
+ placeholder: title.placeholder ?? `Enter ${title.label.toLowerCase()}`,
2330
+ type: 0 /* SHORT */,
2331
+ required: title.required
2332
+ };
2333
+ const descField = {
2334
+ customId: `${customId}_desc`,
2335
+ label: description.label,
2336
+ placeholder: description.placeholder ?? `Enter ${description.label.toLowerCase()}`,
2337
+ type: 1 /* LONG */,
2338
+ required: description.required
2339
+ };
2340
+ modal.addLabelComponents(this._createField(titleField));
2341
+ modal.addLabelComponents(this._createField(descField));
2342
+ return modal;
2295
2343
  }
2296
- static fieldJsonToInput(fieldJson) {
2297
- const input = new TextInputBuilder().setCustomId(fieldJson.customId).setLabel(fieldJson.title.slice(0, 45)).setPlaceholder(fieldJson.placeholder || "Enter value...").setRequired(fieldJson.required !== false).setMinLength(fieldJson.minLength || 0).setMaxLength(fieldJson.maxLength || 400);
2298
- const style = fieldJson.style;
2299
- if (typeof style === "number") {
2300
- input.setStyle(style);
2301
- } else {
2302
- switch (style) {
2303
- case "Number":
2304
- case "Phone":
2305
- case "Date":
2306
- input.setStyle(TextInputStyle.Short);
2307
- input.setPlaceholder(
2308
- style === "Number" ? "123" : style === "Phone" ? "+33 6 12 34 56 78" : "2024-02-05"
2309
- );
2310
- break;
2311
- default:
2312
- input.setStyle(TextInputStyle.Short);
2344
+ /**
2345
+ * Date modal preset
2346
+ */
2347
+ static date(customId, modalTitle = "Select Date", inputLabel = "Date") {
2348
+ return this.simple(`${customId}_date`, modalTitle, { label: inputLabel, type: 3 /* DATE */, placeholder: "YYYY-MM-DD or DD/MM/YYYY" });
2349
+ }
2350
+ /**
2351
+ * Number modal preset
2352
+ */
2353
+ static number(customId, modalTitle = "Enter a Number", inputLabel = "Number") {
2354
+ return this.simple(`${customId}_number`, modalTitle, { label: inputLabel, type: 2 /* NUMBER */, placeholder: "Enter a number" });
2355
+ }
2356
+ /**
2357
+ * Number modal preset
2358
+ */
2359
+ static phone(customId, modalTitle = "Enter a Phone number", inputLabel = "Phone number") {
2360
+ return this.simple(`${customId}_phone_number`, modalTitle, { label: inputLabel, type: 4 /* PHONE */, placeholder: "Enter a phone number" });
2361
+ }
2362
+ static add(modal, field) {
2363
+ if (Array.isArray(field)) {
2364
+ for (const f of field) {
2365
+ this.add(modal, f);
2313
2366
  }
2367
+ return modal;
2314
2368
  }
2315
- return input;
2369
+ const opt = {
2370
+ ...field,
2371
+ customId: `${modal.data.custom_id}_${field.label}`
2372
+ };
2373
+ modal.addLabelComponents(this._createField(opt));
2374
+ return modal;
2316
2375
  }
2376
+ // Keep your existing parse methods
2317
2377
  static parseNumber(value) {
2318
2378
  if (!/^\d+$/.test(value)) return null;
2319
2379
  const num = parseInt(value);
@@ -2342,11 +2402,17 @@ var ModalManager = class _ModalManager {
2342
2402
  }
2343
2403
  return null;
2344
2404
  }
2405
+ /**
2406
+ * Transform modal to interaction.showModal() format
2407
+ */
2408
+ static toInteraction(modal) {
2409
+ return modal;
2410
+ }
2345
2411
  };
2346
2412
 
2347
2413
  // src/manager/interactions/SelectMenuManager.ts
2348
2414
  import {
2349
- ActionRowBuilder as ActionRowBuilder4,
2415
+ ActionRowBuilder as ActionRowBuilder3,
2350
2416
  StringSelectMenuBuilder,
2351
2417
  StringSelectMenuOptionBuilder,
2352
2418
  UserSelectMenuBuilder,
@@ -2377,7 +2443,7 @@ var SelectMenuManager = class {
2377
2443
  * Pagination menu
2378
2444
  */
2379
2445
  static paginated(customId, options, pageSize = 25) {
2380
- const row = new ActionRowBuilder4();
2446
+ const row = new ActionRowBuilder3();
2381
2447
  for (let i = 0; i < options.length; i += pageSize) {
2382
2448
  const pageOptions = options.slice(i, i + pageSize);
2383
2449
  const menu = new StringSelectMenuBuilder().setCustomId(`${customId}_page_${Math.floor(i / pageSize)}`).setPlaceholder(`Page ${Math.floor(i / pageSize) + 1}`).addOptions(pageOptions.map((opt) => {
@@ -2439,7 +2505,7 @@ var SelectMenuManager = class {
2439
2505
  * ActionRow
2440
2506
  */
2441
2507
  static row(component) {
2442
- return new ActionRowBuilder4().addComponents(component);
2508
+ return new ActionRowBuilder3().addComponents(component);
2443
2509
  }
2444
2510
  /**
2445
2511
  * Rows multiples (5 max)
@@ -2492,7 +2558,7 @@ var SimpleMutex = class {
2492
2558
  // package.json
2493
2559
  var package_default = {
2494
2560
  name: "@spatulox/simplediscordbot",
2495
- version: "1.0.42",
2561
+ version: "1.1.1",
2496
2562
  author: "Spatulox",
2497
2563
  description: "Simple discord bot framework to set up a bot under 30 secondes",
2498
2564
  exports: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spatulox/simplediscordbot",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "author": "Spatulox",
5
5
  "description": "Simple discord bot framework to set up a bot under 30 secondes",
6
6
  "exports": {