diff --git a/.eslintrc-no-types.json b/.eslintrc-no-types.json index 81ca8b3b0d..ef5da49d43 100644 --- a/.eslintrc-no-types.json +++ b/.eslintrc-no-types.json @@ -1,7 +1,7 @@ { "root": true, "parserOptions": { - "ecmaVersion": 9, + "ecmaVersion": 10, "sourceType": "script", "ecmaFeatures": { "globalReturn": true diff --git a/.eslintrc.json b/.eslintrc.json index cb20cdc4ba..cf713fb55a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,7 +5,7 @@ "files": ["./config/*.ts", "./data/**/*.ts", "./lib/*.ts", "./server/**/*.ts", "./sim/**/*.ts", "./tools/set-import/*.ts"], "parser": "@typescript-eslint/parser", "parserOptions": { - "ecmaVersion": 9, + "ecmaVersion": 10, "sourceType": "module", "tsconfigRootDir": ".", "project": ["./tsconfig.json"] diff --git a/lib/crashlogger.ts b/lib/crashlogger.ts index d6de606350..01aadd008a 100644 --- a/lib/crashlogger.ts +++ b/lib/crashlogger.ts @@ -24,11 +24,11 @@ let transport: any; * to receive them. */ export function crashlogger( - error: Error | string, description: string, data: AnyObject | null = null + error: unknown, description: string, data: AnyObject | null = null ): string | null { const datenow = Date.now(); - let stack = (typeof error === 'string' ? error : error?.stack) || ''; + let stack = (typeof error === 'string' ? error : (error as Error)?.stack) || ''; if (data) { stack += `\n\nAdditional information:\n`; for (const k in data) { @@ -51,7 +51,7 @@ export function crashlogger( if (!transport) { try { require.resolve('nodemailer'); - } catch (e) { + } catch { throw new Error( 'nodemailer is not installed, but it is required if Config.crashguardemail is configured! ' + 'Run npm install --no-save nodemailer and restart the server.' @@ -65,7 +65,7 @@ export function crashlogger( } else { try { transport = require('nodemailer').createTransport(Config.crashguardemail.options); - } catch (e) { + } catch { throw new Error("Failed to start nodemailer; are you sure you've configured Config.crashguardemail correctly?"); } diff --git a/lib/fs.ts b/lib/fs.ts index 0c4cf78fe5..4d94686d61 100644 --- a/lib/fs.ts +++ b/lib/fs.ts @@ -110,7 +110,7 @@ export class FSPath { readIfExistsSync() { try { return fs.readFileSync(this.path, 'utf8'); - } catch (err) { + } catch (err: any) { if (err.code !== 'ENOENT') throw err; } return ''; @@ -342,7 +342,7 @@ export class FSPath { if (global.Config?.nofswriting) return; try { fs.unlinkSync(this.path); - } catch (err) { + } catch (err: any) { if (err.code !== 'ENOENT') throw err; } } @@ -389,7 +389,7 @@ export class FSPath { if (global.Config?.nofswriting) return; try { fs.mkdirSync(this.path, mode); - } catch (err) { + } catch (err: any) { if (err.code !== 'EEXIST') throw err; } } @@ -401,7 +401,7 @@ export class FSPath { async mkdirp(mode: string | number = 0o755) { try { await this.mkdirIfNonexistent(mode); - } catch (err) { + } catch (err: any) { if (err.code !== 'ENOENT') throw err; await this.parentDir().mkdirp(mode); await this.mkdirIfNonexistent(mode); @@ -415,7 +415,7 @@ export class FSPath { mkdirpSync(mode: string | number = 0o755) { try { this.mkdirIfNonexistentSync(mode); - } catch (err) { + } catch (err: any) { if (err.code !== 'ENOENT') throw err; this.parentDir().mkdirpSync(mode); this.mkdirIfNonexistentSync(mode); diff --git a/lib/process-manager.ts b/lib/process-manager.ts index d9afef1da6..ef59a63580 100644 --- a/lib/process-manager.ts +++ b/lib/process-manager.ts @@ -144,10 +144,6 @@ export class QueryProcessWrapper implements ProcessWrapper { if (!resolve) throw new Error(`Invalid taskId ${message.slice(0, nlLoc)}`); this.pendingTasks.delete(taskId); const resp = this.safeJSON(message.slice(nlLoc + 1)); - if (resp instanceof Error) { - // we'd fail here anyway if it crashed, so at least this way we can log it - return false; - } resolve(resp); if (this.resolveRelease && !this.getLoad()) this.destroy(); @@ -161,13 +157,13 @@ export class QueryProcessWrapper implements ProcessWrapper { } try { return JSON.parse(obj); - } catch (e) { + } catch (e: any) { // this is in the parent, so it should usually exist, but it's possible // it's also futureproofing in case other external modfules require this // we also specifically do not throw here because this json might be sensitive, // so we only want it to go to emails global.Monitor?.crashlog?.(e, `a ${path.basename(this.file)} process`, {result: obj}); - return new Error(e); + return undefined; } } @@ -638,7 +634,7 @@ export class StreamProcessManager extends ProcessManager { let value; ({value, done} = await stream.next()); process.send!(`${taskId}\nPUSH\n${value}`); - } catch (err) { + } catch (err: any) { process.send!(`${taskId}\nTHROW\n${err.stack}`); } } @@ -765,7 +761,7 @@ export class RawProcessManager extends ProcessManager { let value; ({value, done} = await stream.next()); process.send!(value); - } catch (err) { + } catch (err: any) { process.send!(`THROW\n${err.stack}`); } } diff --git a/lib/repl.ts b/lib/repl.ts index 7b368871b3..cf29fbc981 100644 --- a/lib/repl.ts +++ b/lib/repl.ts @@ -31,7 +31,7 @@ export const Repl = new class { for (const s of Repl.socketPathnames) { try { fs.unlinkSync(s); - } catch (e) {} + } catch {} } if (code === 129 || code === 130) { process.exitCode = 0; @@ -48,7 +48,7 @@ export const Repl = new class { let handler; try { handler = require('node-oom-heapdump')(); - } catch (e) { + } catch (e: any) { if (e.code !== 'MODULE_NOT_FOUND') throw e; throw new Error(`node-oom-heapdump is not installed. Run \`npm install --no-save node-oom-heapdump\` and try again.`); } @@ -94,7 +94,7 @@ export const Repl = new class { eval(cmd, context, unusedFilename, callback) { try { return callback(null, evalFunction(cmd)); - } catch (e) { + } catch (e: any) { return callback(e, undefined); } }, diff --git a/lib/sql.ts b/lib/sql.ts index 3264796d92..e8cf1e73f6 100644 --- a/lib/sql.ts +++ b/lib/sql.ts @@ -51,7 +51,7 @@ type ErrorHandler = (error: Error, data: DatabaseQuery) => void; function getModule() { try { return require('better-sqlite3') as typeof sqlite.default; - } catch (e) { + } catch { return null; } } @@ -143,7 +143,7 @@ export class SQLDatabaseManager extends QueryProcessManager this.state.statements.set(query.data, this.database.prepare(query.data)); return query.data; } - } catch (error) { + } catch (error: any) { return this.onError(error, query); } }); diff --git a/lib/utils.ts b/lib/utils.ts index f6ef13ef54..67cb8239a7 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -117,7 +117,7 @@ export function visualize(value: any, depth = 0): string { stringValue !== `[object ${constructor}]`) { return `${constructor}(${stringValue})`; } - } catch (e) {} + } catch {} } let buf = ''; for (const key in value) { diff --git a/logs/chat/README.md b/logs/chat/README.md deleted file mode 100644 index 2171171817..0000000000 --- a/logs/chat/README.md +++ /dev/null @@ -1 +0,0 @@ -Logs of chat rooms are stored in this directory if `logchat` is enabled. diff --git a/logs/logging.md b/logs/logging.md deleted file mode 100644 index ea2caf179c..0000000000 --- a/logs/logging.md +++ /dev/null @@ -1,21 +0,0 @@ -Pokémon Showdown Logging -======================================================================== - -This is the Pokémon Showdown log directory. - -Pokémon Showdown will, by default, log rated battles in each format, but not unrated -battles. To enable logging of unrated battles, turn on the config setting `logchallenges`. -There is currently no config option to disable logs for rated battles. -Battle logs are placed under a subdirectory for each month (e.g. `2013-02`). - -Moderator actions are logged in the subdirectory `modlog`. -Each chat room has a separate log file (e.g. `modlog_lobby.txt`). -Battle rooms share a single log file, which is named `modlog_battle.txt`. - -If the server or the simulator process crashes, a stack trace will -usually be logged to `errors.txt`. - -By default, Pokémon Showdown does not log chat rooms. However, you can -enable their logging by setting the `logchat` option in `config.js`. -If you enable it, the logs are written in the subdirectory named `chat`. -Each room gets their own subdirectory within, which are furthermore classified by month. diff --git a/logs/modlog/README.md b/logs/modlog/README.md deleted file mode 100644 index 6fe5d428f9..0000000000 --- a/logs/modlog/README.md +++ /dev/null @@ -1 +0,0 @@ -Logs of moderation actions are stored in this directory. diff --git a/logs/repl/README.md b/logs/repl/README.md deleted file mode 100644 index cdd04b8ebd..0000000000 --- a/logs/repl/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# repl directory - -The REPL feature is enabled by default; it can be disabled in `config.js`. - -This directory is used by default to store the REPL sockets to all of showdown's processes. - -The intended uses of these REPL sockets are for debugging (especially when the server is seemingly frozen) and scripting. - -You can use any tool capable of talking to Unix sockets such as `nc`. e.g. `nc -U app`, replacing `app` with the name of any socket in this directory. diff --git a/logs/tickets/README.md b/logs/tickets/README.md deleted file mode 100644 index 0af72c3890..0000000000 --- a/logs/tickets/README.md +++ /dev/null @@ -1 +0,0 @@ -Logs of ticket stats are stored in this directory. diff --git a/package.json b/package.json index 23edf919ce..f81cdf036f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "main": ".sim-dist/index.js", "dependencies": { "@swc/core": "^1.2.61", - "@types/better-sqlite3": "^5.4.0", "probe-image-size": "^5.0.0", "sockjs": "^0.3.21", "ts-node": "^10.0.0" @@ -71,18 +70,19 @@ ], "license": "MIT", "devDependencies": { - "@types/cloud-env": "^0.2.1", - "@types/node": "^14.14.6", - "@types/node-static": "^0.7.5", - "@types/nodemailer": "^6.4.0", - "@types/sockjs": "^0.3.32", - "@typescript-eslint/eslint-plugin": "^4.6.0", - "@typescript-eslint/parser": "^4.6.0", - "eslint": "^7.31.0", + "@types/better-sqlite3": "^7.4.0", + "@types/cloud-env": "^0.2.2", + "@types/node": "^14.17.12", + "@types/node-static": "^0.7.7", + "@types/nodemailer": "^6.4.4", + "@types/sockjs": "^0.3.33", + "@typescript-eslint/eslint-plugin": "^4.30.0", + "@typescript-eslint/parser": "^4.30.0", + "eslint": "^7.32.0", "eslint-plugin-import": "^2.22.1", "husky": "^4.3.0", "mocha": "^8.2.0", "smogon": "^1.4.5", - "typescript": "^4.1.0" + "typescript": "^4.4.2" } } diff --git a/server/chat-commands/admin.ts b/server/chat-commands/admin.ts index a965fc893d..0ac3493385 100644 --- a/server/chat-commands/admin.ts +++ b/server/chat-commands/admin.ts @@ -114,7 +114,7 @@ async function updateserver(context: Chat.CommandContext, codePath: string) { } return true; - } catch (e) { + } catch { // failed while rebasing or popping the stash await exec(`git reset --hard ${oldHash}`); if (stashedChanges) await exec(`git stash pop`); @@ -744,7 +744,7 @@ export const commands: Chat.ChatCommands = { } else { return this.errorReply("Your hot-patch command was unrecognized."); } - } catch (e) { + } catch (e: any) { Rooms.global.notifyRooms( ['development', 'staff'] as RoomID[], `|c|${user.getIdentity()}|/log ${user.name} used /hotpatch ${target} - but something failed while trying to hot-patch.` @@ -1259,7 +1259,7 @@ export const commands: Chat.ChatCommands = { this.sendReply(`|html|${generateHTML('<', result)}`); } logRoom?.roomlog(`<< ${result}`); - } catch (e) { + } catch (e: any) { const message = ('' + e.stack).replace(/\n *at CommandContext\.eval [\s\S]*/m, ''); const command = uhtmlId ? `|uhtmlchange|${uhtmlId}|` : '|html|'; this.sendReply(`${command}${generateHTML('<', message)}`); @@ -1325,14 +1325,14 @@ export const commands: Chat.ChatCommands = { // presume it's attempting to get data first result = await database.all(query, []); if ((result as any).err) parseError(result as any); - } catch (err) { + } catch (err: any) { // it's not getting data, but it might still be a valid statement - try to run instead if (err.stack?.includes(`Use run() instead`)) { try { result = await database.run(query, []); if ((result as any).err) parseError(result as any); result = Utils.visualize(result); - } catch (e) { + } catch (e: any) { result = ('' + e.stack).replace(/\n *at CommandContext\.evalsql [\s\S]*/m, ''); } } else { diff --git a/server/chat-commands/info.ts b/server/chat-commands/info.ts index c69a31fde7..54712537da 100644 --- a/server/chat-commands/info.ts +++ b/server/chat-commands/info.ts @@ -2475,7 +2475,7 @@ export const commands: Chat.ChatCommands = { if (!/^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)(\/|$)/i.test(link)) { try { dimensions = await Chat.fitImage(link); - } catch (e) { + } catch { throw new Chat.ErrorMessage('Invalid link.'); } } @@ -2589,7 +2589,7 @@ export const commands: Chat.ChatCommands = { const [width, height, resized] = await Chat.fitImage(link); buf = Utils.html``; if (resized) buf += Utils.html`
full-size image`; - } catch (err) { + } catch { return this.errorReply('Invalid image'); } } @@ -2636,7 +2636,7 @@ export const commands: Chat.ChatCommands = { let rawResult; try { rawResult = await Net(`https://${Config.routes.root}/users/${target}.json`).get(); - } catch (e) { + } catch (e: any) { if (e.message.includes('Not found')) throw new Chat.ErrorMessage(`User '${target}' is unregistered.`); throw new Chat.ErrorMessage(e.message); } diff --git a/server/chat-commands/moderation.ts b/server/chat-commands/moderation.ts index d5b3f55379..7b731ddb1a 100644 --- a/server/chat-commands/moderation.ts +++ b/server/chat-commands/moderation.ts @@ -213,11 +213,14 @@ export const commands: Chat.ChatCommands = { const userid = toID(toPromote); if (!userid) return this.parse('/help roompromote'); - const oldSymbol = room.auth.getDirect(userid); + // weird ts bug (?) - 7022 + // it implicitly is 'any' because it has no annotation and is "is referenced directly or indirectly in its own initializer." + // dunno why this happens, but for now we can just cast over it. + const oldSymbol: GroupSymbol = room.auth.getDirect(userid); let shouldPopup; try { shouldPopup = runPromote(user, room, userid, nextSymbol, toPromote, force); - } catch (err) { + } catch (err: any) { if (err.name?.endsWith('ErrorMessage')) { this.errorReply(err.message); continue; diff --git a/server/chat-plugins/battlesearch.ts b/server/chat-plugins/battlesearch.ts index 4c9cec683d..c71a4ef2ff 100644 --- a/server/chat-plugins/battlesearch.ts +++ b/server/chat-plugins/battlesearch.ts @@ -31,7 +31,7 @@ export async function runBattleSearch(userids: ID[], month: string, tierid: ID, let files = []; try { files = await FS(pathString).readdir(); - } catch (err) { + } catch (err: any) { if (err.code === 'ENOENT') { return results; } @@ -47,7 +47,7 @@ export async function runBattleSearch(userids: ID[], month: string, tierid: ID, let output; try { output = await ProcessManager.exec(['rg', '-i', regexString, '--no-line-number', '-P', '-tjson', ...files]); - } catch (error) { + } catch { return results; } for (const line of output.stdout.split('\n').reverse()) { diff --git a/server/chat-plugins/calculator.ts b/server/chat-plugins/calculator.ts index b6a1d4a267..727fc970c4 100644 --- a/server/chat-plugins/calculator.ts +++ b/server/chat-plugins/calculator.ts @@ -191,7 +191,7 @@ export const commands: Chat.ChatCommands = { resultStr = `${result}`; } this.sendReplyBox(`${expression}
= ${resultStr}`); - } catch (e) { + } catch (e: any) { this.sendReplyBox( Utils.html`${expression}
= Invalid input: ${e.message}` ); diff --git a/server/chat-plugins/chat-monitor.ts b/server/chat-plugins/chat-monitor.ts index 8258afffe2..e48c9807e9 100644 --- a/server/chat-plugins/chat-monitor.ts +++ b/server/chat-plugins/chat-monitor.ts @@ -68,7 +68,7 @@ export const Filters = new class { } else { return new RegExp((isShortener ? `\\b${word}` : word), (isReplacement ? 'igu' : 'iu')); } - } catch (e) { + } catch (e: any) { throw new Chat.ErrorMessage( e.message.startsWith('Invalid regular expression: ') ? e.message : `Invalid regular expression: /${word}/: ${e.message}` ); @@ -153,7 +153,7 @@ export const Filters = new class { let data; try { data = FS(LEGACY_MONITOR_FILE).readSync(); - } catch (e) { + } catch (e: any) { if (e.code !== 'ENOENT') throw e; } if (!data) return; diff --git a/server/chat-plugins/chatlog.ts b/server/chat-plugins/chatlog.ts index 4561d0f361..afb06f2de7 100644 --- a/server/chat-plugins/chatlog.ts +++ b/server/chat-plugins/chatlog.ts @@ -66,7 +66,7 @@ export class LogReaderRoom { try { const listing = await FS(`logs/chat/${this.roomid}`).readdir(); return listing.filter(file => /^[0-9][0-9][0-9][0-9]-[0-9][0-9]$/.test(file)); - } catch (err) { + } catch { return []; } } @@ -75,7 +75,7 @@ export class LogReaderRoom { try { const listing = await FS(`logs/chat/${this.roomid}/${month}`).readdir(); return listing.filter(file => file.endsWith(".txt")).map(file => file.slice(0, -4)); - } catch (err) { + } catch { return []; } } @@ -212,7 +212,7 @@ export const LogReader = new class { const days = (await FS(`logs/${month}/${tier}/`).readdir()).filter(this.isDay).sort(); firstDay = days[0]; break; - } catch (err) {} + } catch {} months.shift(); } if (!firstDay) return null; @@ -225,7 +225,7 @@ export const LogReader = new class { const days = (await FS(`logs/${month}/${tier}/`).readdir()).filter(this.isDay).sort(); lastDay = days[days.length - 1]; break; - } catch (err) {} + } catch {} months.pop(); } if (!lastDay) throw new Error(`getBattleLog month range search for ${tier}`); @@ -242,7 +242,7 @@ export const LogReader = new class { Utils.sortBy(battles, getBattleNum); return [getBattleNum(battles[0]), getBattleNum(battles[battles.length - 1])]; - } catch (err) { + } catch { return null; } }; @@ -1085,7 +1085,7 @@ export class RipgrepLogSearcher extends Searcher { cwd: `${__dirname}/../../`, }); results = stdout.split(resultSep); - } catch (e) { + } catch (e: any) { if (e.code !== 1 && !e.message.includes('stdout maxBuffer') && !e.message.includes('No such file or directory')) { throw e; // 2 means an error in ripgrep } @@ -1230,7 +1230,7 @@ export class RipgrepLogSearcher extends Searcher { const battleName = name.split('/').pop()!; results.push(battleName.slice(0, -9)); } - } catch (e) { + } catch (e: any) { if (e.code !== 1) throw e; } return results.filter(Boolean); @@ -1268,7 +1268,7 @@ export const PM = new ProcessManager.QueryProcessManager(module, Monitor.slow(`[Slow chatlog query]: ${elapsedTime}ms: ${JSON.stringify(data)}`); } return result; - } catch (e) { + } catch (e: any) { if (e.name?.endsWith('ErrorMessage')) { return LogViewer.error(e.message); } diff --git a/server/chat-plugins/daily-spotlight.ts b/server/chat-plugins/daily-spotlight.ts index 3951c43dec..12588c3f4d 100644 --- a/server/chat-plugins/daily-spotlight.ts +++ b/server/chat-plugins/daily-spotlight.ts @@ -11,7 +11,7 @@ export let spotlights: {[k: string]: {[k: string]: {image?: StoredImage, descrip try { spotlights = JSON.parse(FS(SPOTLIGHT_FILE).readIfExistsSync() || "{}"); -} catch (e) { +} catch (e: any) { if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'ENOENT') throw e; } if (!spotlights || typeof spotlights !== 'object') spotlights = {}; @@ -50,7 +50,7 @@ export async function renderSpotlight(roomid: RoomID, key: string, index: number const [width, height] = await Chat.fitImage(image, 150, 300); imgHTML = ``; spotlights[roomid][key][index].image = [image, width, height]; - } catch (err) {} + } catch {} } } @@ -179,7 +179,7 @@ export const commands: Chat.ChatCommands = { img = img.trim(); try { [width, height] = await Chat.fitImage(img); - } catch (e) { + } catch { return this.errorReply(`Invalid image url: ${img}`); } } diff --git a/server/chat-plugins/hangman.ts b/server/chat-plugins/hangman.ts index b13de6c221..60ab6aa88f 100644 --- a/server/chat-plugins/hangman.ts +++ b/server/chat-plugins/hangman.ts @@ -37,7 +37,7 @@ try { if (save) { FS(HANGMAN_FILE).writeUpdate(() => JSON.stringify(hangmanData)); } -} catch (e) {} +} catch {} const maxMistakes = 6; diff --git a/server/chat-plugins/helptickets.ts b/server/chat-plugins/helptickets.ts index 26dbdaf653..342c18a866 100644 --- a/server/chat-plugins/helptickets.ts +++ b/server/chat-plugins/helptickets.ts @@ -100,7 +100,7 @@ try { tickets[t] = ticket; } } -} catch (e) { +} catch (e: any) { if (e.code !== 'ENOENT') throw e; } @@ -124,7 +124,7 @@ function writeStats(line: string) { const month = Chat.toTimestamp(date).split(' ')[0].split('-', 2).join('-'); try { FS(`logs/tickets/${month}.tsv`).appendSync(line + '\n'); - } catch (e) { + } catch (e: any) { if (e.code !== 'ENOENT') throw e; } } @@ -453,7 +453,7 @@ export class HelpTicket extends Rooms.RoomGame { lines = await ProcessManager.exec([ `rg`, `${__dirname}/../../logs/tickets/${date ? `${date}.jsonl` : ''}`, ...args, ]); - } catch (e) { + } catch (e: any) { if (e.message.includes('No such file or directory')) { throw new Chat.ErrorMessage(`No ticket logs for that month.`); } @@ -766,7 +766,7 @@ export async function getOpponent(link: string, submitter: ID): Promise { url: `https://${Config.routes.replays}/${battle}`, }; } - } catch (e) {} + } catch {} return null; } diff --git a/server/chat-plugins/hosts.ts b/server/chat-plugins/hosts.ts index 1786c04600..8e8f6b3b75 100644 --- a/server/chat-plugins/hosts.ts +++ b/server/chat-plugins/hosts.ts @@ -256,7 +256,7 @@ export const commands: Chat.ChatCommands = { let result; try { result = IPTools.checkRangeConflicts(range, IPTools.ranges, widen); - } catch (e) { + } catch (e: any) { return this.errorReply(e.message); } if (typeof result === 'number') { diff --git a/server/chat-plugins/mafia.ts b/server/chat-plugins/mafia.ts index 6c23d783f5..960585f165 100644 --- a/server/chat-plugins/mafia.ts +++ b/server/chat-plugins/mafia.ts @@ -114,7 +114,7 @@ function readFile(path: string) { return false; } return Object.assign(Object.create(null), JSON.parse(json)); - } catch (e) { + } catch (e: any) { if (e.code !== 'ENOENT') throw e; } } diff --git a/server/chat-plugins/net-filters.ts b/server/chat-plugins/net-filters.ts index b200cd5bdc..823c93260b 100644 --- a/server/chat-plugins/net-filters.ts +++ b/server/chat-plugins/net-filters.ts @@ -34,7 +34,7 @@ interface TrainingLine { function modelExists() { try { require.resolve('brain.js'); - } catch (e) { + } catch { return false; } return true; @@ -49,7 +49,7 @@ export class NeuralNetChecker { constructor(path?: string) { try { this.model = new (require('brain.js').recurrent.LSTM)(); - } catch (e) { + } catch { this.model = null; } if (path) this.load(path); @@ -109,7 +109,7 @@ export class NeuralNetChecker { if (!this.model) return result; try { result = this.model.run(data); - } catch (e) {} + } catch {} // usually means someone didn't train it, carry on // acceptable to drop since training is very slow return result; @@ -178,7 +178,7 @@ export const PM = new QueryProcessManager(module, async query => let response = ''; try { response = net.run(data as string); - } catch (e) {} // uninitialized (usually means intializing, which can be slow) - drop it for now + } catch {} // uninitialized (usually means intializing, which can be slow) - drop it for now return response; case 'train': return net.train(data as TrainingLine[], options?.iterations); @@ -187,7 +187,7 @@ export const PM = new QueryProcessManager(module, async query => case 'load': try { net.load(data as string); - } catch (e) { + } catch (e: any) { return e.message; } return 'success'; diff --git a/server/chat-plugins/responder.ts b/server/chat-plugins/responder.ts index 1ffa14ba7b..9d9cc4a425 100644 --- a/server/chat-plugins/responder.ts +++ b/server/chat-plugins/responder.ts @@ -18,7 +18,7 @@ export let answererData: {[roomid: string]: PluginData} = {}; try { answererData = JSON.parse(FS(DATA_PATH).readSync()); -} catch (e) {} +} catch {} /** * A message caught by the filter. diff --git a/server/chat-plugins/the-studio.ts b/server/chat-plugins/the-studio.ts index 682a6d2f23..8036a4977b 100644 --- a/server/chat-plugins/the-studio.ts +++ b/server/chat-plugins/the-studio.ts @@ -82,7 +82,7 @@ export class LastFMInterface { limit: 1, api_key: Config.lastfmkey, format: 'json', }, }); - } catch (e) { + } catch { throw new Chat.ErrorMessage(`No scrobble data found.`); } const res = JSON.parse(raw); @@ -108,7 +108,7 @@ export class LastFMInterface { let videoIDs: string[] | undefined; try { videoIDs = await YouTube.searchVideo(trackName, 1); - } catch (e) { + } catch (e: any) { throw new Chat.ErrorMessage(`Error while fetching video data: ${e.message}`); } if (!videoIDs?.length) { @@ -158,7 +158,7 @@ export class LastFMInterface { let raw; try { raw = await Net(API_ROOT).get({query}); - } catch (e) { + } catch { throw new Chat.ErrorMessage(`No track data found.`); } const req = JSON.parse(raw); @@ -182,7 +182,7 @@ export class LastFMInterface { let videoIDs: string[] | undefined; try { videoIDs = await YouTube.searchVideo(searchName, 1); - } catch (e) { + } catch (e: any) { throw new Chat.ErrorMessage(`Error while fetching video data: ${e.message}`); } if (!videoIDs?.length) { diff --git a/server/chat-plugins/thing-of-the-day.ts b/server/chat-plugins/thing-of-the-day.ts index 526a16990c..7382416b22 100644 --- a/server/chat-plugins/thing-of-the-day.ts +++ b/server/chat-plugins/thing-of-the-day.ts @@ -394,7 +394,7 @@ class OtdHandler { try { const [width, height] = await Chat.fitImage(winner.image, 100, 100); output += Utils.html ``; - } catch (err) {} + } catch {} } output += ``; if (winner.event) output += Utils.html `Event: ${winner.event}
`; diff --git a/server/chat-plugins/trivia/database.ts b/server/chat-plugins/trivia/database.ts index 991bb63815..d9eea16f9b 100644 --- a/server/chat-plugins/trivia/database.ts +++ b/server/chat-plugins/trivia/database.ts @@ -621,7 +621,7 @@ export class TriviaSQLiteDatabase implements TriviaDatabase { try { triviaData = JSON.parse(FS(this.legacyJSONPath).readIfExistsSync() || "{}"); if (!triviaData) throw new Error(`no JSON`); - } catch (e) { + } catch { return; } @@ -704,7 +704,7 @@ export class TriviaSQLiteDatabase implements TriviaDatabase { // move legacy JSON file try { await FS(this.legacyJSONPath).rename(this.legacyJSONPath + '.converted'); - } catch (e) {} + } catch {} } private rowToQuestion(row: AnyObject): Promise { diff --git a/server/chat-plugins/trivia/trivia.ts b/server/chat-plugins/trivia/trivia.ts index efda3d384d..65ed22c5d2 100644 --- a/server/chat-plugins/trivia/trivia.ts +++ b/server/chat-plugins/trivia/trivia.ts @@ -168,7 +168,7 @@ function getMastermindGame(room: Room | null) { function getTriviaOrMastermindGame(room: Room | null) { try { return getMastermindGame(room); - } catch (e) { + } catch { return getTriviaGame(room); } } @@ -1627,7 +1627,7 @@ const triviaCommands: Chat.ChatCommands = { const mastermindRound = getMastermindGame(room).currentRound; if (!mastermindRound) throw new Error; game = mastermindRound; - } catch (e) { + } catch { game = getTriviaGame(room); } @@ -2310,7 +2310,7 @@ const triviaCommands: Chat.ChatCommands = { try { await mergeAlts(user.id, altid); return this.sendReply(`Your Trivia leaderboard score has been transferred to '${altid}'!`); - } catch (err) { + } catch (err: any) { if (!err.message.includes('/trivia mergescore')) throw err; await requestAltMerge(altid, user.id); diff --git a/server/chat-plugins/username-prefixes.ts b/server/chat-plugins/username-prefixes.ts index 28db21b3e4..05d9fb5d4f 100644 --- a/server/chat-plugins/username-prefixes.ts +++ b/server/chat-plugins/username-prefixes.ts @@ -28,7 +28,7 @@ export class PrefixManager { let data: AnyObject; try { data = JSON.parse(FS(PREFIXES_FILE).readSync()); - } catch (e) { + } catch (e: any) { if (e.code !== 'ENOENT') throw e; return; } diff --git a/server/chat-plugins/youtube.ts b/server/chat-plugins/youtube.ts index 0d053fc580..14cd4e5af2 100644 --- a/server/chat-plugins/youtube.ts +++ b/server/chat-plugins/youtube.ts @@ -170,7 +170,7 @@ export class YoutubeInterface { raw = await Net(`${ROOT}videos`).get({ query: {part: 'snippet,statistics', id, key: Config.youtubeKey}, }); - } catch (e) { + } catch (e: any) { throw new Chat.ErrorMessage(`Failed to retrieve video data: ${e.message}.`); } const res = JSON.parse(raw); @@ -336,7 +336,7 @@ export const Twitch = new class { }, query: {query: channel}, }); - } catch (e) { + } catch (e: any) { throw new Chat.ErrorMessage(`Error retrieving twitch channel: ${e.message}`); } const data = JSON.parse(res); diff --git a/server/chat.ts b/server/chat.ts index 39b4b1d7ec..a40b3c001f 100644 --- a/server/chat.ts +++ b/server/chat.ts @@ -451,7 +451,7 @@ export class PageContext extends MessageContext { try { if (typeof handler !== 'function') this.pageDoesNotExist(); res = await handler.call(this, parts, this.user, this.connection); - } catch (err) { + } catch (err: any) { if (err.name?.endsWith('ErrorMessage')) { if (err.message) this.errorReply(err.message); return; @@ -598,7 +598,7 @@ export class CommandContext extends MessageContext { message = this.checkChat(message); } - } catch (err) { + } catch (err: any) { if (err.name?.endsWith('ErrorMessage')) { this.errorReply(err.message); this.update(); @@ -2094,7 +2094,7 @@ export const Chat = new class { try { // eslint-disable-next-line no-new new RegExp(word); - } catch (e) { + } catch (e: any) { throw new Chat.ErrorMessage( e.message.startsWith('Invalid regular expression: ') ? e.message : diff --git a/server/config-loader.ts b/server/config-loader.ts index cfa3b7460a..0548378bf0 100644 --- a/server/config-loader.ts +++ b/server/config-loader.ts @@ -32,7 +32,7 @@ export function load(invalidate = false) { if (config.usesqlite) { try { require('better-sqlite3'); - } catch (e) { + } catch { throw new Error(`better-sqlite3 is not installed or could not be loaded, but Config.usesqlite is enabled.`); } } @@ -149,7 +149,7 @@ export function checkRipgrepAvailability() { await ProcessManager.exec(['rg', '--version'], {cwd: `${__dirname}/../`}); await ProcessManager.exec(['tac', '--version'], {cwd: `${__dirname}/../`}); return true; - } catch (error) { + } catch { return false; } })(); diff --git a/server/friends.ts b/server/friends.ts index cda7a19347..f3e970a64e 100644 --- a/server/friends.ts +++ b/server/friends.ts @@ -99,7 +99,7 @@ export class FriendsDatabase { let val; try { val = database.prepare(`SELECT val FROM database_settings WHERE name = 'version'`).get().val; - } catch (e) {} + } catch {} const actualVersion = FS(`databases/migrations/friends`).readdirIfExistsSync().length; if (val === undefined) { // hasn't been set up before, write new version. @@ -118,7 +118,7 @@ export class FriendsDatabase { for (const k in ACTIONS) { try { statements[k] = database.prepare(ACTIONS[k as keyof typeof ACTIONS]); - } catch (e) { + } catch (e: any) { throw new Error(`Friends DB statement crashed: ${ACTIONS[k as keyof typeof ACTIONS]} (${e.message})`); } } @@ -383,7 +383,7 @@ export const PM = new ProcessManager.QueryProcessManager { if (!fs.statSync(key).isFile()) throw new Error(); try { key = fs.readFileSync(key); - } catch (e) { + } catch (e: any) { crashlogger( new Error(`Failed to read the configured SSL private key PEM file:\n${e.stack}`), `Socket process ${process.pid}` ); } - } catch (e) { + } catch { console.warn('SSL private key config values will not support HTTPS server option values in the future. Please set it to use the absolute path of its PEM file.'); key = config.ssl.options.key; } @@ -310,13 +310,13 @@ export class ServerStream extends Streams.ObjectReadWriteStream { if (!fs.statSync(cert).isFile()) throw new Error(); try { cert = fs.readFileSync(cert); - } catch (e) { + } catch (e: any) { crashlogger( new Error(`Failed to read the configured SSL certificate PEM file:\n${e.stack}`), `Socket process ${process.pid}` ); } - } catch (e) { + } catch (e: any) { console.warn('SSL certificate config values will not support HTTPS server option values in the future. Please set it to use the absolute path of its PEM file.'); cert = config.ssl.options.cert; } @@ -325,7 +325,7 @@ export class ServerStream extends Streams.ObjectReadWriteStream { try { // In case there are additional SSL config settings besides the key and cert... this.serverSsl = https.createServer({...config.ssl.options, key, cert}); - } catch (e) { + } catch (e: any) { crashlogger(new Error(`The SSL settings are misconfigured:\n${e.stack}`), `Socket process ${process.pid}`); } } @@ -370,7 +370,7 @@ export class ServerStream extends Streams.ObjectReadWriteStream { this.server.on('request', staticRequestHandler); if (this.serverSsl) this.serverSsl.on('request', staticRequestHandler); - } catch (e) { + } catch (e: any) { if (e.message === 'disablenodestatic') { console.log('node-static is disabled'); } else { @@ -396,7 +396,7 @@ export class ServerStream extends Streams.ObjectReadWriteStream { try { const deflate = (require as any)('permessage-deflate').configure(config.wsdeflate); options.faye_server_options = {extensions: [deflate]}; - } catch (e) { + } catch { crashlogger( new Error("Dependency permessage-deflate is not installed or is otherwise unaccessable. No message compression will take place until server restart."), "Sockets" @@ -454,7 +454,7 @@ export class ServerStream extends Streams.ObjectReadWriteStream { for (const socket of this.sockets.values()) { try { socket.destroy(); - } catch (e) {} + } catch {} } this.sockets.clear(); this.rooms.clear(); @@ -477,7 +477,7 @@ export class ServerStream extends Streams.ObjectReadWriteStream { // address from connection request headers. try { socket.destroy(); - } catch (e) {} + } catch {} return; } @@ -559,7 +559,7 @@ if (!PM.isParentProcess) { if (Config.sockets) { try { require.resolve('node-oom-heapdump'); - } catch (e) { + } catch (e: any) { if (e.code !== 'MODULE_NOT_FOUND') throw e; // should never happen throw new Error( 'node-oom-heapdump is not installed, but it is a required dependency if Config.ofesockets is set to true! ' + diff --git a/server/tournaments/index.ts b/server/tournaments/index.ts index a8c03edc92..07a871e138 100644 --- a/server/tournaments/index.ts +++ b/server/tournaments/index.ts @@ -211,7 +211,7 @@ export class Tournament extends Rooms.RoomGame { setCustomRules(rules: string) { try { this.fullFormat = Dex.formats.validate(`${this.baseFormat}@@@${rules}`); - } catch (e) { + } catch (e: any) { throw new Chat.ErrorMessage(`Custom rule error: ${e.message}`); } diff --git a/server/verifier.ts b/server/verifier.ts index 2f623ea771..e66a99a422 100644 --- a/server/verifier.ts +++ b/server/verifier.ts @@ -21,7 +21,7 @@ export const PM = new QueryProcessManager<{data: string, signature: string}, boo let success = false; try { success = verifier.verify(Config.loginserverpublickey, signature, 'hex'); - } catch (e) {} + } catch {} return success; }); diff --git a/sim/battle-stream.ts b/sim/battle-stream.ts index 209f4e5472..fb4cf0c643 100644 --- a/sim/battle-stream.ts +++ b/sim/battle-stream.ts @@ -63,7 +63,7 @@ export class BattleStream extends Streams.ObjectReadWriteStream { } else { try { this._writeLines(chunk); - } catch (err) { + } catch (err: any) { this.pushError(err, true); return; } @@ -202,7 +202,7 @@ export class BattleStream extends Streams.ObjectReadWriteStream { result = result.replace(/\n/g, '\n||'); battle.add('', '<<< ' + result); } - } catch (e) { + } catch (e: any) { battle.add('', '<<< error: ' + e.message); } break; diff --git a/sim/dex-formats.ts b/sim/dex-formats.ts index a83e80bea3..dfba93c173 100644 --- a/sim/dex-formats.ts +++ b/sim/dex-formats.ts @@ -508,7 +508,7 @@ export class DexFormats { if (!Array.isArray(customFormats)) { throw new TypeError(`Exported property 'Formats' from "./config/custom-formats.ts" must be an array`); } - } catch (e) { + } catch (e: any) { if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'ENOENT') { throw e; } @@ -595,7 +595,7 @@ export class DexFormats { try { name = this.validate(name); isTrusted = true; - } catch (e) {} + } catch {} } const [newName, customRulesString] = name.split('@@@', 2); name = newName.trim(); diff --git a/sim/dex.ts b/sim/dex.ts index 46033ef3c5..6fa39035c4 100644 --- a/sim/dex.ts +++ b/sim/dex.ts @@ -283,8 +283,8 @@ export class ModdedDex { shortDesc: '', }; for (let i = this.gen; i < dexes['base'].gen; i++) { - const curDesc = entry[`gen${i}`]?.desc; - const curShortDesc = entry[`gen${i}`]?.shortDesc; + const curDesc = entry[`gen${i}` as keyof typeof entry]?.desc; + const curShortDesc = entry[`gen${i}` as keyof typeof entry]?.shortDesc; if (!descs.desc && curDesc) { descs.desc = curDesc; } @@ -405,7 +405,7 @@ export class ModdedDex { for (const j in searchObj) { const ld = Utils.levenshtein(cmpTarget, j, maxLd); if (ld <= maxLd) { - const word = searchObj[j].name || searchObj[j].species || j; + const word = (searchObj[j] as DexTable).name || (searchObj[j] as DexTable).species || j; const results = this.dataSearch(word, searchIn, word); if (results) { searchResults = results; @@ -429,7 +429,7 @@ export class ModdedDex { throw new TypeError(`${filePath}, if it exists, must export an object whose '${dataType}' property is an Object`); } return dataObject[dataType]; - } catch (e) { + } catch (e: any) { if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'ENOENT') { throw e; } diff --git a/sim/teams.ts b/sim/teams.ts index 08e46f5eae..a612ea6546 100644 --- a/sim/teams.ts +++ b/sim/teams.ts @@ -549,7 +549,7 @@ export const Teams = new class Teams { } } return team; - } catch (e) {} + } catch {} } const lines = buffer.split("\n"); diff --git a/sim/tools/runner.ts b/sim/tools/runner.ts index e7f6e4d705..c78a14e421 100644 --- a/sim/tools/runner.ts +++ b/sim/tools/runner.ts @@ -220,7 +220,7 @@ class DualStream { const test = this.test.battle.toJSON(); try { assert.deepEqual(State.normalize(test), State.normalize(control)); - } catch (err) { + } catch (err: any) { if (this.debug) { // NOTE: diffing these directly won't work because the key ordering isn't stable. fs.writeFileSync('logs/control.json', JSON.stringify(control, null, 2)); diff --git a/test/main.js b/test/main.js index 9dc042553a..04e1fa8ba8 100644 --- a/test/main.js +++ b/test/main.js @@ -43,7 +43,7 @@ require('./../lib/process-manager').ProcessManager.disabled = true; try { const chatrooms = require('../config/chatrooms.json'); chatrooms.splice(0, chatrooms.length); -} catch (e) {} +} catch {} // Don't create a REPL require('../lib/repl').Repl.start = noop; diff --git a/test/server/ladders.js b/test/server/ladders.js index ffe2413948..9f8b9d1f04 100644 --- a/test/server/ladders.js +++ b/test/server/ladders.js @@ -129,7 +129,7 @@ describe('Matchmaker', function () { p2: {user: this.p1, team: this.s2.team}, rated: 1000, }); - } catch (e) {} + } catch {} assert.equal(room, undefined); }); diff --git a/tools/build-utils.js b/tools/build-utils.js index 5f99841976..d9640aa260 100644 --- a/tools/build-utils.js +++ b/tools/build-utils.js @@ -113,7 +113,7 @@ function sucrase(src, out, opts, excludeDirs = []) { if (!force && !needsSucrase(src, out) && src !== "./config") { return false; } - } catch (e) {} + } catch {} const sucraseOptions = { transforms: ["typescript", "imports"], enableLegacyTypeScriptModuleInterop: true, @@ -255,7 +255,7 @@ exports.transpile = (doForce, decl) => { exports.buildDecls = () => { try { child_process.execSync(`node ./node_modules/typescript/bin/tsc -p sim`, {stdio: 'inherit'}); - } catch (e) {} + } catch {} for (const file of fs.readdirSync(`./.sim-dist/lib/`)) { fs.renameSync(`./.sim-dist/lib/${file}`, `./.lib-dist/${file}`); } diff --git a/tools/modlog/converter.ts b/tools/modlog/converter.ts index e63d4b8cb9..3b07dc508c 100644 --- a/tools/modlog/converter.ts +++ b/tools/modlog/converter.ts @@ -9,7 +9,7 @@ if (!global.Config) { let hasSQLite = true; try { require.resolve('better-sqlite3'); - } catch (e) { + } catch { console.warn(`Warning: the modlog conversion script is running without a SQLite library.`); hasSQLite = false; } @@ -394,7 +394,7 @@ export function modernizeLog(line: string, nextLine?: string): string | undefine if (line.includes(oldAction)) { try { return prefix + modernizerTransformations[oldAction](line); - } catch (err) { + } catch (err: any) { if (Config.nofswriting) throw err; process.stderr.write(`${err.message}\n`); } diff --git a/tools/set-import/importer.ts b/tools/set-import/importer.ts index 03810b1368..3d5b8e8ab5 100644 --- a/tools/set-import/importer.ts +++ b/tools/set-import/importer.ts @@ -399,7 +399,7 @@ const SMOGON = { const getAnalysis = retrying(async (u: string) => { try { return smogon.Analyses.process(await request(u)); - } catch (err) { + } catch (err: any) { // Don't try HTTP errors that we've already retried if (err.message.startsWith('HTTP')) { return Promise.reject(err); @@ -426,7 +426,7 @@ async function getAnalysesByFormat(pokemon: string, gen: GenerationNum) { } return analysesByFormat; - } catch (err) { + } catch { error(`Unable to process analysis for ${pokemon} in generation ${gen}`); return undefined; }