From 5559f8df330ffb4db00dcbfc8b0b0542cb7ab5d1 Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Thu, 21 Apr 2022 18:49:24 +0100 Subject: [PATCH] Add a command to validate Discord title configuration --- src/cli/util.ts | 4 +- src/cli/util/index.ts | 1 + src/cli/util/validate-discord-titles.ts | 75 +++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/cli/util/validate-discord-titles.ts diff --git a/src/cli/util.ts b/src/cli/util.ts index 0959a6c..523bfe4 100644 --- a/src/cli/util.ts +++ b/src/cli/util.ts @@ -1,6 +1,6 @@ import createDebug from 'debug'; import type { Arguments as ParentArguments } from '../cli.js'; -import { Argv, YargsArguments } from '../util.js'; +import { Argv, dev, YargsArguments } from '../util.js'; import * as commands from './util/index.js'; const debug = createDebug('cli:util'); @@ -10,6 +10,8 @@ export const desc = 'Utilities'; export function builder(yargs: Argv) { for (const command of Object.values(commands)) { + if (command.command === 'validate-discord-titles' && !dev) continue; + // @ts-expect-error yargs.command(command); } diff --git a/src/cli/util/index.ts b/src/cli/util/index.ts index 7560de2..e2da355 100644 --- a/src/cli/util/index.ts +++ b/src/cli/util/index.ts @@ -1 +1,2 @@ export * as captureid from './captureid.js'; +export * as validateDiscordTitles from './validate-discord-titles.js'; diff --git a/src/cli/util/validate-discord-titles.ts b/src/cli/util/validate-discord-titles.ts new file mode 100644 index 0000000..acda58a --- /dev/null +++ b/src/cli/util/validate-discord-titles.ts @@ -0,0 +1,75 @@ +import createDebug from 'debug'; +import type { Arguments as ParentArguments } from '../../cli.js'; +import { ArgumentsCamelCase } from '../../util.js'; +import * as publishers from '../../discord/titles/index.js'; + +const debug = createDebug('cli:util:validate-discord-titles'); +debug.enabled = true; + +export const command = 'validate-discord-titles'; +export const desc = 'Validate Discord title configuration'; + +type Arguments = ParentArguments; + +export async function handler(argv: ArgumentsCamelCase) { + const titles = []; + let errors = 0; + + for (const [publisher, m] of Object.entries(publishers)) { + if (!('titles' in m)) continue; + + let index = 0; + let filtered = 0; + const clients = new Set(); + const clients_filtered = new Set(); + const title_ids = new Set(); + + for (const title of m.titles) { + clients.add(title.client); + const i = index++; + + if (title.id && title_ids.has(title.id)) { + debug('[%s#%d] Duplicate title ID', publisher, i, title.id); + errors++; + } + title_ids.add(title.id); + + let has_errors = false; + const warn = (msg: string, ...args: any[]) => { + has_errors = true; + errors++; + debug('[%s#%d] ' + msg, publisher, i, ...args); + }; + + if (!title.id.match(/^0100([0-9a-f]{8})[02468ace]000$/)) { + if (title.id.match(/^0100([0-9a-f]{8})[02468ace]000$/i)) + warn('Invalid title ID, must be lowercase hex', title.id); + else warn('Invalid title ID', title.id); + } + if (!title.client.match(/^\d{18}$/)) warn('Invalid Discord client ID', title.id, title.client); + + if (has_errors) continue; + + titles.push(title); + + clients_filtered.add(title.client); + filtered++; + } + + if (clients.size !== clients_filtered.size) { + debug('[%s] Loaded %d titles, using %d Discord clients (%d clients including invalid titles)', + publisher, filtered, clients_filtered.size, clients.size); + } else { + debug('[%s] Loaded %d titles, using %d Discord clients', + publisher, filtered, clients_filtered.size); + } + } + + debug('Loaded %d titles from %d publishers', titles.length, + Object.values(publishers).filter(p => 'titles' in p).length); + + if (errors) { + debug('Found %d issue' + (errors === 1 ? '' : 's'), errors); + process.exit(1); + } +}