Ostatnio aktywny 1 month ago

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

1 file changed, 105 insertions

switch.ts(stworzono plik)

@@ -0,0 +1,105 @@
1 + import { ChatInputCommandInteraction, TextChannel } from "discord.js";
2 + import { cfg } from "../systems/config";
3 + import { resolveUser, hasOfficerRole } from "../systems/users";
4 + import { setActiveCharacter, getActiveCharacter, getCharacterByName } from "../systems/characters";
5 + import { setSessionBorrow, getSessionBorrow, setPersistentPreference, clearPersistentPreference } from "../systems/borrow";
6 + import { polls, updatePollMessage } from "../systems/poll";
7 + import { replyAndDelete } from "../utils";
8 + import fs from "fs";
9 + import path from "path";
10 +
11 + const CHARS_PATH = path.join(__dirname, "../../data/characters.json");
12 +
13 + function findSharedChar(usermapKey: string, charName: string): { ownerKey: string; char: any } | null {
14 + try {
15 + const chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
16 + for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
17 + if (ownerKey === usermapKey) continue;
18 + const char = data.characters?.find(
19 + (c: any) => c.name.toLowerCase() === charName.toLowerCase() && c.sharedWith?.includes(usermapKey)
20 + );
21 + if (char) return { ownerKey, char };
22 + }
23 + } catch {}
24 + return null;
25 + }
26 +
27 + // Reverse-lookup: find Discord userId for a usermapKey from current poll voters
28 + function findUserIdInPoll(state: any, usermapKey: string): string | null {
29 + for (const [id, entry] of [...state.yes.entries(), ...state.no.entries()]) {
30 + if (entry.usermapKey === usermapKey) return id;
31 + }
32 + return null;
33 + }
34 +
35 + export async function handleSwitch(interaction: ChatInputCommandInteraction): Promise<void> {
36 + const member = await interaction.guild!.members.fetch(interaction.user.id);
37 + const isOfficer = hasOfficerRole(member, cfg("officerRoles"));
38 + const nameArg = interaction.options.getString("name");
39 + const charName = interaction.options.getString("char_name", true);
40 +
41 + let usermapKey: string | null;
42 + if (nameArg) {
43 + if (!isOfficer) return void replyAndDelete(interaction, "❌ Only officers can switch other players' characters.");
44 + usermapKey = nameArg;
45 + } else {
46 + const user = await resolveUser(member);
47 + usermapKey = user.usermapKey;
48 + }
49 +
50 + if (!usermapKey) return void replyAndDelete(interaction, "❌ You are not registered in the system.");
51 +
52 + let resolvedChar: any = null;
53 + let borrowedFrom: string | null = null;
54 +
55 + // Try own characters first
56 + const set = setActiveCharacter(usermapKey, charName);
57 + if (set) {
58 + clearPersistentPreference(usermapKey);
59 + // Also clear any active session borrow so own char takes priority
60 + const { clearSessionBorrowForUser } = require("../systems/borrow");
61 + clearSessionBorrowForUser(usermapKey);
62 + resolvedChar = getActiveCharacter(usermapKey);
63 + } else {
64 + // Fall back to shared characters
65 + const shared = findSharedChar(usermapKey, charName);
66 + if (shared) {
67 + setSessionBorrow(usermapKey, shared.ownerKey, shared.char.name);
68 + setPersistentPreference(usermapKey, shared.ownerKey, shared.char.name);
69 + resolvedChar = shared.char;
70 + borrowedFrom = shared.ownerKey;
71 + }
72 + }
73 +
74 + if (!resolvedChar) return void replyAndDelete(interaction, `❌ No character named **${charName}** found.`);
75 +
76 + // Update poll embed if user has voted
77 + const slot = [...polls.keys()][0];
78 + if (slot !== undefined) {
79 + const state = polls.get(slot)!;
80 + const userId = nameArg
81 + ? findUserIdInPoll(state, usermapKey)
82 + : interaction.user.id;
83 +
84 + if (userId && (state.yes.has(userId) || state.no.has(userId))) {
85 + const updateEntry = (map: Map<string, any>) => {
86 + const entry = map.get(userId);
87 + if (entry) {
88 + entry.characterName = resolvedChar.name;
89 + entry.characterClass = resolvedChar.class;
90 + entry.characterLevel = resolvedChar.level;
91 + entry.characterNation = resolvedChar.nation;
92 + entry.borrowedFrom = borrowedFrom ?? undefined;
93 + }
94 + };
95 + updateEntry(state.yes);
96 + updateEntry(state.no);
97 +
98 + const channel = await interaction.client.channels.fetch(cfg("pollChannelId")) as TextChannel;
99 + await updatePollMessage(channel, slot);
100 + }
101 + }
102 +
103 + const borrowNote = borrowedFrom ? ` (shared by **${borrowedFrom}**)` : "";
104 + return void replyAndDelete(interaction, `✅ Switched to **${charName}**${borrowNote}.`);
105 + }
Nowsze Starsze