A scene music post's par2 under the release name; .par/.part before .par2
Test and deploy / test (push) Successful in 47s
Test and deploy / edge (push) Successful in 1m57s
Test and deploy / deploy (push) Successful in 1m31s

"[07/14] - "blaise_mc-in_hellstill_3-ep-web-2022-known.par2"": the tracks and the
00- files are keyed by artist and total, the par2 by its stem, so ~1,900 Meow
and Cat posts were two releases. Under a counter a stem that reads as a scene
music release (artist-…-web|cd|ep|single|vinyl|…-…YYYY(-group)) takes the
artist key. And "goh1Phoz5ahXu.par.vol006+08.par2", "X.part.par2" beside
the volumes: .par/.part before a par2 suffix goes too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daan MeijerandClaude Opus 5.5 committed 2026-10-13 06:56:56 +02:00
1 parent 2bbabc08de
commit 7ad4b70775
3 files changed
+52 -2

No files matched your search

+34 -1
View File
@@ -30,6 +30,7 @@ static SUFFIXES: LazyLock<Vec<(Regex, &'static str)>> = LazyLock::new(|| {
vec![
// A part's par2 files ("X.part1.par2", "X.part1.vol00+34.par2").
(re(r"(?i)\.part[0-9]+(?:\.vol[0-9]+[+-][0-9]+)?\.par2$"), ""),
(re(r"(?i)\.(?:part|par)(?:\.vol[0-9]+[+-][0-9]+)?\.par2$"), ""),
(re(r"(?i)\.vol[0-9]+[+-][0-9]+\.par2$"), ""),
(re(r"(?i)\.par2$"), ""),
(re(r"(?i)\.part[0-9]+\.(?:rar|rev)$"), ""),
@@ -216,6 +217,20 @@ fn strip_suffix_rule(s: &[u8], rule: usize) -> Option<usize> {
let p = m.checked_sub(d + 5).filter(|_| d > 0)?;
eq_ci(&s[p..p + 5], b".part").then_some(p)
}
// \.(?:part|par)(?:\.vol\d+[+-]\d+)?\.par2$
14 => {
if !ends_ci(s, b".par2") {
return None;
}
let m = strip_suffix_rule(s, 0).unwrap_or(n - 5);
if m >= 5 && eq_ci(&s[m - 5..m], b".part") {
Some(m - 5)
} else if m >= 4 && eq_ci(&s[m - 4..m], b".par") {
Some(m - 4)
} else {
None
}
}
// (?:\.\d{1,4})?\.bc$
13 => {
if !ends_ci(s, b".bc") {
@@ -243,7 +258,7 @@ pub fn file_stem(name: &str) -> String {
while changed {
changed = false;
// In the order of SUFFIXES: a part's par2 first, BCArchive volumes after the rar rules.
for rule in [12, 0, 1, 2, 3, 4, 13, 5, 6, 7, 8, 9, 10, 11] {
for rule in [12, 14, 0, 1, 2, 3, 4, 13, 5, 6, 7, 8, 9, 10, 11] {
if let Some(next) = strip_suffix_rule(&b[..len], rule) {
if next > 0 && next < len {
len = next;
@@ -815,6 +830,13 @@ pub fn release_identity(poster: &str, subject: &str, name: &str) -> Release {
return Release { key: hash(&["stem", poster, &artist, &total.to_string()]), name: artist, source: "stem", file_total };
}
}
// And its par2 and sfv under the release's own name ("blaise_mc-in_hellstill_3-ep-web-2022-known.par2").
if !test(&AUDIO, name) {
if let Some(c) = SCENE_RELEASE.captures(stem.as_bytes()) {
let artist = String::from_utf8(c[1].to_vec()).unwrap();
return Release { key: hash(&["stem", poster, &artist, &total.to_string()]), name: artist, source: "stem", file_total };
}
}
}
if image {
// Keyed by its set when its name has one ("diana-040-001.jpg").
@@ -870,6 +892,10 @@ static BOILERPLATE: LazyLock<Regex> =
/// Also one long hex run ("6c57319fbae505679737bd46a76193a1-u4e.part6.rar").
static HASHED: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)^(?:[0-9a-f]{8,}(?:_[0-9a-f]{6,}){2,}|[0-9a-f]{24,})(?:-[0-9a-z]+)?$"));
static SCENE_TRACK: LazyLock<Regex> = LazyLock::new(|| re(r"^[0-9]{1,3}[-_ .]+(.+?)(?:_-_| - |-)"));
/// SCENE_RELEASE (lib/release/identity.ts): a scene music release's name.
static SCENE_RELEASE: LazyLock<Regex> = LazyLock::new(|| {
re(r"(?i)^(.+?)(?:_-_| - |-).*-(?:web|cd[a-z]?|vinyl|vls|sat|cable|fm|dab|single|ep|lp|promo|bootleg)-.*(?:19|20)[0-9]{2}(?:-[A-Za-z0-9_]+)?$")
});
static VOLUME_NUMBER: LazyLock<Regex> = LazyLock::new(|| re(r"^(.*[^0-9. ])[. ]([0-9]{1,5})\.?$"));
static GENERIC: LazyLock<Regex> = LazyLock::new(|| {
@@ -1476,6 +1502,9 @@ mod image_set_tests {
("Licence 700790900887990.z18", "Licence 700790900887990"),
("Licence 077887994400668.x12", "Licence 077887994400668"),
("Reply 987986177631730.x004", "Reply 987986177631730"),
("goh1Phoz5ahXu.par.vol006+08.par2", "goh1Phoz5ahXu"),
("brSWc0Q2KWblQpogOmgbn9.part.par2", "brSWc0Q2KWblQpogOmgbn9"),
("x.parts.par2", "x.parts"),
("Some.Movie.2010.x264", "Some.Movie.2010.x264"),
("chappelle1.part02.rev", "chappelle1"),
("chappelle1.rev", "chappelle1"),
@@ -1574,6 +1603,10 @@ mod image_set_tests {
assert_eq!(meow("01", n).key, tracks, "{n}");
}
assert_ne!(meow("01", "00-frank_van_etten-wie_heeft_jouw_lach_gestolen-single-web-nl-2022-cover.jpg").key, tracks);
let blaise = |i: &str, n: &str| release_identity("p", &format!(r#"[{i}/14] - "{n}" yEnc"#), n);
assert_eq!(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_eq!(blaise("09", "blaise_mc-in_hellstill_3-ep-web-2022-known.vol000+01.par2").key, blaise("05", "01-blaise_mc-intro.mp3").key);
assert_eq!(blaise("01", "Some.Movie.2010.1080p.BluRay.x264-GRP.par2").name, "Some.Movie.2010.1080p.BluRay.x264-GRP");
}
#[test]