Image sets: sizes in brackets and one-word set names
Test and deploy / test (push) Successful in 45s
Test and deploy / edge (push) Successful in 1m51s
Test and deploy / deploy (push) Successful in 1m19s

Old picture groups split every image into a release (the reset's first
hour: 583k releases, 447k of one file; a.b.pictures.erotica.high-heels
262k): "Aletta Ocean - \"100628-035.jpg\" yEnc [347K]" kept its size in
the remainder, and "Corie - \"2877-041.jpg\" yEnc [290K]" named its set
with one word, which namesRelease (two words) refused, so the image's
own name keyed it. Sizes like [347K] (and a cut-off "336573 byt") are
removed; for images a one-word subject (3+ letters) names the set. On
100k high-heels articles: 4,509 releases -> 192. Both implementations;
tests; fixtures identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daan MeijerandClaude Opus 5.5 committed 2026-10-11 21:25:18 +02:00
1 parent 47b445ffb0
commit b1213fbea0
3 files changed
+37 -6

No files matched your search

+24 -3
View File
@@ -304,7 +304,8 @@ static OF_COUNTER: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)[\[(]?\b(?:fileSP
static DASH_COUNTER: LazyLock<Regex> = LazyLock::new(|| re(r"\[([0-9]+)-([0-9]+)\]"));
static SLASH_COUNTER: LazyLock<Regex> = LazyLock::new(|| re(r"\b([0-9]+)/([0-9]+)\b"));
static ZERO_COUNTER: LazyLock<Regex> = LazyLock::new(|| re(r"\b(0[0-9]*)-([0-9]+)\b"));
static SIZES: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)\b[0-9]+(?:[.,][0-9]+)?SP*(?:[kmgt]i?b|bytes?)\b"));
static SIZES: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)\b[0-9]+(?:[.,][0-9]+)?SP*(?:[kmgt]i?b|bytes?|byt)\b"));
static BRACKET_SIZES: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)\[SP*[0-9]+(?:[.,][0-9]+)?SP*[kmgt]SP*\]"));
static EMPTY_BRACKETS: LazyLock<Regex> = LazyLock::new(|| re(r" ?(?:\[ ?\]|\( ?\)) ?"));
fn number(digits: &[u8]) -> f64 {
@@ -326,7 +327,8 @@ fn remove_counters_and_sizes(s: &str) -> String {
let s = replace_counters(&DASH_COUNTER, &s);
let s = replace_counters(&SLASH_COUNTER, &s);
let s = replace_counters(&ZERO_COUNTER, &s);
replace(&SIZES, &s, " ", true)
let s = replace(&SIZES, &s, " ", true);
replace(&BRACKET_SIZES, &s, " ", true)
}
/// The end of subjectRemainder: what's left of brackets, double spaces, trim (after the separators became single spaces).
@@ -532,7 +534,9 @@ pub fn release_identity(poster: &str, subject: &str, name: &str) -> Release {
};
let tag = !image && !numbered && !test(&AUDIO, name) && describes(&stem) && !looks_random(&stem) && is_poster_tag(&remainder, &stem);
let prefix = if image { image_prefix(&stem) } else { String::new() };
if !tag && names_release(&remainder) {
// An image set's subject may be one word, the model's name: /^[A-Za-z]{3,}$/.
let one_word = image && remainder.len() >= 3 && remainder.bytes().all(|c| c.is_ascii_alphabetic());
if !tag && (names_release(&remainder) || one_word) {
let bound = counter_total(subject).unwrap_or_else(|| prefix.clone());
return Release { key: hash(&["subject", poster, &remainder, &bound]), name: remainder, source: "subject", file_total };
}
@@ -1024,4 +1028,21 @@ mod numbered_tests {
assert_eq!(a.name, "ai engineer complete");
}
}
#[cfg(test)]
mod image_set_tests {
use super::{release_identity, subject_remainder, subject_remainder_re};
#[test]
fn sizes_in_brackets_and_one_word_sets() {
for s in [r#"Aletta Ocean - "100628-035.jpg" yEnc [347K]"#, r#"Corie - "2877-041.jpg" yEnc [290K]"#, "x - !!!blob2010-102katie009.jpg 336573 byt"] {
assert_eq!(subject_remainder(s), subject_remainder_re(s), "{s}");
}
assert_eq!(subject_remainder(r#"Aletta Ocean - "100628-035.jpg" yEnc [347K]"#), "Aletta Ocean");
let a = release_identity("p", r#"Corie - "2877-041.jpg" yEnc [290K]"#, "2877-041.jpg");
let b = release_identity("p", r#"Corie - "2877-042.jpg" yEnc [301K]"#, "2877-042.jpg");
assert_eq!(a.key, b.key);
assert_eq!(a.name, "Corie");
}
}
}