import { BaseCommand } from '@adonisjs/core/ace' import { CommandOptions } from '@adonisjs/core/types/ace' import db from '@adonisjs/lucid/services/db' /** Prints how well files are being grouped into releases. */ export default class ReleaseStats extends BaseCommand { public static commandName = 'release:stats' public static description = 'Shows release recognition statistics.' public static options: CommandOptions = { startApp: true, } public async run() { const { rows } = await db.rawQuery(` WITH r AS ( SELECT r.id, r.file_total, r.poster IS NULL AS weak, r.source, count(b.id) AS binaries, count(b.id) FILTER (WHERE b.completed_at IS NOT NULL) AS completed FROM releases r LEFT JOIN binaries b ON b.release_id = r.id GROUP BY r.id ) SELECT count(*) AS releases, count(*) FILTER (WHERE completed > 0) AS with_files, count(*) FILTER (WHERE completed >= 2) AS multi_file, count(*) FILTER (WHERE file_total IS NOT NULL AND completed >= file_total) AS complete_by_counter, count(*) FILTER (WHERE weak) AS from_obfuscated, count(*) FILTER (WHERE weak AND completed > 0) AS from_obfuscated_with_files FROM r`) const { rows: coverage } = await db.rawQuery(` SELECT count(*) AS completed_files, count(*) FILTER (WHERE release_id IS NOT NULL) AS in_release FROM binaries WHERE completed_at IS NOT NULL`) const { rows: bySource } = await db.rawQuery(` SELECT coalesce(r.source, 'unknown') AS source, count(DISTINCT r.id) AS releases, count(b.id) FILTER (WHERE b.completed_at IS NOT NULL) AS completed_files FROM releases r JOIN binaries b ON b.release_id = r.id GROUP BY 1 ORDER BY 2 DESC`) // Readable names: descriptive as posted, or recovered from contents. const { rows: naming } = await db.rawQuery(` WITH f AS ( SELECT real_name IS NOT NULL AS recovered, is_readable_name(coalesce(real_name, filename)) AS readable_name, regexp_replace(coalesce(real_name, filename), '(\\.(part\\d+\\.rar|r\\d{2,3}|rar|vol\\d+[+-]\\d+\\.par2|par2|7z(\\.\\d{3})?|zip|\\d{3}|nfo|sfv|nzb|tar|zst|mkv|mp4|avi|flac|mp3|jpg))+$', '', 'i') AS stem, coalesce(real_name, filename) AS name FROM files ) SELECT count(*) AS files, count(*) FILTER (WHERE recovered) AS names_recovered, count(*) FILTER (WHERE name ~ '\\.[A-Za-z0-9]{1,5}$' AND readable_name) AS readable FROM f`) this.logger.info(JSON.stringify({ ...rows[0], ...coverage[0] })) this.logger.info(`naming: ${JSON.stringify(naming[0])}`) this.logger.info(`by source: ${JSON.stringify(bySource)}`) } }