Skip to content

feat: add date-based episode matching for daily shows - #1351

Open
hiitsrob wants to merge 2 commits into
rivenmedia:mainfrom
hiitsrob:daily-episode-format
Open

hiitsrob wants to merge 2 commits into
rivenmedia:mainfrom
hiitsrob:daily-episode-format

Conversation

@hiitsrob

@hiitsrob hiitsrob commented Jan 17, 2026

Copy link
Copy Markdown

Pull Request Check List

Resolves: #1350

  • Added tests for changed code.
  • Updated documentation for changed code.

Description:

Add support for matching torrents that use air dates (YYYY.MM.DD) instead
of season/episode numbers (S##E##). This enables scraping and downloading
for daily talk shows like The Daily Show, Late Night, etc.

Changes:

  • Add _check_aired_date_match() helper in scrapers/shared.py
  • Update scraper to match episodes by aired_at when no episode numbers
  • Update downloader to match files by date for daily shows
  • Add daily_episode_file_template setting for date-based naming
  • Add aired_year, aired_month, aired_day, aired_date template variables

Summary by CodeRabbit

  • New Features

    • Daily shows can match content by air date when episode numbers are missing.
    • New daily episode naming template and date placeholders (year, month, day, YYYY-MM-DD) for customizable file names.
    • Validation added for daily naming templates to catch formatting errors.
  • Refactor

    • Improved service initialization flow and import organization; better per-service initialization tracking and cooldown handling.

✏️ Tip: You can customize this high-level summary in your review settings.

  Add support for matching torrents that use air dates (YYYY.MM.DD) instead
  of season/episode numbers (S##E##). This enables scraping and downloading
  for daily talk shows like The Daily Show, Late Night, etc.

  Changes:
  - Add _check_aired_date_match() helper in scrapers/shared.py
  - Update scraper to match episodes by aired_at when no episode numbers
  - Update downloader to match files by date for daily shows
  - Add daily_episode_file_template setting for date-based naming
  - Add aired_year, aired_month, aired_day, aired_date template variables
@coderabbitai

coderabbitai Bot commented Jan 17, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Adds date-based episode matching for daily shows across scraper, downloader, and naming. Downloader now supports per-service initialization and cooldown tracking. Naming gains aired_year/month/day/date fields and a daily_episode_file_template setting with validation.

Changes

Cohort / File(s) Summary
Scraper: date matching & ranking
src/program/services/scrapers/shared.py
Added _check_aired_date_match() to compare torrent dates to episode aired_at, extended parse_results() to accept ranking_overrides, and initialized ranking_model/rtn.
Downloader: init & date-based matching
src/program/services/downloaders/__init__.py
Added Downloader.__init__() for multi-service initialization, per-service circuit-breaker cooldowns, and expanded match_file_to_item() to try date-based matching for Episode/Show/Season items; adjusted CircuitBreakerOpen handling.
Filesystem naming & templates
src/program/services/filesystem/vfs/naming.py, src/program/settings/models.py
Added NameBuilder properties aired_year, aired_month, aired_day, aired_date; introduced daily_episode_file_template with validator and added date-based template selection for daily episodes.

Sequence Diagram(s)

sequenceDiagram
    participant RTN as RTN Parser
    participant Scraper as Scraper Service
    participant Matcher as Date Matcher
    participant DB as Metadata DB
    participant Downloader as Downloader Service
    participant FS as FileSystem / Naming

    RTN->>Scraper: Parse torrent -> returns date (no S/E)
    Scraper->>Matcher: _check_aired_date_match(torrent_date)
    Matcher->>DB: query episodes by aired_at
    DB-->>Matcher: episode metadata (aired_at)
    Matcher-->>Scraper: match result (episode id)
    Scraper-->>Downloader: enqueue matching result

    Downloader->>Downloader: initialize services & cooldowns
    Downloader->>Matcher: match_file_to_item(file, item) with torrent date
    Matcher-->>Downloader: matched episode id
    Downloader->>Downloader: mark episode processed (processed_episode_ids)

    Downloader->>FS: request filename for item
    FS->>FS: use daily_episode_file_template with aired_date fields
    FS-->>Downloader: rendered filename
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • dreulavelle
  • davidemarcoli
  • Gaisberg

Poem

🐰 A hop, a sniff, a date in view,

The rabbit badges episodes new,
No S##E## — just YYYY-MM-DD,
My paws arrange the filename spree,
Hooray — daily shows now hop to you!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly and specifically describes the main feature being added: date-based episode matching for daily shows.
Description check ✅ Passed Description follows the template with all required sections: checklist with completed items, resolves issue reference, and detailed explanation of changes made across the codebase.
Linked Issues check ✅ Passed All primary objectives from issue #1350 are implemented: date-based matching in scraper via check_aired_date_match(), date matching in downloader, and daily_episode_file_template settings with new aired* template variables.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #1350 objectives. Import consolidation, circuit-breaker exception handling adjustment, and validator refactoring are all supporting infrastructure for the core feature.
Docstring Coverage ✅ Passed Docstring coverage is 94.12% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/program/services/downloaders/__init__.py`:
- Around line 375-382: The compound boolean expression in the conditional that
checks instances of Show, Season, Episode is ambiguous due to mixed and/or
precedence; update the condition around file_data checks in the if block that
references file_data.episodes, file_data.date, file_data.seasons (the block
starting with "if isinstance(item, (Show, Season, Episode))") by adding explicit
parentheses to group the intended logic — i.e., clearly parenthesize the "no
episodes and no date" check as one unit, the "episodes contains only 0" check as
another, and the "seasons first element equals 0" check — so the final
expression uses parentheses to enforce the intended precedence and avoid
mis-evaluation.
🧹 Nitpick comments (3)
src/program/services/downloaders/__init__.py (2)

358-359: Consider logging the exception for debugging.

The blind except Exception swallows all errors silently. While this may be intentional to prevent crashes, logging the exception at debug level would help diagnose issues.

♻️ Suggested improvement
-                except Exception:
+                except Exception as e:
+                    logger.debug(f"Failed to calculate episode_cap: {e}")
                     pass

372-373: Consider logging parse failures for debugging.

Silently continuing on parse errors makes debugging difficult. A trace-level log would help identify problematic filenames.

♻️ Suggested improvement
-                except Exception:
+                except Exception as e:
+                    logger.trace(f"Failed to parse filename '{file.filename}': {e}")
                     continue
src/program/settings/models.py (1)

446-490: Consider extracting shared test data and improving exception chaining.

  1. The test_data dict is duplicated between validate_naming_template and validate_daily_episode_template. Consider extracting to a module-level constant.

  2. Per static analysis (B904), use raise ... from e for proper exception chaining.

♻️ Suggested improvement for exception chaining
             formatter.format(v, **test_data)
 
             return v
         except Exception as e:
-            raise ValueError(f"Invalid daily episode naming template syntax: {e}")
+            raise ValueError(f"Invalid daily episode naming template syntax: {e}") from e
♻️ Optional: Extract shared test data
# At module level or as a class constant
_TEMPLATE_TEST_DATA = {
    "title": "Test Title",
    "year": 2024,
    "season": 1,
    "episode": 1,
    "show": {
        "title": "Test Show",
        "year": 2024,
        "tvdb_id": "12345",
        "imdb_id": "tt1234567",
    },
    "season_obj": {"number": 1, "title": "Season 1"},
    "tmdb_id": "12345",
    "tvdb_id": "12345",
    "imdb_id": "tt1234567",
    "aired_year": 2024,
    "aired_month": 1,
    "aired_day": 15,
    "aired_date": "2024-01-15",
    # ... rest of fields
}

Comment thread src/program/services/downloaders/__init__.py
  Add explicit parentheses to group conditions checking file_data.episodes,
  file_data.date, and file_data.seasons to avoid ambiguous and/or evaluation.
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.

[feature] Add support for date-based episode matching for daily shows

1 participant