Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wip: CSV import #650

Open
wants to merge 4 commits into
base: wip
Choose a base branch
from
Open

Wip: CSV import #650

wants to merge 4 commits into from

Conversation

ramebd
Copy link

@ramebd ramebd commented Dec 10, 2024

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 on lines +21 to +25
.filter(item =>
(Object.values(mediaTypeSchema.Values).includes(item.type)) // sanity check
&& ((item.type === 'tv' && (item.tmdbid || item.imdbid || item.tvdbid))
||(item.type === 'movie' && (item.tmdbid || item.imdbid)))
);
Copy link
Owner

Choose a reason for hiding this comment

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

Soft failing, without any output for the user is not ideal. Entries, that cannot be identified (due to the lack of external id) are listed at the end of the import progess

imdbId: item.imdbid ? item.imdbid : undefined,
tvdbId: item.tvdbid ? item.tvdbid : undefined,
rating: item.rating,
ratedAt: dateNow,
Copy link
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

tmdbId: item.tmdbid ? item.tmdbid : undefined,
imdbId: item.imdbid ? item.imdbid : undefined,
tvdbId: item.tvdbid ? item.tvdbid : undefined,
seenAt: dateNow,
Copy link
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

.map((list) => (<ImportListItem>{
name: list.name,
description: list.description,
traktId: list.traktId,
Copy link
Owner

Choose a reason for hiding this comment

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

this is only used for Trakt import

Comment on lines +28 to +34
const userLists = await listRepository.getLists({userId: user});
const watchListId = userLists.find(userList => userList.isWatchlist)?.id;

const importLists = _(data)
.map((item) => item.listid)
.uniq()
.value();
Copy link
Owner

Choose a reason for hiding this comment

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

Use list names instead

.filter((item) => item.rating && item.rating > 0)
.map((item) => (<ImportRatingItem>{
itemType: item.type,
tmdbId: item.tmdbid ? item.tmdbid : undefined,
Copy link
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.

tvdbId: item.tvdbid ? item.tvdbid : undefined,
seenAt: dateNow,
episode: item.type === 'tv' ? {
seasonNumber: item.season ? item.season : undefined,
Copy link
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

name: list.name,
description: list.description,
traktId: list.traktId,
createdAt: dateNow,
Copy link
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
Copy link
Owner

bonukai commented Dec 21, 2024

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

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