Take the padded volume back out: it merged a dump's versions
Test and deploy / test (push) Successful in 55s
Test and deploy / edge (push) Successful in 2m7s
Test and deploy / deploy (push) Successful in 2m34s

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>
This commit is contained in:
Daan MeijerandClaude Opus 5.5 committed 2026-10-14 14:11:03 +02:00
1 parent 208ca1d535
commit eddbe2863f
3 files changed
+11 -14

No files matched your search

+4 -6
View File
@@ -895,8 +895,8 @@ pub fn release_identity(poster: &str, subject: &str, name: &str) -> Release {
}
}
// A numbered volume as the extension, within the counter's total ("DN.VPL PCK.1508" of 2195): one upload.
// Also zero-padded after a date ("CHT PCK 2 9.26.001").
let volume = VOLUME_NUMBER.captures(stem.as_bytes()).or_else(|| PADDED_VOLUME.captures(stem.as_bytes()));
// Not after a digit: "CHT PCK 2 9.26.001" looks just like a dump's versions ("K-ML 3.8.233").
let volume = VOLUME_NUMBER.captures(stem.as_bytes());
let base = match (volume, post_total.filter(|&n| n != 0)) {
(Some(c), Some(total)) if number(&c[2]) <= total as f64 => String::from_utf8(c[1].to_vec()).unwrap(),
_ => stem.clone(),
@@ -928,8 +928,6 @@ static SCENE_RELEASE: LazyLock<Regex> = LazyLock::new(|| {
});
/// RANDOM_VOLUME (lib/release/identity.ts): a file of a multi-volume upload.
static RANDOM_VOLUME: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)\.(?:part[0-9]+\.rar|vol[0-9]+[+-][0-9]+\.par2|par2|r[0-9]{2,3}|7z\.[0-9]{3}|zip\.[0-9]{3}|[0-9]{3})$"));
/// PADDED_VOLUME (lib/release/identity.ts): a volume number of 3–5 digits after a dot.
static PADDED_VOLUME: LazyLock<Regex> = LazyLock::new(|| re(r"^(.*[A-Za-z].*?)\.([0-9]{3,5})$"));
/// RANDOM_PART (lib/release/identity.ts): a random name's volume with any short extension, or none.
static RANDOM_PART: LazyLock<Regex> = LazyLock::new(|| re(r"^(.+)\.part[0-9]{2,}(?:\.[A-Za-z0-9]{1,5})?$"));
@@ -1602,8 +1600,8 @@ mod image_set_tests {
assert_eq!(rv("01", "69", "df2BkeRxIvHcWrsWwwz.part01.cer").key, rv("69", "69", "df2BkeRxIvHcWrsWwwz.part69.bdmv").key);
assert_eq!(rv("01", "32", "jA0eSSUMat8tQtIKUyPMA.part01").key, rv("32", "32", "jA0eSSUMat8tQtIKUyPMA.part32").key);
assert_ne!(rv("01", "2", "Some.Movie.Part01.mkv").key, rv("02", "2", "Some.Movie.Part02.mkv").key);
let pck = |i: &str, n: &str| super::release_identity("YME", &format!(r#"(????) [{i}/1009] - "{n}" yEnc"#), n);
assert_eq!(pck("0001", "CHT PCK 2 9.26.001").key, pck("0002", "CHT PCK 2 9.26.002").key);
let dump = |i: &str, n: &str| super::release_identity("janusch", &format!(r#"(????) [{i}/15816] - "{n}""#), n);
assert_ne!(dump("00005", "K-ML 3.8.233").key, dump("00006", "K-ML 3.8.239").key);
let mdg = |post: &str, i: &str, n: &str| super::release_identity("p", &format!(r#"{post} - ({i}/90) "{n}" - 16,14 MB - yEnc"#), n);
assert_eq!(mdg("MDG005b", "01", "IMG_2307.JPG").key, mdg("MDG005b", "02", "IMG_2308.jpg").key);
assert_ne!(mdg("MDG005b", "01", "IMG_2307.JPG").key, mdg("MDG006a", "01", "IMG_4410.JPG").key);
+3 -4
View File
@@ -152,8 +152,6 @@ const SCENE_TRACK = /^\d{1,3}[-_ .]+(.+?)(?:_-_| - |-)/
const SCENE_RELEASE = /^(.+?)(?:_-_| - |-).*-(?:web|cd[a-z]?|vinyl|vls|sat|cable|fm|dab|single|ep|lp|promo|bootleg)-.*(?:19|20)\d{2}(?:-[A-Za-z0-9_]+)?$/i
/** A file of a multi-volume upload: a rar part or volume, a par2 (index or volume), a numbered split. */
const RANDOM_VOLUME = /\.(?:part\d+\.rar|vol\d+[+-]\d+\.par2|par2|r\d{2,3}|7z\.\d{3}|zip\.\d{3}|\d{3})$/i
/** A volume number of 3–5 digits after a dot, whatever comes before it ("CHT PCK 2 9.26.001"). */
const PADDED_VOLUME = /^(.*[A-Za-z].*?)\.(\d{3,5})$/
/** A random name's volume with any short extension, or none ("df2BkeRxIvHcWrsWwwz.part01.cer", "….part69.bdmv"). */
const RANDOM_PART = /^(.+)\.part\d{2,}(?:\.[A-Za-z0-9]{1,5})?$/
@@ -490,8 +488,9 @@ export function releaseIdentity(input: ReleaseInput): ReleaseIdentity | null {
// upload the par2 index without a counter, and it belongs to the same post.
// A numbered volume as the extension, within the counter's total ("(????) [0659/2195] - "DN.VPL PCK.1508"",
// "TKY.ASN PCK.691."): the volumes are one upload.
// Also zero-padded after a date ("(????) [0001/1009] - "CHT PCK 2 9.26.001"": 5,419 single files of YME in a.b.pwp).
const volume = VOLUME_NUMBER.exec(stem) ?? PADDED_VOLUME.exec(stem)
// Not after a digit: YME's "CHT PCK 2 9.26.001" looks just like a dump's versions ("K-ML 3.8.233", "… v2.0.1040"), and
// those merged (505 names on the corpus; LOG.md 2026-10-14 (52)).
const volume = VOLUME_NUMBER.exec(stem)
const base = volume && postTotal && Number(volume[2]) <= postTotal ? volume[1] : 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)).
+4 -4
View File
@@ -458,15 +458,15 @@ test.group('release / par2 names', () => {
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 padded volume after a date", ({ assert }) => {
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)
const pck = (i: string, n: string) => releaseIdentity({ poster: 'YME', subject: `(????) [${i}/1009] - "${n}" yEnc`, name: n, weak: false })!
assert.equal(pck('0001', 'CHT PCK 2 9.26.001').key, pck('0002', 'CHT PCK 2 9.26.002').key)
assert.notEqual(pck('0001', 'CHT PCK 2 9.26.001').key, pck('0400', 'CHT PCK 4 10.26.400').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 }) => {