discord-bot-shared 0.14.2 → 0.14.4

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;EAAA,SAAA,MAAA,EAIU,YAJV;aAGY,CAAA,OAAA,EAGE,UAHF;OACF,CAAA,CAAA,EAcF,OAdE,CAAA,IAAA,CAAA"}
package/dist/bot.js CHANGED
@@ -1,28 +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
- 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
27
  export { Bot };
28
+
28
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":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAsB,MAAM,YAAY,CAAA;AAErE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAejD,MAAM,GAAG;IACE,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;AAED,OAAO,EAAE,GAAG,EAAE,CAAA"}
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.js\"\nimport { EventManager } from \"@/event-manager.js\"\nimport type { BotOptions, DiscordContext } from \"@/types.js\"\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;EAAA,GAAA,EAAA,CAAA,WAAA,EAGH,2BAHG,CAAA,QAAA,CAAA,EAAA,GAAA,IAAA,GAG8C,OAH9C,CAAA,IAAA,CAAA;;AAGH,KAGT,WAAA,GAHS,CAAA,WAAA,EAGmB,2BAHnB,CAAA,QAAA,CAAA,EAAA,GAAA,OAAA,GAGuE,OAHvE,CAAA,OAAA,CAAA;AAAiD,cAKzD,cAAA,CALyD;EAAO,CAAA,OAAA;EAGjE,WAAA,CAAA,OAAW,EAOO,cAPP;EAAA,GAAA,CAAA,OAAA,EAcD,OAdC,CAAA,EAAA,IAAA;sBAAiB,CAAA,WAAA,EAkBG,WAlBH,CAAA,EAAA,IAAA;UAAoD,CAAA,CAAA,EAsBjE,OAtBiE,CAAA,IAAA,CAAA;EAAO,uBAAA,CAAA,CAAA,EA8BzD,OA9ByD,CAAA,IAAA,CAAA;EAEtF,QAAA,wBAAc;EAAA,6BAAA,CAAA,CAAA,EAuDqB,OAvDrB,CAAA,IAAA,CAAA;SAKG,CAAA,CAAA,EAAA,IAAA;iBAOR,UAAA;iBAIqB,gBAAA"}
@@ -1,119 +1,104 @@
1
- import { Collection, Events, MessageFlags, Routes, } from "discord.js";
2
- import { throwUserError, UserError } from "./util.js";
3
- 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
- const listen = async (interaction) => {
58
- if (!interaction.isChatInputCommand())
59
- return;
60
- if (!interaction.guildId)
61
- return;
62
- if (!interaction.inCachedGuild())
63
- await interaction.client.guilds.fetch(interaction.guildId).catch(console.error);
64
- if (!interaction.inCachedGuild()) {
65
- CommandManager.interactionReply(interaction, "Guild is not cached. Try again.");
66
- return;
67
- }
68
- const command = this.#commands.get(interaction.commandName);
69
- if (!command) {
70
- CommandManager.interactionReply(interaction, `Failed to get command with name: ${interaction.commandName}`);
71
- return;
72
- }
73
- if (!(await CommandManager.checkRoles(command, interaction))) {
74
- CommandManager.interactionReply(interaction, "You do not have one of the required roles to run this command.");
75
- return;
76
- }
77
- try {
78
- const shouldContinue = this.#globalCommandHook ? await this.#globalCommandHook(interaction) : true;
79
- if (!shouldContinue)
80
- throwUserError("The global command hook returned false.");
81
- await command.run(interaction);
82
- }
83
- catch (error) {
84
- CommandManager.interactionReply(interaction, error);
85
- }
86
- };
87
- this.#discord.client.on(Events.InteractionCreate, (interaction) => void listen(interaction));
88
- console.log("Listening for commands.");
89
- }
90
- static async checkRoles(command, interaction) {
91
- if (!command.requiredRoles)
92
- return true;
93
- if (command.requiredRoles.length > 0) {
94
- const member = await interaction.guild.members.fetch(interaction.user).catch(console.error);
95
- if (!member)
96
- return false;
97
- return member.roles.cache.some((role) => command.requiredRoles ? command.requiredRoles.includes(role.name) : false);
98
- }
99
- return false;
100
- }
101
- static interactionReply(interaction, error) {
102
- let errorMessage;
103
- if (error instanceof UserError)
104
- errorMessage = error.message;
105
- else if (error instanceof Error && error.stack)
106
- errorMessage = error.stack;
107
- else
108
- errorMessage = String(error);
109
- const message = `There was an error while running this command.\n\`\`\`${errorMessage}\`\`\``;
110
- const handleInteractionReply = async () => {
111
- await (interaction.deferred
112
- ? interaction.editReply(message).catch(console.error)
113
- : interaction.reply({ content: message, flags: MessageFlags.Ephemeral }).catch(console.error));
114
- };
115
- void handleInteractionReply();
116
- }
117
- }
1
+ import { UserError, throwUserError } from "./util.js";
2
+ import { Collection, Events, MessageFlags, Routes } from "discord.js";
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
+ };
118
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":"AAAA,OAAO,EACL,UAAU,EACV,MAAM,EACN,YAAY,EACZ,MAAM,GAIP,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAUrD,MAAM,cAAc;IACT,SAAS,GAAG,IAAI,UAAU,EAAmB,CAAA;IACtD,kBAAkB,CAAc;IACvB,QAAQ,CAAgB;IAEjC,YAAmB,OAAuB;QACxC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;IACzB,CAAC;IAED;;OAEG;IACI,GAAG,CAAC,OAAgB;QACzB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACnD,CAAC;IAEM,oBAAoB,CAAC,WAAwB;QAClD,IAAI,CAAC,kBAAkB,GAAG,WAAW,CAAA;IACvC,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;QACpD,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;QACrE,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAEtD,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAA;IAC3E,CAAC;IAEM,KAAK,CAAC,uBAAuB;QAClC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAA;;YAClE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAA;IAChG,CAAC;IAEO,KAAK,CAAC,wBAAwB;QACpC,IAAI,MAAM,CAAA;QACV,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAA;YAC7E,MAAM,KAAK,CAAA;QACb,CAAC;QAED,MAAM,kBAAkB,GAAG,EAAE,CAAA;QAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,MAAM,CAAC,wBAAwB,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;YACpF,MAAM,uBAAuB,GAAG,KAAK,IAAI,EAAE;gBACzC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;gBACjD,OAAO,CAAC,GAAG,CAAC,qCAAqC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;YAChE,CAAC,CAAA;YACD,kBAAkB,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC,CAAA;QACpD,CAAC;QAED,MAAM,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;IACvC,CAAC;IAEM,KAAK,CAAC,6BAA6B;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;QACrE,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QACjD,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;IACnD,CAAC;IAEM,OAAO;QACZ,MAAM,MAAM,GAAG,KAAK,EAAE,WAAwB,EAAE,EAAE;YAChD,IAAI,CAAC,WAAW,CAAC,kBAAkB,EAAE;gBAAE,OAAM;YAC7C,IAAI,CAAC,WAAW,CAAC,OAAO;gBAAE,OAAM;YAChC,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE;gBAAE,MAAM,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACjH,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,EAAE,CAAC;gBACjC,cAAc,CAAC,gBAAgB,CAAC,WAAW,EAAE,iCAAiC,CAAC,CAAA;gBAC/E,OAAM;YACR,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;YAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,cAAc,CAAC,gBAAgB,CAAC,WAAW,EAAE,oCAAoC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAA;gBAC3G,OAAM;YACR,CAAC;YAED,IAAI,CAAC,CAAC,MAAM,cAAc,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;gBAC7D,cAAc,CAAC,gBAAgB,CAAC,WAAW,EAAE,gEAAgE,CAAC,CAAA;gBAC9G,OAAM;YACR,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;gBAClG,IAAI,CAAC,cAAc;oBAAE,cAAc,CAAC,yCAAyC,CAAC,CAAA;gBAE9E,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YAChC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,cAAc,CAAC,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;YACrD,CAAC;QACH,CAAC,CAAA;QAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,WAAW,CAAC,CAAC,CAAA;QAC5F,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAA;IACxC,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,OAAgB,EAAE,WAAkD;QAClG,IAAI,CAAC,OAAO,CAAC,aAAa;YAAE,OAAO,IAAI,CAAA;QAEvC,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YAC3F,IAAI,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAA;YAEzB,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACtC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAC1E,CAAA;QACH,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAEO,MAAM,CAAC,gBAAgB,CAAC,WAAwC,EAAE,KAAc;QACtF,IAAI,YAAoB,CAAA;QACxB,IAAI,KAAK,YAAY,SAAS;YAAE,YAAY,GAAG,KAAK,CAAC,OAAO,CAAA;aACvD,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK;YAAE,YAAY,GAAG,KAAK,CAAC,KAAK,CAAA;;YACrE,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAEjC,MAAM,OAAO,GAAG,yDAAyD,YAAY,QAAQ,CAAA;QAC7F,MAAM,sBAAsB,GAAG,KAAK,IAAI,EAAE;YACxC,MAAM,CAAC,WAAW,CAAC,QAAQ;gBACzB,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBACrD,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;QAClG,CAAC,CAAA;QACD,KAAK,sBAAsB,EAAE,CAAA;IAC/B,CAAC;CACF;AAED,OAAO,EAAE,cAAc,EAAE,CAAA"}
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.js\"\nimport { throwUserError, UserError } from \"@/util.js\"\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 extends ValidEvents = ValidEvents> = (client: Client, ...args: ClientEvents[E]) => void | Promise<void>;
7
+ type EventHandlerMap = { [E in ValidEvents]: EventHandler<E> };
8
+ interface SingleEvent<E extends ValidEvents = ValidEvents> {
9
+ event: E;
10
+ handler: EventHandlerMap[E];
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,uBAAuB,cAAc,wBAChC,iBACC,aAAa,cACZ;AAPoC,KAS3C,eAAA,GAPW,QAQR,WANS,GAMK,YANL,CAMkB,CANlB,CAAA,EAAA;UASP,WATkB,CAAA,UASI,WATJ,GASkB,WATlB,CAAA,CAAA;OAAc,EAUjC,CAViC;SAChC,EAUC,eAVD,CAUiB,CAVjB,CAAA;;AACc,cAYX,YAAA,CAZW;UACZ;EAAO,WAAA,CAAA,OAAA,EAeW,cAfX;EAEd,GAAA,CAAA,UAoBkB,WApBH,CAAA,CAAA,KAAA,EAoBuB,WApBvB,CAoBmC,CApBnC,CAAA,CAAA,EAAA,IAAA;EAAA,OAAA,CAAA,CAAA,EAAA,IAAA;;AACe,KAyCvB,KAAA,GAzCuB,QA0C3B,WA1Cc,GA0CA,WA1CA,CA0CY,CA1CZ,CAAA,EAAY,CA2ChC,WA3CgC,CAAA"}
@@ -1,31 +1,26 @@
1
- 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
+ };
30
24
  export { EventManager };
25
+
31
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,YAAY;IACP,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;AAMD,OAAO,EAAE,YAAY,EAAE,CAAA"}
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.js\"\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,3 +1,3 @@
1
- export { Bot } from "./bot.js";
2
- export { getChannel, throwError, throwUserError } from "./util.js";
3
- //# 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;;AAGrB,UAHO,cAAA,CAGP;eACF,EAAA,MAAA;EAAI,KAAA,EAAA,MAAA;UADF;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.
@@ -40,7 +42,6 @@ declare function throwError(message: string): never;
40
42
  * @throws UserError
41
43
  */
42
44
  declare function throwUserError(message: string): never;
43
- declare class UserError extends Error {
44
- constructor(message: string);
45
- }
46
- export { UserError, getChannel, throwError, throwUserError };
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;EAAA,CAG9B,WAAA,CAAY,eAAA,CAHkB,EAGA,YAHA;GAI9B,WAAA,CAAY,SAAA,CAHgB,EAGJ,WAHI;GAI5B,WAAA,CAAY,UAAA,CAJA,EAIa,YAJb;GAKZ,WAAA,CAAY,UAAA,CAJoB,EAIP,YAJO;;;;;;;;;;;AAyBnC;;;;;;;;;AAyBgB,iBAzBM,UAyBI,CAAA,UAAA,MAzBuB,uBAyBvB,CAAA,CAAA,KAAA,EAxBjB,KAwBiB,EAAA,eAAA,EAAA,MAAA,EAAA,WAAA,EAtBX,CAsBW,CAAA,EArBvB,OAqBuB,CArBf,uBAqBe,CArBS,CAqBT,CAAA,CAAA;AAU1B;;;;;;iBAVgB,UAAA;;;;;;;iBAUA,cAAA"}
package/dist/util.js CHANGED
@@ -1,58 +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
1
  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}`);
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
10
  function throwError(message) {
39
- throw new Error(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
13
  function throwUserError(message) {
48
- throw new UserError(message);
49
- }
50
- class UserError extends Error {
51
- constructor(message) {
52
- super(message);
53
- this.name = "UserError";
54
- Object.setPrototypeOf(this, new.target.prototype);
55
- }
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
+ };
57
23
  export { UserError, getChannel, throwError, throwUserError };
24
+
58
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,KAAK,UAAU,UAAU,CACvB,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,SAAS,UAAU,CAAC,OAAe;IACjC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;AAC1B,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,IAAI,SAAS,CAAC,OAAO,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,SAAU,SAAQ,KAAK;IAC3B,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;AAED,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,CAAA"}
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.2",
3
+ "version": "0.14.4",
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,29 +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": "bun lint && rm -rf ./dist && tsc -p ./tsconfig.build.json",
31
- "lint": "tsc --noEmit && prettier --write . && eslint .",
32
- "prepare": "find .githooks -type f -exec ln -srf {} .git/hooks/ \\;",
33
- "prepublish": "bun bundle"
28
+ "bundle": "bun lint && tsdown",
29
+ "lint": "markdown-toc -i --bullets '-' --maxdepth 3 ./README.md && tsc --noEmit && biome check --write && adamhl8-knip",
30
+ "prepare": "find .githooks -type f -exec ln -srf {} .git/hooks/ \\; || true",
31
+ "prepublishOnly": "bun bundle"
34
32
  },
35
33
  "peerDependencies": {
36
34
  "discord.js": "^14.0.0"
37
35
  },
38
36
  "devDependencies": {
39
- "@types/bun": "^1.2.17",
40
- "discord.js": "^14.21.0",
41
- "eslint": "^9.29.0",
42
- "eslint-config-builder": "^0.21.2",
43
- "prettier": "^3.6.1",
44
- "typescript": "^5.8.3",
45
- "typescript-eslint": "^8.35.0"
37
+ "@adamhl8/configs": "^0.15.23",
38
+ "@arethetypeswrong/core": "^0.18.2",
39
+ "@biomejs/biome": "^2.2.4",
40
+ "@types/bun": "^1.2.22",
41
+ "discord.js": "^14.22.1",
42
+ "knip": "^5.63.1",
43
+ "markdown-toc": "^1.2.0",
44
+ "publint": "^0.3.13",
45
+ "tsdown": "^0.15.2",
46
+ "typescript": "^5.9.2"
46
47
  }
47
48
  }
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA"}
@@ -1,23 +0,0 @@
1
- import { Client, REST, type ClientOptions } from "discord.js";
2
- import { CommandManager } from "./command-manager.js";
3
- import { EventManager } from "./event-manager.js";
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
- declare class Bot {
16
- #private;
17
- readonly commands: CommandManager;
18
- readonly events: EventManager;
19
- constructor(options: BotOptions);
20
- login(): Promise<void>;
21
- }
22
- export { Bot };
23
- export type { BotOptions, DiscordContext };
@@ -1,23 +0,0 @@
1
- import { type ChatInputCommandInteraction, type RESTPostAPIChatInputApplicationCommandsJSONBody } from "discord.js";
2
- import type { DiscordContext } from "./bot.js";
3
- interface Command {
4
- requiredRoles?: string[];
5
- command: RESTPostAPIChatInputApplicationCommandsJSONBody;
6
- run: (interaction: ChatInputCommandInteraction<"cached">) => void | Promise<void>;
7
- }
8
- type CommandHook = (interaction: ChatInputCommandInteraction<"cached">) => boolean | Promise<boolean>;
9
- 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
- }
22
- export { CommandManager };
23
- export type { Command, CommandHook };
@@ -1,22 +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
- 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 = {
19
- [E in ValidEvents]: SingleEvent<E>;
20
- }[ValidEvents];
21
- export { EventManager };
22
- export type { Event };
@@ -1,4 +0,0 @@
1
- export { Bot } from "./bot.js";
2
- export type { Command, CommandHook } from "./command-manager.js";
3
- export type { Event } from "./event-manager.js";
4
- export { getChannel, throwError, throwUserError } from "./util.js";