Skip to content

Fix/season pack episode count#596

Open
ViieeS wants to merge 5 commits into
g0ldyy:mainfrom
ViieeS:fix/season-pack-episode-count
Open

Fix/season pack episode count#596
ViieeS wants to merge 5 commits into
g0ldyy:mainfrom
ViieeS:fix/season-pack-episode-count

Conversation

@ViieeS

@ViieeS ViieeS commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

RTN misreads the batch count in RU/anime release names (e.g. "E13 of 13",
"13 из 13") as a single episode number, so episode-scope matching dropped
these full-season packs for every episode except that number. Detect the
count-of-total pattern and, when the parsed single episode equals the batch
count, clear the episode list and mark the release complete so it matches
any requested episode within the season.

Summary by CodeRabbit

  • New Features

    • Improved matching for torrent titles that include multiple names separated by slashes.
    • Added better handling for season packs that use “N of M” or similar episode-count wording.
  • Bug Fixes

    • Reduced false rejections when a release title matches through an alternate title format.
    • Improved processing of mapping data when multiple IMDb IDs are present.
    • More reliably marks season packs as complete when the episode count matches the release format.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Three independent improvements: normalize_episode_count_pack is added to comet/utils/parsing.py to detect "N of M" episode-count patterns and mark releases as complete; alternate_title_match is added to comet/services/filtering.py to handle slash-separated multi-title torrents, and both are wired into the filtering worker; AnimeMapper._persist_mapping in comet/services/anime.py is updated to iterate over imdb_id when it is a list.

Changes

Title Matching and Episode Normalization

Layer / File(s) Summary
normalize_episode_count_pack helper
comet/utils/parsing.py
Adds _EPISODE_COUNT_PACK compiled regex and normalize_episode_count_pack() that detects "N of M" / "N из M" patterns; clears parsed.episodes and sets parsed.complete = True for matching series entries.
alternate_title_match helper and filtering wiring
comet/services/filtering.py
Adds _BRACKET_CONTENT regex and alternate_title_match() that splits torrent titles on /, strips bracket metadata, and tries RTN parsing per segment; updates imports; calls normalize_episode_count_pack after ensure_multi_language; broadens title mismatch gate to accept either title_match or alternate_title_match.

Anime Fribb imdb_id List Support

Layer / File(s) Summary
Fribb imdb_id list normalization
comet/services/anime.py
Normalizes imdb_id into imdb_ids list in _persist_mapping and appends one fribb_batch row per non-empty single_imdb_id instead of treating imdb_id as a scalar.

Possibly related PRs

  • g0ldyy/comet#461: Modifies AnimeMapper in comet/services/anime.py, including _persist_mapping behavior, as part of Kitsu-to-IMDB mapping work directly related to the Fribb imdb_id handling changed here.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main fix for season-pack episode counting in release matching.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@comet/services/anime.py`:
- Around line 540-556: The fan-out in the Fribb import path is creating multiple
scalar IMDb rows for one entry without adjusting the reverse lookup contract.
Update the logic around the Fribb batch append in comet/services/anime.py and
the get_imdb_from_kitsu() lookup so Kitsu→IMDb remains deterministic for
multi-season records: either preserve a single canonical IMDb per entry_id in
anime_ids, or make the reverse lookup return and merge all matching IMDb IDs
explicitly instead of relying on a scalar LIMIT 1 join. Ensure the stream path
no longer selects an arbitrary season IMDb ID.

In `@comet/services/filtering.py`:
- Around line 41-45: The title parsing in `is_releasable_torrent` is splitting
on every slash, which breaks canonical titles like `Fate/stay night` into
unrelated fragments. Update the slash handling so only separator slashes are
treated as split points, and keep intact title-like slashes from being fed into
`title_match`. Use the existing `torrent_title` processing block and
`title_match` call site to adjust the segmentation logic without reintroducing
the normal title-mismatch path.

In `@comet/utils/parsing.py`:
- Around line 26-29: The completion check in parsing logic is too permissive
because it only compares the first captured count from _EPISODE_COUNT_PACK
against parsed.episodes[0]. Update the normalization in the parsing function so
the title’s two counts must both match the parsed episode count before setting
parsed.complete to True and clearing parsed.episodes. Use the existing match
handling around _EPISODE_COUNT_PACK and the parsed.episodes/parsed.complete
fields to keep partial packs from being marked complete.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 86686fc2-54c1-4828-9e18-9e5c7268df2d

📥 Commits

Reviewing files that changed from the base of the PR and between a1c6323 and 880806b.

📒 Files selected for processing (3)
  • comet/services/anime.py
  • comet/services/filtering.py
  • comet/utils/parsing.py

Comment thread comet/services/anime.py
Comment on lines +540 to +556
imdb_ids = imdb_id if isinstance(imdb_id, list) else [imdb_id]

for provider, key in _FRIBB_PROVIDER_ORDER:
val = entry.get(key)
if val:
found_entry_id = lookup_map.get(f"{provider}:{val}")
if found_entry_id is not None:
fribb_batch.append(
{
"provider": "imdb",
"provider_id": imdb_id,
"entry_id": found_entry_id,
}
)
for single_imdb_id in imdb_ids:
if not single_imdb_id:
continue
fribb_batch.append(
{
"provider": "imdb",
"provider_id": str(single_imdb_id),
"entry_id": found_entry_id,
}
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Avoid turning one entry into many scalar IMDb IDs without updating reverse lookups.

This fan-out makes anime_ids hold multiple provider='imdb' rows for one entry_id, but get_imdb_from_kitsu() in this file still does a scalar join with LIMIT 1. For multi-season Fribb records, Kitsu → IMDb now becomes ambiguous and the stream path can pick an arbitrary season IMDb ID. Either keep a single canonical IMDb on anime_ids, or update the reverse-lookup contract to return/handle all IMDb IDs deterministically before merging this.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@comet/services/anime.py` around lines 540 - 556, The fan-out in the Fribb
import path is creating multiple scalar IMDb rows for one entry without
adjusting the reverse lookup contract. Update the logic around the Fribb batch
append in comet/services/anime.py and the get_imdb_from_kitsu() lookup so
Kitsu→IMDb remains deterministic for multi-season records: either preserve a
single canonical IMDb per entry_id in anime_ids, or make the reverse lookup
return and merge all matching IMDb IDs explicitly instead of relying on a scalar
LIMIT 1 join. Ensure the stream path no longer selects an arbitrary season IMDb
ID.

Comment on lines +41 to +45
if "/" not in torrent_title:
return False

for segment in torrent_title.split("/"):
segment = _BRACKET_CONTENT.sub(" ", segment).strip()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Split only on separator slashes, not every /.

Line 44 uses split("/"), so canonical titles like Fate/stay night are broken into fragments and fed back into title_match. Since this helper now bypasses the normal title-mismatch rejection, that can wrongly accept or reject releases.

💡 Proposed fix
-    if "/" not in torrent_title:
+    if " / " not in torrent_title:
         return False

-    for segment in torrent_title.split("/"):
+    for segment in re.split(r"\s+/\s+", torrent_title):
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if "/" not in torrent_title:
return False
for segment in torrent_title.split("/"):
segment = _BRACKET_CONTENT.sub(" ", segment).strip()
if " / " not in torrent_title:
return False
for segment in re.split(r"\s+/\s+", torrent_title):
segment = _BRACKET_CONTENT.sub(" ", segment).strip()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@comet/services/filtering.py` around lines 41 - 45, The title parsing in
`is_releasable_torrent` is splitting on every slash, which breaks canonical
titles like `Fate/stay night` into unrelated fragments. Update the slash
handling so only separator slashes are treated as split points, and keep intact
title-like slashes from being fed into `title_match`. Use the existing
`torrent_title` processing block and `title_match` call site to adjust the
segmentation logic without reintroducing the normal title-mismatch path.

Comment thread comet/utils/parsing.py
Comment on lines +26 to +29
match = _EPISODE_COUNT_PACK.search(title)
if match and parsed.episodes[0] == int(match.group(1)):
parsed.episodes = []
parsed.complete = True

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Require the two counts to match before marking the release complete.

Line 27 only checks the first capture, so 3 of 12 / 3 из 12 will also be normalized into complete=True whenever RTN parsed episode 3. That turns partial packs into season-wide matches.

💡 Proposed fix
     match = _EPISODE_COUNT_PACK.search(title)
-    if match and parsed.episodes[0] == int(match.group(1)):
+    if match:
+        current = int(match.group(1))
+        total = int(match.group(2))
+        if current == total and parsed.episodes[0] == current:
-        parsed.episodes = []
-        parsed.complete = True
+            parsed.episodes = []
+            parsed.complete = True
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
match = _EPISODE_COUNT_PACK.search(title)
if match and parsed.episodes[0] == int(match.group(1)):
parsed.episodes = []
parsed.complete = True
match = _EPISODE_COUNT_PACK.search(title)
if match:
current = int(match.group(1))
total = int(match.group(2))
if current == total and parsed.episodes[0] == current:
parsed.episodes = []
parsed.complete = True
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@comet/utils/parsing.py` around lines 26 - 29, The completion check in parsing
logic is too permissive because it only compares the first captured count from
_EPISODE_COUNT_PACK against parsed.episodes[0]. Update the normalization in the
parsing function so the title’s two counts must both match the parsed episode
count before setting parsed.complete to True and clearing parsed.episodes. Use
the existing match handling around _EPISODE_COUNT_PACK and the
parsed.episodes/parsed.complete fields to keep partial packs from being marked
complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant