@stelliajs/framework 1.3.0-dev-1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -28
- package/dist/client/StelliaClient.d.ts +5 -4
- package/dist/client/StelliaClient.js +11 -7
- package/dist/client/StelliaUtils.d.ts +3 -1
- package/dist/client/StelliaUtils.js +71 -51
- package/dist/managers/EventManager.d.ts +5 -0
- package/dist/managers/EventManager.js +55 -27
- package/dist/structures/Event.d.ts +13 -8
- package/dist/structures/Interaction.d.ts +25 -25
- package/dist/typescript/types.d.ts +21 -3
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.js +15 -0
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## About
|
|
4
4
|
|
|
5
5
|
StelliaJS is built using Discord JS V14 and TypeScript. It allows you to quickly set up a new bot with a simple and complete architecture.
|
|
6
|
-
A CLI is
|
|
6
|
+
A CLI is available to help you set up a project with StelliaJS : [link to the CLI](https://github.com/StelliaJS/cli)
|
|
7
7
|
|
|
8
8
|
## Architecture
|
|
9
9
|
Recommended architecture for StelliaJS project.
|
|
@@ -19,6 +19,10 @@ Recommended architecture for StelliaJS project.
|
|
|
19
19
|
│ │ │ ├── ban.ts
|
|
20
20
|
│ │ │ └── mute.ts
|
|
21
21
|
│ │ └── ping.ts
|
|
22
|
+
│ ├── environments/
|
|
23
|
+
│ │ ├── environment.development.ts
|
|
24
|
+
│ │ ├── environment.model.ts
|
|
25
|
+
│ │ └── environment.ts
|
|
22
26
|
│ ├── events/
|
|
23
27
|
│ │ ├── ready.ts
|
|
24
28
|
│ │ └── interactionCreate.ts
|
|
@@ -36,16 +40,17 @@ Recommended architecture for StelliaJS project.
|
|
|
36
40
|
├── .env
|
|
37
41
|
├── package.json
|
|
38
42
|
├── package-lock.json
|
|
43
|
+
├── stellia.json
|
|
39
44
|
└── tsconfig.json
|
|
40
45
|
```
|
|
46
|
+
|
|
41
47
|
## Examples
|
|
42
48
|
|
|
43
|
-
### Simple client
|
|
49
|
+
### Simple client with environment
|
|
44
50
|
|
|
45
51
|
```js
|
|
46
52
|
import { StelliaClient } from "@stelliajs/framework";
|
|
47
|
-
import { GatewayIntentBits } from "discord
|
|
48
|
-
import { Partials } from "discord.js";
|
|
53
|
+
import { GatewayIntentBits, Partials } from "discord.js";
|
|
49
54
|
|
|
50
55
|
const client = new StelliaClient({
|
|
51
56
|
intents: [
|
|
@@ -56,26 +61,31 @@ const client = new StelliaClient({
|
|
|
56
61
|
],
|
|
57
62
|
partials: [Partials.Message, Partials.GuildMember]
|
|
58
63
|
}, {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
managers: {
|
|
65
|
+
autoCompletes: {
|
|
66
|
+
directoryPath: "./interactions/autoCompletes"
|
|
67
|
+
},
|
|
68
|
+
buttons: {
|
|
69
|
+
directoryPath: "./interactions/buttons"
|
|
70
|
+
},
|
|
71
|
+
commands: {
|
|
72
|
+
directoryPath: "./commands/slash"
|
|
73
|
+
},
|
|
74
|
+
contextMenus: {
|
|
75
|
+
directoryPath: "./commands/contextMenus"
|
|
76
|
+
},
|
|
77
|
+
events: {
|
|
78
|
+
directoryPath: "./events"
|
|
79
|
+
},
|
|
80
|
+
modals: {
|
|
81
|
+
directoryPath: "./interactions/modals"
|
|
82
|
+
},
|
|
83
|
+
selectMenus: {
|
|
84
|
+
directoryPath: "./interactions/selectMenus"
|
|
85
|
+
}
|
|
76
86
|
},
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
environment: {
|
|
88
|
+
areGuildsConfigurationEnabled: true
|
|
79
89
|
}
|
|
80
90
|
});
|
|
81
91
|
|
|
@@ -84,34 +94,36 @@ await client.connect(process.env.TOKEN);
|
|
|
84
94
|
|
|
85
95
|
### Simple event
|
|
86
96
|
|
|
87
|
-
#### Ready event
|
|
97
|
+
#### Ready event with environment
|
|
88
98
|
```js
|
|
89
99
|
import { type StelliaClient, type EventStructure } from "@stelliajs/framework";
|
|
90
100
|
import { Events } from "discord.js";
|
|
101
|
+
import { type CustomGuildsConfiguration } from "@environments/environment.model.ts";
|
|
91
102
|
|
|
92
103
|
export default {
|
|
93
104
|
data: {
|
|
94
105
|
name: Events.ClientReady,
|
|
95
106
|
once: true
|
|
96
107
|
},
|
|
97
|
-
async execute(client: StelliaClient<true
|
|
108
|
+
async execute(client: StelliaClient<true>, environment: CustomGuildsConfiguration) { // <true> ensures that the client is Ready
|
|
98
109
|
console.log(`Logged in as ${client.user.tag}`);
|
|
99
110
|
await client.initializeCommands(); // Used to initialise registered commands
|
|
100
111
|
}
|
|
101
112
|
} as EventStructure;
|
|
102
113
|
```
|
|
103
114
|
|
|
104
|
-
#### InteractionCreate event
|
|
115
|
+
#### InteractionCreate event with environment
|
|
105
116
|
```js
|
|
106
117
|
import { type StelliaClient, type EventStructure } from "@stelliajs/framework";
|
|
107
118
|
import { Events, type Interaction } from "discord.js";
|
|
119
|
+
import { type CustomGuildsConfiguration } from "@environments/environment.model.ts";
|
|
108
120
|
|
|
109
121
|
export default {
|
|
110
122
|
data: {
|
|
111
123
|
name: Events.InteractionCreate,
|
|
112
124
|
once: false
|
|
113
125
|
},
|
|
114
|
-
async execute(client: StelliaClient<true>, interaction: Interaction) {
|
|
126
|
+
async execute(client: StelliaClient<true>, environment: CustomGuildsConfiguration, interaction: Interaction) {
|
|
115
127
|
if (interaction.inCachedGuild()) {
|
|
116
128
|
await client.handleInteraction(interaction); // Automatic interaction handling
|
|
117
129
|
}
|
|
@@ -124,11 +136,12 @@ export default {
|
|
|
124
136
|
```js
|
|
125
137
|
import { type CommandStructure, ephemeralFollowUpResponse, type StelliaClient } from "@stelliajs/framework";
|
|
126
138
|
import { type ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
|
139
|
+
import { type CustomGuildsConfiguration } from "@environments/environment.model.ts";
|
|
127
140
|
|
|
128
141
|
export default {
|
|
129
142
|
data: new SlashCommandBuilder()
|
|
130
143
|
.setName("ping"),
|
|
131
|
-
async execute(client: StelliaClient, interaction: ChatInputCommandInteraction<"cached">) { // All interactions are cached
|
|
144
|
+
async execute(client: StelliaClient, environment: CustomGuildsConfiguration, interaction: ChatInputCommandInteraction<"cached">) { // All interactions are cached
|
|
132
145
|
await ephemeralFollowUpResponse(interaction, "Pong!", true); // Response is ephemeral and deleted after 60 seconds
|
|
133
146
|
}
|
|
134
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
|
|
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:
|
|
7
|
+
readonly environment: ClientEnvironment;
|
|
8
8
|
constructor(clientOptions: ClientOptions, stelliaOptions?: StelliaOptions);
|
|
9
9
|
connect: (token: string) => Promise<void>;
|
|
10
10
|
initializeCommands: () => Promise<void>;
|
|
11
|
-
|
|
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?:
|
|
27
|
+
environment?: ClientEnvironment;
|
|
27
28
|
}
|
|
28
29
|
export {};
|
|
@@ -4,12 +4,16 @@ 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 = {};
|
|
10
11
|
environment;
|
|
11
12
|
constructor(clientOptions, stelliaOptions) {
|
|
12
13
|
super(clientOptions);
|
|
14
|
+
if (stelliaOptions?.environment) {
|
|
15
|
+
this.environment = stelliaOptions.environment;
|
|
16
|
+
}
|
|
13
17
|
if (stelliaOptions?.managers.autoCompletes?.directoryPath) {
|
|
14
18
|
this.managers.autoCompletes = new AutoCompleteManager(this, stelliaOptions.managers.autoCompletes.directoryPath);
|
|
15
19
|
}
|
|
@@ -31,29 +35,26 @@ export class StelliaClient extends Client {
|
|
|
31
35
|
if (stelliaOptions?.managers.modals?.directoryPath) {
|
|
32
36
|
this.managers.modals = new ModalManager(this, stelliaOptions.managers.modals.directoryPath);
|
|
33
37
|
}
|
|
34
|
-
if (stelliaOptions?.environment) {
|
|
35
|
-
this.environment = stelliaOptions.environment;
|
|
36
|
-
}
|
|
37
38
|
this.utils = new StelliaUtils(this);
|
|
38
39
|
process.on("unhandledRejection", (error) => {
|
|
39
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
19
|
-
this.client.
|
|
20
|
-
.then((
|
|
21
|
-
this.
|
|
22
|
-
|
|
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) =>
|
|
25
|
+
.catch((error) => logger.error(`Error while loading guilds configuration: ${error}`));
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
initializeCommands = async () => {
|
|
@@ -32,12 +33,24 @@ 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
|
-
|
|
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 {
|
|
50
|
+
general: general,
|
|
51
|
+
guild: guildConfiguration
|
|
52
|
+
};
|
|
53
|
+
};
|
|
41
54
|
handleInteraction = async (interaction) => {
|
|
42
55
|
if (interaction.inCachedGuild()) {
|
|
43
56
|
const interactionType = this.getInteractionType(interaction);
|
|
@@ -59,17 +72,18 @@ export class StelliaUtils {
|
|
|
59
72
|
const autoComplete = autoCompleteManager.getByCustomId(autoCompleteInteraction.commandName);
|
|
60
73
|
if (!autoComplete)
|
|
61
74
|
return;
|
|
62
|
-
if (this.client.environment.
|
|
63
|
-
const
|
|
64
|
-
|
|
75
|
+
if (this.client.environment.areGuildsConfigurationEnabled) {
|
|
76
|
+
const autoCompleteWithGuildConfiguration = autoComplete;
|
|
77
|
+
const guildConfiguration = this.getGuildConfiguration(autoCompleteInteraction.guildId);
|
|
78
|
+
await autoCompleteWithGuildConfiguration.execute(this.client, guildConfiguration, autoCompleteInteraction);
|
|
65
79
|
}
|
|
66
80
|
else {
|
|
67
|
-
const
|
|
68
|
-
await
|
|
81
|
+
const autoCompleteWithoutGuildConfiguration = autoComplete;
|
|
82
|
+
await autoCompleteWithoutGuildConfiguration.execute(this.client, autoCompleteInteraction);
|
|
69
83
|
}
|
|
70
84
|
}
|
|
71
85
|
catch (error) {
|
|
72
|
-
|
|
86
|
+
logger.error(`Error while handling autocomplete interaction: ${error}`);
|
|
73
87
|
}
|
|
74
88
|
};
|
|
75
89
|
handleButtonInteraction = async (interaction) => {
|
|
@@ -81,17 +95,18 @@ export class StelliaUtils {
|
|
|
81
95
|
const button = buttonManager.getByCustomId(buttonInteraction.customId) || buttonManager.getByRegex(buttonInteraction.customId);
|
|
82
96
|
if (!button)
|
|
83
97
|
return;
|
|
84
|
-
if (this.client.environment.
|
|
85
|
-
const
|
|
86
|
-
|
|
98
|
+
if (this.client.environment.areGuildsConfigurationEnabled) {
|
|
99
|
+
const buttonWithGuildConfiguration = button;
|
|
100
|
+
const guildConfiguration = this.getGuildConfiguration(buttonInteraction.guildId);
|
|
101
|
+
await buttonWithGuildConfiguration.execute(this.client, guildConfiguration, buttonInteraction);
|
|
87
102
|
}
|
|
88
103
|
else {
|
|
89
|
-
const
|
|
90
|
-
await
|
|
104
|
+
const buttonWithoutGuildConfiguration = button;
|
|
105
|
+
await buttonWithoutGuildConfiguration.execute(this.client, buttonInteraction);
|
|
91
106
|
}
|
|
92
107
|
}
|
|
93
108
|
catch (error) {
|
|
94
|
-
|
|
109
|
+
logger.error(`Error while handling button interaction: ${error}`);
|
|
95
110
|
}
|
|
96
111
|
};
|
|
97
112
|
handleCommandInteraction = async (interaction) => {
|
|
@@ -103,17 +118,18 @@ export class StelliaUtils {
|
|
|
103
118
|
let command = commandManager.getByCustomId(commandInteraction.commandName);
|
|
104
119
|
if (!command)
|
|
105
120
|
return;
|
|
106
|
-
if (this.client.environment.
|
|
107
|
-
const
|
|
108
|
-
|
|
121
|
+
if (this.client.environment.areGuildsConfigurationEnabled) {
|
|
122
|
+
const commandWithGuildConfiguration = command;
|
|
123
|
+
const guildConfiguration = this.getGuildConfiguration(commandInteraction.guildId);
|
|
124
|
+
await commandWithGuildConfiguration.execute(this.client, guildConfiguration, commandInteraction);
|
|
109
125
|
}
|
|
110
126
|
else {
|
|
111
|
-
const
|
|
112
|
-
await
|
|
127
|
+
const commandWithoutGuildConfiguration = command;
|
|
128
|
+
await commandWithoutGuildConfiguration.execute(this.client, commandInteraction);
|
|
113
129
|
}
|
|
114
130
|
}
|
|
115
131
|
catch (error) {
|
|
116
|
-
|
|
132
|
+
logger.error(`Error while handling command interaction: ${error}`);
|
|
117
133
|
}
|
|
118
134
|
};
|
|
119
135
|
handleContextMenuInteraction = async (interaction) => {
|
|
@@ -129,7 +145,7 @@ export class StelliaUtils {
|
|
|
129
145
|
}
|
|
130
146
|
}
|
|
131
147
|
catch (error) {
|
|
132
|
-
|
|
148
|
+
logger.error(`Error while handling context menu interaction: ${error}`);
|
|
133
149
|
}
|
|
134
150
|
};
|
|
135
151
|
handleModalInteraction = async (interaction) => {
|
|
@@ -141,17 +157,18 @@ export class StelliaUtils {
|
|
|
141
157
|
const modal = modalManager.getByCustomId(modalInteraction.customId) || modalManager.getByRegex(modalInteraction.customId);
|
|
142
158
|
if (!modal)
|
|
143
159
|
return;
|
|
144
|
-
if (this.client.environment.
|
|
145
|
-
const
|
|
146
|
-
|
|
160
|
+
if (this.client.environment.areGuildsConfigurationEnabled) {
|
|
161
|
+
const modalWithGuildConfiguration = modal;
|
|
162
|
+
const guildConfiguration = this.getGuildConfiguration(modalInteraction.guildId);
|
|
163
|
+
await modalWithGuildConfiguration.execute(this.client, guildConfiguration, modalInteraction);
|
|
147
164
|
}
|
|
148
165
|
else {
|
|
149
|
-
const
|
|
150
|
-
await
|
|
166
|
+
const modalWithoutGuildConfiguration = modal;
|
|
167
|
+
await modalWithoutGuildConfiguration.execute(this.client, modalInteraction);
|
|
151
168
|
}
|
|
152
169
|
}
|
|
153
170
|
catch (error) {
|
|
154
|
-
|
|
171
|
+
logger.error(`Error while handling modal interaction: ${error}`);
|
|
155
172
|
}
|
|
156
173
|
};
|
|
157
174
|
handleSelectMenuInteraction = async (interaction) => {
|
|
@@ -163,17 +180,18 @@ export class StelliaUtils {
|
|
|
163
180
|
const selectMenu = selectMenuManager.getByCustomId(selectMenuInteraction.customId) || selectMenuManager.getByRegex(selectMenuInteraction.customId);
|
|
164
181
|
if (!selectMenu)
|
|
165
182
|
return;
|
|
166
|
-
if (this.client.environment.
|
|
167
|
-
const
|
|
168
|
-
|
|
183
|
+
if (this.client.environment.areGuildsConfigurationEnabled) {
|
|
184
|
+
const selectMenuWithGuildConfiguration = selectMenu;
|
|
185
|
+
const guildConfiguration = this.getGuildConfiguration(selectMenuInteraction.guildId);
|
|
186
|
+
await selectMenuWithGuildConfiguration.execute(this.client, guildConfiguration, selectMenuInteraction);
|
|
169
187
|
}
|
|
170
188
|
else {
|
|
171
|
-
const
|
|
172
|
-
await
|
|
189
|
+
const modalWithoutGuildConfiguration = selectMenu;
|
|
190
|
+
await modalWithoutGuildConfiguration.execute(this.client, selectMenuInteraction);
|
|
173
191
|
}
|
|
174
192
|
}
|
|
175
193
|
catch (error) {
|
|
176
|
-
|
|
194
|
+
logger.error(`Error while handling select menu interaction: ${error}`);
|
|
177
195
|
}
|
|
178
196
|
};
|
|
179
197
|
handleMessageContextMenuInteraction = async (interaction) => {
|
|
@@ -184,17 +202,18 @@ export class StelliaUtils {
|
|
|
184
202
|
const messageContextMenu = contextMenuManager.getByCustomId(interaction.commandName);
|
|
185
203
|
if (!messageContextMenu)
|
|
186
204
|
return;
|
|
187
|
-
if (this.client.environment.
|
|
188
|
-
const
|
|
189
|
-
|
|
205
|
+
if (this.client.environment.areGuildsConfigurationEnabled) {
|
|
206
|
+
const messageContextMenuWithGuildConfiguration = messageContextMenu;
|
|
207
|
+
const guildConfiguration = this.getGuildConfiguration(interaction.guildId);
|
|
208
|
+
await messageContextMenuWithGuildConfiguration.execute(this.client, guildConfiguration, interaction);
|
|
190
209
|
}
|
|
191
210
|
else {
|
|
192
|
-
const
|
|
193
|
-
await
|
|
211
|
+
const messageContextMenuWithoutGuildConfiguration = messageContextMenu;
|
|
212
|
+
await messageContextMenuWithoutGuildConfiguration.execute(this.client, interaction);
|
|
194
213
|
}
|
|
195
214
|
}
|
|
196
215
|
catch (error) {
|
|
197
|
-
|
|
216
|
+
logger.error(`Error while handling message context menu interaction: ${error}`);
|
|
198
217
|
}
|
|
199
218
|
};
|
|
200
219
|
handleUserContextMenuInteraction = async (interaction) => {
|
|
@@ -205,17 +224,18 @@ export class StelliaUtils {
|
|
|
205
224
|
const userContextMenu = contextMenuManager.getByCustomId(interaction.commandName);
|
|
206
225
|
if (!userContextMenu)
|
|
207
226
|
return;
|
|
208
|
-
if (this.client.environment.
|
|
209
|
-
const
|
|
210
|
-
|
|
227
|
+
if (this.client.environment.areGuildsConfigurationEnabled) {
|
|
228
|
+
const userContextMenuWithGuildConfiguration = userContextMenu;
|
|
229
|
+
const guildConfiguration = this.getGuildConfiguration(interaction.guildId);
|
|
230
|
+
await userContextMenuWithGuildConfiguration.execute(this.client, guildConfiguration, interaction);
|
|
211
231
|
}
|
|
212
232
|
else {
|
|
213
|
-
const
|
|
214
|
-
await
|
|
233
|
+
const userContextMenuWithoutGuildConfiguration = userContextMenu;
|
|
234
|
+
await userContextMenuWithoutGuildConfiguration.execute(this.client, interaction);
|
|
215
235
|
}
|
|
216
236
|
}
|
|
217
237
|
catch (error) {
|
|
218
|
-
|
|
238
|
+
logger.error(`Error while handling user context menu interaction: ${error}`);
|
|
219
239
|
}
|
|
220
240
|
};
|
|
221
241
|
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,45 +1,32 @@
|
|
|
1
|
-
import { Collection
|
|
1
|
+
import { Collection } 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
22
|
for (const eventStructure of this.interactions.values()) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const environment = await this.client.getEnvironment();
|
|
16
|
-
const event = eventStructure;
|
|
17
|
-
if (name == Events.ClientReady) {
|
|
18
|
-
this.client.once(Events.ClientReady, () => event.execute(this.client, environment));
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
if (once) {
|
|
22
|
-
this.client.once(name, (...args) => event.execute(this.client, environment, ...args));
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
this.client.on(name, (...args) => event.execute(this.client, environment, ...args));
|
|
26
|
-
}
|
|
23
|
+
if (this.client.environment.areGuildsConfigurationEnabled) {
|
|
24
|
+
await this.loadEventWithGuildConfiguration(eventStructure);
|
|
27
25
|
}
|
|
28
26
|
else {
|
|
29
|
-
|
|
30
|
-
if (name == Events.ClientReady) {
|
|
31
|
-
this.client.once(name, () => event.execute(this.client));
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
if (once) {
|
|
35
|
-
this.client.once(name, (...args) => event.execute(this.client, ...args));
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
this.client.on(name, (...args) => event.execute(this.client, ...args));
|
|
39
|
-
}
|
|
27
|
+
await this.loadEventWithoutGuildConfiguration(eventStructure);
|
|
40
28
|
}
|
|
41
29
|
}
|
|
42
|
-
this.client.on(Events.Error, (error) => console.error(error));
|
|
43
30
|
this.setManagerLoaded();
|
|
44
31
|
}
|
|
45
32
|
getByCustomId(id) {
|
|
@@ -53,4 +40,45 @@ export class EventManager extends BaseManager {
|
|
|
53
40
|
const events = this.interactions;
|
|
54
41
|
return events;
|
|
55
42
|
}
|
|
43
|
+
async loadEventWithGuildConfiguration(eventStructure) {
|
|
44
|
+
const { name, once } = eventStructure.data;
|
|
45
|
+
const event = eventStructure;
|
|
46
|
+
if (once) {
|
|
47
|
+
this.client.once(name, (...args) => this.eventHandler(event, ...args));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
this.client.on(name, (...args) => this.eventHandler(event, ...args));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
eventHandler = (event, ...args) => {
|
|
54
|
+
const mainArgument = args[0];
|
|
55
|
+
const guildConfiguration = this.getGuildConfiguration(mainArgument);
|
|
56
|
+
if (guildConfiguration) {
|
|
57
|
+
const eventStructure = event;
|
|
58
|
+
return eventStructure.execute(this.client, guildConfiguration, ...args);
|
|
59
|
+
}
|
|
60
|
+
const eventStructure = event;
|
|
61
|
+
return eventStructure.execute(this.client, this.guildsConfiguration);
|
|
62
|
+
};
|
|
63
|
+
async loadEventWithoutGuildConfiguration(eventStructure) {
|
|
64
|
+
const { name, once } = eventStructure.data;
|
|
65
|
+
const event = eventStructure;
|
|
66
|
+
if (once) {
|
|
67
|
+
this.client.once(name, (...args) => event.execute(this.client, ...args));
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.client.on(name, (...args) => event.execute(this.client, ...args));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
getGuildConfiguration(mainArgument) {
|
|
74
|
+
if (mainArgument && typeof mainArgument === "object") {
|
|
75
|
+
if ("guildId" in mainArgument && mainArgument.guildId) {
|
|
76
|
+
return this.client.getGuildConfiguration(mainArgument.guildId);
|
|
77
|
+
}
|
|
78
|
+
if ("guild" in mainArgument && mainArgument.guild) {
|
|
79
|
+
return this.client.getGuildConfiguration(mainArgument.guild.id);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
56
84
|
}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import { type Awaitable, type ClientEvents } from "discord.js";
|
|
2
2
|
import { type StelliaClient } from "../client/index.js";
|
|
3
|
-
import { type
|
|
4
|
-
export interface
|
|
5
|
-
execute(client: StelliaClient,
|
|
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>;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
8
|
-
execute(client: StelliaClient, ...args:
|
|
7
|
+
export interface EventStructureWithAllGuildsConfiguration extends EventInteractionStructure {
|
|
8
|
+
execute(client: StelliaClient, guildsConfiguration: GuildsConfiguration, ...args: ClientEventsArgs): Awaitable<unknown>;
|
|
9
9
|
}
|
|
10
|
-
export
|
|
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;
|
|
11
15
|
interface EventInteractionStructure {
|
|
12
16
|
data: EventDataStructure;
|
|
13
17
|
}
|
|
14
18
|
interface EventDataStructure {
|
|
15
|
-
name:
|
|
19
|
+
name: EventKeys;
|
|
16
20
|
once: boolean;
|
|
17
21
|
}
|
|
18
|
-
type
|
|
22
|
+
export type ClientEventsArgs = ClientEvents[keyof ClientEvents];
|
|
23
|
+
export type EventKeys = keyof ClientEvents;
|
|
19
24
|
export {};
|
|
@@ -1,49 +1,49 @@
|
|
|
1
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
|
|
3
|
+
import { type GuildConfigurationType } from "../typescript/index.js";
|
|
4
4
|
import { type EventStructure } from "./Event.js";
|
|
5
|
-
export interface
|
|
6
|
-
execute(client: StelliaClient,
|
|
5
|
+
export interface AutoCompleteStructureWithGuildConfiguration extends MessageInteractionStructure {
|
|
6
|
+
execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: AutocompleteInteraction<"cached">): Awaitable<unknown>;
|
|
7
7
|
}
|
|
8
|
-
export interface
|
|
8
|
+
export interface AutoCompleteStructureWithoutGuildConfiguration extends MessageInteractionStructure {
|
|
9
9
|
execute(client: StelliaClient, interaction: AutocompleteInteraction<"cached">): Awaitable<unknown>;
|
|
10
10
|
}
|
|
11
|
-
export type AutoCompleteStructure =
|
|
12
|
-
export interface
|
|
13
|
-
execute(client: StelliaClient,
|
|
11
|
+
export type AutoCompleteStructure = AutoCompleteStructureWithGuildConfiguration | AutoCompleteStructureWithoutGuildConfiguration;
|
|
12
|
+
export interface ButtonStructureWithGuildConfiguration extends MessageInteractionStructure {
|
|
13
|
+
execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: ButtonInteraction<"cached">): Awaitable<unknown>;
|
|
14
14
|
}
|
|
15
|
-
export interface
|
|
15
|
+
export interface ButtonStructureWithoutGuildConfiguration extends MessageInteractionStructure {
|
|
16
16
|
execute(client: StelliaClient, interaction: ButtonInteraction<"cached">): Awaitable<unknown>;
|
|
17
17
|
}
|
|
18
|
-
export type ButtonStructure =
|
|
19
|
-
export interface
|
|
20
|
-
execute(client: StelliaClient,
|
|
18
|
+
export type ButtonStructure = ButtonStructureWithGuildConfiguration | ButtonStructureWithoutGuildConfiguration;
|
|
19
|
+
export interface CommandStructureWithGuildConfiguration extends CommandInteractionStructure {
|
|
20
|
+
execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: ChatInputCommandInteraction<"cached">): Awaitable<unknown>;
|
|
21
21
|
}
|
|
22
|
-
export interface
|
|
22
|
+
export interface CommandStructureWithoutGuildConfiguration extends CommandInteractionStructure {
|
|
23
23
|
execute(client: StelliaClient, interaction: ChatInputCommandInteraction<"cached">): Awaitable<unknown>;
|
|
24
24
|
}
|
|
25
|
-
export type CommandStructure =
|
|
26
|
-
export interface
|
|
27
|
-
execute(client: StelliaClient,
|
|
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
28
|
}
|
|
29
|
-
export interface
|
|
29
|
+
export interface ContextMenuStructureWithoutGuildConfiguration extends ContextMenuInteractionStructure {
|
|
30
30
|
execute(client: StelliaClient, interaction: MessageContextMenuCommandInteraction<"cached"> | UserContextMenuCommandInteraction<"cached">): Awaitable<unknown>;
|
|
31
31
|
}
|
|
32
|
-
export type ContextMenuStructure =
|
|
33
|
-
export interface
|
|
34
|
-
execute(client: StelliaClient,
|
|
32
|
+
export type ContextMenuStructure = ContextMenuStructureWithGuildConfiguration | ContextMenuStructureWithoutGuildConfiguration;
|
|
33
|
+
export interface ModalStructureWithGuildConfiguration extends MessageInteractionStructure {
|
|
34
|
+
execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: ModalSubmitInteraction<"cached">): Awaitable<unknown>;
|
|
35
35
|
}
|
|
36
|
-
export interface
|
|
36
|
+
export interface ModalStructureWithoutGuildConfiguration extends MessageInteractionStructure {
|
|
37
37
|
execute(client: StelliaClient, interaction: ModalSubmitInteraction<"cached">): Awaitable<unknown>;
|
|
38
38
|
}
|
|
39
|
-
export type ModalStructure =
|
|
40
|
-
export interface
|
|
41
|
-
execute(client: StelliaClient,
|
|
39
|
+
export type ModalStructure = ModalStructureWithGuildConfiguration | ModalStructureWithoutGuildConfiguration;
|
|
40
|
+
export interface SelectMenuStructureWithGuildConfiguration extends MessageInteractionStructure {
|
|
41
|
+
execute(client: StelliaClient, guildConfiguration: GuildConfigurationType, interaction: AnySelectMenuInteraction<"cached">): Awaitable<unknown>;
|
|
42
42
|
}
|
|
43
|
-
export interface
|
|
43
|
+
export interface SelectMenuStructureWithoutGuildConfiguration extends MessageInteractionStructure {
|
|
44
44
|
execute(client: StelliaClient, interaction: AnySelectMenuInteraction<"cached">): Awaitable<unknown>;
|
|
45
45
|
}
|
|
46
|
-
export type SelectMenuStructure =
|
|
46
|
+
export type SelectMenuStructure = SelectMenuStructureWithGuildConfiguration | SelectMenuStructureWithoutGuildConfiguration;
|
|
47
47
|
export type AnyInteractionStructure = AutoCompleteStructure | ButtonStructure | CommandStructure | ContextMenuStructure | EventStructure | ModalStructure | SelectMenuStructure;
|
|
48
48
|
interface CommandInteractionStructure {
|
|
49
49
|
data: SlashCommandOptionsOnlyBuilder;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type AutoCompleteManager, type ButtonManager, type CommandManager, type ContextMenuManager, type EventManager, type ModalManager, type SelectMenuManager } from "../managers/index.js";
|
|
2
|
+
import { type Snowflake } from "discord.js";
|
|
2
3
|
export type StructureCustomId = string | RegExp;
|
|
3
4
|
export type InteractionCustomId = string;
|
|
4
5
|
export declare enum InteractionType {
|
|
@@ -20,9 +21,26 @@ export interface Managers {
|
|
|
20
21
|
selectMenus?: SelectMenuManager;
|
|
21
22
|
modals?: ModalManager;
|
|
22
23
|
}
|
|
23
|
-
export interface
|
|
24
|
-
|
|
24
|
+
export interface ClientEnvironment {
|
|
25
|
+
areGuildsConfigurationEnabled: boolean;
|
|
25
26
|
}
|
|
26
|
-
export interface
|
|
27
|
+
export interface BaseGuildConfiguration {
|
|
28
|
+
locale: string;
|
|
27
29
|
[key: string]: unknown;
|
|
28
30
|
}
|
|
31
|
+
export interface BaseGeneralConfiguration {
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
export interface GuildsConfiguration {
|
|
35
|
+
general: {
|
|
36
|
+
[key: string]: unknown;
|
|
37
|
+
};
|
|
38
|
+
guilds: {
|
|
39
|
+
[guildId in Snowflake]: BaseGuildConfiguration;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export interface GuildConfiguration {
|
|
43
|
+
general: BaseGeneralConfiguration;
|
|
44
|
+
guild: BaseGuildConfiguration;
|
|
45
|
+
}
|
|
46
|
+
export type GuildConfigurationType = GuildConfiguration | undefined;
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -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.3.0
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -15,13 +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.38.
|
|
19
|
-
"discord.js": "^14.19.3"
|
|
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.
|
|
24
|
+
"tsc-alias": "^1.8.16"
|
|
24
25
|
},
|
|
25
26
|
"type": "module",
|
|
26
|
-
"packageManager": "pnpm@10.
|
|
27
|
+
"packageManager": "pnpm@10.11.1"
|
|
27
28
|
}
|