Skip to content

fix(import): align json and csv import with our guidelines and export - #3163

Open
seferturan wants to merge 9 commits into
mainfrom
fix/json_import
Open

fix(import): align json and csv import with our guidelines and export#3163
seferturan wants to merge 9 commits into
mainfrom
fix/json_import

Conversation

@seferturan

Copy link
Copy Markdown
Contributor

🎶 Notes 🎶

Collection of fixes so the JSON and CSV importers support what our own guidelines document, and can ingest our own export.

Guidelines

  • Flat *_id entries dropped type. A documented "type": "show" went out as a movie lookup against a TMDB show id, so no match, or a match on an unrelated movie.
  • type: "season" was documented but never implemented. No branch in toType, no seasons bucket anywhere.
  • Only movies had tmdb in their id priority, so a show or episode carrying just a tmdb_id resolved to nothing and was dropped.
  • Episodes never resolved by imdb. They were pushed into the shows bucket under an episode imdb id, which no show carries, so they vanished or marked a whole show watched. Also fixes IMDb tvEpisode rows.
  • Ratings and watchlist payloads had no episodes bucket, so episode ratings and watchlisted episodes were dropped.
  • One entry can carry a watch, a rating and a watchlist date at once, like our own example does. inferAction only ever returned one of them. CSV already fanned these out, JSON now matches.
  • String ids ("tmdb_id": "67324") are coerced at the parse boundary.
    • Contract hygiene rather than a fix. Rails casts them and the bulk resolver keys by to_s, so they did resolve.

Export

  • The zip reader looked for watched/history*, ratings/ratings* and lists/watchlist.json. Exports name their entries watched-history-1.json, ratings-movies-1.json and lists-watchlist.json, so nothing matched and a raw export imported zero items.
    • Separators are folded together rather than swapped, so the v2 layout keeps working for anyone holding an older export.
  • Season ratings nest their ids under season.ids, sibling to a show. Those were falling through to the show's ids.

Verified

  • Three real exports through the parser and payload builders: 22643, 44568 and 26445 items, all landing in a payload, none dropped.
  • A reporter's 9408 row CSV, same. Before, only the 881 movies resolved.
  • TV Time and Letterboxd unchanged. Diffed payloads against the base branch engine on real fixtures. IMDb does change, and both changes are the episode fix above.

Follow ups

  • ⚠️ Seasons cannot resolve by imdb, there is no imdb branch for them server side. Guidelines still promise trakt/imdb/tmdb for every type, so that line needs a caveat.
  • @trakt/api episode ids omit tmdb and imdb, and season tmdb is typed as a string. All wrong against find_by_multi, the payload builders cast around it for now.
  • Silently dropped items are still invisible in the UI, left the fixme for Importer updates #2055.

Third-party exports send numeric ids as strings ("tmdb_id": "67324"). The
JSON parser passed them straight through, so the sync payload shipped a
string where Trakt expects an integer and the item silently matched nothing.
Both flat entry shapes hardcoded a movie type, so a documented
"type": "show" or "episode" was silently discarded and the item went out as
a movie lookup against a TMDB id from the show namespace. Only the nested
movie/show/episode wrapper ever reached toType.
Only movies had tmdb in their id priority, so a show or episode carrying
nothing but a tmdb id resolved to nothing and was dropped from the payload.
Both are supported server side: find_by_multi resolves a show by
trakt/imdb/tmdb/tvdb and an episode by trakt/tmdb/tvdb/imdb.

Inserted ahead of trakt only, so anything that already resolved keeps
resolving to the same id.
A single entry can carry a watch, a rating and a watchlist date at once, as
the documented example does. inferAction only ever returned one of them, so
an entry with both watched_at and a rating was counted and imported as a
rating alone and the watch was dropped. The CSV parser already fans these
out; JSON now matches.
The guide has always listed season as a valid type, but toType had no branch
for it so a season entry parsed as a movie, and none of the payload builders
had a seasons bucket. Seasons resolve by trakt, tmdb or tvdb id server side,
never imdb, hence the SEASON_IDS priority.
buildWatchlistPayload only ever emitted movies and shows, so a watchlisted
episode was dropped without a trace. It also backs syncLists, so episodes
were missing from imported custom lists too.
buildRatingsPayload only emitted movies and shows, so an episode rating was
dropped even though the guide documents rating for every type and the sync
endpoint takes an episodes bucket.
An episode carrying only an imdb id had nowhere to go, so it was pushed into
the shows bucket under that id. No show carries an episode's imdb id, so the
entry either vanished or, worse, marked a whole show watched. Episodes do
resolve by imdb server side, so route them as episodes and drop the punt.

Fixes IMDb tvEpisode rows, which only ever carry an episode imdb id.
An export names its entries watched-history-1.json, ratings-movies-1.json and
lists-watchlist.json, but the zip reader only looked for watched/history*,
ratings/ratings* and lists/watchlist.json. Nothing matched, so dropping a raw
export on the JSON tab imported zero items.

Separators are folded together rather than swapped, so the v2 layout keeps
working for anyone holding an older export.

@claude claude 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.

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, reopen this pull request to trigger a review.

@trakt-bot
trakt-bot Bot enabled auto-merge (rebase) August 20, 2026 18:59
@deepsource-io

deepsource-io Bot commented Aug 20, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in 1d441c3...62c7d25 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Coverage  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Aug 20, 2026 6:59p.m. Review ↗
Code coverage Aug 20, 2026 6:59p.m. Review ↗

Code Coverage Summary

Language Line Coverage (Overall)
Aggregate
69.3%
Javascript
69.3%

➟ Additional coverage metrics may have been reported. See full coverage report ↗


Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

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