@stelliajs/framework 1.2.3 → 1.3.0-dev-2

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
@@ -85,7 +85,7 @@ const client = new StelliaClient({
85
85
  }
86
86
  },
87
87
  environment: {
88
- areEnvironmentsEnabled: true
88
+ areGuildsConfigurationEnabled: true
89
89
  }
90
90
  });
91
91
 
@@ -98,14 +98,14 @@ await client.connect(process.env.TOKEN);
98
98
  ```js
99
99
  import { type StelliaClient, type EventStructure } from "@stelliajs/framework";
100
100
  import { Events } from "discord.js";
101
- import { type CustomEnvironment } from "@environments/environment.model.ts";
101
+ import { type CustomGuildsConfiguration } from "@environments/environment.model.ts";
102
102
 
103
103
  export default {
104
104
  data: {
105
105
  name: Events.ClientReady,
106
106
  once: true
107
107
  },
108
- async execute(client: StelliaClient<true>, environment: CustomEnvironment) { // <true> ensures that the client is Ready
108
+ async execute(client: StelliaClient<true>, environment: CustomGuildsConfiguration) { // <true> ensures that the client is Ready
109
109
  console.log(`Logged in as ${client.user.tag}`);
110
110
  await client.initializeCommands(); // Used to initialise registered commands
111
111
  }
@@ -116,14 +116,14 @@ export default {
116
116
  ```js
117
117
  import { type StelliaClient, type EventStructure } from "@stelliajs/framework";
118
118
  import { Events, type Interaction } from "discord.js";
119
- import { type CustomEnvironment } from "@environments/environment.model.ts";
119
+ import { type CustomGuildsConfiguration } from "@environments/environment.model.ts";
120
120
 
121
121
  export default {
122
122
  data: {
123
123
  name: Events.InteractionCreate,
124
124
  once: false
125
125
  },
126
- async execute(client: StelliaClient<true>, environment: CustomEnvironment, interaction: Interaction) {
126
+ async execute(client: StelliaClient<true>, environment: CustomGuildsConfiguration, interaction: Interaction) {
127
127
  if (interaction.inCachedGuild()) {
128
128
  await client.handleInteraction(interaction); // Automatic interaction handling
129
129
  }
@@ -136,12 +136,12 @@ export default {
136
136
  ```js
137
137
  import { type CommandStructure, ephemeralFollowUpResponse, type StelliaClient } from "@stelliajs/framework";
138
138
  import { type ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
139
- import { type CustomEnvironment } from "@environments/environment.model.ts";
139
+ import { type CustomGuildsConfiguration } from "@environments/environment.model.ts";
140
140
 
141
141
  export default {
142
142
  data: new SlashCommandBuilder()
143
143
  .setName("ping"),
144
- async execute(client: StelliaClient, environment: CustomEnvironment, interaction: ChatInputCommandInteraction<"cached">) { // All interactions are cached
144
+ async execute(client: StelliaClient, environment: CustomGuildsConfiguration, interaction: ChatInputCommandInteraction<"cached">) { // All interactions are cached
145
145
  await ephemeralFollowUpResponse(interaction, "Pong!", true); // Response is ephemeral and deleted after 60 seconds
146
146
  }
147
147
  } as CommandStructure;
@@ -1,14 +1,15 @@
1
1
  import { Client, type ClientOptions, type Interaction } from "discord.js";
2
2
  import { type ManagerOptions } from "../managers/index.js";
3
- import { type Environment, type EnvironmentConfiguration, type Managers } from "../typescript/index.js";
3
+ import { type ClientEnvironment, type GuildConfigurationType, type GuildsConfiguration, type Managers } from "../typescript/index.js";
4
4
  export declare class StelliaClient<Ready extends boolean = boolean> extends Client<Ready> {
5
5
  private readonly utils;
6
6
  readonly managers: Managers;
7
- readonly environment: Environment;
7
+ readonly environment: ClientEnvironment;
8
8
  constructor(clientOptions: ClientOptions, stelliaOptions?: StelliaOptions);
9
9
  connect: (token: string) => Promise<void>;
10
10
  initializeCommands: () => Promise<void>;
11
- getEnvironment: <CustomEnvironment extends EnvironmentConfiguration>() => Promise<CustomEnvironment>;
11
+ getGuildsConfiguration: <CustomGuildsConfiguration extends GuildsConfiguration>() => Promise<CustomGuildsConfiguration>;
12
+ getGuildConfiguration: (guildId: string) => GuildConfigurationType;
12
13
  handleInteraction: (interaction: Interaction<"cached">) => Promise<void>;
13
14
  private areManagersLoaded;
14
15
  private static convertFilePathToProduction;
@@ -23,6 +24,6 @@ interface StelliaOptions {
23
24
  selectMenus?: ManagerOptions;
24
25
  modals?: ManagerOptions;
25
26
  };
26
- environment?: Environment;
27
+ environment?: ClientEnvironment;
27
28
  }
28
29
  export {};
@@ -4,6 +4,7 @@ import { StelliaUtils } from "./index.js";
4
4
  import path from "path";
5
5
  import * as fs from "node:fs";
6
6
  import { pathToFileURL } from "url";
7
+ import { logger } from "../utils/logger.js";
7
8
  export class StelliaClient extends Client {
8
9
  utils;
9
10
  managers = {};
@@ -36,24 +37,24 @@ export class StelliaClient extends Client {
36
37
  }
37
38
  this.utils = new StelliaUtils(this);
38
39
  process.on("unhandledRejection", (error) => {
39
- console.error(`Unhandled promise rejection: ${error}`);
40
+ logger.error(`Unhandled promise rejection: ${error}`);
40
41
  });
41
42
  }
42
43
  connect = async (token) => {
43
44
  if (!this.areManagersLoaded()) {
44
45
  setTimeout(() => {
45
- console.log("Managers are not loaded yet, retrying in 500ms...");
46
+ logger.warn("Managers are not loaded yet, retrying in 500ms...");
46
47
  this.connect(token);
47
48
  }, 500);
48
49
  return;
49
50
  }
50
- console.log("Managers are loaded, connecting to Discord...");
51
+ logger.success("Managers are loaded, connecting to Discord...");
51
52
  await this.login(token);
52
53
  };
53
54
  initializeCommands = async () => {
54
55
  await this.utils.initializeCommands();
55
56
  };
56
- getEnvironment = async () => {
57
+ getGuildsConfiguration = async () => {
57
58
  const chosenEnvironment = process.argv.find(arg => arg.startsWith("--config"))?.split("=")[1];
58
59
  if (!chosenEnvironment) {
59
60
  throw new Error("Environment not provided");
@@ -82,6 +83,9 @@ export class StelliaClient extends Client {
82
83
  });
83
84
  });
84
85
  };
86
+ getGuildConfiguration = (guildId) => {
87
+ return this.utils.getGuildConfiguration(guildId);
88
+ };
85
89
  handleInteraction = async (interaction) => {
86
90
  await this.utils.handleInteraction(interaction);
87
91
  };
@@ -1,11 +1,13 @@
1
1
  import { type StelliaClient } from "./index.js";
2
2
  import { type Interaction } from "discord.js";
3
+ import { type GuildConfiguration } from "../typescript/index.js";
3
4
  export declare class StelliaUtils {
4
5
  readonly client: StelliaClient;
5
6
  private readonly interactionHandlers;
6
- private environment;
7
+ private guildsConfiguration;
7
8
  constructor(client: StelliaClient);
8
9
  initializeCommands: () => Promise<void>;
10
+ getGuildConfiguration: (guildId: string) => GuildConfiguration | undefined;
9
11
  handleInteraction: (interaction: Interaction<"cached">) => Promise<void>;
10
12
  private handleAutoCompleteInteraction;
11
13
  private handleButtonInteraction;
@@ -1,10 +1,11 @@
1
1
  import { ApplicationCommandType, REST, Routes } from "discord.js";
2
2
  import { DISCORD_API_VERSION } from "../constants/index.js";
3
3
  import { InteractionType } from "../typescript/index.js";
4
+ import { logger } from "../utils/logger.js";
4
5
  export class StelliaUtils {
5
6
  client;
6
7
  interactionHandlers;
7
- environment;
8
+ guildsConfiguration;
8
9
  constructor(client) {
9
10
  this.client = client;
10
11
  this.interactionHandlers = new Map([
@@ -15,13 +16,13 @@ export class StelliaUtils {
15
16
  [InteractionType.ModalSubmit, this.handleModalInteraction],
16
17
  [InteractionType.SelectMenu, this.handleSelectMenuInteraction]
17
18
  ]);
18
- if (this.client.environment.areEnvironmentsEnabled) {
19
- this.client.getEnvironment()
20
- .then((environment) => {
21
- this.environment = environment;
22
- console.log("Environment loaded");
19
+ if (this.client.environment.areGuildsConfigurationEnabled) {
20
+ this.client.getGuildsConfiguration()
21
+ .then((guildsConfiguration) => {
22
+ this.guildsConfiguration = guildsConfiguration;
23
+ logger.success("Guilds configuration loaded successfully for interactions");
23
24
  })
24
- .catch((error) => console.error(error));
25
+ .catch((error) => logger.error(`Error while loading guilds configuration: ${error}`));
25
26
  }
26
27
  }
27
28
  initializeCommands = async () => {
@@ -32,12 +33,21 @@ export class StelliaUtils {
32
33
  const rest = new REST({ version: DISCORD_API_VERSION }).setToken(this.client.token);
33
34
  try {
34
35
  await rest.put(Routes.applicationCommands(this.client.user.id), { body: applicationCommands });
36
+ logger.success("Application commands registered successfully");
35
37
  }
36
38
  catch (error) {
37
- console.error(error);
39
+ logger.error(`Error while registering application commands: ${error}`);
38
40
  }
39
41
  }
40
42
  };
43
+ getGuildConfiguration = (guildId) => {
44
+ if (!this.client.environment.areGuildsConfigurationEnabled || !this.guildsConfiguration) {
45
+ return undefined;
46
+ }
47
+ const { guilds, ...general } = this.guildsConfiguration;
48
+ const guildConfiguration = guilds[guildId];
49
+ return { general, guild: guildConfiguration };
50
+ };
41
51
  handleInteraction = async (interaction) => {
42
52
  if (interaction.inCachedGuild()) {
43
53
  const interactionType = this.getInteractionType(interaction);
@@ -52,21 +62,25 @@ export class StelliaUtils {
52
62
  };
53
63
  handleAutoCompleteInteraction = async (interaction) => {
54
64
  try {
55
- const interactionAutoComplete = interaction;
65
+ const autoCompleteInteraction = interaction;
56
66
  const autoCompleteManager = this.client.managers.autoCompletes;
57
67
  if (!autoCompleteManager)
58
68
  return;
59
- const autoComplete = autoCompleteManager.getByCustomId(interactionAutoComplete.commandName);
69
+ const autoComplete = autoCompleteManager.getByCustomId(autoCompleteInteraction.commandName);
60
70
  if (!autoComplete)
61
71
  return;
62
- if (this.client.environment.areEnvironmentsEnabled) {
63
- await autoComplete.execute(this.client, this.environment, interactionAutoComplete);
64
- return;
72
+ if (this.client.environment.areGuildsConfigurationEnabled) {
73
+ const autoCompleteWithGuildConfiguration = autoComplete;
74
+ const guildConfiguration = this.getGuildConfiguration(autoCompleteInteraction.guildId);
75
+ await autoCompleteWithGuildConfiguration.execute(this.client, guildConfiguration, autoCompleteInteraction);
76
+ }
77
+ else {
78
+ const autoCompleteWithoutGuildConfiguration = autoComplete;
79
+ await autoCompleteWithoutGuildConfiguration.execute(this.client, autoCompleteInteraction);
65
80
  }
66
- await autoComplete.execute(this.client, interactionAutoComplete);
67
81
  }
68
82
  catch (error) {
69
- console.error(error);
83
+ logger.error(`Error while handling autocomplete interaction: ${error}`);
70
84
  }
71
85
  };
72
86
  handleButtonInteraction = async (interaction) => {
@@ -78,33 +92,41 @@ export class StelliaUtils {
78
92
  const button = buttonManager.getByCustomId(buttonInteraction.customId) || buttonManager.getByRegex(buttonInteraction.customId);
79
93
  if (!button)
80
94
  return;
81
- if (this.client.environment.areEnvironmentsEnabled) {
82
- await button.execute(this.client, this.environment, buttonInteraction);
83
- return;
95
+ if (this.client.environment.areGuildsConfigurationEnabled) {
96
+ const buttonWithGuildConfiguration = button;
97
+ const guildConfiguration = this.getGuildConfiguration(buttonInteraction.guildId);
98
+ await buttonWithGuildConfiguration.execute(this.client, guildConfiguration, buttonInteraction);
99
+ }
100
+ else {
101
+ const buttonWithoutGuildConfiguration = button;
102
+ await buttonWithoutGuildConfiguration.execute(this.client, buttonInteraction);
84
103
  }
85
- await button.execute(this.client, buttonInteraction);
86
104
  }
87
105
  catch (error) {
88
- console.error(error);
106
+ logger.error(`Error while handling button interaction: ${error}`);
89
107
  }
90
108
  };
91
109
  handleCommandInteraction = async (interaction) => {
92
110
  try {
93
- const interactionCommand = interaction;
111
+ const commandInteraction = interaction;
94
112
  const commandManager = this.client.managers.commands;
95
113
  if (!commandManager)
96
114
  return;
97
- const command = commandManager.getByCustomId(interactionCommand.commandName);
115
+ let command = commandManager.getByCustomId(commandInteraction.commandName);
98
116
  if (!command)
99
117
  return;
100
- if (this.client.environment.areEnvironmentsEnabled) {
101
- await command.execute(this.client, this.environment, interactionCommand);
102
- return;
118
+ if (this.client.environment.areGuildsConfigurationEnabled) {
119
+ const commandWithGuildConfiguration = command;
120
+ const guildConfiguration = this.getGuildConfiguration(commandInteraction.guildId);
121
+ await commandWithGuildConfiguration.execute(this.client, guildConfiguration, commandInteraction);
122
+ }
123
+ else {
124
+ const commandWithoutGuildConfiguration = command;
125
+ await commandWithoutGuildConfiguration.execute(this.client, commandInteraction);
103
126
  }
104
- await command.execute(this.client, interactionCommand);
105
127
  }
106
128
  catch (error) {
107
- console.error(error);
129
+ logger.error(`Error while handling command interaction: ${error}`);
108
130
  }
109
131
  };
110
132
  handleContextMenuInteraction = async (interaction) => {
@@ -120,45 +142,53 @@ export class StelliaUtils {
120
142
  }
121
143
  }
122
144
  catch (error) {
123
- console.error(error);
145
+ logger.error(`Error while handling context menu interaction: ${error}`);
124
146
  }
125
147
  };
126
148
  handleModalInteraction = async (interaction) => {
127
149
  try {
128
- const interactionModal = interaction;
150
+ const modalInteraction = interaction;
129
151
  const modalManager = this.client.managers.modals;
130
152
  if (!modalManager)
131
153
  return;
132
- const modal = modalManager.getByCustomId(interactionModal.customId) || modalManager.getByRegex(interactionModal.customId);
154
+ const modal = modalManager.getByCustomId(modalInteraction.customId) || modalManager.getByRegex(modalInteraction.customId);
133
155
  if (!modal)
134
156
  return;
135
- if (this.client.environment.areEnvironmentsEnabled) {
136
- await modal.execute(this.client, this.environment, interactionModal);
137
- return;
157
+ if (this.client.environment.areGuildsConfigurationEnabled) {
158
+ const modalWithGuildConfiguration = modal;
159
+ const guildConfiguration = this.getGuildConfiguration(modalInteraction.guildId);
160
+ await modalWithGuildConfiguration.execute(this.client, guildConfiguration, modalInteraction);
161
+ }
162
+ else {
163
+ const modalWithoutGuildConfiguration = modal;
164
+ await modalWithoutGuildConfiguration.execute(this.client, modalInteraction);
138
165
  }
139
- await modal.execute(this.client, interactionModal);
140
166
  }
141
167
  catch (error) {
142
- console.error(error);
168
+ logger.error(`Error while handling modal interaction: ${error}`);
143
169
  }
144
170
  };
145
171
  handleSelectMenuInteraction = async (interaction) => {
146
172
  try {
147
- const interactionSelectMenu = interaction;
173
+ const selectMenuInteraction = interaction;
148
174
  const selectMenuManager = this.client.managers.selectMenus;
149
175
  if (!selectMenuManager)
150
176
  return;
151
- const selectMenu = selectMenuManager.getByCustomId(interactionSelectMenu.customId) || selectMenuManager.getByRegex(interactionSelectMenu.customId);
177
+ const selectMenu = selectMenuManager.getByCustomId(selectMenuInteraction.customId) || selectMenuManager.getByRegex(selectMenuInteraction.customId);
152
178
  if (!selectMenu)
153
179
  return;
154
- if (this.client.environment.areEnvironmentsEnabled) {
155
- await selectMenu.execute(this.client, this.environment, interactionSelectMenu);
156
- return;
180
+ if (this.client.environment.areGuildsConfigurationEnabled) {
181
+ const selectMenuWithGuildConfiguration = selectMenu;
182
+ const guildConfiguration = this.getGuildConfiguration(selectMenuInteraction.guildId);
183
+ await selectMenuWithGuildConfiguration.execute(this.client, guildConfiguration, selectMenuInteraction);
184
+ }
185
+ else {
186
+ const modalWithoutGuildConfiguration = selectMenu;
187
+ await modalWithoutGuildConfiguration.execute(this.client, selectMenuInteraction);
157
188
  }
158
- await selectMenu.execute(this.client, interactionSelectMenu);
159
189
  }
160
190
  catch (error) {
161
- console.error(error);
191
+ logger.error(`Error while handling select menu interaction: ${error}`);
162
192
  }
163
193
  };
164
194
  handleMessageContextMenuInteraction = async (interaction) => {
@@ -169,14 +199,18 @@ export class StelliaUtils {
169
199
  const messageContextMenu = contextMenuManager.getByCustomId(interaction.commandName);
170
200
  if (!messageContextMenu)
171
201
  return;
172
- if (this.client.environment.areEnvironmentsEnabled) {
173
- await messageContextMenu.execute(this.client, this.environment, interaction);
174
- return;
202
+ if (this.client.environment.areGuildsConfigurationEnabled) {
203
+ const messageContextMenuWithGuildConfiguration = messageContextMenu;
204
+ const guildConfiguration = this.getGuildConfiguration(interaction.guildId);
205
+ await messageContextMenuWithGuildConfiguration.execute(this.client, guildConfiguration, interaction);
206
+ }
207
+ else {
208
+ const messageContextMenuWithoutGuildConfiguration = messageContextMenu;
209
+ await messageContextMenuWithoutGuildConfiguration.execute(this.client, interaction);
175
210
  }
176
- await messageContextMenu.execute(this.client, interaction);
177
211
  }
178
212
  catch (error) {
179
- console.error(error);
213
+ logger.error(`Error while handling message context menu interaction: ${error}`);
180
214
  }
181
215
  };
182
216
  handleUserContextMenuInteraction = async (interaction) => {
@@ -187,14 +221,18 @@ export class StelliaUtils {
187
221
  const userContextMenu = contextMenuManager.getByCustomId(interaction.commandName);
188
222
  if (!userContextMenu)
189
223
  return;
190
- if (this.client.environment.areEnvironmentsEnabled) {
191
- await userContextMenu.execute(this.client, this.environment, interaction);
192
- return;
224
+ if (this.client.environment.areGuildsConfigurationEnabled) {
225
+ const userContextMenuWithGuildConfiguration = userContextMenu;
226
+ const guildConfiguration = this.getGuildConfiguration(interaction.guildId);
227
+ await userContextMenuWithGuildConfiguration.execute(this.client, guildConfiguration, interaction);
228
+ }
229
+ else {
230
+ const userContextMenuWithoutGuildConfiguration = userContextMenu;
231
+ await userContextMenuWithoutGuildConfiguration.execute(this.client, interaction);
193
232
  }
194
- await userContextMenu.execute(this.client, interaction);
195
233
  }
196
234
  catch (error) {
197
- console.error(error);
235
+ logger.error(`Error while handling user context menu interaction: ${error}`);
198
236
  }
199
237
  };
200
238
  getInteractionType(interaction) {
@@ -4,9 +4,14 @@ import { BaseManager } from "./index.js";
4
4
  import { type StructureCustomId, type InteractionCustomId } from "../typescript/index.js";
5
5
  export declare class EventManager extends BaseManager {
6
6
  private interactions;
7
+ private guildsConfiguration;
7
8
  constructor(client: StelliaClient, directoryPath: string);
8
9
  loadData(): Promise<void>;
9
10
  getByCustomId<EventStructure>(id: InteractionCustomId): EventStructure | undefined;
10
11
  getByRegex<EventStructure>(id: InteractionCustomId): EventStructure | undefined;
11
12
  getAll<EventStructure>(): Collection<StructureCustomId, EventStructure>;
13
+ private loadEventWithGuildConfiguration;
14
+ private eventHandler;
15
+ private loadEventWithoutGuildConfiguration;
16
+ private getGuildConfiguration;
12
17
  }
@@ -1,43 +1,33 @@
1
1
  import { Collection, Events } from "discord.js";
2
2
  import { BaseManager } from "./index.js";
3
3
  import { requiredFiles } from "../utils/index.js";
4
+ import { logger } from "../utils/logger.js";
4
5
  export class EventManager extends BaseManager {
5
6
  interactions = new Collection();
7
+ guildsConfiguration;
6
8
  constructor(client, directoryPath) {
7
9
  super(client, directoryPath);
10
+ if (this.client.environment.areGuildsConfigurationEnabled) {
11
+ this.client.getGuildsConfiguration()
12
+ .then((guildsConfiguration) => {
13
+ this.guildsConfiguration = guildsConfiguration;
14
+ logger.success("Guilds configuration loaded successfully for event manager");
15
+ })
16
+ .catch((error) => logger.error(`Error while loading guilds configuration: ${error}`));
17
+ }
8
18
  }
9
19
  async loadData() {
10
20
  const events = await requiredFiles(this.directoryPath);
11
21
  this.interactions = events;
12
- for (const event of this.interactions.values()) {
13
- const { name, once } = event.data;
14
- if (this.client.environment.areEnvironmentsEnabled) {
15
- const environment = await this.client.getEnvironment();
16
- if (name == Events.ClientReady) {
17
- this.client.once(name, () => event.execute(this.client, environment));
18
- continue;
19
- }
20
- if (once) {
21
- this.client.once(name, (...args) => event.execute(this.client, environment, ...args));
22
- }
23
- else {
24
- this.client.on(name, (...args) => event.execute(this.client, environment, ...args));
25
- }
22
+ for (const eventStructure of this.interactions.values()) {
23
+ if (this.client.environment.areGuildsConfigurationEnabled) {
24
+ await this.loadEventWithGuildConfiguration(eventStructure);
26
25
  }
27
26
  else {
28
- if (name == Events.ClientReady) {
29
- this.client.once(name, () => event.execute(this.client));
30
- continue;
31
- }
32
- if (once) {
33
- this.client.once(name, (...args) => event.execute(this.client, ...args));
34
- }
35
- else {
36
- this.client.on(name, (...args) => event.execute(this.client, ...args));
37
- }
27
+ await this.loadEventWithoutGuildConfiguration(eventStructure);
38
28
  }
39
29
  }
40
- this.client.on(Events.Error, (error) => console.error(error));
30
+ this.client.on(Events.Error, (error) => logger.error(`Client error: ${error}`));
41
31
  this.setManagerLoaded();
42
32
  }
43
33
  getByCustomId(id) {
@@ -51,4 +41,48 @@ export class EventManager extends BaseManager {
51
41
  const events = this.interactions;
52
42
  return events;
53
43
  }
44
+ async loadEventWithGuildConfiguration(eventStructure) {
45
+ const { name, once } = eventStructure.data;
46
+ const event = eventStructure;
47
+ if (once) {
48
+ this.client.once(name, (...args) => this.eventHandler(event, ...args));
49
+ }
50
+ else {
51
+ this.client.on(name, (...args) => this.eventHandler(event, ...args));
52
+ }
53
+ }
54
+ eventHandler = (event, ...args) => {
55
+ const mainArgument = args[0];
56
+ if (!mainArgument) {
57
+ const eventStructure = event;
58
+ return eventStructure.execute(this.client, this.guildsConfiguration);
59
+ }
60
+ const guildConfiguration = this.getGuildConfiguration(mainArgument);
61
+ if (guildConfiguration) {
62
+ const eventStructure = event;
63
+ return eventStructure.execute(this.client, guildConfiguration, ...args);
64
+ }
65
+ logger.warn(`No guild configuration found for event ${event.data.name} with main argument ${mainArgument}`);
66
+ };
67
+ async loadEventWithoutGuildConfiguration(eventStructure) {
68
+ const { name, once } = eventStructure.data;
69
+ const event = eventStructure;
70
+ if (once) {
71
+ this.client.once(name, (...args) => event.execute(this.client, ...args));
72
+ }
73
+ else {
74
+ this.client.on(name, (...args) => event.execute(this.client, ...args));
75
+ }
76
+ }
77
+ getGuildConfiguration(mainArgument) {
78
+ if (mainArgument && typeof mainArgument === "object") {
79
+ if ("guildId" in mainArgument && mainArgument.guildId) {
80
+ return this.client.getGuildConfiguration(mainArgument.guildId);
81
+ }
82
+ if ("guild" in mainArgument && mainArgument.guild) {
83
+ return this.client.getGuildConfiguration(mainArgument.guild.id);
84
+ }
85
+ }
86
+ return undefined;
87
+ }
54
88
  }
@@ -1,14 +1,24 @@
1
1
  import { type Awaitable, type ClientEvents } from "discord.js";
2
2
  import { type StelliaClient } from "../client/index.js";
3
- import type { EnvironmentConfiguration } from "../typescript/types.js";
4
- export interface EventStructure<Event extends keyof ClientEvents = keyof ClientEvents> {
5
- data: {
6
- name: Event;
7
- once: boolean;
8
- };
9
- execute(client: StelliaClient): Awaitable<unknown>;
10
- execute(...args: ClientEvents[Event]): Awaitable<unknown>;
11
- execute(client: StelliaClient, ...args: ClientEvents[Event]): Awaitable<unknown>;
12
- execute<CustomEnvironment extends EnvironmentConfiguration>(client: StelliaClient, environment: CustomEnvironment): Awaitable<unknown>;
13
- execute<CustomEnvironment extends EnvironmentConfiguration>(client: StelliaClient, environment: CustomEnvironment, ...args: ClientEvents[Event]): Awaitable<unknown>;
3
+ import { type GuildConfigurationType, type GuildsConfiguration } from "../typescript/types.js";
4
+ export interface EventStructureWithGuildConfiguration extends EventInteractionStructure {
5
+ execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, ...args: ClientEventsArgs): Awaitable<unknown>;
14
6
  }
7
+ export interface EventStructureWithAllGuildsConfiguration extends EventInteractionStructure {
8
+ execute(client: StelliaClient, guildsConfiguration: GuildsConfiguration, ...args: ClientEventsArgs): Awaitable<unknown>;
9
+ }
10
+ export interface EventStructureWithoutGuildConfiguration extends EventInteractionStructure {
11
+ execute(client: StelliaClient, ...args: ClientEventsArgs): Awaitable<unknown>;
12
+ }
13
+ export type EventStructureWithConfiguration = EventStructureWithGuildConfiguration | EventStructureWithAllGuildsConfiguration;
14
+ export type EventStructure = EventStructureWithGuildConfiguration | EventStructureWithAllGuildsConfiguration | EventStructureWithoutGuildConfiguration;
15
+ interface EventInteractionStructure {
16
+ data: EventDataStructure;
17
+ }
18
+ interface EventDataStructure {
19
+ name: EventKeys;
20
+ once: boolean;
21
+ }
22
+ export type ClientEventsArgs = ClientEvents[keyof ClientEvents];
23
+ export type EventKeys = keyof ClientEvents;
24
+ export {};
@@ -1,39 +1,64 @@
1
- import { type AnySelectMenuInteraction, type AutocompleteInteraction, type Awaitable, type ButtonInteraction, type ChatInputCommandInteraction, type ContextMenuCommandBuilder, type MessageContextMenuCommandInteraction, type ModalSubmitInteraction, type SlashCommandBuilder, type UserContextMenuCommandInteraction } from "discord.js";
1
+ import { type AnySelectMenuInteraction, type AutocompleteInteraction, type Awaitable, type ButtonInteraction, type ChatInputCommandInteraction, type ContextMenuCommandType, type MessageContextMenuCommandInteraction, type ModalSubmitInteraction, type SlashCommandOptionsOnlyBuilder, type UserContextMenuCommandInteraction } from "discord.js";
2
2
  import { type StelliaClient } from "../client/index.js";
3
- import { type EnvironmentConfiguration } from "../typescript/index.js";
3
+ import { type GuildConfigurationType } from "../typescript/index.js";
4
4
  import { type EventStructure } from "./Event.js";
5
- export interface AutoCompleteStructure {
6
- data: DefaultDataStructure;
5
+ export interface AutoCompleteStructureWithGuildConfiguration extends MessageInteractionStructure {
6
+ execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: AutocompleteInteraction<"cached">): Awaitable<unknown>;
7
+ }
8
+ export interface AutoCompleteStructureWithoutGuildConfiguration extends MessageInteractionStructure {
7
9
  execute(client: StelliaClient, interaction: AutocompleteInteraction<"cached">): Awaitable<unknown>;
8
- execute<CustomEnvironment extends EnvironmentConfiguration>(client: StelliaClient, environment: CustomEnvironment, interaction: AutocompleteInteraction<"cached">): Awaitable<unknown>;
9
10
  }
10
- export interface ButtonStructure {
11
- data: DefaultDataStructure;
11
+ export type AutoCompleteStructure = AutoCompleteStructureWithGuildConfiguration | AutoCompleteStructureWithoutGuildConfiguration;
12
+ export interface ButtonStructureWithGuildConfiguration extends MessageInteractionStructure {
13
+ execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: ButtonInteraction<"cached">): Awaitable<unknown>;
14
+ }
15
+ export interface ButtonStructureWithoutGuildConfiguration extends MessageInteractionStructure {
12
16
  execute(client: StelliaClient, interaction: ButtonInteraction<"cached">): Awaitable<unknown>;
13
- execute<CustomEnvironment extends EnvironmentConfiguration>(client: StelliaClient, environment: CustomEnvironment, interaction: ButtonInteraction<"cached">): Awaitable<unknown>;
14
17
  }
15
- export interface CommandStructure {
16
- data: SlashCommandBuilder;
18
+ export type ButtonStructure = ButtonStructureWithGuildConfiguration | ButtonStructureWithoutGuildConfiguration;
19
+ export interface CommandStructureWithGuildConfiguration extends CommandInteractionStructure {
20
+ execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: ChatInputCommandInteraction<"cached">): Awaitable<unknown>;
21
+ }
22
+ export interface CommandStructureWithoutGuildConfiguration extends CommandInteractionStructure {
17
23
  execute(client: StelliaClient, interaction: ChatInputCommandInteraction<"cached">): Awaitable<unknown>;
18
- execute<CustomEnvironment extends EnvironmentConfiguration>(client: StelliaClient, environment: CustomEnvironment, interaction: ChatInputCommandInteraction<"cached">): Awaitable<unknown>;
19
24
  }
20
- export interface ContextMenuStructure {
21
- data: ContextMenuCommandBuilder;
25
+ export type CommandStructure = CommandStructureWithGuildConfiguration | CommandStructureWithoutGuildConfiguration;
26
+ export interface ContextMenuStructureWithGuildConfiguration extends ContextMenuInteractionStructure {
27
+ execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: MessageContextMenuCommandInteraction<"cached"> | UserContextMenuCommandInteraction<"cached">): Awaitable<unknown>;
28
+ }
29
+ export interface ContextMenuStructureWithoutGuildConfiguration extends ContextMenuInteractionStructure {
22
30
  execute(client: StelliaClient, interaction: MessageContextMenuCommandInteraction<"cached"> | UserContextMenuCommandInteraction<"cached">): Awaitable<unknown>;
23
- execute<CustomEnvironment extends EnvironmentConfiguration>(client: StelliaClient, environment: CustomEnvironment, interaction: MessageContextMenuCommandInteraction<"cached"> | UserContextMenuCommandInteraction<"cached">): Awaitable<unknown>;
24
31
  }
25
- export interface ModalStructure {
26
- data: DefaultDataStructure;
32
+ export type ContextMenuStructure = ContextMenuStructureWithGuildConfiguration | ContextMenuStructureWithoutGuildConfiguration;
33
+ export interface ModalStructureWithGuildConfiguration extends MessageInteractionStructure {
34
+ execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: ModalSubmitInteraction<"cached">): Awaitable<unknown>;
35
+ }
36
+ export interface ModalStructureWithoutGuildConfiguration extends MessageInteractionStructure {
27
37
  execute(client: StelliaClient, interaction: ModalSubmitInteraction<"cached">): Awaitable<unknown>;
28
- execute<CustomEnvironment extends EnvironmentConfiguration>(client: StelliaClient, environment: CustomEnvironment, interaction: ModalSubmitInteraction<"cached">): Awaitable<unknown>;
29
38
  }
30
- export interface SelectMenuStructure {
31
- data: DefaultDataStructure;
39
+ export type ModalStructure = ModalStructureWithGuildConfiguration | ModalStructureWithoutGuildConfiguration;
40
+ export interface SelectMenuStructureWithGuildConfiguration extends MessageInteractionStructure {
41
+ execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: AnySelectMenuInteraction<"cached">): Awaitable<unknown>;
42
+ }
43
+ export interface SelectMenuStructureWithoutGuildConfiguration extends MessageInteractionStructure {
32
44
  execute(client: StelliaClient, interaction: AnySelectMenuInteraction<"cached">): Awaitable<unknown>;
33
- execute<CustomEnvironment extends EnvironmentConfiguration>(client: StelliaClient, environment: CustomEnvironment, interaction: AnySelectMenuInteraction<"cached">): Awaitable<unknown>;
34
45
  }
46
+ export type SelectMenuStructure = SelectMenuStructureWithGuildConfiguration | SelectMenuStructureWithoutGuildConfiguration;
35
47
  export type AnyInteractionStructure = AutoCompleteStructure | ButtonStructure | CommandStructure | ContextMenuStructure | EventStructure | ModalStructure | SelectMenuStructure;
36
- interface DefaultDataStructure {
48
+ interface CommandInteractionStructure {
49
+ data: SlashCommandOptionsOnlyBuilder;
50
+ }
51
+ interface ContextMenuInteractionStructure {
52
+ data: ContextMenuDataStructure;
53
+ }
54
+ interface ContextMenuDataStructure {
55
+ name: string;
56
+ type: ContextMenuCommandType;
57
+ }
58
+ interface MessageInteractionStructure {
59
+ data: MessageDataStructure;
60
+ }
61
+ interface MessageDataStructure {
37
62
  name: string | RegExp;
38
63
  once: boolean;
39
64
  }
@@ -20,9 +20,26 @@ export interface Managers {
20
20
  selectMenus?: SelectMenuManager;
21
21
  modals?: ModalManager;
22
22
  }
23
- export interface Environment {
24
- areEnvironmentsEnabled: boolean;
23
+ export interface ClientEnvironment {
24
+ areGuildsConfigurationEnabled: boolean;
25
25
  }
26
- export interface EnvironmentConfiguration {
26
+ export interface BaseGuildConfiguration {
27
+ locale: string;
27
28
  [key: string]: unknown;
28
29
  }
30
+ export interface BaseGeneralConfiguration {
31
+ [key: string]: unknown;
32
+ }
33
+ export interface GuildsConfiguration {
34
+ general: {
35
+ [key: string]: unknown;
36
+ };
37
+ guilds: {
38
+ [guildId: string]: BaseGuildConfiguration;
39
+ };
40
+ }
41
+ export interface GuildConfiguration {
42
+ general: BaseGeneralConfiguration;
43
+ guild: BaseGuildConfiguration;
44
+ }
45
+ export type GuildConfigurationType = GuildConfiguration | undefined;
@@ -0,0 +1,6 @@
1
+ export declare const logger: {
2
+ info: (message: string) => void;
3
+ success: (message: string) => void;
4
+ warn: (message: string) => void;
5
+ error: (message: string) => void;
6
+ };
@@ -0,0 +1,15 @@
1
+ import logSymbols from "log-symbols";
2
+ export const logger = {
3
+ info: (message) => {
4
+ console.log(`${logSymbols.info} ${message}`);
5
+ },
6
+ success: (message) => {
7
+ console.log(`${logSymbols.success} ${message}`);
8
+ },
9
+ warn: (message) => {
10
+ console.warn(`${logSymbols.warning} ${message}`);
11
+ },
12
+ error: (message) => {
13
+ console.error(`${logSymbols.error} ${message}`);
14
+ }
15
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stelliajs/framework",
3
- "version": "1.2.3",
3
+ "version": "1.3.0-dev-2",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "scripts": {
@@ -15,12 +15,14 @@
15
15
  "description": "A framework for simplify the creation of discord bots",
16
16
  "keywords": ["discord", "bot", "discordjs", "typescript", "framework"],
17
17
  "dependencies": {
18
- "discord-api-types": "^0.37.119",
19
- "discord.js": "^14.18.0"
18
+ "discord-api-types": "^0.38.10",
19
+ "discord.js": "^14.19.3",
20
+ "log-symbols": "^7.0.1"
20
21
  },
21
22
  "devDependencies": {
22
23
  "ts-node": "^10.9.2",
23
- "tsc-alias": "^1.8.10"
24
+ "tsc-alias": "^1.8.16"
24
25
  },
25
- "type": "module"
26
+ "type": "module",
27
+ "packageManager": "pnpm@10.11.1"
26
28
  }