From 093d0a71ad4e9f61d2f17cbd9c3dc69d133ad005 Mon Sep 17 00:00:00 2001 From: Daan Meijer Date: Fri, 16 Oct 2026 11:01:07 +0200 Subject: [PATCH] The judge hides scraped celebrity pictures; no ? in its patterns (a raw query takes it for a binding) Co-Authored-By: Claude Opus 5.5 --- app/services/release_judge.ts | 19 +++++++++++++++++-- tests/functional/release_judge.spec.ts | 10 ++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/app/services/release_judge.ts b/app/services/release_judge.ts index 2d54c83..b7a8340 100644 --- a/app/services/release_judge.ts +++ b/app/services/release_judge.ts @@ -8,9 +8,15 @@ const ROUND_MS = 60 * 60 * 1000 /** A file's first 16 KiB and size in this many releases is one file posted again and again (test files, spam). */ const REPEATED_RELEASES = 20 -/** A name that says it's a film, an episode or music: a resolution, a codec, a rip source, a media extension. */ +/** + * A name that says it's a film, an episode or music: a resolution, a codec, a rip source, a media extension. No "?" in + * these patterns: a raw query takes it for a binding ("h[ .]?26[45]" and "web[ .-]?dl" never matched; LOG.md + * 2026-10-16 (64)), so {0,1}. + */ const MEDIA = - `(^|[^a-z0-9])(s[0-9]{1,2}e[0-9]{1,3}|[0-9]{3,4}p|x26[45]|h[ .]?26[45]|hevc|xvid|divx|bluray|bdrip|brrip|web[ .-]?dl|webrip|hdtv|dvdrip|dvdr|remux|mkv|mp4|avi|wmv|m4v|flac|mp3)([^a-z0-9]|$)` + `(^|[^a-z0-9])(s[0-9]{1,2}e[0-9]{1,3}|[0-9]{3,4}p|x26[45]|h[ .]{0,1}26[45]|hevc|xvid|divx|bluray|bdrip|brrip|web[ .-]{0,1}dl|webrip|hdtv|dvdrip|dvdr|remux|mkv|mp4|avi|wmv|m4v|flac|mp3)([^a-z0-9]|$)` +/** The posters of scraped celebrity pictures. */ +const SCRAPED_POSTERS = `celeb[-_ ]{0,1}movie|celebwow|celebfx|iluvcelebs|nude[-_ ]{0,1}celebs|celeb-sex-tapes` /** An executable's name. */ const EXECUTABLE = `\\.(exe|scr|com|bat|cmd|msi|lnk|vbs|js|jar|pif|cpl|hta|ps1|dll)$` @@ -52,6 +58,15 @@ export const RULES: Rule[] = [ sql: `SELECT DISTINCT h.release_id FROM file_hashes h JOIN (SELECT hash16k, size FROM file_hashes GROUP BY 1, 2 HAVING count(DISTINCT release_id) >= ${REPEATED_RELEASES}) x USING (hash16k, size)`, }, + { + name: 'scraped', + says: 'celebrity pictures scraped from the web, reposted by one spam family', + // "@_CelebMovie_@", "NudeCelebs@CelebMovie.com", "@_CelebWow_@", "@_CelebFX_@", "@_iLuvCelebs_@", "@nude-celebs", …: + // a celebrity's scraped pictures as a folder under a typed subject, the same files again and again under other + // titles (LOG.md 2026-10-16 (64)). Not Celeborn, CelebTA or other posters with "celeb" in their name. + sql: `SELECT r.id FROM releases r + WHERE r.poster ~* '${SCRAPED_POSTERS}' AND r.source = 'subject' AND r.file_total IS NULL`, + }, { name: 'locked', says: 'passworded, and no spot, NZB or title gives the password', diff --git a/tests/functional/release_judge.spec.ts b/tests/functional/release_judge.spec.ts index 66dac23..7eb2ab4 100644 --- a/tests/functional/release_judge.spec.ts +++ b/tests/functional/release_judge.spec.ts @@ -40,6 +40,9 @@ test.group('ReleaseJudge', (group) => { const fakeArchive = await release('Das.A-Team.S02E23.Das.Spiel.ist.aus') await inspect(fakeArchive, 'archive', { type: 'rar4', names: ['Das.A-Team.S02E23.Das.Spiel.ist.aus.exe'], entries: 1 }) const fakeFile = await release('Some.Film.2021.1080p.WEB-DL') + // Only "H.264" and "WEB-DL" say it's media here (a "?" in the pattern never matched). + const fakeCodec = await release('Some.Show.H.264.WEB-DL') + await inspect(fakeCodec, 'lone', { type: 'exe', yencName: 'setup.exe' }) await inspect(fakeFile, 'lone', { type: 'exe', yencName: 'Some.Film.2021.1080p.WEB-DL.mkv' }) // A program under a program's name is software, not fake. const software = await release('LimeWire 4.19.6') @@ -53,7 +56,10 @@ test.group('ReleaseJudge', (group) => { await db.table('file_hashes').insert({ candidate_id: 20000 + i, release_id: id, hash16k: hash, size: 1073741824 }) } + const scraped = await release('Jamie Lee Curtis Nude Celebrity Pictures', { poster: '@_CelebMovie_@', source: 'subject' }) + const celeborn = await release('Some.Album.2010', { poster: 'celeborn@not.here (Celeborn)', source: 'subject' }) const locked = await release('Locked.Thing', { passworded: true }) + const unlocked = await release('Known.Password', { passworded: true }) await db.table('release_passwords').insert({ release_id: unlocked, password: 'pw', source: 'spot-text' }) @@ -68,14 +74,18 @@ test.group('ReleaseJudge', (group) => { assert.isUndefined(verdicts.get(halfDead)) assert.equal(verdicts.get(fakeArchive), 'fake') assert.equal(verdicts.get(fakeFile), 'fake') + assert.equal(verdicts.get(fakeCodec), 'fake') assert.isUndefined(verdicts.get(software)) assert.deepEqual([...new Set(repeatedIds.map((id) => verdicts.get(id)))], ['repeated']) + assert.equal(verdicts.get(scraped), 'scraped') + assert.isUndefined(verdicts.get(celeborn)) assert.equal(verdicts.get(locked), 'locked') assert.isUndefined(verdicts.get(unlocked)) assert.equal(verdicts.get(unusable), 'unusable') assert.isUndefined(verdicts.get(fresh)) assert.isUndefined(verdicts.get(spotted)) assert.equal(round.rules.repeated.added, 20) + assert.equal(round.rules.scraped.matched, 1) // Search leaves them out, unless asked. const found = await SearchService.search({ q: 'Locked' })