Skip to content

Netflix viewing history for household members, counted like Plex - #250

Merged
Randomname653 merged 2 commits into
mainfrom
claude/netflix-import
Oct 25, 2026
Merged

Randomname653 merged 2 commits into
mainfrom
claude/netflix-import

Conversation

@Randomname653

Copy link
Copy Markdown
Owner

Don's call: a Netflix play counts exactly like a Plex play, just not against Sonarr. The consumers that only understood Plex are adapted.

Import (Settings → Users → Netflix history import)

  • Both exports are read:
    • the data export zip (only CONTENT_INTERACTION/ViewingActivity.csv: every profile, start time, watched time, bookmark, device; trailers, previews and starts under 2 min are dropped and counted);
    • a profile's NetflixViewingHistory.csv (title + day; the locale date format is inferred from the file's newest-first order).
  • Profiles to members: each profile found gets a household-member picker (or skip). Re-importing adds nothing; the dedupe key is the Netflix title ref + end time.
  • Rows: watch_history, source="netflix", stamped at the end like Plex. listened_ms holds the watched time (the played time), view_offset_ms the bookmark. Two new columns: source_ref and date_only.

Matching onto the library (services/netflix_match.py)

  • Films: exact normalized title, else a TMDB search in en-US and de-DE with an exact title or original-title hit. A matched film takes the key its Plex plays use (else radarr:N) and the library title.
  • Series: take Sonarr's title and category (show/anime) and the TMDB id. plex_item_id stays the episode's own Netflix id.
  • Episode numbers Netflix leaves out: filled from Sonarr's episode list, else from TMDB's season list in English and German.
  • Later arrivals: a daily custodian pass (netflix_relink, no network) links titles that arrive in the library after the import.
  • Checked on the NAS copy plus real TMDB:
    • Haus des Geldes → Money Heist;
    • Die Verurteilten → The Shawshank Redemption;
    • Dark: Staffel 1: Lügen → Dark S1E2.

Consumers (from an audit of every watch_history reader)

  • Episodes without a number count by title (viewing_sessions.episode_id). This covers:
    • the household protection in the deletion judge (_other_users_watch, needs ≥3 distinct episodes);
    • _owner_watch;
    • watch_status.watched_lookup;
    • Wrap-Up comfort / prior completions;
    • proactive series completion.
  • Played time: played_ms_sql / _estimated_sql use Netflix's watched time.
  • Day-only plays: they stay out of the clock, peak hour, dayparts, weekend daytime and sittings. They still count for their day and weekday.
  • Plex writers leave Netflix rows alone:
    • the sync's in-progress advance and resume promotion;
    • reattribute_watch_history;
    • cleanup_orphan_watch_history;
    • fill_players;
    • scripts/dedupe_watch_history.py.

Not in this PR

  • The "watched a recommendation" follow-up fires only from the Plex sync.
  • genres stays NULL on Netflix rows until enrichment.
  • Remakes that share a title are matched to TMDB's first exact hit, because Netflix gives no year.

Tests: tests/test_netflix_import.py (42). The full battery is green, 262/262.

🤖 Generated with Claude Code

Settings -> Users -> Netflix history import reads the data export's
ViewingActivity.csv (every profile, watched time, bookmark, device;
trailers and short starts left out) and a profile's simple CSV (title
and day). Each profile is attached to a household member; re-imports add
nothing.

The plays are watch_history rows with source="netflix", matched onto
the library's titles (exact title, else TMDB in English and German; a
film takes its Plex plays' key, a series Sonarr's title). Missing
episode numbers come from Sonarr's list, else TMDB's season list in both
languages. A daily custodian pass links titles that arrive later.

The readers that counted episodes only by number now fall back to the
episode title (viewing_sessions.episode_id): household protection, the
owner's watch line, watch status, comfort replays, series completion.
Played time is Netflix's watched time; day-only plays keep out of the
clock and sittings. The Plex sync's resume/merge, re-attribution,
orphan cleanup, player backfill and the dedupe script leave Netflix rows
alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread src/services/netflix_import.py Fixed
Comment thread src/services/netflix_import.py Fixed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Randomname653
Randomname653 merged commit 5206ffa into main Oct 25, 2026
9 of 10 checks passed
@Randomname653
Randomname653 deleted the claude/netflix-import branch October 25, 2026 15:15
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.

2 participants