From 60d01657ebe437a1c0e5434f08a3fc1612122f56 Mon Sep 17 00:00:00 2001 From: Breadway Date: Tue, 21 Jul 2026 19:32:13 +0800 Subject: [PATCH] Allow a trailing fansub revision tag in SxxExx parsing "S01E01v2" (a fixed re-release of an episode) glued the version marker directly onto the episode number with no separator, so the word-boundary check after the digits never matched and the whole file fell through as unparsed. Verified live: some shows had zero episode files linked because every release happened to be a v2. --- breadarrd/src/parser/mod.rs | 10 ++++++++++ breadarrd/src/parser/tokens.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/breadarrd/src/parser/mod.rs b/breadarrd/src/parser/mod.rs index b6f9c36..888a959 100644 --- a/breadarrd/src/parser/mod.rs +++ b/breadarrd/src/parser/mod.rs @@ -131,6 +131,16 @@ mod tests { assert_eq!(p.title_normalized, "Ascendance of a Bookworm"); } + #[test] + fn parses_sxxexx_with_a_trailing_fansub_revision_tag() { + // "v2" glued directly onto the episode number ("a fixed re-release + // of this episode") previously broke the word-boundary check + // entirely, leaving season/episode both None. + let p = parse("[Judas] Chainsaw Man - S01E01v2 1080p WEB-DL"); + assert_eq!(p.season, Some(1)); + assert_eq!(p.episode, Some(1)); + } + #[test] fn parses_subsplease_dash_episode_with_group_and_hash() { let p = parse("[SubsPlease] Honzuki no Gekokujou S4 - 13 (1080p) [A4FE0990].mkv"); diff --git a/breadarrd/src/parser/tokens.rs b/breadarrd/src/parser/tokens.rs index 2c722ee..f052603 100644 --- a/breadarrd/src/parser/tokens.rs +++ b/breadarrd/src/parser/tokens.rs @@ -38,8 +38,16 @@ static YEAR_RE: LazyLock = LazyLock::new(|| Regex::new(r"[(\[](19|20)\d{2 static BARE_YEAR_RE: LazyLock = LazyLock::new(|| Regex::new(r"\b((?:19|20)\d{2})\b").unwrap()); +// The trailing `v\d+` is a fansub revision tag ("v2" = "second release of +// this episode, fixed encode/subs") stuck directly onto the episode number +// with no separator — "S01E01v2". Without consuming it before the `\b`, +// the boundary check fails outright (digit→letter isn't a word boundary), +// so the whole pattern silently doesn't match and the file falls through +// to unparsed (verified live: every v2 release of several shows, e.g. an +// entire show that only had v2 releases, ended up with zero linked +// episode files during a library scan). static SXXEXX_RE: LazyLock = - LazyLock::new(|| Regex::new(r"(?i)\bS(\d{1,2})E(\d{1,3})\b").unwrap()); + LazyLock::new(|| Regex::new(r"(?i)\bS(\d{1,2})E(\d{1,3})(?:v\d+)?\b").unwrap()); static SXX_DASH_EP_RE: LazyLock = LazyLock::new(|| Regex::new(r"(?i)\bS(\d{1,2})\s*-\s*(\d{1,3})\b").unwrap()); static SEASON_PACK_RE: LazyLock =