Ostatnio aktywny 1 month ago

nuno zrewidował ten Gist 1 month ago. Przejdź do rewizji

1 file changed, 111 insertions

autocomplete.ts(stworzono plik)

@@ -0,0 +1,111 @@
1 + import { AutocompleteInteraction } from "discord.js";
2 + import { resolveUser } from "@systems/users";
3 + import { getCharacters, getCharacterByName } from "@systems/characters";
4 + import { getPersistentPreference, getSessionBorrow } from "@systems/borrow";
5 + import { cfg } from "@systems/config";
6 + import fs from "fs";
7 + import path from "path";
8 +
9 + // ─── Autocomplete subsets ─────────────────────────────────────────────────────
10 +
11 + // Character names — own chars + shared chars accessible to this user
12 + async function autocompleteCharNames(
13 + interaction: AutocompleteInteraction,
14 + focused: string
15 + ): Promise<void> {
16 + const member = await interaction.guild!.members.fetch(interaction.user.id);
17 + const user = await resolveUser(member);
18 + if (!user.userKey) return interaction.respond([]);
19 +
20 + const ownChars = getCharacters(user.userKey).map((c) => ({
21 + name: `${c.class} ${c.level} ${c.name}`,
22 + value: c.name,
23 + }));
24 +
25 + // Include shared chars (scan all users' sharedWith arrays)
26 + const sharedChars: { name: string; value: string }[] = [];
27 + try {
28 + const chars = JSON.parse(
29 + fs.readFileSync(path.join(__dirname, "../../data/characters.json"), "utf8")
30 + );
31 + for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
32 + if (ownerKey === user.userKey) continue;
33 + for (const char of data.characters ?? []) {
34 + if (char.sharedWith?.includes(user.userKey)) {
35 + sharedChars.push({
36 + name: `${char.class} ${char.level} ${char.name} (shared by ${ownerKey})`,
37 + value: char.name,
38 + });
39 + }
40 + }
41 + }
42 + } catch {}
43 +
44 + const all = [...ownChars, ...sharedChars]
45 + .filter((c) => c.name.toLowerCase().includes(focused.toLowerCase()))
46 + .slice(0, 25);
47 +
48 + await interaction.respond(all);
49 + }
50 +
51 + // Usermap keys — all registered users (officer commands)
52 + async function autocompleteUserKeys(
53 + interaction: AutocompleteInteraction,
54 + focused: string
55 + ): Promise<void> {
56 + try {
57 + const usermap = JSON.parse(
58 + fs.readFileSync(path.join(__dirname, "../../data/usermap.json"), "utf8")
59 + );
60 + const choices = Object.entries(usermap)
61 + .map(([, entry]: [string, any]) => {
62 + const fileKey = typeof entry === "string" ? entry : entry.file;
63 + const alias = typeof entry === "object" ? (entry.aliases?.[0] ?? fileKey) : fileKey;
64 + return { name: `${alias} (${fileKey})`, value: fileKey };
65 + })
66 + .filter((c) => c.name.toLowerCase().includes(focused.toLowerCase()))
67 + .slice(0, 25);
68 + await interaction.respond(choices);
69 + } catch {
70 + await interaction.respond([]);
71 + }
72 + }
73 +
74 + // TG slots — active slot hours
75 + async function autocompleteSlots(
76 + interaction: AutocompleteInteraction,
77 + focused: string
78 + ): Promise<void> {
79 + const slots = cfg("slots")
80 + .filter((s) => s.active)
81 + .map((s) => ({ name: `${s.tgHour}:00`, value: String(s.tgHour) }))
82 + .filter((s) => s.name.includes(focused));
83 + await interaction.respond(slots);
84 + }
85 +
86 + // ─── Router ───────────────────────────────────────────────────────────────────
87 +
88 + export async function handleAutocomplete(interaction: AutocompleteInteraction): Promise<void> {
89 + try {
90 + const focused = interaction.options.getFocused(true);
91 + const optionName = focused.name;
92 + const focusedValue = focused.value as string;
93 +
94 + // Route by option name
95 + if (optionName === "char_name") {
96 + return await autocompleteCharNames(interaction, focusedValue);
97 + }
98 + if (optionName === "name") {
99 + // Officer user key args
100 + return await autocompleteUserKeys(interaction, focusedValue);
101 + }
102 + if (optionName === "slot") {
103 + return await autocompleteSlots(interaction, focusedValue);
104 + }
105 +
106 + await interaction.respond([]);
107 + } catch (err) {
108 + console.error("[autocomplete] error:", err);
109 + try { await interaction.respond([]); } catch {}
110 + }
111 + }
Nowsze Starsze