discord-bot-shared 0.14.3 → 0.14.5

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/README.md CHANGED
@@ -4,6 +4,8 @@ A small package that makes creating [discord.js](https://github.com/discordjs/di
4
4
 
5
5
  ---
6
6
 
7
+ <!-- toc -->
8
+
7
9
  - [Installation](#installation)
8
10
  - [Quick Start](#quick-start)
9
11
  - [Creating a `Bot` instance](#creating-a-bot-instance)
@@ -21,6 +23,8 @@ A small package that makes creating [discord.js](https://github.com/discordjs/di
21
23
  - [Utilities](#utilities)
22
24
  - [getChannel](#getchannel)
23
25
 
26
+ <!-- tocstop -->
27
+
24
28
  ## Installation
25
29
 
26
30
  ```sh
package/dist/bot.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { BotOptions } from "./types.js";
2
+ import { CommandManager } from "./command-manager.js";
3
+ import { EventManager } from "./event-manager.js";
4
+
5
+ //#region src/bot.d.ts
6
+ declare class Bot {
7
+ #private;
8
+ readonly commands: CommandManager;
9
+ readonly events: EventManager;
10
+ constructor(options: BotOptions);
11
+ login(): Promise<void>;
12
+ }
13
+ //#endregion
14
+ export { Bot };
15
+ //# sourceMappingURL=bot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot.d.ts","names":[],"sources":["../src/bot.ts"],"sourcesContent":[],"mappings":";;;;;cAMa,GAAA;;EAAA,SAAG,QAAA,EAGY,cAHZ;EAGY,SAAA,MAAA,EACF,YADE;EACF,WAAA,CAAA,OAAA,EAEI,UAFJ;EAEI,KAAA,CAAA,CAAA,EAYN,OAZM,CAAA,IAAA,CAAA"}
package/dist/bot.js CHANGED
@@ -1,27 +1,29 @@
1
- import { Client, Events, REST } from "discord.js";
2
1
  import { CommandManager } from "./command-manager.js";
3
2
  import { EventManager } from "./event-manager.js";
4
- export class Bot {
5
- #discord;
6
- commands;
7
- events;
8
- constructor(options) {
9
- this.#discord = {
10
- applicationId: options.applicationId,
11
- token: options.token,
12
- client: new Client(options.clientOptions),
13
- rest: new REST().setToken(options.token),
14
- };
15
- this.commands = new CommandManager(this.#discord);
16
- this.events = new EventManager(this.#discord);
17
- }
18
- async login() {
19
- this.#discord.client.once(Events.ClientReady, () => {
20
- console.log("Client is ready.");
21
- });
22
- this.commands._listen();
23
- this.events._listen();
24
- await this.#discord.client.login(this.#discord.token);
25
- }
26
- }
3
+ import { Client, Events, REST } from "discord.js";
4
+ var Bot = class {
5
+ #discord;
6
+ commands;
7
+ events;
8
+ constructor(options) {
9
+ this.#discord = {
10
+ applicationId: options.applicationId,
11
+ token: options.token,
12
+ client: new Client(options.clientOptions),
13
+ rest: new REST().setToken(options.token)
14
+ };
15
+ this.commands = new CommandManager(this.#discord);
16
+ this.events = new EventManager(this.#discord);
17
+ }
18
+ async login() {
19
+ this.#discord.client.once(Events.ClientReady, () => {
20
+ console.log("Client is ready.");
21
+ });
22
+ this.commands._listen();
23
+ this.events._listen();
24
+ await this.#discord.client.login(this.#discord.token);
25
+ }
26
+ };
27
+ export { Bot };
28
+
27
29
  //# sourceMappingURL=bot.js.map
package/dist/bot.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bot.js","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAejD,MAAM,OAAO,GAAG;IACL,QAAQ,CAAgB;IAEjB,QAAQ,CAAgB;IACxB,MAAM,CAAc;IAEpC,YAAmB,OAAmB;QACpC,IAAI,CAAC,QAAQ,GAAG;YACd,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;YACzC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;SACzC,CAAA;QAED,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACjD,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC/C,CAAC;IAEM,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,EAAE;YACjD,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;QACjC,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAA;QACvB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;QACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACvD,CAAC;CACF"}
1
+ {"version":3,"file":"bot.js","names":["#discord"],"sources":["../src/bot.ts"],"sourcesContent":["import { Client, Events, REST } from \"discord.js\"\n\nimport { CommandManager } from \"~/command-manager.ts\"\nimport { EventManager } from \"~/event-manager.ts\"\nimport type { BotOptions, DiscordContext } from \"~/types.ts\"\n\nexport class Bot {\n readonly #discord: DiscordContext\n\n public readonly commands: CommandManager\n public readonly events: EventManager\n\n public constructor(options: BotOptions) {\n this.#discord = {\n applicationId: options.applicationId,\n token: options.token,\n client: new Client(options.clientOptions),\n rest: new REST().setToken(options.token),\n }\n\n this.commands = new CommandManager(this.#discord)\n this.events = new EventManager(this.#discord)\n }\n\n public async login(): Promise<void> {\n this.#discord.client.once(Events.ClientReady, () => {\n console.log(\"Client is ready.\")\n })\n\n this.commands._listen()\n this.events._listen()\n await this.#discord.client.login(this.#discord.token)\n }\n}\n"],"mappings":";;;AAMA,IAAa,MAAb,MAAiB;CACf;CAEA;CACA;CAEA,YAAmB,SAAqB;AACtC,QAAA,UAAgB;GACd,eAAe,QAAQ;GACvB,OAAO,QAAQ;GACf,QAAQ,IAAI,OAAO,QAAQ,cAAc;GACzC,MAAM,IAAI,MAAM,CAAC,SAAS,QAAQ,MAAM;GACzC;AAED,OAAK,WAAW,IAAI,eAAe,MAAA,QAAc;AACjD,OAAK,SAAS,IAAI,aAAa,MAAA,QAAc;;CAG/C,MAAa,QAAuB;AAClC,QAAA,QAAc,OAAO,KAAK,OAAO,mBAAmB;AAClD,WAAQ,IAAI,mBAAmB;IAC/B;AAEF,OAAK,SAAS,SAAS;AACvB,OAAK,OAAO,SAAS;AACrB,QAAM,MAAA,QAAc,OAAO,MAAM,MAAA,QAAc,MAAM"}
@@ -0,0 +1,26 @@
1
+ import { DiscordContext } from "./types.js";
2
+ import { ChatInputCommandInteraction, RESTPostAPIChatInputApplicationCommandsJSONBody } from "discord.js";
3
+
4
+ //#region src/command-manager.d.ts
5
+ interface Command {
6
+ requiredRoles?: string[];
7
+ command: RESTPostAPIChatInputApplicationCommandsJSONBody;
8
+ run: (interaction: ChatInputCommandInteraction<"cached">) => void | Promise<void>;
9
+ }
10
+ type CommandHook = (interaction: ChatInputCommandInteraction<"cached">) => boolean | Promise<boolean>;
11
+ declare class CommandManager {
12
+ #private;
13
+ constructor(discord: DiscordContext);
14
+ add(command: Command): void;
15
+ setGlobalCommandHook(commandHook: CommandHook): void;
16
+ register(): Promise<void>;
17
+ unregisterGuildCommands(): Promise<void>;
18
+ private _unregisterGuildCommands;
19
+ unregisterApplicationCommands(): Promise<void>;
20
+ _listen(): void;
21
+ private static checkRoles;
22
+ private static interactionReply;
23
+ }
24
+ //#endregion
25
+ export { Command, CommandHook, CommandManager };
26
+ //# sourceMappingURL=command-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-manager.d.ts","names":[],"sources":["../src/command-manager.ts"],"sourcesContent":[],"mappings":";;;;UAYiB,OAAA;;EAAA,OAAA,EAEN,+CAFa;EAEb,GAAA,EAAA,CAAA,WAAA,EACU,2BADV,CAAA,QAAA,CAAA,EAAA,GAAA,IAAA,GAC2D,OAD3D,CAAA,IAAA,CAAA;;AAC2D,KAG1D,WAAA,GAH0D,CAAA,WAAA,EAG9B,2BAH8B,CAAA,QAAA,CAAA,EAAA,GAAA,OAAA,GAGsB,OAHtB,CAAA,OAAA,CAAA;AAAO,cAKhE,cAAA,CALgE;EAGjE,CAAA,OAAA;EAEC,WAAA,CAAA,OAAc,EAKG,cALH;EAKG,GAAA,CAAA,OAAA,EAOR,OAPQ,CAAA,EAAA,IAAA;EAOR,oBAAA,CAAA,WAAA,EAIqB,WAJrB,CAAA,EAAA,IAAA;EAIqB,QAAA,CAAA,CAAA,EAIhB,OAJgB,CAAA,IAAA,CAAA;EAIhB,uBAAA,CAAA,CAAA,EAQe,OARf,CAAA,IAAA,CAAA;EAQe,QAAA,wBAAA;EA2BM,6BAAA,CAAA,CAAA,EAAA,OAAA,CAAA,IAAA,CAAA;EAAO,OAAA,CAAA,CAAA,EAAA,IAAA"}
@@ -1,119 +1,104 @@
1
+ import { UserError, throwUserError } from "./util.js";
1
2
  import { Collection, Events, MessageFlags, Routes } from "discord.js";
2
- import { throwUserError, UserError } from "./util.js";
3
- export class CommandManager {
4
- #commands = new Collection();
5
- #globalCommandHook;
6
- #discord;
7
- constructor(discord) {
8
- this.#discord = discord;
9
- }
10
- /*
11
- * Add a command
12
- */
13
- add(command) {
14
- this.#commands.set(command.command.name, command);
15
- }
16
- setGlobalCommandHook(commandHook) {
17
- this.#globalCommandHook = commandHook;
18
- }
19
- async register() {
20
- const payload = this.#commands.map((c) => c.command);
21
- const route = Routes.applicationCommands(this.#discord.applicationId);
22
- await this.#discord.rest.put(route, { body: payload });
23
- console.log(`Registered ${this.#commands.size.toString()} (/) commands.`);
24
- }
25
- async unregisterGuildCommands() {
26
- if (this.#discord.client.readyAt)
27
- await this._unregisterGuildCommands();
28
- else
29
- this.#discord.client.once(Events.ClientReady, () => void this._unregisterGuildCommands());
30
- }
31
- async _unregisterGuildCommands() {
32
- let guilds;
33
- try {
34
- guilds = await this.#discord.client.guilds.fetch();
35
- }
36
- catch (error) {
37
- console.error("Unable to unregister guild commands. Failed to fetch guilds.");
38
- throw error;
39
- }
40
- const unregisterPromises = [];
41
- for (const guild of guilds.values()) {
42
- const route = Routes.applicationGuildCommands(this.#discord.applicationId, guild.id);
43
- const unregisterGuildCommands = async () => {
44
- await this.#discord.rest.put(route, { body: [] });
45
- console.log(`Unregistered commands from guild: ${guild.name}`);
46
- };
47
- unregisterPromises.push(unregisterGuildCommands());
48
- }
49
- await Promise.all(unregisterPromises);
50
- }
51
- async unregisterApplicationCommands() {
52
- const route = Routes.applicationCommands(this.#discord.applicationId);
53
- await this.#discord.rest.put(route, { body: [] });
54
- console.log("Unregistered application commands.");
55
- }
56
- _listen() {
57
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: ignore
58
- const listen = async (interaction) => {
59
- if (!interaction.isChatInputCommand())
60
- return;
61
- if (!interaction.guildId)
62
- return;
63
- if (!interaction.inCachedGuild())
64
- await interaction.client.guilds.fetch(interaction.guildId).catch(console.error);
65
- if (!interaction.inCachedGuild()) {
66
- CommandManager.interactionReply(interaction, "Guild is not cached. Try again.");
67
- return;
68
- }
69
- const command = this.#commands.get(interaction.commandName);
70
- if (!command) {
71
- CommandManager.interactionReply(interaction, `Failed to get command with name: ${interaction.commandName}`);
72
- return;
73
- }
74
- if (!(await CommandManager.checkRoles(command, interaction))) {
75
- CommandManager.interactionReply(interaction, "You do not have one of the required roles to run this command.");
76
- return;
77
- }
78
- try {
79
- const shouldContinue = this.#globalCommandHook ? await this.#globalCommandHook(interaction) : true;
80
- if (!shouldContinue)
81
- throwUserError("The global command hook returned false.");
82
- await command.run(interaction);
83
- }
84
- catch (error) {
85
- CommandManager.interactionReply(interaction, error);
86
- }
87
- };
88
- this.#discord.client.on(Events.InteractionCreate, (interaction) => void listen(interaction));
89
- console.log("Listening for commands.");
90
- }
91
- static async checkRoles(command, interaction) {
92
- if (!command.requiredRoles)
93
- return true;
94
- if (command.requiredRoles.length > 0) {
95
- const member = await interaction.guild.members.fetch(interaction.user).catch(console.error);
96
- if (!member)
97
- return false;
98
- return member.roles.cache.some((role) => command.requiredRoles ? command.requiredRoles.includes(role.name) : false);
99
- }
100
- return false;
101
- }
102
- static interactionReply(interaction, error) {
103
- let errorMessage;
104
- if (error instanceof UserError)
105
- errorMessage = error.message;
106
- else if (error instanceof Error && error.stack)
107
- errorMessage = error.stack;
108
- else
109
- errorMessage = String(error);
110
- const message = `There was an error while running this command.\n\`\`\`${errorMessage}\`\`\``;
111
- const handleInteractionReply = async () => {
112
- await (interaction.deferred
113
- ? interaction.editReply(message).catch(console.error)
114
- : interaction.reply({ content: message, flags: MessageFlags.Ephemeral }).catch(console.error));
115
- };
116
- void handleInteractionReply();
117
- }
118
- }
3
+ var CommandManager = class CommandManager {
4
+ #commands = new Collection();
5
+ #globalCommandHook;
6
+ #discord;
7
+ constructor(discord) {
8
+ this.#discord = discord;
9
+ }
10
+ add(command) {
11
+ this.#commands.set(command.command.name, command);
12
+ }
13
+ setGlobalCommandHook(commandHook) {
14
+ this.#globalCommandHook = commandHook;
15
+ }
16
+ async register() {
17
+ const payload = this.#commands.map((c) => c.command);
18
+ const route = Routes.applicationCommands(this.#discord.applicationId);
19
+ await this.#discord.rest.put(route, { body: payload });
20
+ console.log(`Registered ${this.#commands.size.toString()} (/) commands.`);
21
+ }
22
+ async unregisterGuildCommands() {
23
+ if (this.#discord.client.readyAt) await this._unregisterGuildCommands();
24
+ else this.#discord.client.once(Events.ClientReady, () => void this._unregisterGuildCommands());
25
+ }
26
+ async _unregisterGuildCommands() {
27
+ let guilds;
28
+ try {
29
+ guilds = await this.#discord.client.guilds.fetch();
30
+ } catch (error) {
31
+ console.error("Unable to unregister guild commands. Failed to fetch guilds.");
32
+ throw error;
33
+ }
34
+ const unregisterPromises = [];
35
+ for (const guild of guilds.values()) {
36
+ const route = Routes.applicationGuildCommands(this.#discord.applicationId, guild.id);
37
+ const unregisterGuildCommands = async () => {
38
+ await this.#discord.rest.put(route, { body: [] });
39
+ console.log(`Unregistered commands from guild: ${guild.name}`);
40
+ };
41
+ unregisterPromises.push(unregisterGuildCommands());
42
+ }
43
+ await Promise.all(unregisterPromises);
44
+ }
45
+ async unregisterApplicationCommands() {
46
+ const route = Routes.applicationCommands(this.#discord.applicationId);
47
+ await this.#discord.rest.put(route, { body: [] });
48
+ console.log("Unregistered application commands.");
49
+ }
50
+ _listen() {
51
+ const listen = async (interaction) => {
52
+ if (!interaction.isChatInputCommand()) return;
53
+ if (!interaction.guildId) return;
54
+ if (!interaction.inCachedGuild()) await interaction.client.guilds.fetch(interaction.guildId).catch(console.error);
55
+ if (!interaction.inCachedGuild()) {
56
+ CommandManager.interactionReply(interaction, "Guild is not cached. Try again.");
57
+ return;
58
+ }
59
+ const command = this.#commands.get(interaction.commandName);
60
+ if (!command) {
61
+ CommandManager.interactionReply(interaction, `Failed to get command with name: ${interaction.commandName}`);
62
+ return;
63
+ }
64
+ if (!await CommandManager.checkRoles(command, interaction)) {
65
+ CommandManager.interactionReply(interaction, "You do not have one of the required roles to run this command.");
66
+ return;
67
+ }
68
+ try {
69
+ if (!(this.#globalCommandHook ? await this.#globalCommandHook(interaction) : true)) throwUserError("The global command hook returned false.");
70
+ await command.run(interaction);
71
+ } catch (error) {
72
+ CommandManager.interactionReply(interaction, error);
73
+ }
74
+ };
75
+ this.#discord.client.on(Events.InteractionCreate, (interaction) => void listen(interaction));
76
+ console.log("Listening for commands.");
77
+ }
78
+ static async checkRoles(command, interaction) {
79
+ if (!command.requiredRoles) return true;
80
+ if (command.requiredRoles.length > 0) {
81
+ const member = await interaction.guild.members.fetch(interaction.user).catch(console.error);
82
+ if (!member) return false;
83
+ return member.roles.cache.some((role) => command.requiredRoles ? command.requiredRoles.includes(role.name) : false);
84
+ }
85
+ return false;
86
+ }
87
+ static interactionReply(interaction, error) {
88
+ let errorMessage;
89
+ if (error instanceof UserError) errorMessage = error.message;
90
+ else if (error instanceof Error && error.stack) errorMessage = error.stack;
91
+ else errorMessage = String(error);
92
+ const message = `There was an error while running this command.\n\`\`\`${errorMessage}\`\`\``;
93
+ const handleInteractionReply = async () => {
94
+ await (interaction.deferred ? interaction.editReply(message).catch(console.error) : interaction.reply({
95
+ content: message,
96
+ flags: MessageFlags.Ephemeral
97
+ }).catch(console.error));
98
+ };
99
+ handleInteractionReply();
100
+ }
101
+ };
102
+ export { CommandManager };
103
+
119
104
  //# sourceMappingURL=command-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-manager.js","sourceRoot":"","sources":["../src/command-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"command-manager.js","names":["#commands","#discord","#globalCommandHook","guilds: Collection<Snowflake, OAuth2Guild>","unregisterPromises: Promise<void>[]","errorMessage: string"],"sources":["../src/command-manager.ts"],"sourcesContent":["import type {\n ChatInputCommandInteraction,\n Interaction,\n OAuth2Guild,\n RESTPostAPIChatInputApplicationCommandsJSONBody,\n Snowflake,\n} from \"discord.js\"\nimport { Collection, Events, MessageFlags, Routes } from \"discord.js\"\n\nimport type { DiscordContext } from \"~/types.ts\"\nimport { throwUserError, UserError } from \"~/util.ts\"\n\nexport interface Command {\n requiredRoles?: string[]\n command: RESTPostAPIChatInputApplicationCommandsJSONBody\n run: (interaction: ChatInputCommandInteraction<\"cached\">) => void | Promise<void>\n}\n\nexport type CommandHook = (interaction: ChatInputCommandInteraction<\"cached\">) => boolean | Promise<boolean>\n\nexport class CommandManager {\n readonly #commands = new Collection<string, Command>()\n #globalCommandHook?: CommandHook\n readonly #discord: DiscordContext\n\n public constructor(discord: DiscordContext) {\n this.#discord = discord\n }\n\n /*\n * Add a command\n */\n public add(command: Command): void {\n this.#commands.set(command.command.name, command)\n }\n\n public setGlobalCommandHook(commandHook: CommandHook): void {\n this.#globalCommandHook = commandHook\n }\n\n public async register(): Promise<void> {\n const payload = this.#commands.map((c) => c.command)\n const route = Routes.applicationCommands(this.#discord.applicationId)\n await this.#discord.rest.put(route, { body: payload })\n\n console.log(`Registered ${this.#commands.size.toString()} (/) commands.`)\n }\n\n public async unregisterGuildCommands(): Promise<void> {\n if (this.#discord.client.readyAt) await this._unregisterGuildCommands()\n else this.#discord.client.once(Events.ClientReady, () => void this._unregisterGuildCommands())\n }\n\n private async _unregisterGuildCommands(): Promise<void> {\n let guilds: Collection<Snowflake, OAuth2Guild>\n try {\n guilds = await this.#discord.client.guilds.fetch()\n } catch (error) {\n console.error(\"Unable to unregister guild commands. Failed to fetch guilds.\")\n throw error\n }\n\n const unregisterPromises: Promise<void>[] = []\n for (const guild of guilds.values()) {\n const route = Routes.applicationGuildCommands(this.#discord.applicationId, guild.id)\n const unregisterGuildCommands = async () => {\n await this.#discord.rest.put(route, { body: [] })\n console.log(`Unregistered commands from guild: ${guild.name}`)\n }\n unregisterPromises.push(unregisterGuildCommands())\n }\n\n await Promise.all(unregisterPromises)\n }\n\n public async unregisterApplicationCommands(): Promise<void> {\n const route = Routes.applicationCommands(this.#discord.applicationId)\n await this.#discord.rest.put(route, { body: [] })\n console.log(\"Unregistered application commands.\")\n }\n\n public _listen(): void {\n const listen = async (interaction: Interaction) => {\n if (!interaction.isChatInputCommand()) return\n if (!interaction.guildId) return\n if (!interaction.inCachedGuild()) await interaction.client.guilds.fetch(interaction.guildId).catch(console.error)\n if (!interaction.inCachedGuild()) {\n CommandManager.interactionReply(interaction, \"Guild is not cached. Try again.\")\n return\n }\n\n const command = this.#commands.get(interaction.commandName)\n if (!command) {\n CommandManager.interactionReply(interaction, `Failed to get command with name: ${interaction.commandName}`)\n return\n }\n\n if (!(await CommandManager.checkRoles(command, interaction))) {\n CommandManager.interactionReply(interaction, \"You do not have one of the required roles to run this command.\")\n return\n }\n\n try {\n const shouldContinue = this.#globalCommandHook ? await this.#globalCommandHook(interaction) : true\n if (!shouldContinue) throwUserError(\"The global command hook returned false.\")\n\n await command.run(interaction)\n } catch (error) {\n CommandManager.interactionReply(interaction, error)\n }\n }\n\n this.#discord.client.on(Events.InteractionCreate, (interaction) => void listen(interaction))\n console.log(\"Listening for commands.\")\n }\n\n private static async checkRoles(command: Command, interaction: ChatInputCommandInteraction<\"cached\">) {\n if (!command.requiredRoles) return true\n\n if (command.requiredRoles.length > 0) {\n const member = await interaction.guild.members.fetch(interaction.user).catch(console.error)\n if (!member) return false\n\n return member.roles.cache.some((role) =>\n command.requiredRoles ? command.requiredRoles.includes(role.name) : false,\n )\n }\n\n return false\n }\n\n private static interactionReply(interaction: ChatInputCommandInteraction, error: unknown) {\n let errorMessage: string\n if (error instanceof UserError) errorMessage = error.message\n else if (error instanceof Error && error.stack) errorMessage = error.stack\n else errorMessage = String(error)\n\n const message = `There was an error while running this command.\\n\\`\\`\\`${errorMessage}\\`\\`\\``\n const handleInteractionReply = async () => {\n await (interaction.deferred\n ? interaction.editReply(message).catch(console.error)\n : interaction.reply({ content: message, flags: MessageFlags.Ephemeral }).catch(console.error))\n }\n void handleInteractionReply()\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { DiscordContext } from "./types.js";
2
+ import { Client, ClientEvents } from "discord.js";
3
+
4
+ //#region src/event-manager.d.ts
5
+ type ValidEvents = keyof ClientEvents;
6
+ type EventHandler<E$1 extends ValidEvents = ValidEvents> = (client: Client, ...args: ClientEvents[E$1]) => void | Promise<void>;
7
+ type EventHandlerMap = { [E in ValidEvents]: EventHandler<E> };
8
+ interface SingleEvent<E$1 extends ValidEvents = ValidEvents> {
9
+ event: E$1;
10
+ handler: EventHandlerMap[E$1];
11
+ }
12
+ declare class EventManager {
13
+ #private;
14
+ constructor(discord: DiscordContext);
15
+ add<N extends ValidEvents>(event: SingleEvent<N>): void;
16
+ _listen(): void;
17
+ }
18
+ type Event = { [E in ValidEvents]: SingleEvent<E> }[ValidEvents];
19
+ //#endregion
20
+ export { Event, EventManager };
21
+ //# sourceMappingURL=event-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-manager.d.ts","names":[],"sources":["../src/event-manager.ts"],"sourcesContent":[],"mappings":";;;;KAIK,WAAA,SAAoB;KAEpB,yBAAuB,cAAc,wBAChC,iBACC,aAAa,gBACZ;AAPoC,KAS3C,eAAA,GAPW,QAQR,WANS,GAMK,YANL,CAMkB,CANlB,CAAA,EAAW;UASlB,WATgC,CAAA,YASV,WATU,GASI,WATJ,CAAA,CAAA;EAChC,KAAA,EASD,GATC;EACC,OAAA,EASA,eATA,CASgB,GAThB,CAAA;;AACC,cAWC,YAAA,CAXD;EAAO,CAAA,OAAA;EAEd,WAAA,CAAA,OAAe,EAaU,cAbV;EACZ,GAAA,CAAA,UAmBe,WAnBf,CAAA,CAAA,KAAA,EAmBmC,WAnBnC,CAmB+C,CAnB/C,CAAA,CAAA,EAAA,IAAA;EAA2B,OAAA,CAAA,CAAA,EAAA,IAAA;;AAAD,KAyCtB,KAAA,GAzCsB,QA0C1B,WAvCa,GAuCC,WAvCD,CAuCa,CAvCb,CAAA,EAAW,CAwC9B,WAxC8B,CAAA"}
@@ -1,30 +1,26 @@
1
- export class EventManager {
2
- #events = [];
3
- #discord;
4
- constructor(discord) {
5
- this.#discord = discord;
6
- }
7
- /*
8
- * Add an event listener
9
- */
10
- add(event) {
11
- this.#events.push(event);
12
- }
13
- _listen() {
14
- for (const event of this.#events) {
15
- const listen = async (...args) => {
16
- try {
17
- // TS Error: Expression produces a union type that is too complex to represent.
18
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
19
- await event.handler(this.#discord.client, ...args);
20
- }
21
- catch (error) {
22
- console.error(error);
23
- }
24
- };
25
- this.#discord.client.on(event.event, (...args) => void listen(...args));
26
- }
27
- console.log(`Listening for (${this.#events.length.toString()}) events.`);
28
- }
29
- }
1
+ var EventManager = class {
2
+ #events = [];
3
+ #discord;
4
+ constructor(discord) {
5
+ this.#discord = discord;
6
+ }
7
+ add(event) {
8
+ this.#events.push(event);
9
+ }
10
+ _listen() {
11
+ for (const event of this.#events) {
12
+ const listen = async (...args) => {
13
+ try {
14
+ await event.handler(this.#discord.client, ...args);
15
+ } catch (error) {
16
+ console.error(error);
17
+ }
18
+ };
19
+ this.#discord.client.on(event.event, (...args) => void listen(...args));
20
+ }
21
+ console.log(`Listening for (${this.#events.length.toString()}) events.`);
22
+ }
23
+ };
24
+ export { EventManager };
25
+
30
26
  //# sourceMappingURL=event-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-manager.js","sourceRoot":"","sources":["../src/event-manager.ts"],"names":[],"mappings":"AAoBA,MAAM,OAAO,YAAY;IACd,OAAO,GAAkB,EAAE,CAAA;IAC3B,QAAQ,CAAgB;IAEjC,YAAmB,OAAuB;QACxC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;IACzB,CAAC;IAED;;OAEG;IACI,GAAG,CAAwB,KAAqB;QACrD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;IAEM,OAAO;QACZ,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,KAAK,EAAE,GAAG,IAAsC,EAAE,EAAE;gBACjE,IAAI,CAAC;oBACH,+EAA+E;oBAC/E,uEAAuE;oBACvE,MAAO,KAAK,CAAC,OAAwB,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;gBACtE,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;gBACtB,CAAC;YACH,CAAC,CAAA;YAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QACzE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;IAC1E,CAAC;CACF"}
1
+ {"version":3,"file":"event-manager.js","names":["#events","#discord"],"sources":["../src/event-manager.ts"],"sourcesContent":["import type { Client, ClientEvents } from \"discord.js\"\n\nimport type { DiscordContext } from \"~/types.ts\"\n\ntype ValidEvents = keyof ClientEvents\n\ntype EventHandler<E extends ValidEvents = ValidEvents> = (\n client: Client,\n ...args: ClientEvents[E]\n) => void | Promise<void>\n\ntype EventHandlerMap = {\n [E in ValidEvents]: EventHandler<E>\n}\n\ninterface SingleEvent<E extends ValidEvents = ValidEvents> {\n event: E\n handler: EventHandlerMap[E]\n}\n\nexport class EventManager {\n readonly #events: SingleEvent[] = []\n readonly #discord: DiscordContext\n\n public constructor(discord: DiscordContext) {\n this.#discord = discord\n }\n\n /*\n * Add an event listener\n */\n public add<N extends ValidEvents>(event: SingleEvent<N>): void {\n this.#events.push(event)\n }\n\n public _listen(): void {\n for (const event of this.#events) {\n const listen = async (...args: ClientEvents[typeof event.event]) => {\n try {\n // TS Error: Expression produces a union type that is too complex to represent.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n await (event.handler as EventHandler)(this.#discord.client, ...args)\n } catch (error) {\n console.error(error)\n }\n }\n\n this.#discord.client.on(event.event, (...args) => void listen(...args))\n }\n console.log(`Listening for (${this.#events.length.toString()}) events.`)\n }\n}\n\nexport type Event = {\n [E in ValidEvents]: SingleEvent<E>\n}[ValidEvents]\n"],"mappings":"AAoBA,IAAa,eAAb,MAA0B;CACxB,UAAkC,EAAE;CACpC;CAEA,YAAmB,SAAyB;AAC1C,QAAA,UAAgB;;CAMlB,IAAkC,OAA6B;AAC7D,QAAA,OAAa,KAAK,MAAM;;CAG1B,UAAuB;AACrB,OAAK,MAAM,SAAS,MAAA,QAAc;GAChC,MAAM,SAAS,OAAO,GAAG,SAA2C;AAClE,QAAI;AAGF,WAAO,MAAM,QAAyB,MAAA,QAAc,QAAQ,GAAG,KAAK;aAC7D,OAAO;AACd,aAAQ,MAAM,MAAM;;;AAIxB,SAAA,QAAc,OAAO,GAAG,MAAM,QAAQ,GAAG,SAAS,KAAK,OAAO,GAAG,KAAK,CAAC;;AAEzE,UAAQ,IAAI,kBAAkB,MAAA,OAAa,OAAO,UAAU,CAAC,WAAW"}
@@ -0,0 +1,5 @@
1
+ import { Command, CommandHook } from "./command-manager.js";
2
+ import { Event } from "./event-manager.js";
3
+ import { Bot } from "./bot.js";
4
+ import { getChannel, throwError, throwUserError } from "./util.js";
5
+ export { Bot, type Command, type CommandHook, type Event, getChannel, throwError, throwUserError };
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- /** biome-ignore-all lint/performance/noBarrelFile: ignore */
2
- export { Bot } from "./bot.js";
3
- export { getChannel, throwError, throwUserError } from "./util.js";
4
- //# sourceMappingURL=index.js.map
1
+ import { getChannel, throwError, throwUserError } from "./util.js";
2
+ import { Bot } from "./bot.js";
3
+ export { Bot, getChannel, throwError, throwUserError };
@@ -0,0 +1,17 @@
1
+ import { Client, ClientOptions, REST } from "discord.js";
2
+
3
+ //#region src/types.d.ts
4
+ interface BotOptions {
5
+ applicationId: string;
6
+ token: string;
7
+ clientOptions: ClientOptions;
8
+ }
9
+ interface DiscordContext {
10
+ applicationId: string;
11
+ token: string;
12
+ client: Client;
13
+ rest: REST;
14
+ }
15
+ //#endregion
16
+ export { BotOptions, DiscordContext };
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;UAEiB,UAAA;;EAAA,KAAA,EAAA,MAAU;EAMV,aAAA,EAHA,aAGc;;UAAd,cAAA;;;UAGP;QACF"}
@@ -1,11 +1,13 @@
1
- import type { CategoryChannel, ChannelType, ForumChannel, Guild, NewsChannel, StageChannel, TextChannel, VoiceChannel } from "discord.js";
1
+ import { CategoryChannel, ChannelType, ForumChannel, Guild, NewsChannel, StageChannel, TextChannel, VoiceChannel } from "discord.js";
2
+
3
+ //#region src/util.d.ts
2
4
  interface ChannelTypeToChannelMap {
3
- [ChannelType.GuildCategory]: CategoryChannel;
4
- [ChannelType.GuildAnnouncement]: NewsChannel;
5
- [ChannelType.GuildStageVoice]: StageChannel;
6
- [ChannelType.GuildText]: TextChannel;
7
- [ChannelType.GuildVoice]: VoiceChannel;
8
- [ChannelType.GuildForum]: ForumChannel;
5
+ [ChannelType.GuildCategory]: CategoryChannel;
6
+ [ChannelType.GuildAnnouncement]: NewsChannel;
7
+ [ChannelType.GuildStageVoice]: StageChannel;
8
+ [ChannelType.GuildText]: TextChannel;
9
+ [ChannelType.GuildVoice]: VoiceChannel;
10
+ [ChannelType.GuildForum]: ForumChannel;
9
11
  }
10
12
  /**
11
13
  * Returns the guild channel of the given name/ID and type, otherwise throws.
@@ -25,22 +27,21 @@ interface ChannelTypeToChannelMap {
25
27
  *
26
28
  * Getting a properly typed channel with discord.js can be a bit of a pain, so this is an alternative.
27
29
  */
28
- export declare function getChannel<T extends keyof ChannelTypeToChannelMap>(guild: Guild, channelNameOrId: string, channelType: T): Promise<ChannelTypeToChannelMap[T]>;
30
+ declare function getChannel<T extends keyof ChannelTypeToChannelMap>(guild: Guild, channelNameOrId: string, channelType: T): Promise<ChannelTypeToChannelMap[T]>;
29
31
  /**
30
32
  * Throws an error with the given message.
31
33
  *
32
34
  * @param message The message to throw
33
35
  * @throws Error
34
36
  */
35
- export declare function throwError(message: string): never;
37
+ declare function throwError(message: string): never;
36
38
  /**
37
39
  * Throws a UserError with the given message.
38
40
  *
39
41
  * @param message The message to throw
40
42
  * @throws UserError
41
43
  */
42
- export declare function throwUserError(message: string): never;
43
- export declare class UserError extends Error {
44
- constructor(message: string);
45
- }
46
- export {};
44
+ declare function throwUserError(message: string): never;
45
+ //#endregion
46
+ export { getChannel, throwError, throwUserError };
47
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","names":[],"sources":["../src/util.ts"],"sourcesContent":[],"mappings":";;;UAYU,uBAAA;GACP,WAAA,CAAY,aAAA,GAAgB;EADrB,CAEP,WAAA,CAAY,iBAAA,CAFkB,EAEE,WAFF;EACF,CAE5B,WAAA,CAAY,eAAA,CAFgB,EAEE,YAFF;EAA5B,CAGA,WAAA,CAAY,SAAA,CAHA,EAGY,WAHZ;EACoB,CAGhC,WAAA,CAAY,UAAA,CAHoB,EAGP,YAHO;EAAhC,CAIA,WAAA,CAAY,UAAA,CAJA,EAIa,YAJb;;;;;;;;;;AAyBf;;;;;;;;AAyBA;AAUA;iBAnCsB,2BAA2B,gCACxC,6CAEM,IACZ,QAAQ,wBAAwB;;;;;;;iBAqBnB,UAAA;;;;;;;iBAUA,cAAA"}
package/dist/util.js CHANGED
@@ -1,57 +1,25 @@
1
- /**
2
- * Returns the guild channel of the given name/ID and type, otherwise throws.
3
- *
4
- * @param guild The Guild to fetch the channel from
5
- * @param channelNameOrId The name or ID of the channel to fetch
6
- * @param channelType The type of channel to fetch
7
- * @returns The channel of the given name/ID and type
8
- * @example
9
- * ```ts
10
- * import { getChannel } from "discord-bot-shared"
11
- * import { ChannelType } from "discord.js"
12
- *
13
- * // guild is of type Guild from discord.js
14
- * const someTextChannel = await getChannel(guild, "some-text-channel", ChannelType.GuildText)
15
- * ```
16
- *
17
- * Getting a properly typed channel with discord.js can be a bit of a pain, so this is an alternative.
18
- */
19
- export async function getChannel(guild, channelNameOrId, channelType) {
20
- const channels = await guild.channels.fetch();
21
- let channel;
22
- channel = channels.find((chan) => (chan ? chan.name === channelNameOrId : false));
23
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
24
- if (channel && channel.type === channelType)
25
- return channel;
26
- channel = channels.get(channelNameOrId);
27
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
28
- if (channel && channel.type === channelType)
29
- return channel;
30
- throwError(`Failed to get channel: ${channelNameOrId}`);
1
+ async function getChannel(guild, channelNameOrId, channelType) {
2
+ const channels = await guild.channels.fetch();
3
+ let channel;
4
+ channel = channels.find((chan) => chan ? chan.name === channelNameOrId : false);
5
+ if (channel && channel.type === channelType) return channel;
6
+ channel = channels.get(channelNameOrId);
7
+ if (channel && channel.type === channelType) return channel;
8
+ throwError(`Failed to get channel: ${channelNameOrId}`);
31
9
  }
32
- /**
33
- * Throws an error with the given message.
34
- *
35
- * @param message The message to throw
36
- * @throws Error
37
- */
38
- export function throwError(message) {
39
- throw new Error(message);
10
+ function throwError(message) {
11
+ throw new Error(message);
40
12
  }
41
- /**
42
- * Throws a UserError with the given message.
43
- *
44
- * @param message The message to throw
45
- * @throws UserError
46
- */
47
- export function throwUserError(message) {
48
- throw new UserError(message);
49
- }
50
- export class UserError extends Error {
51
- constructor(message) {
52
- super(message);
53
- this.name = "UserError";
54
- Object.setPrototypeOf(this, new.target.prototype);
55
- }
13
+ function throwUserError(message) {
14
+ throw new UserError(message);
56
15
  }
16
+ var UserError = class extends Error {
17
+ constructor(message) {
18
+ super(message);
19
+ this.name = "UserError";
20
+ Object.setPrototypeOf(this, new.target.prototype);
21
+ }
22
+ };
23
+ export { UserError, getChannel, throwError, throwUserError };
24
+
57
25
  //# sourceMappingURL=util.js.map
package/dist/util.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAY,EACZ,eAAuB,EACvB,WAAc;IAEd,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;IAE7C,IAAI,OAAsD,CAAA;IAC1D,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IACjF,uEAAuE;IACvE,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,OAAqC,CAAA;IAEzF,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IACvC,uEAAuE;IACvE,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,OAAqC,CAAA;IAEzF,UAAU,CAAC,0BAA0B,eAAe,EAAE,CAAC,CAAA;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,IAAI,SAAS,CAAC,OAAO,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAmB,OAAe;QAChC,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,WAAW,CAAA;QAEvB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACnD,CAAC;CACF"}
1
+ {"version":3,"file":"util.js","names":["channel: NonThreadGuildBasedChannel | undefined | null"],"sources":["../src/util.ts"],"sourcesContent":["import type {\n CategoryChannel,\n ChannelType,\n ForumChannel,\n Guild,\n NewsChannel,\n NonThreadGuildBasedChannel,\n StageChannel,\n TextChannel,\n VoiceChannel,\n} from \"discord.js\"\n\ninterface ChannelTypeToChannelMap {\n [ChannelType.GuildCategory]: CategoryChannel\n [ChannelType.GuildAnnouncement]: NewsChannel\n [ChannelType.GuildStageVoice]: StageChannel\n [ChannelType.GuildText]: TextChannel\n [ChannelType.GuildVoice]: VoiceChannel\n [ChannelType.GuildForum]: ForumChannel\n}\n\n/**\n * Returns the guild channel of the given name/ID and type, otherwise throws.\n *\n * @param guild The Guild to fetch the channel from\n * @param channelNameOrId The name or ID of the channel to fetch\n * @param channelType The type of channel to fetch\n * @returns The channel of the given name/ID and type\n * @example\n * ```ts\n * import { getChannel } from \"discord-bot-shared\"\n * import { ChannelType } from \"discord.js\"\n *\n * // guild is of type Guild from discord.js\n * const someTextChannel = await getChannel(guild, \"some-text-channel\", ChannelType.GuildText)\n * ```\n *\n * Getting a properly typed channel with discord.js can be a bit of a pain, so this is an alternative.\n */\nexport async function getChannel<T extends keyof ChannelTypeToChannelMap>(\n guild: Guild,\n channelNameOrId: string,\n channelType: T,\n): Promise<ChannelTypeToChannelMap[T]> {\n const channels = await guild.channels.fetch()\n\n let channel: NonThreadGuildBasedChannel | undefined | null\n channel = channels.find((chan) => (chan ? chan.name === channelNameOrId : false))\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n if (channel && channel.type === channelType) return channel as ChannelTypeToChannelMap[T]\n\n channel = channels.get(channelNameOrId)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n if (channel && channel.type === channelType) return channel as ChannelTypeToChannelMap[T]\n\n throwError(`Failed to get channel: ${channelNameOrId}`)\n}\n\n/**\n * Throws an error with the given message.\n *\n * @param message The message to throw\n * @throws Error\n */\nexport function throwError(message: string): never {\n throw new Error(message)\n}\n\n/**\n * Throws a UserError with the given message.\n *\n * @param message The message to throw\n * @throws UserError\n */\nexport function throwUserError(message: string): never {\n throw new UserError(message)\n}\n\nexport class UserError extends Error {\n public constructor(message: string) {\n super(message)\n this.name = \"UserError\"\n\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n"],"mappings":"AAuCA,eAAsB,WACpB,OACA,iBACA,aACqC;CACrC,MAAM,WAAW,MAAM,MAAM,SAAS,OAAO;CAE7C,IAAIA;AACJ,WAAU,SAAS,MAAM,SAAU,OAAO,KAAK,SAAS,kBAAkB,MAAO;AAEjF,KAAI,WAAW,QAAQ,SAAS,YAAa,QAAO;AAEpD,WAAU,SAAS,IAAI,gBAAgB;AAEvC,KAAI,WAAW,QAAQ,SAAS,YAAa,QAAO;AAEpD,YAAW,0BAA0B,kBAAkB;;AASzD,SAAgB,WAAW,SAAwB;AACjD,OAAM,IAAI,MAAM,QAAQ;;AAS1B,SAAgB,eAAe,SAAwB;AACrD,OAAM,IAAI,UAAU,QAAQ;;AAG9B,IAAa,YAAb,cAA+B,MAAM;CACnC,YAAmB,SAAiB;AAClC,QAAM,QAAQ;AACd,OAAK,OAAO;AAEZ,SAAO,eAAe,MAAM,IAAI,OAAO,UAAU"}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "discord-bot-shared",
3
- "version": "0.14.3",
3
+ "version": "0.14.5",
4
4
  "type": "module",
5
5
  "description": "Modules for creating discord bots.",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/adamhl8/discord-bot-shared"
8
+ "url": "git+https://github.com/adamhl8/discord-bot-shared.git"
9
9
  },
10
10
  "homepage": "https://github.com/adamhl8/discord-bot-shared",
11
11
  "bugs": {
@@ -19,27 +19,30 @@
19
19
  "license": "MIT",
20
20
  "exports": {
21
21
  ".": {
22
- "import": "./dist/index.js",
23
- "types": "./dist/types/index.d.ts"
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
24
  }
25
25
  },
26
- "files": [
27
- "dist/"
28
- ],
26
+ "files": ["dist/"],
29
27
  "scripts": {
30
- "bundle": "rm -rf ./dist && bun lint && tsc",
31
- "lint": "tsc --noEmit && biome check --write",
32
- "prepare": "find .githooks -type f -exec ln -srf {} .git/hooks/ \\;",
28
+ "bundle": "bun lint && tsdown",
29
+ "lint": "markdown-toc -i --bullets '-' --maxdepth 3 ./README.md && ts-import-fix -w && tsc --noEmit && biome check --write && adamhl8-knip",
30
+ "prepare": "find .githooks -type f -exec ln -srf {} .git/hooks/ \\; || true",
33
31
  "prepublishOnly": "bun bundle"
34
32
  },
35
33
  "peerDependencies": {
36
34
  "discord.js": "^14.0.0"
37
35
  },
38
36
  "devDependencies": {
39
- "@adamhl8/configs": "^0.5.0",
40
- "@biomejs/biome": "^2.0.6",
41
- "@types/bun": "^1.2.17",
42
- "discord.js": "^14.21.0",
43
- "typescript": "^5.8.3"
37
+ "@adamhl8/configs": "^0.17.9",
38
+ "@arethetypeswrong/core": "^0.18.2",
39
+ "@biomejs/biome": "^2.3.4",
40
+ "@types/bun": "^1.3.2",
41
+ "discord.js": "^14.24.2",
42
+ "knip": "^5.68.0",
43
+ "markdown-toc": "^1.2.0",
44
+ "publint": "^0.3.15",
45
+ "tsdown": "^0.16.1",
46
+ "typescript": "^5.9.3"
44
47
  }
45
48
  }
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA"}
@@ -1,22 +0,0 @@
1
- import type { ClientOptions } from "discord.js";
2
- import { Client, REST } from "discord.js";
3
- import { CommandManager } from "./command-manager.js";
4
- import { EventManager } from "./event-manager.js";
5
- export interface BotOptions {
6
- applicationId: string;
7
- token: string;
8
- clientOptions: ClientOptions;
9
- }
10
- export interface DiscordContext {
11
- applicationId: string;
12
- token: string;
13
- client: Client;
14
- rest: REST;
15
- }
16
- export declare class Bot {
17
- #private;
18
- readonly commands: CommandManager;
19
- readonly events: EventManager;
20
- constructor(options: BotOptions);
21
- login(): Promise<void>;
22
- }
@@ -1,21 +0,0 @@
1
- import type { ChatInputCommandInteraction, RESTPostAPIChatInputApplicationCommandsJSONBody } from "discord.js";
2
- import type { DiscordContext } from "./bot.js";
3
- export interface Command {
4
- requiredRoles?: string[];
5
- command: RESTPostAPIChatInputApplicationCommandsJSONBody;
6
- run: (interaction: ChatInputCommandInteraction<"cached">) => void | Promise<void>;
7
- }
8
- export type CommandHook = (interaction: ChatInputCommandInteraction<"cached">) => boolean | Promise<boolean>;
9
- export declare class CommandManager {
10
- #private;
11
- constructor(discord: DiscordContext);
12
- add(command: Command): void;
13
- setGlobalCommandHook(commandHook: CommandHook): void;
14
- register(): Promise<void>;
15
- unregisterGuildCommands(): Promise<void>;
16
- private _unregisterGuildCommands;
17
- unregisterApplicationCommands(): Promise<void>;
18
- _listen(): void;
19
- private static checkRoles;
20
- private static interactionReply;
21
- }
@@ -1,21 +0,0 @@
1
- import type { Client, ClientEvents } from "discord.js";
2
- import type { DiscordContext } from "./bot.js";
3
- type ValidEvents = keyof ClientEvents;
4
- type EventHandler<E extends ValidEvents = ValidEvents> = (client: Client, ...args: ClientEvents[E]) => void | Promise<void>;
5
- type EventHandlerMap = {
6
- [E in ValidEvents]: EventHandler<E>;
7
- };
8
- interface SingleEvent<E extends ValidEvents = ValidEvents> {
9
- event: E;
10
- handler: EventHandlerMap[E];
11
- }
12
- export declare class EventManager {
13
- #private;
14
- constructor(discord: DiscordContext);
15
- add<N extends ValidEvents>(event: SingleEvent<N>): void;
16
- _listen(): void;
17
- }
18
- export type Event = {
19
- [E in ValidEvents]: SingleEvent<E>;
20
- }[ValidEvents];
21
- export {};
@@ -1,5 +0,0 @@
1
- /** biome-ignore-all lint/performance/noBarrelFile: ignore */
2
- export { Bot } from "./bot.js";
3
- export type { Command, CommandHook } from "./command-manager.js";
4
- export type { Event } from "./event-manager.js";
5
- export { getChannel, throwError, throwUserError } from "./util.js";