Skip to content

Wip: CSV import - #650

Open
ramebd wants to merge 6 commits into
bonukai:wipfrom
ramebd:wip
Open

Wip: CSV import#650
ramebd wants to merge 6 commits into
bonukai:wipfrom
ramebd:wip

Conversation

@ramebd

@ramebd ramebd commented Dec 10, 2024

Copy link
Copy Markdown

This PR adds in a CSV import mechanism to complement restoring from a backup and also to simplify switching from other system(s). Given it's such a universal input type, and nearly anything can be converted into it, this feels like a good option to have. Personally, this is helps me convert from a few separate things into one local, self-managed system, non-reliant on any large megacorp owned website that may or may not decide to completely ruin theirs (eg: 1).

The functionality extends the existing import processes, so similarly provides a progress indicator and a summary report at the end. I've put in several sanity and validation checks, so it should be reasonably safe to use to import data.

It only (currently) supports importing tv and movie items. I'll look at extending it to games, books & audiobooks as well, and I'd like to add in an export function as well. Feature wise, this lets you add items to Lists, Watchlist, Ratings and Seen history. There is some basic documentation on the csv import page in a click-to-expand.

Ignore the "Resolve pg errors on orderby in count(*)" commit, it doesn't change anything, because I'd already done a fix in my local before the sort/filter queries were re-written in b969d42.

Also solves #567

@ramebd ramebd changed the title Wip Wip: CSV import Dec 10, 2024
Comment thread src/import/csvImport.ts
Comment thread src/import/csvImport.ts
imdbId: item.imdbid ? item.imdbid : undefined,
tvdbId: item.tvdbid ? item.tvdbid : undefined,
rating: item.rating,
ratedAt: dateNow,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

either use the date provided by the user, or do not set date at all

Comment thread src/import/csvImport.ts
tmdbId: item.tmdbid ? item.tmdbid : undefined,
imdbId: item.imdbid ? item.imdbid : undefined,
tvdbId: item.tvdbid ? item.tvdbid : undefined,
seenAt: dateNow,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

either use the date provided by the user, or do not set date at all

Comment thread src/import/csvImport.ts
Comment thread src/import/csvImport.ts
Comment thread src/import/csvImport.ts
.filter((item) => item.rating && item.rating > 0)
.map((item) => (<ImportRatingItem>{
itemType: item.type,
tmdbId: item.tmdbid ? item.tmdbid : undefined,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

0 is falsy in JavaScript, and in this very rare case, 0 would be overwritten by undefined.

tmdbId can be null or undefined so passing it without any checks is the fastest option.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I had considered this, but a tmdbId value of 0 is invalid anyway, so ending up with undefined ensures no bodgy data is passed any further down the line to be queried against the TMDB API or stored in the database. In that case, it might even be better to explicitly fail the whole import on parsing errors where no (valid) ids are found for a given row, but that might be overkill 🙂

Querying tmdb api for a movie id of "0" returns a 404 with:
{ "success": false, "status_code": 6, "status_message": "Invalid id: The pre-requisite id is invalid or not found." }

Comment thread src/import/csvImport.ts
tvdbId: item.tvdbid ? item.tvdbid : undefined,
seenAt: dateNow,
episode: item.type === 'tv' ? {
seasonNumber: item.season ? item.season : undefined,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

if item.season is 0 (special seasons), then this will be undefined

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ahh yep, dang it, I missed that one 🤦‍♂️

Comment thread src/import/csvImport.ts
name: list.name,
description: list.description,
traktId: list.traktId,
createdAt: dateNow,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

either use the date provided by the user, or do not set date at all

@bonukai

bonukai commented Dec 21, 2024

Copy link
Copy Markdown
Owner

There are few more fields I would like to include on the CSV import: seen date, rated date, added to the list data, all optional, and other media items as well.

Structure of the import data is not flat, a single movie can be seen multiple times, have only one rating, it can be on a watchlist and on other lists. One option to deal with this is to have four separate import files: seen history, ratings, watchlist, and lists

@bonukai

bonukai commented Jan 8, 2025

Copy link
Copy Markdown
Owner

@ramebd Could you please add separate pull request for 400c537. Great job on it, but it's not related to CSV import :)

@ramebd

ramebd commented Jan 8, 2025

Copy link
Copy Markdown
Author

Ahhh, sorry yep, that one wasn't supposed to land here. Just started trying to use Github desktop and mixed up my origin/upstream branches. Might just close this PR and do a new one with the right commits, make it cleaner.

Structure of the import data is not flat, a single movie can be seen multiple times, have only one rating, it can be on a watchlist and on other lists. One option to deal with this is to have four separate import files: seen history, ratings, watchlist, and lists

Re the comments tho, My though on how to deal with this was simply to include the same movie on multiple rows. For example, the same imdbId on 4 rows with 4 different list names/ids would just add that same mediaItem to each list. This shouldn't have much impact except an extra db round trip.
Eg, in my testing, this CSV file imports the same movie to 3 different Lists including the Watchlist:

| type  | imdbId    | list             |
| movie | tt1234567 | Watchlist        |
| movie | tt1234567 | Movies           |
| movie | tt1234567 | BlurayCollection |

.

either use the date provided by the user, or do not set date at all

As for the various date fields, one benefit of CSV data is that it is entirely agnostic on the data source and could come from anything, including from the user themselves (ie: manual). Other formats like XML or JSON are less likely to be done this way, so are more likely to have libs/writers doing the work. Asking users to supply dates (in very specific formats) just makes the import process a bit more cumbersome, but lets hope we don't have to parse native Excel dates like 45665.73957 😁
So I just thought it would be easier to not have to deal with it. However, yeh it should still be an option in case someone does want to use it. I'm thinking to implement it like this:

| type  | imdbId    | seen | seenDate             | list      |
| movie | tt8765432 | N    |                      | Watchlist |  <-- does NOT mark as Seen, but adds to Watchlist
| movie | tt2222333 |      | 2024-12-02           | Movies    |  <-- does NOT mark as Seen, but will add to Movies list
| movie | tt1234567 | Y    |                      |           |  <-- marks as Seen (no date specified)
| movie | tt0000111 | Y    |                      | Movies    |  <-- marks as Seen (no date specified), and adds to Movies list
| movie | tt1234567 | Y    | 2024-12-01           |           |  <-- marks as Seen (date = 1st Dec 2024 @ 00:00:00 in local TZ)
| movie | tt1234567 | Y    | 2024-12-19T10:18:00  |           |  <-- marks as Seen (date = 19th Dec 2024 @ 10:18AM in local TZ)
| movie | tt1234567 | Y    | 2024-12-19T10:18:00Z |           |  <-- marks as Seen (date = 19th Dec 2024 @ 10:18AM UTC)

So movie tt1234567 would end up with three Seen entries, but all would have a different date/time (unless the user happens to live in GMT+0).

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