diff --git a/edge/src/names.rs b/edge/src/names.rs index 45e133a..905e28e 100644 --- a/edge/src/names.rs +++ b/edge/src/names.rs @@ -731,7 +731,12 @@ pub fn release_identity(poster: &str, subject: &str, name: &str) -> Release { (Some(c), Some(total)) if number(&c[2]) <= total as f64 => String::from_utf8(c[1].to_vec()).unwrap(), _ => stem.clone(), }; - Release { key: hash(&["stem", poster, &base]), name: stem, source: "stem", file_total } + // Without case and a scene index's "00-" ("00-laura_van_dam_-_…-talion.m3u" beside "Laura_van_Dam_-_…-TALiON.par2"). + let lower = base.to_lowercase(); + let b = lower.as_bytes(); + let index = if b.starts_with(b"00") { 2 + b[2..].iter().take_while(|c| matches!(c, b'-' | b'_' | b' ' | b'.')).count() } else { 0 }; + let key_stem = if index > 2 { &lower[index..] } else { &lower[..] }; + Release { key: hash(&["stem", poster, key_stem]), name: stem, source: "stem", file_total } } static SIZE_AFTER_COUNTER: LazyLock = LazyLock::new(|| re(r"(\[[0-9]+/[0-9]+\])SP*-SP*\[[0-9]+\]")); @@ -1296,6 +1301,15 @@ mod image_set_tests { assert_ne!(vlad("185", 77, "P8250001.JPG").key, vlad("234", 77, "P5300085.JPG").key); } + #[test] + fn scene_index_files_go_with_the_release() { + let p = "SavageCobra "; + let a = release_identity(p, "00-laura_van_dam_-_capture_radio_113-cable-10-10-2026-talion.m3u", "00-laura_van_dam_-_capture_radio_113-cable-10-10-2026-talion.m3u"); + let b = release_identity(p, "Laura_van_Dam_-_Capture_Radio_113-CABLE-10-10-2026-TALiON.vol000+001.par2", "Laura_van_Dam_-_Capture_Radio_113-CABLE-10-10-2026-TALiON.vol000+001.par2"); + assert_eq!(a.key, b.key); + assert_eq!(b.name, "Laura_van_Dam_-_Capture_Radio_113-CABLE-10-10-2026-TALiON"); + } + #[test] fn split_rar_volumes_and_sizes_after_the_counter() { assert_eq!(super::file_stem("rld-gtre.r13.002"), "rld-gtre"); diff --git a/lib/release/identity.ts b/lib/release/identity.ts index 177fb3d..1765b0c 100644 --- a/lib/release/identity.ts +++ b/lib/release/identity.ts @@ -368,7 +368,9 @@ export function releaseIdentity(input: ReleaseInput): ReleaseIdentity | null { // "TKY.ASN PCK.691."): the volumes are one upload. const volume = VOLUME_NUMBER.exec(stem) const base = volume && postTotal && Number(volume[2]) <= postTotal ? volume[1] : stem - return { key: hash('stem', poster, base), name: stem, fileTotal, source: 'stem' } + // Without case and a scene index's "00-" ("00-laura_van_dam_-_capture_radio_113-cable-10-10-2026-talion.m3u" beside + // "Laura_van_Dam_-_Capture_Radio_113-CABLE-10-10-2026-TALiON.par2": one upload, two releases; LOG.md 2026-10-12 (19)). + return { key: hash('stem', poster, base.toLowerCase().replace(/^00[-_ .]+/, '')), name: stem, fileTotal, source: 'stem' } } /** Release of a par2 recovery set; every file listed in it belongs to it. */ diff --git a/tests/unit/release/identity.spec.ts b/tests/unit/release/identity.spec.ts index c506ce8..1849b37 100644 --- a/tests/unit/release/identity.spec.ts +++ b/tests/unit/release/identity.spec.ts @@ -276,6 +276,14 @@ test.group('release / par2 names', () => { assert.notEqual(vlad('185', 77, 'P8250001.JPG').key, vlad('234', 77, 'P5300085.JPG').key) }) + test("a scene index's files go with the release: no case, no 00-", ({ assert }) => { + const id = (n: string) => releaseIdentity({ poster: 'SavageCobra ', 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("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) =>