Última actividad 3 weeks ago

nuno revisó este gist 3 weeks ago. Ir a la revisión

1 file changed, 137 insertions

gistfile1.txt(archivo creado)

@@ -0,0 +1,137 @@
1 + function formatCharRow(entry: VoteEntry, showNationEmoji = false, nationHasRank = false): string {
2 + const cfgFormat = cfg("charDisplayFormat");
3 + const nation = entry.characterNation;
4 + const wRankEntry = entry.characterName && entry.characterNation
5 + ? WRank.entry(entry.characterName, entry.characterNation)
6 + : null;
7 +
8 + let wrank = "";
9 + if (wRankEntry) {
10 + const wRankGoal = cfg("wRankGoal");
11 + wrank = format.wrank.full(wRankEntry, { goal: wRankGoal, brackets: true });
12 + } else if (nationHasRank) {
13 + wrank = format.wrank.noRank();
14 + }
15 +
16 + const classStr = entry.characterClass
17 + ? (Emoji.class(entry.characterClass) || entry.characterClass)
18 + : "";
19 +
20 + const levelStr = entry.characterLevel && cfg("showLevelInMessages" as any)
21 + ? `${entry.characterLevel}`
22 + : "";
23 +
24 + let row = cfgFormat
25 + .replace("{wrank}", wrank)
26 + .replace("{class}", classStr)
27 + .replace("{level}", levelStr)
28 + .replace("{name}", entry.characterName ?? entry.displayName ?? "")
29 + .replace(/\s+/g, " ")
30 + .trim();
31 +
32 + // Bringer title — independent of W.Rank so override always shows
33 + if (nation && entry.userKey) {
34 + const bringer = Bringer.get({ nation });
35 +
36 + if (bringer && bringer === entry.characterName) {
37 + row += ` · ${format.bringer(nation)}`;
38 + }
39 + }
40 +
41 + if (entry.borrowedFrom) {
42 + row += ` ${Emoji.get("borrowed") || "🔗"}`;
43 + }
44 +
45 + if (showNationEmoji && nation) row = `${Emoji.nation(nation)} ${row}`;
46 +
47 + return row;
48 + }
49 +
50 + export function buildEmbed(state: PollState, overrideLockMsg?: string): EmbedBuilder {
51 + const yesByNation = { Capella: [] as VoteEntry[], Procyon: [] as VoteEntry[] };
52 + const noVoters: VoteEntry[] = [];
53 + const allMessages: { entry: VoteEntry; voteType: "yes" | "no" }[] = [];
54 + const showNoInline = (cfg as any)("showNoInNationField") ?? false;
55 +
56 + for (const entry of state.yes.values()) {
57 + const nation = entry.characterNation ?? Nation.Capella;
58 + yesByNation[nation].push(entry);
59 + allMessages.push({ entry, voteType: "yes" });
60 + }
61 + for (const entry of state.no.values()) {
62 + noVoters.push(entry);
63 + allMessages.push({ entry, voteType: "no" });
64 + }
65 +
66 + const capellaEmoji = Emoji.get("capella");
67 + const procyonEmoji = Emoji.get("procyon");
68 +
69 + const formatNationField = (nation: Nation): string => {
70 + const yesEntries = yesByNation[nation];
71 + const hasRank = yesEntries.some((e) => e.characterName && WRank.entry(e.characterName, nation) !== null);
72 + const noEntries = showNoInline
73 + ? noVoters.filter((e) => e.characterNation === nation)
74 + : [];
75 + const lines = [
76 + ...yesEntries.map((e) => formatCharRow(e, false, hasRank)),
77 + ...noEntries.map((e) => `❌ ${formatCharRow(e, false, hasRank)}`),
78 + ];
79 + return lines.length > 0 ? lines.join("\n") : "—";
80 + };
81 +
82 + const formatMessages = (): string => {
83 + if (allMessages.length === 0) return "";
84 + return allMessages
85 + .map((m) => {
86 + const name = m.entry.characterName ?? m.entry.displayName;
87 + const prefix = m.voteType === "no" ? "✗ " : "✓ ";
88 + const msg = m.entry.publicMessage ? ` — ${m.entry.publicMessage}` : "";
89 + return `${prefix}${name} · ${m.entry.votedAt}${msg}`;
90 + })
91 + .join("\n");
92 + };
93 +
94 + const locked = state.locked;
95 + const confirmed = state.confirmed;
96 +
97 + const color =
98 + confirmed === "yes" ? 0x57f287 :
99 + confirmed === "no" ? 0xed4245 :
100 + locked ? 0x888888 :
101 + 0xe8a317;
102 +
103 + // Title with nation + no counts (hidden when confirmed or locked)
104 + const counts = !locked && confirmed === null
105 + ? ` ${capellaEmoji} ${yesByNation.Capella.length} ${procyonEmoji} ${yesByNation.Procyon.length}`
106 + : "";
107 + const statusSuffix =
108 + locked ? " 🔒" :
109 + confirmed === "yes" ? " ✅" :
110 + confirmed === "no" ? " ❌" : "";
111 +
112 + const title = `⚔️ TG — ${state.slot}:00${counts}${statusSuffix}`;
113 +
114 + const embed = new EmbedBuilder()
115 + .setTitle(title)
116 + .setColor(color)
117 + .addFields(
118 + { name: `${capellaEmoji} Capella (${yesByNation[Nation.Capella].length})`, value: formatNationField(Nation.Capella), inline: false },
119 + { name: "\u200b", value: "\u200b", inline: false },
120 + { name: `${procyonEmoji} Procyon (${yesByNation[Nation.Procyon].length})`, value: formatNationField(Nation.Procyon), inline: false },
121 + )
122 + .setTimestamp();
123 +
124 + const msgSection = formatMessages();
125 + if (msgSection) {
126 + embed.addFields({ name: "\u200b", value: msgSection, inline: false });
127 + }
128 +
129 + let footer: string;
130 + if (confirmed === "yes") footer = cfg("confirmYesMessage");
131 + else if (confirmed === "no") footer = cfg("confirmNoMessage");
132 + else if (locked) footer = overrideLockMsg ?? cfg("lockMessage");
133 + else footer = `❌ ${noVoters.length} • Vote updates live • Anyone can vote • /tg switch to change character`;
134 + embed.setFooter({ text: footer });
135 +
136 + return embed;
137 + }
Siguiente Anterior