Example #1
0
    private async Task <Either <BaseError, Unit> > ScanLibrary(
        PlexConnection connection,
        PlexServerAuthToken token,
        PlexLibrary library,
        string ffmpegPath,
        string ffprobePath,
        bool deepScan,
        List <PlexShow> showEntries,
        CancellationToken cancellationToken)
    {
        List <PlexItemEtag> existingShows = await _plexTelevisionRepository.GetExistingPlexShows(library);

        List <PlexPathReplacement> pathReplacements = await _mediaSourceRepository
                                                      .GetPlexPathReplacements(library.MediaSourceId);

        foreach (PlexShow incoming in showEntries)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(new ScanCanceled());
            }

            decimal percentCompletion = (decimal)showEntries.IndexOf(incoming) / showEntries.Count;
            await _mediator.Publish(new LibraryScanProgress(library.Id, percentCompletion), cancellationToken);

            // TODO: figure out how to rebuild playlists
            Either <BaseError, MediaItemScanResult <PlexShow> > maybeShow = await _televisionRepository
                                                                            .GetOrAddPlexShow(library, incoming)
                                                                            .BindT(existing => UpdateMetadata(existing, incoming, library, connection, token, deepScan))
                                                                            .BindT(existing => UpdateArtwork(existing, incoming));

            if (maybeShow.IsLeft)
            {
                foreach (BaseError error in maybeShow.LeftToSeq())
                {
                    _logger.LogWarning(
                        "Error processing plex show at {Key}: {Error}",
                        incoming.Key,
                        error.Value);
                }

                continue;
            }

            foreach (MediaItemScanResult <PlexShow> result in maybeShow.RightToSeq())
            {
                Either <BaseError, Unit> scanResult = await ScanSeasons(
                    library,
                    pathReplacements,
                    result.Item,
                    connection,
                    token,
                    ffmpegPath,
                    ffprobePath,
                    deepScan,
                    cancellationToken);

                foreach (ScanCanceled error in scanResult.LeftToSeq().OfType <ScanCanceled>())
                {
                    return(error);
                }

                await _plexTelevisionRepository.SetPlexEtag(result.Item, incoming.Etag);

                // TODO: if any seasons are unavailable or not found, flag show as unavailable/not found

                if (result.IsAdded)
                {
                    await _searchIndex.AddItems(_searchRepository, new List <MediaItem> {
                        result.Item
                    });
                }
                else if (result.IsUpdated)
                {
                    await _searchIndex.UpdateItems(
                        _searchRepository,
                        new List <MediaItem> {
                        result.Item
                    });
                }
            }
        }

        // trash items that are no longer present on the media server
        var        fileNotFoundKeys = existingShows.Map(m => m.Key).Except(showEntries.Map(m => m.Key)).ToList();
        List <int> ids = await _plexTelevisionRepository.FlagFileNotFoundShows(library, fileNotFoundKeys);

        await _searchIndex.RebuildItems(_searchRepository, ids);

        await _mediator.Publish(new LibraryScanProgress(library.Id, 0), cancellationToken);

        return(Unit.Default);
    }
Example #2
0
        public async Task <Either <BaseError, Unit> > ScanLibrary(
            PlexConnection connection,
            PlexServerAuthToken token,
            PlexLibrary plexMediaSourceLibrary)
        {
            Either <BaseError, List <PlexShow> > entries = await _plexServerApiClient.GetShowLibraryContents(
                plexMediaSourceLibrary,
                connection,
                token);

            return(await entries.Match <Task <Either <BaseError, Unit> > >(
                       async showEntries =>
            {
                foreach (PlexShow incoming in showEntries)
                {
                    // TODO: figure out how to rebuild playlists
                    Either <BaseError, MediaItemScanResult <PlexShow> > maybeShow = await _televisionRepository
                                                                                    .GetOrAddPlexShow(plexMediaSourceLibrary, incoming)
                                                                                    .BindT(existing => UpdateMetadata(existing, incoming))
                                                                                    .BindT(existing => UpdateArtwork(existing, incoming));

                    await maybeShow.Match(
                        async result =>
                    {
                        if (result.IsAdded)
                        {
                            await _searchIndex.AddItems(new List <MediaItem> {
                                result.Item
                            });
                        }
                        else if (result.IsUpdated)
                        {
                            await _searchIndex.UpdateItems(new List <MediaItem> {
                                result.Item
                            });
                        }

                        await ScanSeasons(plexMediaSourceLibrary, result.Item, connection, token);
                    },
                        error =>
                    {
                        _logger.LogWarning(
                            "Error processing plex show at {Key}: {Error}",
                            incoming.Key,
                            error.Value);
                        return Task.CompletedTask;
                    });
                }

                var showKeys = showEntries.Map(s => s.Key).ToList();
                List <int> ids =
                    await _televisionRepository.RemoveMissingPlexShows(plexMediaSourceLibrary, showKeys);
                await _searchIndex.RemoveItems(ids);

                return Unit.Default;
            },
                       error =>
            {
                _logger.LogWarning(
                    "Error synchronizing plex library {Path}: {Error}",
                    plexMediaSourceLibrary.Name,
                    error.Value);

                return Left <BaseError, Unit>(error).AsTask();
            }));
        }