最終更新 3 weeks ago

gistfile1.txt Raw
1// autocomplete.ts
2let _usermapCache: Record<string, any> | null = null;
3
4function getUsermapCache(): Record<string, any> {
5 if (!_usermapCache) {
6 try { _usermapCache = JSON.parse(fs.readFileSync(Paths.data("usermap.json"), "utf8")); }
7 catch { _usermapCache = {}; }
8 }
9 return _usermapCache!;
10}
11
12// interactions.ts
13 const chars = JSON.parse(
14 fs.readFileSync(path.join(__dirname, "../../data/characters.json"), "utf8")
15 );
16
17 // subcommands/switch.ts
18 function findSharedChar(userKey: string, charName: string): { ownerKey: string; char: any } | null {
19 try {
20 const chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
21 for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
22 if (ownerKey === userKey) continue;
23 const char = data.characters?.find(
24 (c: any) => c.name.toLowerCase() === charName.toLowerCase() && c.sharedWith?.includes(userKey)
25 );
26 if (char) return { ownerKey, char };
27 }
28 } catch {}
29 return null;
30}
31
32// subcommands.admin.ts (userMap)
33 if (sub === "map") {
34 const target = interaction.options.getUser("user", true);
35 const userKey = interaction.options.getString("userkey", true);
36
37 // Check if userKey exists in characters.json
38 const fs = require("fs");
39 const path = require("path");
40 const chars = JSON.parse(fs.readFileSync(path.join(__dirname, "../../../data/characters.json"), "utf8"));
41 if (!chars[userKey]) {
42 return void replyAndDelete(interaction, `❌ No characters found for userKey **${userKey}**. Make sure it exists in characters.json first.`, true);
43 }
44
45 // Check if this Discord ID is already mapped
46 const existing = getUsermapEntryById(target.id, target.username);
47 const entry = existing ?? { file: userKey, aliases: [target.globalName ?? target.username] };
48 entry.file = userKey;
49
50 setUsermapEntry(target.id, entry);
51 return void replyAndDelete(interaction, `✅ Mapped **${target.username}** (${target.id}) → **${userKey}**`, true);
52 }
53
54 const raw = JSON.parse(fs.readFileSync(path.join(__dirname, "../../../data/usermap.json"), "utf8"));
55
56
57// subcommands/char (looks a lot like the previous one, maybe extract?)
58function findSharedChar(userKey: string, charName: string): { ownerKey: string; charName: string } | null {
59 try {
60 const chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
61 for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
62 if (ownerKey === userKey) continue;
63 const char = data.characters?.find(
64 (c: any) => c.name.toLowerCase() === charName.toLowerCase() && c.sharedWith?.includes(userKey)
65 );
66 if (char) return { ownerKey, charName: char.name };
67 }
68 } catch {}
69 return null;
70}
71
72// subcommands/share.ts
73function loadRawChars(): any {
74 return JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
75}
76
77// subcommands/poll/seed.ts
78 usermap = JSON.parse(fs.readFileSync(path.join(__dirname, "../../../data/usermap.json"), "utf8"));
79
80// attendance.ts
81 function load(): void {
82 try { _data = JSON.parse(fs.readFileSync(Paths.data("attendance.json"), "utf8")); }
83 catch { _data = {}; }
84 }
85
86 function save(): void {
87 fs.writeFileSync(Paths.data("attendance.json"), JSON.stringify(_data, null, 2));
88 }
89
90// borrow.ts
91 let _prefs: Record<string, { ownerKey: string; charName: string }> = {};
92
93function loadPrefs(): void {
94 try { _prefs = JSON.parse(fs.readFileSync(PREFS_PATH, "utf8")); }
95 catch { _prefs = {}; }
96}
97
98function savePrefs(): void {
99 try { fs.writeFileSync(PREFS_PATH, JSON.stringify(_prefs, null, 2)); }
100 catch (err) { console.error("Failed to save sessionPreferences.json:", err); }
101}
102
103// systems/charSelect.ts
104
105 const sharedChars: Character[] = [];
106 try {
107 const chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
108 for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
109 if (ownerKey === userKey) continue;
110 for (const c of data.characters ?? []) {
111 if (c.sharedWith?.includes(userKey)) sharedChars.push(c);
112 }
113 }
114 } catch {}
115
116// systems/config.ts
117let _cfg: BotConfig = {};
118
119export function loadConfig(): void {
120 try { _cfg = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8")); }
121 catch { _cfg = {}; }
122}
123
124export function saveConfig(): void {
125 try { fs.writeFileSync(CONFIG_PATH, JSON.stringify(_cfg, null, 2)); }
126 catch (err) { console.error("Failed to save config.json:", err); }
127}
128
129// systems/emojis.ts
130function loadEmojiMap(): Record<string, string> {
131 if (_map) return _map;
132
133 _map = {};
134 const dir = Paths.emojis();
135
136 if (!fs.existsSync(dir)) {
137 // Fallback to legacy messages/emojis.json
138 try {
139 _map = JSON.parse(fs.readFileSync(Paths.messages("emojis.json"), "utf8"));
140 console.warn("[emojis] data/emojis/ not found, using legacy messages/emojis.json");
141 } catch {}
142 return _map!;
143 }
144
145 for (const file of fs.readdirSync(dir)) {
146 if (!file.endsWith(".json")) continue;
147 try {
148 const data = JSON.parse(fs.readFileSync(Paths.emojis(file), "utf8"));
149 Object.assign(_map!, data);
150 } catch (err) {
151 console.error(`[emojis] Failed to load ${file}:`, err);
152 }
153 }
154
155 return _map!;
156 }
157
158 // systems/history.ts
159 export function loadResult(date: string, slot: number): TGResult | null {
160 try {
161 return JSON.parse(fs.readFileSync(historyPath(historyKey(date, slot)), "utf8"));
162 } catch {
163 return null;
164 }
165}
166
167export function saveResult(result: TGResult): void {
168 if (!fs.existsSync(HISTORY_DIR)) fs.mkdirSync(HISTORY_DIR, { recursive: true });
169 const key = historyKey(result.date, result.slot);
170 fs.writeFileSync(historyPath(key), JSON.stringify(result, null, 2));
171}
172
173export function listRecentResults(limit = 10): TGResult[] {
174 if (!fs.existsSync(HISTORY_DIR)) return [];
175 return fs.readdirSync(HISTORY_DIR)
176 .filter((f) => f.endsWith(".json"))
177 .sort()
178 .reverse()
179 .slice(0, limit)
180 .map((f) => {
181 try { return JSON.parse(fs.readFileSync(path.join(HISTORY_DIR, f), "utf8")) as TGResult; }
182 catch { return null; }
183 })
184 .filter(Boolean) as TGResult[];
185}
186
187// systems.impersonate.ts
188 const usermap = JSON.parse(fs.readFileSync(Paths.data("usermap.json"), "utf-8"));
189
190// systems/messages.ts
191export function loadMessages(): void {
192 try {
193 MESSAGES.global = JSON.parse(fs.readFileSync(path.join(MESSAGES_DIR, "global.json"), "utf8"));
194 } catch (err) {
195 console.error("Failed to load global.json:", err);
196 }
197
198 try {
199 MESSAGES.userMap = JSON.parse(fs.readFileSync(USERMAP_PATH, "utf8"));
200 } catch {
201 MESSAGES.userMap = {};
202 }
203
204 const usersDir = path.join(MESSAGES_DIR, "users");
205 MESSAGES.users = {};
206 if (fs.existsSync(usersDir)) {
207 for (const file of fs.readdirSync(usersDir)) {
208 if (!file.endsWith(".json")) continue;
209 const key = path.basename(file, ".json");
210 try {
211 MESSAGES.users[key] = JSON.parse(fs.readFileSync(path.join(usersDir, file), "utf8"));
212 } catch (err) {
213 console.error(`Failed to load user message file ${file}:`, err);
214 }
215 }
216 }
217
218 console.log(`Messages loaded — ${Object.keys(MESSAGES.users).length} user file(s).`);
219}
220
221export function setUsermapEntry(discordId: string, entry: UsermapEntry): void {
222 MESSAGES.userMap[discordId] = entry;
223
224 // Persist to disk
225 const USERMAP_PATH = path.join(__dirname, "../../data/usermap.json");
226 try {
227 const raw = JSON.parse(fs.readFileSync(USERMAP_PATH, "utf8"));
228 raw[discordId] = entry;
229 fs.writeFileSync(USERMAP_PATH, JSON.stringify(raw, null, 2));
230 } catch (err) {
231 console.error("Failed to save usermap.json:", err);
232 }
233}
234export function removeUsermapEntry(discordId: string): void {
235 delete MESSAGES.userMap[discordId];
236
237 const USERMAP_PATH = path.join(__dirname, "../../data/usermap.json");
238 try {
239 const raw = JSON.parse(fs.readFileSync(USERMAP_PATH, "utf8"));
240 delete raw[discordId];
241 fs.writeFileSync(USERMAP_PATH, JSON.stringify(raw, null, 2));
242 } catch (err) {
243 console.error("Failed to save usermap.json:", err);
244 }
245}
246
247// systems/pollPersistence.ts
248export namespace persist {
249 export function save(polls: Map<number, PollState>): void {
250 try {
251 fs.writeFileSync(PERSIST_PATH, JSON.stringify(serialize(polls), null, 2), "utf8");
252 } catch (err) {
253 console.error("[pollPersistence] Failed to save poll state:", err);
254 }
255 }
256
257 export function load(): Map<number, PollState> | null {
258 try {
259 if (!fs.existsSync(PERSIST_PATH)) return null;
260 const raw = fs.readFileSync(PERSIST_PATH, "utf8");
261 const data = JSON.parse(raw) as SerializedPollState[];
262 const polls = deserialize(data);
263 console.log(`[pollPersistence] Restored ${polls.size} poll(s) from disk.`);
264 return polls;
265 } catch (err) {
266 console.error("[pollPersistence] Failed to load poll state:", err);
267 return null;
268 }
269 }
270
271 export function clear(): void {
272 try {
273 if (fs.existsSync(PERSIST_PATH)) fs.unlinkSync(PERSIST_PATH);
274 } catch (err) {
275 console.error("[pollPersistence] Failed to clear poll state:", err);
276 }
277 }
278}
279
280// systems/score.ts
281 function getHistoryPath(historyKey: HistoryKey): string {
282 return Paths.data("tg-history", `${historyKey}.json`);
283 }
284
285 function loadHistory(historyKey: HistoryKey): { scores: TGScore[] } {
286 try { return JSON.parse(fs.readFileSync(getHistoryPath(historyKey), "utf8")); }
287 catch { return { scores: [] }; }
288 }
289
290 function saveHistory(historyKey: HistoryKey, data: { scores: TGScore[] }): void {
291 fs.writeFileSync(getHistoryPath(historyKey), JSON.stringify(data, null, 2));
292 }
293
294 // systems/registry.ts
295 function loadUsermap(): Record<string, RawUsermapValue> {
296 if (!_cache) {
297 try { _cache = JSON.parse(fs.readFileSync(Paths.data("usermap.json"), "utf8")); }
298 catch { _cache = {}; }
299 }
300 return _cache!;
301 }
302