private async Task <string> GetPlayoutItemPath(PlayoutItem playoutItem)
    {
        MediaVersion version = playoutItem.MediaItem.GetHeadVersion();

        MediaFile file = version.MediaFiles.Head();
        string    path = file.Path;

        return(playoutItem.MediaItem switch
        {
            PlexMovie plexMovie => await _plexPathReplacementService.GetReplacementPlexPath(
                plexMovie.LibraryPathId,
                path),
            PlexEpisode plexEpisode => await _plexPathReplacementService.GetReplacementPlexPath(
                plexEpisode.LibraryPathId,
                path),
            JellyfinMovie jellyfinMovie => await _jellyfinPathReplacementService.GetReplacementJellyfinPath(
                jellyfinMovie.LibraryPathId,
                path),
            JellyfinEpisode jellyfinEpisode => await _jellyfinPathReplacementService.GetReplacementJellyfinPath(
                jellyfinEpisode.LibraryPathId,
                path),
            EmbyMovie embyMovie => await _embyPathReplacementService.GetReplacementEmbyPath(
                embyMovie.LibraryPathId,
                path),
            EmbyEpisode embyEpisode => await _embyPathReplacementService.GetReplacementEmbyPath(
                embyEpisode.LibraryPathId,
                path),
            _ => path
        });
Пример #2
0
    public async Task <Either <BaseError, Unit> > ScanLibrary(
        string address,
        string apiKey,
        EmbyLibrary library,
        string ffmpegPath,
        string ffprobePath,
        CancellationToken cancellationToken)
    {
        List <EmbyPathReplacement> pathReplacements =
            await _mediaSourceRepository.GetEmbyPathReplacements(library.MediaSourceId);

        string GetLocalPath(EmbyMovie movie)
        {
            return(_pathReplacementService.GetReplacementEmbyPath(
                       pathReplacements,
                       movie.GetHeadVersion().MediaFiles.Head().Path,
                       false));
        }

        return(await ScanLibrary(
                   _embyMovieRepository,
                   new EmbyConnectionParameters(address, apiKey),
                   library,
                   GetLocalPath,
                   ffmpegPath,
                   ffprobePath,
                   false,
                   cancellationToken));
    }
Пример #3
0
    private async Task <Either <BaseError, Unit> > ProcessSeasons(
        string address,
        string apiKey,
        EmbyLibrary library,
        string ffmpegPath,
        string ffprobePath,
        List <EmbyPathReplacement> pathReplacements,
        EmbyShow show,
        List <EmbyItemEtag> existingSeasons,
        List <EmbySeason> seasons,
        CancellationToken cancellationToken)
    {
        foreach (EmbySeason incoming in seasons)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(new ScanCanceled());
            }

            Option <EmbyItemEtag> maybeExisting = existingSeasons.Find(ie => ie.ItemId == incoming.ItemId);
            if (maybeExisting.IsNone)
            {
                incoming.LibraryPathId = library.Paths.Head().Id;

                _logger.LogDebug(
                    "INSERT: Item id is new for show {Show} season {Season}",
                    show.ShowMetadata.Head().Title,
                    incoming.SeasonMetadata.Head().Title);

                if (await _televisionRepository.AddSeason(show, incoming))
                {
                    incoming.Show = show;
                    await _searchIndex.AddItems(_searchRepository, new List <MediaItem> {
                        incoming
                    });
                }
            }

            foreach (EmbyItemEtag existing in maybeExisting)
            {
                if (existing.Etag != incoming.Etag)
                {
                    _logger.LogDebug(
                        "UPDATE: Etag has changed for show {Show} season {Season}",
                        show.ShowMetadata.Head().Title,
                        incoming.SeasonMetadata.Head().Title);

                    incoming.ShowId        = show.Id;
                    incoming.LibraryPathId = library.Paths.Head().Id;

                    foreach (EmbySeason updated in await _televisionRepository.Update(incoming))
                    {
                        incoming.Show = show;

                        foreach (MediaItem toIndex in await _searchRepository.GetItemToIndex(updated.Id))
                        {
                            await _searchIndex.UpdateItems(_searchRepository, new List <MediaItem> {
                                toIndex
                            });
                        }
                    }
                }
            }

            List <EmbyItemEtag> existingEpisodes =
                await _televisionRepository.GetExistingEpisodes(library, incoming.ItemId);

            Either <BaseError, List <EmbyEpisode> > maybeEpisodes =
                await _embyApiClient.GetEpisodeLibraryItems(address, apiKey, incoming.ItemId);

            foreach (BaseError error in maybeEpisodes.LeftToSeq())
            {
                _logger.LogWarning(
                    "Error synchronizing emby library {Path}: {Error}",
                    library.Name,
                    error.Value);
            }

            foreach (List <EmbyEpisode> episodes in maybeEpisodes.RightToSeq())
            {
                var validEpisodes = new List <EmbyEpisode>();
                foreach (EmbyEpisode episode in episodes)
                {
                    string localPath = _pathReplacementService.GetReplacementEmbyPath(
                        pathReplacements,
                        episode.MediaVersions.Head().MediaFiles.Head().Path,
                        false);

                    if (!_localFileSystem.FileExists(localPath))
                    {
                        _logger.LogWarning(
                            "Skipping emby episode that does not exist at {Path}",
                            localPath);
                    }
                    else
                    {
                        validEpisodes.Add(episode);
                    }
                }

                Either <BaseError, Unit> scanResult = await ProcessEpisodes(
                    show.ShowMetadata.Head().Title,
                    incoming.SeasonMetadata.Head().Title,
                    library,
                    ffmpegPath,
                    ffprobePath,
                    pathReplacements,
                    incoming,
                    existingEpisodes,
                    validEpisodes,
                    cancellationToken);

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

                foreach (Unit _ in scanResult.RightToSeq())
                {
                    var incomingEpisodeIds = episodes.Map(s => s.ItemId).ToList();
                    var episodeIds         = existingEpisodes
                                             .Filter(i => !incomingEpisodeIds.Contains(i.ItemId))
                                             .Map(m => m.ItemId)
                                             .ToList();
                    List <int> missingEpisodeIds =
                        await _televisionRepository.RemoveMissingEpisodes(library, episodeIds);

                    await _searchIndex.RemoveItems(missingEpisodeIds);

                    _searchIndex.Commit();
                }
            }
        }

        return(Unit.Default);
    }