tangled
alpha
login
or
join now
thevoid.cafe
/
voidy
0
fork
atom
A powerful and extendable Discord bot, with it's own module system :3
thevoid.cafe/projects/voidy
0
fork
atom
overview
issues
pulls
pipelines
✨ Add button handling
thevoid.cafe
6 months ago
77656eb6
e058c8c6
+62
-5
6 changed files
expand all
collapse all
unified
split
src
core
Registry.ts
VoidyClient.ts
handlers
ButtonHandler.ts
loaders
ButtonLoader.ts
modules
core
events
interactionCreate.ts
module.ts
+5
src/core/Registry.ts
···
1
1
+
import { ButtonLoader, type Button } from "../loaders/ButtonLoader"
1
2
import { CommandLoader, type Command } from "../loaders/CommandLoader"
2
3
import { EventLoader, type Event } from "../loaders/EventLoader"
3
4
import { ModuleLoader, type Module } from "../loaders/ModuleLoader"
···
7
8
dataSource: string
8
9
modules: Module[]
9
10
commands: Command[]
11
11
+
buttons: Button[]
10
12
events: Event[]
11
13
active: boolean
12
14
···
20
22
public dataSource: string;
21
23
public modules: Module[] = [];
22
24
public commands: Command[] = [];
25
25
+
public buttons: Button[] = [];
23
26
public events: Event[] = [];
24
27
public active = false;
25
28
···
50
53
this.commands.push(...loader.getJSON());
51
54
} else if (loader instanceof EventLoader) {
52
55
this.events.push(...loader.getJSON());
56
56
+
} else if (loader instanceof ButtonLoader) {
57
57
+
this.buttons.push(...loader.getJSON());
53
58
}
54
59
}
55
60
}
+14
-4
src/core/VoidyClient.ts
···
10
10
import { Registry } from "./Registry";
11
11
import type { Event } from "../loaders/EventLoader";
12
12
import type { Command } from "../loaders/CommandLoader";
13
13
+
import type { Button } from "../loaders/ButtonLoader";
13
14
14
15
export class VoidyClient extends Client {
15
16
public registries: Registry[];
16
16
-
public cache: Command[] = [];
17
17
+
public cache: { commands: Command[], buttons: Button[] } = {
18
18
+
commands: [],
19
19
+
buttons: [],
20
20
+
};
17
21
18
22
public constructor(options: ClientOptions) {
19
23
super(options);
···
28
32
const {
29
33
commands,
30
34
commandsJSON,
35
35
+
buttons,
31
36
events
32
37
} = await this.collectBundledRegistryData();
33
38
34
34
-
// 1.1 Cache collected commands
35
35
-
this.cache = [...commands];
39
39
+
// 1.1 Cache collected commands and buttons
40
40
+
this.cache.commands = [...commands];
41
41
+
this.cache.buttons = [...buttons];
36
42
37
43
// 2. Register event listeners
38
44
await this.registerEventHandlers(events);
···
76
82
.flatMap(registry => registry.commands)
77
83
.flatMap(commands => commands.data.toJSON())
78
84
79
79
-
return { commands, commandsJSON, events };
85
85
+
// Collect raw buttons from active registries
86
86
+
const buttons = activeRegistries
87
87
+
.flatMap(registry => registry.buttons)
88
88
+
89
89
+
return { commands, commandsJSON, buttons, events };
80
90
}
81
91
82
92
private async registerEventHandlers(events: Event[]) {
+9
src/handlers/ButtonHandler.ts
···
1
1
+
import type { ButtonInteraction } from "discord.js";
2
2
+
import type { Button } from "../loaders/ButtonLoader";
3
3
+
import type { VoidyClient } from "../core/VoidyClient";
4
4
+
5
5
+
export class ButtonHandler {
6
6
+
public static invoke(interaction: ButtonInteraction, payload: Button, client: VoidyClient): void {
7
7
+
payload.execute(interaction, client);
8
8
+
}
9
9
+
}
+17
src/loaders/ButtonLoader.ts
···
1
1
+
import type { ButtonInteraction } from "discord.js";
2
2
+
import { Loader } from "../core/Loader";
3
3
+
import type { VoidyClient } from "../core/VoidyClient";
4
4
+
5
5
+
export interface Button {
6
6
+
id: string,
7
7
+
execute: (
8
8
+
interaction: ButtonInteraction, client: VoidyClient
9
9
+
) => Promise<void>
10
10
+
}
11
11
+
12
12
+
export class ButtonLoader extends Loader<Button> {
13
13
+
public override async validate(data: Partial<Button>) {
14
14
+
if (!data.id || !data.execute) return null;
15
15
+
return data as Button;
16
16
+
}
17
17
+
}
+12
-1
src/modules/core/events/interactionCreate.ts
···
2
2
import type { Event } from "../../../loaders/EventLoader";
3
3
import type { VoidyClient } from "../../../core/VoidyClient";
4
4
import { ChatInputCommandHandler } from "../../../handlers/CommandHandler";
5
5
+
import { ButtonHandler } from "../../../handlers/ButtonHandler";
5
6
6
7
export default {
7
8
name: Events.InteractionCreate,
8
9
execute: async (client: VoidyClient, interaction: Interaction) => {
9
10
if (interaction.isChatInputCommand() && interaction.isCommand()) {
10
11
// Filter the client command cache to locate the invoked command
11
11
-
const payload = client.cache.filter(commands => commands.data.name === interaction.commandName)[0];
12
12
+
const payload = client.cache.commands.filter(commands => commands.data.name === interaction.commandName)[0];
12
13
13
14
if (!payload) return interaction.reply({
14
15
content: `Sorry, but the command ${interaction.commandName} could not be located in my command cache >:3`,
···
16
17
});
17
18
18
19
ChatInputCommandHandler.invoke(interaction, payload, client);
20
20
+
} else if (interaction.isButton()) {
21
21
+
// Filter the client button cache to locate the invoked button
22
22
+
const payload = client.cache.buttons.filter(buttons => buttons.id === interaction.customId)[0];
23
23
+
24
24
+
if (!payload) return interaction.reply({
25
25
+
content: `Sorry, but the button ${interaction.customId} could not be located in my button cache >:3`,
26
26
+
flags: [MessageFlags.Ephemeral]
27
27
+
});
28
28
+
29
29
+
ButtonHandler.invoke(interaction, payload, client);
19
30
} else {
20
31
let dmChannel = interaction.user.dmChannel;
21
32
+5
src/modules/core/module.ts
···
1
1
+
import { ButtonLoader } from "../../loaders/ButtonLoader";
1
2
import { CommandLoader } from "../../loaders/CommandLoader";
2
3
import { EventLoader } from "../../loaders/EventLoader";
3
4
import type { Module } from "../../loaders/ModuleLoader";
···
15
16
{
16
17
source: `${import.meta.dir}/commands`,
17
18
loader: CommandLoader,
19
19
+
},
20
20
+
{
21
21
+
source: `${import.meta.dir}/buttons`,
22
22
+
loader: ButtonLoader,
18
23
}
19
24
]
20
25
} as Module;