Остання активність 4 weeks ago

gistfile1.txt Неформатований
1async function handleSwitchAfterReclaim(btn: ButtonInteraction): Promise<void> {
2 const prefix = btn.customId.startsWith("companion_switch:") ? "companion_switch:" : "switch_after_reclaim:";
3 const withoutPrefix = btn.customId.slice(prefix.length);
4 const firstColon = withoutPrefix.indexOf(":");
5 const userKey = withoutPrefix.slice(0, firstColon);
6 const rest = withoutPrefix.slice(firstColon + 1);
7 const lastColon = rest.lastIndexOf(":");
8 const charName = rest.slice(0, lastColon);
9 const prevVoteType = (rest.slice(lastColon + 1) || "yes") as "yes" | "no";
10
11 const chars = JSON.parse(
12 fs.readFileSync(path.join(__dirname, "../../data/characters.json"), "utf8")
13 );
14
15 let resolvedChar: any = null;
16 let borrowedFrom: string | null = null;
17
18 // Try own char first
19 const ownEntry = chars[userKey]?.characters?.find((c: any) => c.name === charName);
20 if (ownEntry) {
21 setActiveCharacter(userKey, charName);
22 clearSessionBorrowForUser(userKey);
23 clearPersistentPreference(userKey);
24 resolvedChar = ownEntry;
25 } else {
26 // Try shared char
27 for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
28 const char = data.characters?.find(
29 (c: any) => c.name === charName && c.sharedWith?.includes(userKey)
30 );
31 if (char) {
32 setPersistentPreference(userKey, ownerKey, charName);
33 clearSessionBorrowForUser(userKey);
34 resolvedChar = char;
35 borrowedFrom = ownerKey;
36 break;
37 }
38 }
39 }
40
41 if (!resolvedChar) {
42 await btn.reply({ content: `❌ Could not switch to **${charName}**.`, ephemeral: true });
43 return;
44 }
45
46 // Re-add to poll with previous vote type
47 const slot = [...polls.keys()][0];
48 const state = slot !== undefined ? polls.get(slot) : null;
49
50 let existingVoteId: string | null = null;
51 if (state) {
52 for (const [id, entry] of [...state.yes.entries(), ...state.no.entries()]) {
53 if (entry.userKey === userKey) {
54 existingVoteId = id;
55 break;
56 }
57 }
58 }
59
60 // Conflict check
61 if (state && resolvedChar) {
62 for (const [id, entry] of state.yes.entries()) {
63 if (id !== existingVoteId && id !== btn.user.id &&
64 entry.characterName === resolvedChar.name &&
65 entry.userKey !== userKey) {
66 await btn.reply({
67 content: `❌ ${format.char(resolvedChar)} is already in the poll by another player.`,
68 ephemeral: true,
69 });
70 return;
71 }
72 }
73 }
74
75 if (state && !state.locked && state.confirmed === null) {
76 const { char } = getEffectiveCharacter(userKey);
77 const now = nowFormatted();
78 const publicMsg = resolveMessage("public", prevVoteType, 1, userKey, null, null);
79 const voteEntry = {
80 userKey,
81 displayName: charName,
82 characterName: char?.name ?? charName,
83 characterClass: char?.class ?? resolvedChar.class,
84 characterLevel: char?.level ?? resolvedChar.level,
85 characterNation: char?.nation ?? resolvedChar.nation,
86 borrowedFrom: borrowedFrom ?? undefined,
87 discordId: btn.user.id,
88 votedAt: now,
89 publicMessage: publicMsg ?? undefined,
90 };
91
92 // Find and reuse existing vote ID — avoids duplicate entries
93 let existingVoteId: string | null = null;
94 for (const [id, entry] of [...state.yes.entries(), ...state.no.entries()]) {
95 if (entry.userKey === userKey) {
96 if (!existingVoteId) existingVoteId = id;
97 state.yes.delete(id);
98 state.no.delete(id);
99 }
100 }
101 const voteId = existingVoteId ?? btn.user.id;
102
103 if (prevVoteType === "yes") {
104 state.yes.set(voteId, voteEntry);
105 } else {
106 state.no.set(voteId, voteEntry);
107 }
108
109 console.log(`[switch_reclaim] cleaning up for userKey=${userKey}`);
110 console.log(`[switch_reclaim] yes keys:`, [...state.yes.entries()].map(([id, e]) => `${id}:${e.userKey}`));
111 console.log(`[switch_reclaim] no keys:`, [...state.no.entries()].map(([id, e]) => `${id}:${e.userKey}`));
112
113 const channel = await btn.client.channels.fetch(cfg("pollChannelId")) as TextChannel;
114 await updatePollMessage(channel, slot!);
115 }
116
117 const charDisplay = resolvedChar ? format.char(resolvedChar) : charName;
118 const borrowNote = borrowedFrom ? ` *(shared by ${borrowedFrom})*` : "";
119 await btn.reply({
120 content: `🔄 ${charDisplay}${borrowNote}${state ? ` — re-added to poll as **${prevVoteType}**.` : ""}`,
121 ephemeral: true,
122 });
123}