commit remaining modified project files

This commit is contained in:
windyboy
2026-04-07 08:07:18 +08:00
parent d010cf936c
commit fb128c70d6
28 changed files with 4140 additions and 19643 deletions
+41 -8
View File
@@ -23,9 +23,11 @@ QUALITY_TAGS = [
r'\b10bit\b', r'\b8bit\b',
]
# Release group patterns (in brackets, but NOT years in parentheses)
# Release group patterns (in brackets or parentheses at start/end)
RELEASE_GROUP_PATTERNS = [
r'\[[\w\s\-\.]+\]', # [RARBG], [YTS], etc.
r'^\[[\w\s\-\.]+\]', # [Group] at start
r'\[[\w\s\-\.]+\]$', # [Group] at end
r'\b[\w\s\-\.]+[-_]Subs\b', # Group_Subs
]
@@ -56,6 +58,12 @@ def remove_release_groups(text: str) -> str:
result = text
for pattern in RELEASE_GROUP_PATTERNS:
result = re.sub(pattern, '', result)
# Remove trailing parenthetical groups, but keep years like (2020)
match = re.search(r'\s*(\([^)]+\))$', result)
if match and not re.fullmatch(r'\(\d{4}\)', match.group(1)):
result = result[:match.start()].rstrip()
return result
@@ -77,6 +85,22 @@ def normalize_title(title: str) -> str:
return title.strip()
def humanize_parsed_title(title: str) -> str:
"""Make parsed titles less likely to contain accidental all-caps tags.
This keeps short acronyms like "IV" intact while softening long all-caps
words that are likely part of the filename rather than intentional styling.
"""
normalized = normalize_title(title)
words = []
for word in normalized.split():
if word.isalpha() and word.isupper() and len(word) > 3:
words.append(word.capitalize())
else:
words.append(word)
return ' '.join(words).strip()
def parse_movie(
filename: str,
extensions: Optional[list[str]] = None,
@@ -127,7 +151,7 @@ def parse_movie(
# Now clean the title
title = remove_quality_tags(title)
title = remove_release_groups(title)
title = normalize_title(title)
title = humanize_parsed_title(title or match.group(1))
return MovieIdentity(
title=title,
@@ -140,7 +164,7 @@ def parse_movie(
# No year found - clean and extract title, flag for review
cleaned = remove_quality_tags(name_without_ext)
cleaned = remove_release_groups(cleaned)
title = normalize_title(cleaned)
title = humanize_parsed_title(cleaned or name_without_ext)
return MovieIdentity(
title=title,
@@ -189,6 +213,8 @@ def parse_series(
(r'(?<!\d)(\d{1,2})x(\d{1,2})(?!\d)', 0.9),
# Pattern: Season X Episode Y - Medium confidence
(r'[Ss]eason\s*(\d{1,2})\s*[Ee]pisode\s*(\d{1,2})', 0.7),
# Pattern: Hyphen Episode (Anime style: Name - 01) - Medium confidence, assume Season 1
(r'\s+-\s+(\d{1,3})(?!\d)', 0.6),
]
season = None
@@ -199,8 +225,14 @@ def parse_series(
for pattern, conf in patterns:
match = re.search(pattern, name_without_ext, re.IGNORECASE)
if match:
season = int(match.group(1))
episodes = [int(match.group(2))]
if len(match.groups()) == 2:
season = int(match.group(1))
episodes = [int(match.group(2))]
else:
# Hyphen episode only
season = 1
episodes = [int(match.group(1))]
confidence = conf
# Extract title (everything before the match)
@@ -222,12 +254,12 @@ def parse_series(
if title_part:
title_part = remove_quality_tags(title_part)
title_part = remove_release_groups(title_part)
title_part = normalize_title(title_part)
title_part = humanize_parsed_title(title_part or name_without_ext)
else:
# If no title part found, use the whole filename cleaned
title_part = remove_quality_tags(name_without_ext)
title_part = remove_release_groups(title_part)
title_part = normalize_title(title_part)
title_part = humanize_parsed_title(title_part or name_without_ext)
# Determine if review is needed
needs_review = season is None or len(episodes) == 0
@@ -247,6 +279,7 @@ def parse_series(
def group_episodes(episodes: list[SeriesIdentity]) -> dict[tuple[str, int], list[SeriesIdentity]]:
"""Group parsed episodes by normalized series title and season number.
Episodes are grouped by (normalized_title, season) tuple. Episodes with