Files
usenet-indexer/tests/unit/release/identity.spec.ts
T
Daan MeijerandClaude Opus 5.5 eddbe2863f
Test and deploy / test (push) Successful in 55s
Test and deploy / edge (push) Successful in 2m7s
Test and deploy / deploy (push) Successful in 2m34s
Take the padded volume back out: it merged a dump's versions
208ca1d's volume of 3-5 digits after a digit (YME's "CHT PCK 2 9.26.001")
also took versions for volumes: "K-ML 3.8.233", "3.8.239", "3.8.241" and
Kaizen's "v2.0.1021" ... "v2.0.1057" became one release (505 names on the
corpus). The random name's volumes with their own extensions stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 14:11:03 +02:00

587 lines
42 KiB
TypeScript

import { test } from '@japa/runner'
import { fileStem, releaseIdentity, runOn, sizeAfterName, subjectRemainder } from '#lib/release/index'
import { looksLikeFilename, weakFileKey } from '#lib/headers/index'
test.group('release / fileStem', () => {
test('reduces all files of a set to the same stem', ({ assert }) => {
const names = [
'1790546808_nicovideo_jp_watch_sm26679715.tar.zst',
'1790546808_nicovideo_jp_watch_sm26679715.tar.zst.par2',
'1790546808_nicovideo_jp_watch_sm26679715.tar.zst.vol03+04.par2',
]
assert.deepEqual(new Set(names.map(fileStem)), new Set(['1790546808_nicovideo_jp_watch_sm26679715']))
})
test('handles rar, split and par2 volume naming', ({ assert }) => {
assert.equal(fileStem('lJzuoIKA3T8xjzAD3vqtw0.part036.rar'), 'lJzuoIKA3T8xjzAD3vqtw0')
assert.equal(fileStem('Some.Movie.2024.r07'), 'Some.Movie.2024')
assert.equal(fileStem('Some.Movie.2024.mkv.001'), 'Some.Movie.2024')
assert.equal(fileStem('Some.Movie.2024.2160p.WEB-DL.H.265.mkv'), 'Some.Movie.2024.2160p.WEB-DL.H.265')
assert.equal(fileStem('Some.Movie.2024.H.264.nzb'), 'Some.Movie.2024.H.264')
assert.equal(fileStem('Some.Movie.2024.vol127-128.par2'), 'Some.Movie.2024')
assert.equal(fileStem('Some.Movie.2024.nfo'), 'Some.Movie.2024')
assert.equal(fileStem('00-artist-album-web-2026.m3u'), '00-artist-album-web-2026')
assert.equal(fileStem('f6dd6b156692a52b.bin'), 'f6dd6b156692a52b')
})
test('never reduces a name to nothing', ({ assert }) => {
assert.equal(fileStem('.par2'), '.par2')
})
})
test.group('release / subjectRemainder', () => {
test('is empty when the subject only has counters, filename and size', ({ assert }) => {
assert.equal(subjectRemainder('[1/4] - "x.tar.zst" yEnc 15411409'), '')
assert.equal(subjectRemainder('. - [00/88] - "60SHkTQSvn5RZGExwju2.nzb" yEnc'), '')
})
test('keeps a release name written outside the quotes', ({ assert }) => {
assert.equal(
subjectRemainder('Some.Show.S01E02.1080p [03/40] - "abc.part02.rar" yEnc'),
'Some Show S01E02 1080p'
)
})
})
test.group('release / releaseIdentity', () => {
test('groups a par2 set with its archive by stem, per poster', ({ assert }) => {
const base = { poster: 'p', weak: false }
const a = releaseIdentity({ ...base, subject: '[1/4] - "x.tar.zst" yEnc 1', name: 'x.tar.zst' })!
const b = releaseIdentity({ ...base, subject: '[3/4] - "x.tar.zst.vol01+02.par2" yEnc 2', name: 'x.tar.zst.vol01+02.par2' })!
assert.equal(a.key, b.key)
assert.equal(a.name, 'x')
assert.equal(a.fileTotal, 4)
const other = releaseIdentity({ ...base, poster: 'q', subject: '[1/4] - "x.tar.zst" yEnc 1', name: 'x.tar.zst' })!
assert.notEqual(a.key, other.key)
})
test('a par2 index posted without [i/M] counter joins its release', ({ assert }) => {
const base = { poster: 'nicovideo_archiver', weak: false }
const archive = releaseIdentity({ ...base, subject: '[1/6] - "x.tar.zst" yEnc 105054576', name: 'x.tar.zst' })!
const index = releaseIdentity({ ...base, subject: '"x.tar.zst.par2" yEnc 3100', name: 'x.tar.zst.par2' })!
assert.equal(index.key, archive.key)
assert.equal(archive.fileTotal, 6)
assert.isUndefined(index.fileTotal)
})
test('uses the subject text when it names the release', ({ assert }) => {
const base = { poster: 'p', weak: false }
const a = releaseIdentity({ ...base, subject: 'My.Release [01/40] - "abc.part01.rar" yEnc', name: 'abc.part01.rar' })!
const b = releaseIdentity({ ...base, subject: 'My.Release [40/40] - "abc.par2" yEnc', name: 'abc.par2' })!
assert.equal(a.key, b.key)
assert.equal(a.name, 'My Release')
})
test('obfuscated volumes group by stem regardless of the random poster', ({ assert }) => {
const a = releaseIdentity({ poster: '3Uzx7TTSFpLzz@ngPost.com', subject: '"lJzu.part033.rar" yEnc', name: 'lJzu.part033.rar', weak: true })!
const b = releaseIdentity({ poster: 'bGLd1oaXRdrK1@ngPost.com', subject: '"lJzu.part034.rar" yEnc', name: 'lJzu.part034.rar', weak: true })!
assert.equal(a.key, b.key)
})
test('capitals and digits switching all over a token are random', async ({ assert }) => {
const { looksRandom } = await import('#lib/release/index')
assert.isTrue(looksRandom('51294P1CUKR2R35X'))
assert.isTrue(looksRandom('51294P1CUKR2R35X.part01.rar'.replace(/\.part01\.rar$/, '')))
assert.isFalse(looksRandom('COD4MW2REMASTERED'))
assert.isFalse(looksRandom('BEATLES1964REMASTER'))
assert.isFalse(looksRandom('HDTV1080P'))
})
test('random extensionless names cannot be grouped by name', ({ assert }) => {
const name = '204b914a977e5f891590ff1099c7a8caf1a0be537bfa5bf7f3a8b1213231'
assert.isNull(releaseIdentity({ poster: 'x', subject: `"${name}" yEnc`, name, weak: true }))
})
})
test.group('subject / weakFileKey', () => {
test('ignores random per-article names, keeps real filenames', ({ assert }) => {
assert.isFalse(looksLikeFilename('204b914a977e5f891590ff1099c7a8caf1a0be537bfa5bf7f3a8b1213231'))
assert.isTrue(looksLikeFilename('lJzuoIKA3T8xjzAD3vqtw0.part033.rar'))
// Same file, different random names per article: same key.
assert.equal(weakFileKey('aaaa1111', 5000, 7), weakFileKey('bbbb2222', 5000, 7))
// Equal-sized volumes with real names: different keys.
assert.notEqual(weakFileKey('x.part01.rar', 5000, 7), weakFileKey('x.part02.rar', 5000, 7))
assert.notEqual(weakFileKey('aaaa1111', 5000, 7), weakFileKey('aaaa1111', 5001, 7))
})
})
test.group('release / rarReleaseIdentity', () => {
test('groups volumes by the shared top-level directory', async ({ assert }) => {
const { rarReleaseIdentity } = await import('#lib/release/index')
const first = rarReleaseIdentity([
{ name: 'LASZR_-_DYING_ALIVE-(PRO094)-WEB-2026-DIM/00-cover.jpg', size: 589382 },
{ name: 'LASZR_-_DYING_ALIVE-(PRO094)-WEB-2026-DIM/01-track.flac', size: 30_000_000 },
])!
const later = rarReleaseIdentity([{ name: 'LASZR_-_DYING_ALIVE-(PRO094)-WEB-2026-DIM/03-track.flac', size: 29_000_000 }])!
assert.equal(first.key, later.key)
assert.equal(first.name, 'LASZR_-_DYING_ALIVE-(PRO094)-WEB-2026-DIM')
assert.equal(first.source, 'rar')
})
test('without a directory, volumes of one file share its first entry', async ({ assert }) => {
const { rarReleaseIdentity } = await import('#lib/release/index')
const a = rarReleaseIdentity([{ name: 'Some.Show.S01E01.1080p.mkv', size: 3_000_000_000 }])!
const b = rarReleaseIdentity([{ name: 'Some.Show.S01E01.1080p.mkv', size: 3_000_000_000 }])!
assert.equal(a.key, b.key)
assert.equal(a.name, 'Some.Show.S01E01.1080p')
assert.isNull(rarReleaseIdentity([]))
})
})
test.group('release / namesRelease', () => {
test('random per-file tags and poster ids are not a release name', async ({ assert }) => {
const { namesRelease, subjectRemainder, releaseIdentity } = await import('#lib/release/index')
const subject = 'elys-de81bcabef5faf6a - [Nyh5Q07Y] "JkpNIFg7En50zU1U" yEnc'
assert.isFalse(namesRelease(subjectRemainder(subject)))
const a = releaseIdentity({ poster: 'elys', subject, name: 'JkpNIFg7En50zU1U', weak: false })!
assert.equal(a.source, 'stem')
assert.isTrue(namesRelease(subjectRemainder('Some.Show.S01E02.1080p [03/40] - "abc.part02.rar" yEnc')))
assert.isTrue(namesRelease('My Release'))
})
})
test.group('release / post id', () => {
test('groups random-named files of one post by poster, post id and file count', async ({ assert }) => {
const { releaseIdentity, isPostToken } = await import('#lib/release/index')
const base = { poster: 'jW344UtC8R2bZEegrVLz@x', weak: false }
const a = releaseIdentity({ ...base, subject: '83110629-n [10/18] - "eiae6fulpolas2adfts6o8643n3e6j6ct8d3219aau0jc33ol9r50tohncgr46evpl0dqoqktfb7k" yEnc', name: 'eiae6fulpolas2adfts6o8643n3e6j6ct8d3219aau0jc33ol9r50tohncgr46evpl0dqoqktfb7k' })!
const b = releaseIdentity({ ...base, subject: '83110629-n [01/18] - "2ef0vm4kb618nv17kn0qsb0j1ofh7pgqtk5a3v5lkqqf1f7g6ed0" yEnc', name: '2ef0vm4kb618nv17kn0qsb0j1ofh7pgqtk5a3v5lkqqf1f7g6ed0' })!
assert.equal(a.key, b.key)
assert.equal(a.source, 'post')
assert.equal(a.fileTotal, 18)
const other = releaseIdentity({ ...base, subject: '83110630-n [01/18] - "x" yEnc', name: 'x' })!
assert.notEqual(a.key, other.key)
assert.isTrue(isPostToken('83110629 n'))
assert.isFalse(isPostToken('PRiVATE'))
assert.isFalse(isPostToken(''))
// Without a counter there is nothing to bound the post: fall back to the stem.
assert.equal(releaseIdentity({ ...base, subject: '83110629-n - "x.bin" yEnc', name: 'x.bin' })!.source, 'stem')
})
})
test.group('release / par2 names', () => {
test('names a season pack after what its episodes share', async ({ assert }) => {
const { par2ReleaseName } = await import('#lib/release/index')
const eps = Array.from({ length: 20 }, (_, i) =>
`SEAL.Team.S03E${String(i + 1).padStart(2, '0')}.1080p.AMZN.WEB-DL.AAC2.0.H.265.DUAL-nitrato.mkv`)
assert.equal(par2ReleaseName(eps), 'SEAL.Team.S03.1080p.AMZN.WEB-DL.AAC2.0.H.265.DUAL-nitrato')
// Movie plus sample and nfo: the movie's (longest) name.
assert.equal(
par2ReleaseName(['Some.Movie.2024.1080p.BluRay.x264-GRP.mkv', 'Some.Movie.2024.1080p.BluRay.x264-GRP.nfo', 'sample.mkv']),
'Some.Movie.2024.1080p.BluRay.x264-GRP'
)
// Numbered parts: the shared name without the part number.
assert.equal(par2ReleaseName(['Album.Name-2024-GRP.part01.rar', 'Album.Name-2024-GRP.part02.rar']), 'Album.Name-2024-GRP')
assert.equal(par2ReleaseName(['only.one.file.2024.mkv']), 'only.one.file.2024')
})
test('a random poster per file is no part of the key; a real poster is', async ({ assert }) => {
const { randomPoster } = await import('#lib/release/identity')
const ftd = '-Alight_Upon_the_Lake_(Live_at_the_Jazz_Showcase_Jun_1975)-WEB-2026-FTD'
const a = releaseIdentity({ poster: 'N9vplIaavBCz@aCTVoAsk.JSE', subject: `[1/6] - "Yusef_Lateef${ftd}.par2" yEnc 1744`, name: `Yusef_Lateef${ftd}.par2`, weak: false })!
const b = releaseIdentity({ poster: 'FVWWHku0fGAg@QfaTz0g0.RVH', subject: `[3/6] - "Yusef_Lateef${ftd}.part2.rar" yEnc 104857600`, name: `Yusef_Lateef${ftd}.part2.rar`, weak: false })!
assert.equal(a.key, b.key)
assert.isTrue(randomPoster('N9vplIaavBCz@aCTVoAsk.JSE'))
assert.isFalse(randomPoster('Captain Salvo <Capt@Salvo.com>'))
assert.isFalse(randomPoster('Poster49118 <Poster49118@generic.mail>'))
assert.isFalse(randomPoster('w.merklein@freenet.de (muffin)'))
})
test('album tracks with unquoted names are one release per disc', async ({ assert }) => {
const { parseSubject } = await import('#lib/headers/index')
const id = (subject: string) => releaseIdentity({ poster: 'Hannah_Qe@hotmail.com (Spidey)', subject: subject.replace(/ \(\d+\/\d+\)$/, ''), name: parseSubject(subject)!.name, weak: false })!
const album = 'A Strange Light from the East - Eastern Influenced Western Music (1965-72) - CD2'
assert.equal(id(`${album} - 07 - Rascals - Sattva.mp3 (1/43)`).key, id(`${album} - 08 - Incredible String Band - Koeeoaddi There.mp3 (1/47)`).key)
})
test('more splits from the re-index: spaces in unquoted names, audio tracks, sizes before yEnc, posters with separators', async ({ assert }) => {
const { parseSubject } = await import('#lib/headers/index')
const { randomPoster } = await import('#lib/release/identity')
// As the edge worker: the subject without its counter and with collapsed spaces, the name as parsed.
const id = (poster: string, subject: string) => {
const name = parseSubject(subject)!.name
const base = subject.replace(/\(\d+\/\d+\)\s*$/, '').replace(/\s+/g, ' ').trim()
return releaseIdentity({ poster, subject: base, name, weak: false })!
}
const makz = 'Makz@BlueRadiance.uni (makz)'
assert.equal(id(makz, 'G:\\posting\\thegoodnudes\\lara_bath 15of19 larabath_2.5.jpg (1/1)').key, id(makz, 'G:\\posting\\thegoodnudes\\lara_bath 16of19 larabath_2.6.jpg (1/1)').key)
const mara = 'Mara <guest@cox.net>'
assert.equal(id(mara, 'RP - File 268 of 295 - yEnc "Elizabeth Peters - (Peabody 09) Seeing A Large Cat - D11.16-22.mp3" (1/3)').key, id(mara, 'RP - File 269 of 295 - yEnc "Elizabeth Peters - (Peabody 09) Seeing A Large Cat - D11.17-22.mp3" (1/3)').key)
const mb = 'misterb@sure.com (MisterB)'
assert.equal(id(mb, 'Herb Ernst@256 - NMR -[07/17] "Herb Ernst - Dreamflight II - 05 - The Light of Forever.mp3" - 8123 yEnc (1/9)').key, id(mb, 'Herb Ernst@256 - NMR -[08/17] "Herb Ernst - Dreamflight II - 06 - Other.mp3" - 9001 yEnc (1/9)').key)
assert.isTrue(randomPoster('SOFZRw1-OTEd@EEFUbh.srG'))
assert.isTrue(randomPoster('vMgGYlZB9ZcTNk8WxYFGV_OOW@x6YR.abc'))
assert.isFalse(randomPoster('w.merklein@freenet.de (muffin)'))
})
test('image sets by their numbered name, digits kept; names without numbers name no set', ({ assert }) => {
const silver = (n: string) => releaseIdentity({ poster: 'p', subject: `The excellent STIRILING SILVER - Always popular - "${n}" yEnc 320794 bytes`, name: n, weak: false })!
assert.equal(silver('stp250x001.jpg').key, silver('stp250x002.jpg').key)
assert.notEqual(silver('stp250x001.jpg').key, silver('stp305x001.jpg').key)
const mint = (n: string) => releaseIdentity({ poster: 'Cert', subject: `I'm not a breath mint, but I am not all there either. [${n}" yEnc]`, name: n, weak: false })!
assert.equal(mint('JimAndJoey Kindly Husband-to-Be.JPG').key, mint('Oops OnlyOneMore.JPG').key)
})
test("an image's set: suffixes that don't count the images go first", async ({ assert }) => {
const { imageSet } = await import('#lib/release/identity')
for (const [stem, set] of [
['stp250x001', 'stp250x'],
['cutie-071-032', 'cutie-071-'],
['katelg010_10', 'katelg'],
['kate112lg035_35', 'kate112lg'],
['!!hgrscans1097_2009', '!!hgrscans'],
['pj02kristina_24of40_1600', 'pj02kristina_'],
['keira_s04_l keira_s04_0040_l', 'keira_s04_l keira_s04_'],
['IMG_2676', 'IMG_'],
['2877-041', '2877-'],
['051 - White leather kate054001_1_1', '051 - White leather kate'],
['108 - Schoolwall kate108lg029_28', '108 - Schoolwall kate108lg'],
['kurozo-2006-7-26-15-21', ''],
['bwp2_037_5', 'bwp2_'],
['Set 008 10of63 new0464', 'Set 008 '],
['202/430 princess-079-058', ''],
['( 098 /500) 002 148', ''],
['New Folder (17) sexypattycake_0903040445[1]', 'New Folder ('],
['092_081_2000x1500', '092_'],
['KP0027_197_00', 'KP'],
['01079-106-2048px', '01079-'],
['diana-050-052[1][1]', 'diana-050-'],
['sss-70556-3474182-23-10825418-pc', ''],
['Alena p 26663_alena-p-2-8323_123_39lo', ''],
['she has sensual legs 172 _ 172', 'she has sensual legs '],
['jamie.lee.curtis_the.tailor.of.panama_17_123_244lo', 'jamie.lee.curtis_the.tailor.of.panama_'],
['JimAndJoey Kindly Husband-to-Be', ''],
]) assert.equal(imageSet(stem), set, stem)
})
test("a set's number before the closing yEnc is no size", ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
const destiny = (set: number, i: number) => {
const name = `destiny-${String(set).padStart(3, '0')}-${String(i).padStart(3, '0')}.jpg`
return id(`Newstar Destiny I set ${set} [${i} of 60] "${name}" yEnc`, name)
}
assert.equal(destiny(1, 1).key, destiny(1, 2).key)
assert.notEqual(destiny(1, 1).key, destiny(63, 34).key)
assert.equal(destiny(63, 34).name, 'Newstar Destiny I set 63')
})
test('other quoted text and text separators name the release', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
const cc = (name: string, n: string) =>
id(`>>> CREATIVE COMMONS NZB <<< "${name} " - File 1 of 9: "creative_commons_nzb_${n}.rar" yEnc`, `creative_commons_nzb_${n}.rar`)
assert.notEqual(cc('0190 alarm 5.0', '0190_alarm_5.0_').key, cc('portable irfanview 4.22', 'portable_irfanview_4.22').key)
const vlad = (dir: string, total: number, n: string) =>
id(`Posting & deleting, read 0 file "E:\\VladModels\\y038_Irina\\${dir}" Day 5/6 [01/${total}] - ${n} yEnc`, n)
assert.equal(vlad('185', 77, 'P8250001.JPG').source, 'subject')
assert.notEqual(vlad('185', 77, 'P8250001.JPG').key, vlad('234', 77, 'P5300085.JPG').key)
})
test('per-file hex ids go; dated stems are specific; season packs under a bare counter', ({ assert }) => {
const id = (poster: string, subject: string, name: string) => releaseIdentity({ poster, subject, name, weak: false })!
const nz = (hex: string, i: number, n: string) =>
id('nEwZ', `[PRiVATE] Rosewood.S02E08.SPANiSH.1080p.HDTV.x264-FCC [${hex}] [newzNZB] [${String(i).padStart(2, '0')}/22] - "${n}" yEnc`, n)
assert.equal(nz('1f1793f68d5321', 1, '[05cbdb538a]_x.nfo').key, nz('65e6464bc03cad', 2, '[e8a4e2c182]_x.r03').key)
const show = (n: string) => id('#sterntuary <aa@aa.com>', `#sterntuary - Coast To Coast Radio Show - "${n}" yEnc`, n)
assert.equal(show('09-30-2008_CTC.nfo').key, show('09-30-2008_CTC.r00').key)
assert.notEqual(show('09-30-2008_CTC.r00').key, show('10-01-2008_CTC.r00').key)
const ep = (i: number, n: string) => id('p', `[${String(i).padStart(2, '0')}/36] "${n}"`, n)
assert.equal(ep(1, 'Pokemon - S02E01 - Pallet Party Panic.mkv').key, ep(2, 'Pokemon - S02E02 - Gotta Catch Ya Later.mkv').key)
assert.equal(ep(1, 'Pokemon - S02E01 - Pallet Party Panic.mkv').name, 'Pokemon S02')
assert.notEqual(ep(1, 'Pokemon - S02E01 - Pallet Party Panic.mkv').key, ep(1, 'Pokemon - S03E01 - x.mkv').key)
})
test('spaces at a dash are no part of a stem key', ({ assert }) => {
const id = (i: string, n: string) => releaseIdentity({ poster: 'JBinUp', subject: `[${i}/58] - Summer Power Up - "${n}" yEnc`, name: n, weak: false })!
assert.equal(id('01', 'www.realmom.info - XVID- Farbiges Krabbeltier.r00').key, id('54', 'www.realmom.info - XVID-Farbiges Krabbeltier.vol03+04.par2').key)
})
test("a scene index's files go with the release: no case, no 00-", ({ assert }) => {
const id = (n: string) => releaseIdentity({ poster: 'SavageCobra <x@y.nhc>', subject: n, name: n, weak: false })!
const a = id('00-laura_van_dam_-_capture_radio_113-cable-10-10-2026-talion.m3u')
const b = id('Laura_van_Dam_-_Capture_Radio_113-CABLE-10-10-2026-TALiON.vol000+001.par2')
assert.equal(a.key, b.key)
assert.equal(b.name, 'Laura_van_Dam_-_Capture_Radio_113-CABLE-10-10-2026-TALiON')
})
test('old rar volumes, recovery volumes, a part\'s par2, BCArchive volumes; a size after an unquoted name', ({ assert }) => {
assert.equal(fileStem('BD_NoTHing018.s41'), 'BD_NoTHing018')
assert.equal(fileStem('x8ZRmX5N83mrokOwqJtoIGHTrqXQrgCyj.s00'), 'x8ZRmX5N83mrokOwqJtoIGHTrqXQrgCyj')
// A season stays.
assert.equal(fileStem('the.office.us.s01.rar'), 'the.office.us.s01')
assert.equal(fileStem('Some.Show.S01'), 'Some.Show.S01')
assert.equal(fileStem('Electric.Rain.Swift.3D.PS.v1.0.142.x64'), 'Electric.Rain.Swift.3D.PS.v1.0.142.x64')
assert.equal(fileStem('App.x86'), 'App.x86')
assert.equal(fileStem('Licence 700790900887990.z18'), 'Licence 700790900887990')
assert.equal(fileStem('Licence 077887994400668.x12'), 'Licence 077887994400668')
assert.equal(fileStem('Reply 987986177631730.x004'), 'Reply 987986177631730')
assert.equal(fileStem('goh1Phoz5ahXu.par.vol006+08.par2'), 'goh1Phoz5ahXu')
assert.equal(fileStem('brSWc0Q2KWblQpogOmgbn9.part.par2'), 'brSWc0Q2KWblQpogOmgbn9')
assert.equal(fileStem('x.parts.par2'), 'x.parts')
assert.equal(fileStem('Some.Movie.2010.x264'), 'Some.Movie.2010.x264')
assert.equal(runOn('lois 1258 Billy Joel - Extremes.part01.rar lois 1258 Billy Joel - Extremes '), 'lois 1258 Billy Joel - Extremes.part01.rar')
assert.equal(runOn('GrooveCoverage.part26.rarGrooveCoveragebestof'), 'GrooveCoverage.part26.rar')
assert.equal(runOn('Goga Sekulic.part134.rar - Goga Sekulic - Diskografija (2000-2014).'), 'Goga Sekulic.part134.rar')
assert.equal(runOn('HASf293jLAIWUELvhaG3.part091.rar HASf293jLAIWUELvhaG3'), 'HASf293jLAIWUELvhaG3.part091.rar')
assert.equal(runOn('Movie.rar.Collection.mkv'), 'Movie.rar.Collection.mkv')
assert.equal(runOn('Angry.Birds.Rio.v1.2.2.cracked.READ.NFO-THETA.rar'), 'Angry.Birds.Rio.v1.2.2.cracked.READ.NFO-THETA.rar')
assert.equal(runOn('x.part01.rar'), 'x.part01.rar')
const lois = (i: string, n: string) => releaseIdentity({ poster: 'p', subject: `(thnx to original poster) [${i}/92] - "${n}" yEnc`, name: n, weak: false })!
assert.equal(lois('02', 'lois 1258 Billy Joel - Extremes.part01.rar lois 1258 Billy Joel - Extremes ').key, lois('01', 'lois 1258 Billy Joel - Extremes.par2 lois 1258 Billy Joel - Extremes ').key)
assert.equal(fileStem('chappelle1.part02.rev'), 'chappelle1')
assert.equal(fileStem('chappelle1.rev'), 'chappelle1')
assert.equal(fileStem('VwE3i90MVX9dqMFuDfzdS7Q6.part1.par2'), 'VwE3i90MVX9dqMFuDfzdS7Q6')
assert.equal(fileStem('VwE3i90MVX9dqMFuDfzdS7Q6.part1.vol00+34.par2'), 'VwE3i90MVX9dqMFuDfzdS7Q6')
assert.equal(fileStem('Movie.Part1.mkv'), 'Movie.Part1')
assert.equal(fileStem('NZPECQUztWOponTpCratvvTPDBXBjvHIULOUPvSH.180.bc'), 'NZPECQUztWOponTpCratvvTPDBXBjvHIULOUPvSH')
assert.equal(sizeAfterName('(Hot MILF getting banged hard)[27/70] - 2407.jpg - 28', '2407.jpg'), '(Hot MILF getting banged hard)[27/70] - 2407.jpg')
assert.equal(sizeAfterName('Show [01/10] - "a.jpg" - 28', 'a.jpg'), 'Show [01/10] - "a.jpg" - 28')
assert.equal(sizeAfterName('Show - Episode 05', 'x.mkv'), 'Show - Episode 05')
const milf = (i: string, n: string, kb: string) => releaseIdentity({ poster: 'p', subject: `(Hot MILF getting banged hard)[${i}/70] - ${n} - ${kb}`, name: n, weak: false })!
assert.equal(milf('27', '2407.jpg', '28').key, milf('28', '2408.jpg', '31').key)
})
test("split rar volumes; a file's size in brackets after its counter", ({ assert }) => {
assert.equal(fileStem('rld-gtre.r13.002'), 'rld-gtre')
const k = (i: number, size: number, n: string) =>
releaseIdentity({ poster: 'Kingdn', subject: `Buffy The Vampire Slayer s02e04 [${i}/32] - [${size}] "${n}" yEnc`, name: n, weak: false })!
assert.equal(k(26, 4929, 'Buffy s02e04 xvid-tns.part24.rar').key, k(27, 400, 'Buffy s02e04 xvid-tns.vol00+01.PAR2').key)
})
test('a total padded wider than its index is no counter', ({ assert }) => {
const who = (i: number, n: string) =>
releaseIdentity({ poster: 'p', subject: `Very Best Of The Who [${String(i).padStart(2, '0')}/${String(i * 10).padStart(3, '0')}] - "${n}" yEnc`, name: n, weak: false })!
assert.equal(who(3, "The Who - 01 - I Can't Explain.mp3").key, who(4, 'The Who - 02 - Anyway.mp3').key)
assert.isUndefined(who(3, "The Who - 01 - I Can't Explain.mp3").fileTotal)
})
test('a leading date numbers no item; a file name repeated in the subject goes everywhere', ({ assert }) => {
const id = (subject: string, name: string, poster = 'p') => releaseIdentity({ poster, subject, name, weak: false })!
const show = (n: string) => id(`#sterntuary - Jeff Rense Radio Program - "${n}" yEnc`, n, '#sterntuary <aa@aa.com>')
assert.equal(show('09-30-2008_BAK_JRS.nfo').key, show('09-30-2008_BAK_JRS.r00').key)
assert.notEqual(show('09-30-2008_BAK_JRS.r00').key, show('10-01-2008_BAK_JRS.r00').key)
const nelet = (n: string, i: number) => id(`(${n}) [${String(i).padStart(2, '0')}/58] - "${n}" yEnc`, n)
assert.equal(nelet('NELET11.par2', 1).key, nelet('NELET11.part01.rar', 2).key)
const wl = (n: string) => id(`(01/26) "${n}" "Silicon Dream - Time Machine_BY_WaRLoRD\`\`\`\` yEnc`, n)
assert.equal(wl('01 Time Machine.mp3').key, wl('02 Jimmy Dean Loved Marilyn.mp3').key)
})
test('hashed stems under a tag, volume numbers as extensions, scene tracks under a bare counter', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
const u4e = (n: string) => id(`Seit 1753 Tagen - usenet4ever.info - "${n}" yEnc`, n)
assert.equal(u4e('055631a1_b6c820bc_a856086c_85112a5-u4e.part01.rar').key, u4e('055631a1_b6c820bc_a856086c_85112a5-u4e.par2').key)
assert.notEqual(u4e('055631a1_b6c820bc_a856086c_85112a5-u4e.part01.rar').key, u4e('4cc7c4c6_d3c2fecf_0bff51d6_d10df86-u4e.part01.rar').key)
const gb = (n: string) => id(`German Board - [Usenet4ever.info] und [SecretUsenet.com] - "${n}" yEnc`, n)
assert.equal(gb('6c57319fbae505679737bd46a76193a1-u4e.part6.rar').key, gb('6c57319fbae505679737bd46a76193a1-u4e.par2').key)
assert.notEqual(gb('6c57319fbae505679737bd46a76193a1-u4e.part6.rar').key, gb('6fc0ff192a355703b3e81557893013b1-u4e.part6.rar').key)
assert.notEqual(gb('21.Jump.Street.2012.BDRip.AC3.German.XviD-POE.part01.rar').key, gb('Ice.Age.4.Voll.verschoben.2012.BDRip.AC3.German.XviD-POE.part01.rar').key)
assert.equal(gb('21.Jump.Street.2012.BDRip.AC3.German.XviD-POE.part01.rar').key, gb('21.Jump.Street.2012.BDRip.AC3.German.XviD-POE.par2').key)
const mac = (i: string, n: string) => id(`[1598]-[FULL]-[#a.b.teevee@EFNet]-[ MacGyver.S01E03.DVDRip.XviD-MEDiEVAL ]-[${i}/38] - "${n}" yEnc`, n)
assert.equal(mac('04', 'sample.macgy.s01e03-med.avi').key, mac('05', 'macgy.s01e03-med.r00').key)
const pck = (i: string, n: string) => id(`(????) [${i}/2195] - "${n}" yEnc`, n)
assert.equal(pck('0659', 'DN.VPL PCK.1508').key, pck('0660', 'DN.VPL PCK.1509').key)
assert.equal(pck('0659', 'DN.VPL PCK.1508').name, 'DN.VPL PCK.1508')
const movie = (i: string, n: string) => id(`[${i}/30] - "${n}" yEnc`, n)
assert.notEqual(movie('01', 'Movie.2008').key, movie('02', 'Movie.2009').key)
const track = (i: string, n: string) => id(`[${i}/14] - "${n}" yEnc`, n)
assert.equal(track('06', '02-repiet_-_dont_think_twice_(extended_mix).mp3').key, track('07', '03-repiet_-_other_song.mp3').key)
assert.equal(track('06', '02-repiet_-_dont_think_twice_(extended_mix).mp3').name, 'repiet')
assert.equal(track('01', '01-2bm_mq-real_rap_(intro).mp3').name, '2bm_mq')
const meow = (i: string, n: string) => id(`[${i}/13] - "${n}" yEnc`, n)
const tracks = meow('05', '01-ammar-turk_uit_de_kroeg.mp3').key
for (const n of ['00-ammar-turk_uit_de_kroeg-single-web-nl-2022-cover.jpg', '00-ammar-turk_uit_de_kroeg-single-web-nl-2022.nfo', '00-ammar-turk_uit_de_kroeg-single-web-nl-2022.sfv']) {
assert.equal(meow('01', n).key, tracks, n)
}
assert.notEqual(meow('01', '00-frank_van_etten-wie_heeft_jouw_lach_gestolen-single-web-nl-2022-cover.jpg').key, tracks)
const blaise = (i: string, n: string) => id(`[${i}/14] - "${n}" yEnc`, n)
assert.equal(blaise('07', 'blaise_mc-in_hellstill_3-ep-web-2022-known.par2').key, blaise('03', '00-blaise_mc-in_hellstill_3-ep-web-2022.nfo').key)
assert.equal(blaise('09', 'blaise_mc-in_hellstill_3-ep-web-2022-known.vol000+01.par2').key, blaise('05', '01-blaise_mc-intro.mp3').key)
// A rar upload keeps its full name: albums by artist and total would merge.
const hou = (i: string, n: string) => id(`[${i}/20] - "${n}" - 181.46 MB www.house-of-usenet.com yEnc`, n)
assert.notEqual(hou('03', 'VA - Best Of Shamania Pro 2K16-(SHB 006)-WEB-2016-ZzZz.part01.rar').key, hou('03', 'VA - Other Album-(SHB 007)-WEB-2016-ZzZz.part01.rar').key)
assert.equal(blaise('01', 'Ace_Of_Base-Wheel_Of_Fortune-(861_545-2)-CDM-FLAC-1992-REETKEVER.par2').key, blaise('02', 'Ace_Of_Base-Wheel_Of_Fortune-(861_545-2)-CDM-FLAC-1992-REETKEVER.part1.rar').key)
assert.notEqual(blaise('01', 'Ace_Of_Base-Wheel_Of_Fortune-(861_545-2)-CDM-FLAC-1992-REETKEVER.par2').key, blaise('01', 'Ace_Of_Base-Other-(861_546-2)-CDM-FLAC-1993-REETKEVER.par2').key)
// A film isn't a scene music release.
assert.equal(blaise('01', 'Some.Movie.2010.1080p.BluRay.x264-GRP.par2').source, 'stem')
assert.equal(blaise('01', 'Some.Movie.2010.1080p.BluRay.x264-GRP.par2').name, 'Some.Movie.2010.1080p.BluRay.x264-GRP')
})
test('a host and a sponsor without a counter name no upload', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
const tn = (tag: string, n: string) => id(`(www.Thunder-News.org) >${tag}< <Sponsored by Secretusenet> - "${n}" yEnc`, n)
assert.equal(tn('XXX', 'ps-itb10b.r00').key, tn('XXX', 'ps-itb10b.par2').key)
assert.notEqual(tn('XXX', 'ps-itb10b.r00').key, tn('XXX', 'swe6-legsa.r00').key)
assert.equal(tn('XXX', 'ps-itb10b.r00').source, 'stem')
const named = tn('For.Rent.XXX.720p.Bluray.x264-DPXXXHD', 'dp-for.rent.720p.x264.r00')
assert.equal(named.source, 'subject')
assert.equal(named.key, tn('For.Rent.XXX.720p.Bluray.x264-DPXXXHD', 'dp-for.rent.720p.x264.par2').key)
assert.equal(named.name, '>For Rent XXX 720p Bluray x264 DPXXXHD<')
// With a counter the subject stays as it was: the total bounds it.
assert.equal(id('(www.Thunder-News.org) >XXX< [01/20] - "ps-itb10b.r00" yEnc', 'ps-itb10b.r00').source, 'subject')
})
test('an image under a post token is keyed by the post too', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
const mdg = (post: string, i: string, n: string) => id(`${post} - (${i}/90) "${n}" - 16,14 MB - yEnc`, n)
assert.equal(mdg('MDG005b', '01', 'IMG_2307.JPG').key, mdg('MDG005b', '02', 'IMG_2308.jpg').key)
assert.notEqual(mdg('MDG005b', '01', 'IMG_2307.JPG').key, mdg('MDG006a', '01', 'IMG_4410.JPG').key)
// A size isn't a post token.
// The whole text before "(1/1)" is the name; the size follows the segment counter.
const alexi = (i: string, size: string) => {
const n = `${i}of37 ## Alexi uses strange toys to make herself come ## alexis0${i}.jpg`
return id(`${n} ${size}`, n)
}
assert.equal(alexi('01', '57295b').key, alexi('02', '32202b').key)
})
test('a set named by its prefix alone is bounded by its counter', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
const lop = (i: string, total: string, n: string) => id(`[${i}/${total}] - "${n}" yEnc`, n)
assert.equal(lop('001', '559', 'lop1001.jpg').key, lop('002', '559', 'lop1002.jpg').key)
assert.notEqual(lop('001', '559', 'lop1001.jpg').key, lop('001', '1018', 'lop5001.jpg').key)
const r = (i: string, total: string, n: string) => id(`[${i}/${total}] - "${n}" yEnc`, n)
assert.equal(r('022', '457', "r86_022 - Gwen Guthrie - Ain't Nothing Going on but the Rent.mp3").key, r('085', '457', "r88_085 - Gregory Abbott - I'll Prove It to You.mp3").key)
assert.notEqual(r('022', '457', "r86_022 - Gwen Guthrie - Ain't Nothing Going on but the Rent.mp3").key, r('022', '333', "r98_333 - Jellie - Roller Coaster.mp3").key)
})
test("under a constant tag an upload's random stem bounds the subject", ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'Kim <Jong-Un@town.ag>', subject, name, weak: false })!
const town = (i: string, n: string) => id(`[ TOWN ] [ www.town.ag ] [ TV ] [${i}/20] - "${n}" yEnc`, n)
assert.equal(town('01', 'Z3mMTMPsoT4ikE_Di3fKnNF21.part01.rar').key, town('18', 'Z3mMTMPsoT4ikE_Di3fKnNF21.vol4+4.par2').key)
assert.equal(town('01', 'Z3mMTMPsoT4ikE_Di3fKnNF21.part01.rar').name, town('01', 'i3DpbaTUJT4L6V48fEBdbVV46.part01.rar').name)
assert.notEqual(town('01', 'Z3mMTMPsoT4ikE_Di3fKnNF21.part01.rar').key, town('01', 'i3DpbaTUJT4L6V48fEBdbVV46.part01.rar').key)
// A scene name keeps the subject's key, so its nfo stays with it.
const show = (i: string, n: string) => id(`Some.Show.S01E01 [${i}/20] - "${n}" yEnc`, n)
assert.equal(show('01', 'The.Big.Bang.Theory.S01E01.part01.rar').key, show('20', 'The.Big.Bang.Theory.S01E01.nfo').key)
// An image set under one subject stays one release whatever its images are named ("a1.jpg", "a1 (2).jpg"; "468_1000.jpg").
const tender = (i: string, n: string) => id(`Tender TEEN SEX in HD - File ${i} of 435 - ${n}`, n)
assert.equal(tender('001', 'a1 (2).jpg').key, tender('002', 'a1.jpg').key)
assert.equal(tender('003', 'a2 (2).jpg').key, tender('002', 'a1.jpg').key)
})
test("a random name's volumes with extensions of their own; a dump's versions apart", ({ assert }) => {
const id = (i: string, total: string, n: string) => releaseIdentity({ poster: 'p', subject: `[${i}/${total}] - "${n}" yEnc`, name: n, weak: false })!
assert.equal(id('01', '69', 'df2BkeRxIvHcWrsWwwz.part01.cer').key, id('69', '69', 'df2BkeRxIvHcWrsWwwz.part69.bdmv').key)
assert.equal(id('01', '32', 'jA0eSSUMat8tQtIKUyPMA.part01').key, id('32', '32', 'jA0eSSUMat8tQtIKUyPMA.part32').key)
// A readable name keeps its part.
assert.notEqual(id('01', '2', 'Some.Movie.Part01.mkv').key, id('02', '2', 'Some.Movie.Part02.mkv').key)
// A dump's versions stay apart.
const dump = (i: string, n: string) => releaseIdentity({ poster: 'janusch', subject: `(????) [${i}/15816] - "${n}.zip"`, name: `${n}.zip`, weak: false })!
assert.notEqual(dump('00005', 'K-ML 3.8.233').key, dump('00006', 'K-ML 3.8.239').key)
})
test('an image without words around it is keyed by its set', ({ assert }) => {
const id = (name: string, counter: string) => releaseIdentity({ poster: 'p', subject: `##[ "${name}" (${counter})`, name, weak: false })!
assert.equal(id('diana-040-001.jpg', '01/68').key, id('diana-040-002.jpg', '02/68').key)
assert.notEqual(id('diana-040-001.jpg', '01/68').key, id('diana-407-081.jpg', '81/82').key)
})
test('an unquoted file name is no file counter', ({ assert }) => {
const shy = (name: string) => releaseIdentity({ poster: 'p', subject: `${name} hardcore SHYLA STYLEZ & SHY LOVE`, name, weak: false })!
assert.equal(shy('shyla-shy-09-0195.jpg').key, shy('shyla-shy-09-0766.jpg').key)
assert.isUndefined(shy('shyla-shy-09-0195.jpg').fileTotal)
})
test('dates are no file counters', async ({ assert }) => {
const { counterTotal } = await import('#lib/release/identity')
assert.isUndefined(counterTotal('Avira AntiVir Rescue System 08-29-2011.rar'))
assert.isUndefined(counterTotal('Android Apps and Games Pack 27-02-2011.rar'))
assert.isUndefined(counterTotal('Supernova-clubbin (slamfm)-cable-18-08-2012-1king.rar'))
assert.equal(counterTotal('Some.Album [03/12] - "x.mp3"'), 12)
assert.equal(counterTotal('File 07390 of 19411 "x.epub"'), 19411)
})
test('split parts with two-digit numbers share a stem', ({ assert }) => {
assert.equal(fileStem('Admiral.EP05.2008.720p.Rus.HDCLUB.mkv.21'), fileStem('Admiral.EP05.2008.720p.Rus.HDCLUB.mkv.22'))
assert.equal(fileStem('Naslednica_po_prjamoy_DVDRip.avi.05'), 'Naslednica_po_prjamoy_DVDRip')
})
test('image sets: sizes in brackets and one-word set names', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
assert.equal(id('Aletta Ocean - "100628-035.jpg" yEnc [347K]', '100628-035.jpg').key, id('Aletta Ocean - "100628-036.jpg" yEnc [298K]', '100628-036.jpg').key)
const corie = id('Corie - "2877-041.jpg" yEnc [290K]', '2877-041.jpg')
assert.equal(corie.key, id('Corie - "2877-042.jpg" yEnc [301K]', '2877-042.jpg').key)
assert.equal(corie.name, 'Corie')
})
test('numbered items of a set stay one release under the set name (a course, not a poster tag)', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'Poster49118 <Poster49118@generic.mail>', subject, name, weak: false })!
const a = id('ai-engineer-complete [401/465] - "003 Defining Tools with JSON Schema.mp4" yEnc', '003 Defining Tools with JSON Schema.mp4')
const b = id('ai-engineer-complete [422/465] - "006 ai-lesson-4-5-web-search-tools.zip" yEnc', '006 ai-lesson-4-5-web-search-tools.zip')
assert.equal(a.key, b.key)
assert.equal(a.name, 'ai engineer complete')
// Karaoke discs: a disc code before the track number.
const sc = (track: string) => releaseIdentity({ poster: 'p', subject: `Spotlight - 83xx's [16/19] - "${track}.zip" yEnc`, name: `${track}.zip`, weak: false })!
assert.equal(sc('SC8367-12 - Wynette, Tammy - Singing My Song').key, sc('SC8367-13 - Jones, George - He Stopped Loving Her Today').key)
})
test("a poster's constant tag doesn't make one release of all their uploads", ({ assert }) => {
const id = (poster: string, subject: string, name: string) => releaseIdentity({ poster, subject, name, weak: false })!
// [KiLL…] tag on every upload: each album by its stem, its nfo included.
const kill = 'www.ggb.6x.to <darkness@earth.de>'
const a = id(kill, '[KiLL.dA.FuCkIn.EaStErRaBbIt]---- (03/10) "Cephalgy.-.Weisses.Fleisch.2003[[g.6x.to]].r00" yEnc', 'Cephalgy.-.Weisses.Fleisch.2003[[g.6x.to]].r00')
const aNfo = id(kill, '[KiLL.dA.FuCkIn.EaStErRaBbIt]---- (01/10) "Cephalgy.-.Weisses.Fleisch.2003[[g.6x.to]].nfo" yEnc', 'Cephalgy.-.Weisses.Fleisch.2003[[g.6x.to]].nfo')
const b = id(kill, '[KiLL.dA.FuCkIn.EaStErRaBbIt]---- (03/10) "Shnarph.-.Lautlos.2008[[g.6x.to]].r00" yEnc', 'Shnarph.-.Lautlos.2008[[g.6x.to]].r00')
assert.equal(a.key, aNfo.key)
assert.notEqual(a.key, b.key)
assert.equal(a.source, 'stem')
// A tag taken for a post id: "(PowBeertje80 Posted)" with the same [i/M] on every album.
const pow = (album: string) => id('pow', `(PowBeertje80 Posted) [01/026] - "${album}.part01.rar" yEnc`, `${album}.part01.rar`)
assert.notEqual(pow('Bravo Hits Vol.14 2CD -1996-').key, pow('Bravo Hits Vol.33 2CD -2001-').key)
})
test('the text outside the quotes still groups when it describes the files, or is a per-post id', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
// A word in common ("ketchup"): one album of many track files.
const t1 = id('!!!!! FTA www.ftaclub.net BodyCrew Presents VA-Ketchup_Dance2008 !!!!! [01/28] - "fta-01-a_track-2008.mp3" yEnc', 'fta-01-a_track-2008.mp3')
const t2 = id('!!!!! FTA www.ftaclub.net BodyCrew Presents VA-Ketchup_Dance2008 !!!!! [02/28] - "fta-02-coyote-ketchup_mix.mp3" yEnc', 'fta-02-coyote-ketchup_mix.mp3')
assert.equal(t1.key, t2.key)
assert.equal(t1.source, 'subject')
// A number in common ("35"), and a per-post id ("FTD769997").
assert.equal(id('[Audiofiles_DIE_ZEIT_35] [01/24] - "35_China_dl.mp3" yEnc', '35_China_dl.mp3').key, id('[Audiofiles_DIE_ZEIT_35] [02/24] - "35_Bamberg_dl.mp3" yEnc', '35_Bamberg_dl.mp3').key)
assert.equal(id('FTD769997 [01/23] - "Prison.Break.S04E02.720p.part01.rar" yEnc', 'Prison.Break.S04E02.720p.part01.rar').key, id('FTD769997 [23/23] - "Prison.Break.S04E02.720p.part.par2" yEnc', 'Prison.Break.S04E02.720p.part.par2').key)
// Without a counter a long number is the board's, not a post's: a dump of separate releases.
const kere = (n: string) => id(`<kere.ws/illuminatenboard.org> - ID - 1855891249 - ${n}`, n)
assert.notEqual(kere('Along.The.Ridge.2006.Limited.PAL.DVDr-TWCiSO.rar').key, kere('Altera.QUARTUS.II.DSP.Builder.v7.2.SP1-SHooTERS.rar').key)
// A scene name with abbreviated file names, and a generically named sidecar.
const scene = id('Some.Movie.2008.DVDRip.XviD-GRP [01/40] - "grp-sm.part01.rar" yEnc', 'grp-sm.part01.rar')
assert.equal(scene.name, 'Some Movie 2008 DVDRip XviD GRP')
assert.equal(id('Better.Jpeg.v2.0-DOA [02/10] - "file_id.diz" yEnc', 'file_id.diz').key, id('Better.Jpeg.v2.0-DOA [03/10] - "doa-bj20.zip" yEnc', 'doa-bj20.zip').key)
})
test('image sets: counters written out, sizes and the set by its counter or name', ({ assert }) => {
const id = (subject: string, name: string, poster = 'p') => releaseIdentity({ poster, subject, name, weak: false })!
// "File 027 of 132": one set, not a release per image; another set of the same title apart by its total.
const a = id('What about this? - File 027 of 132: "DSC_027.jpg" yEnc', 'DSC_027.jpg')
const b = id('What about this? - File 028 of 132: "DSC_028.jpg" yEnc', 'DSC_028.jpg')
const other = id('What about this? - File 001 of 90: "DSC_001.jpg" yEnc', 'DSC_001.jpg')
assert.equal(a.key, b.key)
assert.notEqual(a.key, other.key)
assert.equal(a.name, 'What about this?')
// No counter: the image's name up to its last number.
const k1 = id('Proud to be a poster "Kitchen Hottie 1 set233-76-lg.jpg" yEnc', 'Kitchen Hottie 1 set233-76-lg.jpg')
const k2 = id('Proud to be a poster "Kitchen Hottie 1 set233-77-lg.jpg" yEnc', 'Kitchen Hottie 1 set233-77-lg.jpg')
const k3 = id('Proud to be a poster "Office Chair set12-01-lg.jpg" yEnc', 'Office Chair set12-01-lg.jpg')
assert.equal(k1.key, k2.key)
assert.notEqual(k1.key, k3.key)
// Per-file sizes and other counter forms don't split a post.
assert.equal(subjectRemainder('Minutemen (001/104) "x.cbr" - 76.88 MB - yEnc'), 'Minutemen')
assert.equal(subjectRemainder('Babes P A R T 3 ("Charlotte 03 16.jpg" 0097-1574 156.87 kB-273.03 MB) yEnc'), 'Babes P A R T 3')
assert.equal(subjectRemainder('*MaryKate* - OfficeChair [23of61] - "OfficeChair023.jpg" yEnc 187924 bytes'), '*MaryKate* OfficeChair')
assert.equal(subjectRemainder('Adventure Comics [1948-12] - "x.rar"'), 'Adventure Comics [1948 12]')
})
test('documents are a release each; audio tracks stay with their album', ({ assert }) => {
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
const c1 = id('cw-horror&mystery [10/28] "Vampirella Magazine 061.cbr" yEnc', 'Vampirella Magazine 061.cbr')
const c2 = id('cw-horror&mystery [11/28] "Mystery Tales 12.cbr" yEnc', 'Mystery Tales 12.cbr')
assert.notEqual(c1.key, c2.key)
assert.equal(c2.name, 'Mystery Tales 12')
const t1 = id('(Geisterjäger John Sinclair Hörspiele Vol. 2) [04/59] - "042 - 011 - Der unheimliche Bogenschütze.mp3 - by DeckaR" yEnc', '042 - 011 - Der unheimliche Bogenschütze.mp3 - by DeckaR')
const t2 = id('(Geisterjäger John Sinclair Hörspiele Vol. 2) [34/59] - "072 - 027 - Die Teufelsuhr.MP3 - by DeckaR" yEnc', '072 - 027 - Die Teufelsuhr.MP3 - by DeckaR')
const par2 = id('(Geisterjäger John Sinclair Hörspiele Vol. 2) [59/59] - "Hörspiele Vol. 2.par2" yEnc', 'Hörspiele Vol. 2.par2')
assert.equal(t1.key, t2.key)
assert.equal(t1.key, par2.key)
// A cover without words around it joins its stem's archive.
assert.equal(id('[2/6] - "x.jpg" yEnc', 'x.jpg').key, id('[1/6] - "x.part01.rar" yEnc', 'x.part01.rar').key)
})
})