Migration 1200 passed regexes with `?` through knex, which made them bindings: the live function held blu-$1ray, web-$2dl and h\.$326[45], so BluRay, WEB-DL and H.264 names without a resolution were Misc. 93% of recent releases were Misc, as the category came from the name alone. category becomes a plain column (DROP EXPRESSION, no rewrite) set by a trigger: the name's category (fixed, no `?` anywhere; adds XXX, audiobooks, console and PC games, and TV codes like S01e07[ and S04E01E02), else the prober's inner name's, else one given before (a spot's), else the groups'. The spot inspector sets a spot's category (spot_category) on Misc releases it links and on its own releases. The Newznab and web category lists gain Console, PC Games, Audiobook, Anime, XXX and Comics. releases:recategorize recomputes existing rows in id batches, writing only changed rows and waiting under a free-space floor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
2.0 KiB
TypeScript
43 lines
2.0 KiB
TypeScript
/** Newznab categories this indexer assigns (release_category_for() and spot_category() in SQL, migration …5200). */
|
|
export const CATEGORIES: { id: number; name: string; subcats: { id: number; name: string }[] }[] = [
|
|
{ id: 1000, name: 'Console', subcats: [] },
|
|
{ id: 2000, name: 'Movies', subcats: [{ id: 2030, name: 'SD' }, { id: 2040, name: 'HD' }, { id: 2045, name: 'UHD' }] },
|
|
{ id: 3000, name: 'Audio', subcats: [{ id: 3010, name: 'MP3' }, { id: 3030, name: 'Audiobook' }, { id: 3040, name: 'Lossless' }] },
|
|
{ id: 4000, name: 'PC', subcats: [{ id: 4050, name: 'Games' }] },
|
|
{ id: 5000, name: 'TV', subcats: [{ id: 5030, name: 'SD' }, { id: 5040, name: 'HD' }, { id: 5045, name: 'UHD' }, { id: 5070, name: 'Anime' }] },
|
|
{ id: 6000, name: 'XXX', subcats: [{ id: 6040, name: 'x264' }, { id: 6045, name: 'UHD' }, { id: 6060, name: 'ImgSet' }, { id: 6070, name: 'Other' }] },
|
|
{ id: 7000, name: 'Books', subcats: [{ id: 7020, name: 'Ebook' }, { id: 7030, name: 'Comics' }] },
|
|
{ id: 8000, name: 'Other', subcats: [{ id: 8010, name: 'Misc' }] },
|
|
]
|
|
|
|
/** Parent category of a (sub)category, e.g. 5040 → 5000. */
|
|
export function parentCategory(id: number): number {
|
|
return Math.floor(id / 1000) * 1000
|
|
}
|
|
|
|
/** "TV > HD" style label. */
|
|
export function categoryLabel(id: number): string {
|
|
const parent = CATEGORIES.find((c) => c.id === parentCategory(id))
|
|
if (!parent) return 'Other'
|
|
const sub = parent.subcats.find((s) => s.id === id)
|
|
return sub ? `${parent.name} > ${sub.name}` : parent.name
|
|
}
|
|
|
|
/**
|
|
* Expands requested categories (`cat=5000,2040`) to the concrete ones to
|
|
* match: a parent includes all of its subcategories.
|
|
*/
|
|
export function expandCategories(requested: number[]): number[] {
|
|
const result = new Set<number>()
|
|
for (const id of requested) {
|
|
const parent = CATEGORIES.find((c) => c.id === id)
|
|
if (parent) {
|
|
result.add(parent.id)
|
|
for (const sub of parent.subcats) result.add(sub.id)
|
|
} else {
|
|
result.add(id)
|
|
}
|
|
}
|
|
return [...result]
|
|
}
|