Skip to content

Commit 8617d51

Browse files
authored
feat: autocompleter (#14)
* feat: autocompleter * fix: don't format dist * fix: copypasted namings
1 parent ed10db2 commit 8617d51

File tree

7 files changed

+70
-4
lines changed

7 files changed

+70
-4
lines changed

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist/

src/Autocompleter.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { AutocompleteInteraction } from "discord.js";
2+
3+
export abstract class Autocompleter {
4+
public readonly command: string;
5+
6+
protected constructor(command: string) {
7+
this.command = command;
8+
}
9+
10+
abstract execute(interaction: AutocompleteInteraction): Promise<void>;
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Autocompleter } from "../Autocompleter";
2+
import { AutocompleteInteraction } from "discord.js";
3+
4+
class CountryAutocompleter extends Autocompleter {
5+
constructor() {
6+
super("country"); // command which this autocompleter is for
7+
}
8+
9+
async execute(interaction: AutocompleteInteraction): Promise<void> {
10+
// your options
11+
const country = ["Finland", "Sweden", "Norway"];
12+
// for example return all options which start with the user input
13+
await interaction.respond(
14+
country.filter((c) => c.startsWith(interaction.options.getFocused() as string)).map((c) => ({ name: c, value: c })),
15+
);
16+
}
17+
}
18+
19+
export default new CountryAutocompleter();

src/ctx.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { ButtonHandler } from "./ButtonHandler";
22
import { Collection } from "discord.js";
33
import { Command } from "./Command";
4+
import { Autocompleter } from "Autocompleter";
45

56
class Ctx {
67
public readonly defaultGuild;
78
public readonly commands: Collection<string, Command> = new Collection<string, Command>();
89
public readonly buttons: Collection<string, ButtonHandler> = new Collection<string, ButtonHandler>();
10+
public readonly autocompleters: Collection<string, Autocompleter> = new Collection<string, Autocompleter>();
911
public readonly logLevel: string;
1012

1113
// Databases are gonna go here
@@ -18,9 +20,14 @@ class Ctx {
1820
this.logLevel = LOG_LEVEL || "error";
1921
}
2022

21-
update(commands: Collection<string, Command>, buttons: Collection<string, ButtonHandler>) {
23+
update(
24+
commands: Collection<string, Command>,
25+
buttons: Collection<string, ButtonHandler>,
26+
autocompleters: Collection<string, Autocompleter>
27+
) {
2228
commands.forEach((v, k) => this.commands.set(k, v));
2329
buttons.forEach((v, k) => this.buttons.set(k, v));
30+
autocompleters.forEach((v, k) => this.autocompleters.set(k, v));
2431
}
2532
}
2633

src/events/interactionCreate.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ButtonInteraction, CommandInteraction, Interaction } from "discord.js";
1+
import { AutocompleteInteraction, ButtonInteraction, CommandInteraction, Interaction } from "discord.js";
22
import { ctx } from "../ctx";
33
import { logger } from "../logger";
44

@@ -8,6 +8,8 @@ export default async function interactionCreate(interaction: Interaction) {
88
await handleCommandInteractions(interaction);
99
} else if (interaction.isButton()) {
1010
await handleButtonInteractions(interaction);
11+
} else if (interaction.isAutocomplete()) {
12+
await handleAutocompleteInteraction(interaction);
1113
}
1214
} catch (err: unknown) {
1315
if (err instanceof Error) {
@@ -41,3 +43,13 @@ async function handleButtonInteractions(interaction: ButtonInteraction) {
4143
await interaction.reply("An error occurred. Please contact a developer");
4244
}
4345
}
46+
47+
async function handleAutocompleteInteraction(interaction: AutocompleteInteraction) {
48+
const autocompleter = ctx.autocompleters.get(interaction.commandName);
49+
if (autocompleter) {
50+
await autocompleter.execute(interaction);
51+
} else {
52+
logger.error(`error resolving autocompleter for ${interaction.commandName}`);
53+
await interaction.respond([]);
54+
}
55+
}

src/loader.ts

+16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Client, Collection } from "discord.js";
22
import { Command } from "./Command";
3+
import { Autocompleter } from "./Autocompleter";
34
import * as fs from "fs";
45
import { ButtonHandler } from "./ButtonHandler";
56
import { logger } from "./logger";
@@ -46,3 +47,18 @@ export async function loadEvents(client: Client) {
4647
})
4748
);
4849
}
50+
51+
export async function loadAutocompleters(): Promise<Collection<string, Autocompleter>> {
52+
logger.debug("loading autocompleters...");
53+
const loadedAutocompleters = new Collection<string, Autocompleter>();
54+
await Promise.all(
55+
fs
56+
.readdirSync("./dist/autocompleters")
57+
.filter((f) => f.endsWith(".js"))
58+
.map(async (filename) => {
59+
const autocompleter = (await import(`./autocompleters/${filename}`)).default as Autocompleter;
60+
loadedAutocompleters.set(autocompleter.command, autocompleter);
61+
})
62+
);
63+
return loadedAutocompleters;
64+
}

src/start.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import "dotenv/config";
2-
import { loadButtonHandlers, loadCommands, loadEvents } from "./loader";
2+
import { loadAutocompleters, loadButtonHandlers, loadCommands, loadEvents } from "./loader";
33
import { Client } from "discord.js";
44
import { ctx } from "./ctx";
55
import { logger } from "./logger";
@@ -19,7 +19,7 @@ async function start(): Promise<Client> {
1919
const client = new Client({ intents: [] });
2020

2121
logger.debug("Loading context...");
22-
ctx.update(await loadCommands(), await loadButtonHandlers());
22+
ctx.update(await loadCommands(), await loadButtonHandlers(), await loadAutocompleters());
2323
logger.debug("Loading events...");
2424
await loadEvents(client);
2525
logger.debug("Attempting login");

0 commit comments

Comments
 (0)