fix(parse): pack titles and degenerate ranges

COMPLETE before the season tag was weak junk, so it stayed in
the title and exact-title matching failed silently (#135). It
now closes the boundary wherever it lands.

S01-S01 produced no claim because the dash-range branch required
last > season; a degenerate range is one season's pack, matching
the rule match_episode lifted.
This commit is contained in:
Miguel Palhas
2026-08-23 18:02:39 +01:00
parent 384e260d72
commit 8d79c7c378
4 changed files with 74 additions and 9 deletions
+4 -3
View File
@@ -36,7 +36,7 @@ pub(crate) fn tag_of(token: &str) -> Option<EpisodeClaim> {
.or_else(|| date_tag(token))
}
/// `S01`, `S01-S03`, `S01E02`, `S01E02E03`, `S01E02-E04`.
/// `S01`, `S01-S03`, `S01-S01`, `S01E02`, `S01E02E03`, `S01E02-E04`.
fn season_tag(token: &str) -> Option<EpisodeClaim> {
let rest = token.strip_prefix('s')?;
let (season, mut rest) = digits(rest);
@@ -55,7 +55,8 @@ fn season_tag(token: &str) -> Option<EpisodeClaim> {
return None;
}
let last: u32 = last.parse().ok()?;
return (last > season).then_some(EpisodeClaim::Seasons {
// A degenerate range (`S01-S01`) is one season's pack, not nothing.
return (last >= season).then_some(EpisodeClaim::Seasons {
first: season,
last,
});
@@ -148,7 +149,7 @@ fn season_words(token: &str) -> Option<EpisodeClaim> {
return None;
}
let last: u32 = last.parse().ok()?;
(last > first).then_some(EpisodeClaim::Seasons { first, last })
(last >= first).then_some(EpisodeClaim::Seasons { first, last })
}
/// Splits a leading run of ASCII digits off a token.
+3 -3
View File
@@ -135,9 +135,9 @@ fn classify_exact(t: &str) -> Option<(Marker, Strength)> {
// "Legendado" claims pt-BR *subtitles* over original audio — it must
// NOT become a PtBr audio claim or main-root originals get rejected.
"proper" | "repack" | "internal" | "hybrid" | "10bit" | "8bit" | "hi10p" | "amzn"
| "dsnp" | "atvp" | "hmax" | "pcok" | "legendado" => (Marker::Junk, Strong),
"nf" | "hulu" | "max" | "itunes" | "cr" | "complete" | "sample" | "subbed" | "subs"
| "sub" | "mkv" | "mp4" | "avi" | "www" | "com" | "net" | "org" | "retail" | "readnfo" => {
| "dsnp" | "atvp" | "hmax" | "pcok" | "legendado" | "complete" => (Marker::Junk, Strong),
"nf" | "hulu" | "max" | "itunes" | "cr" | "sample" | "subbed" | "subs" | "sub" | "mkv"
| "mp4" | "avi" | "www" | "com" | "net" | "org" | "retail" | "readnfo" => {
(Marker::Junk, Weak)
}
_ => return None,