import { BaseSchema } from '@adonisjs/lucid/schema' /** * A release's Newznab category from its name (REBUILD.md, part 9): voyager * 1's release_category() without the archive contents (phase 2 has them). * TV (5030/5040/5045), movies (2030/2040/2045), audio (3010/3040), * books (7020), otherwise 8010. */ export default class extends BaseSchema { async up() { this.schema.raw(String.raw` CREATE OR REPLACE FUNCTION release_category(name text) RETURNS integer IMMUTABLE LANGUAGE sql AS $$ SELECT CASE -- TV: S01E02, 1x02, or a season pack (S01). WHEN name ~* '(^|[._ -])(S\d{1,2}E\d{1,3}|\d{1,2}x\d{2})([._ -]|$)' OR name ~* '[._ -]S\d{1,2}([._ -]|$)' THEN CASE WHEN name ~* '2160p|(^|[._ -])(uhd|4k)([._ -]|$)' THEN 5045 WHEN name ~* '720p|1080p' THEN 5040 ELSE 5030 END -- Movies: a year plus a source or quality marker. WHEN name ~* '(^|[._ (-])(19|20)\d{2}([._ )-]|$)' AND name ~* '(480p|576p|720p|1080p|2160p|blu-?ray|web-?dl|webrip|bdrip|brrip|dvdrip|hdtv|x26[45]|h\.?26[45]|hevc|remux)' THEN CASE WHEN name ~* '2160p|(^|[._ -])(uhd|4k)([._ -]|$)' THEN 2045 WHEN name ~* '720p|1080p|blu-?ray' THEN 2040 ELSE 2030 END -- Audio: lossless, mp3, or scene music names (-WEB-2026-GROUP). WHEN name ~* '(^|[._ -])flac([._ -]|$)' THEN 3040 WHEN name ~* '(^|[._ -])mp3([._ -]|$)' OR name ~* '-(WEB|CD|CDM|CDS|EP|VINYL|VLS|SAT|FM|DAB)-(19|20)\d{2}-[A-Za-z0-9]+$' THEN 3010 WHEN name ~* '(^|[._ -])(epub|ebook|mobi)([._ -]|$)' THEN 7020 ELSE 8010 END $$`) this.schema.raw(`ALTER TABLE releases ADD COLUMN IF NOT EXISTS category integer GENERATED ALWAYS AS (release_category(name)) STORED`) // Newznab and the web interface list a category newest first. this.schema.raw(`CREATE INDEX IF NOT EXISTS releases_category_posted_idx ON releases (category, posted_at DESC)`) } async down() { this.schema.raw(`ALTER TABLE releases DROP COLUMN IF EXISTS category`) this.schema.raw(`DROP FUNCTION IF EXISTS release_category(text)`) } }