コード例 #1
0
    private static string Artwork(
        Metadata metadata,
        ArtworkKind artworkKind,
        Option <JellyfinMediaSource> maybeJellyfin,
        Option <EmbyMediaSource> maybeEmby)
    {
        string artwork = Optional(metadata.Artwork.FirstOrDefault(a => a.ArtworkKind == artworkKind))
                         .Match(a => a.Path, string.Empty);

        if (maybeJellyfin.IsSome && artwork.StartsWith("jellyfin://"))
        {
            Url url = JellyfinUrl.RelativeProxyForArtwork(artwork);
            if (artworkKind is ArtworkKind.Poster or ArtworkKind.Thumbnail)
            {
                url.SetQueryParam("fillHeight", 440);
            }

            artwork = url;
        }
        else if (maybeEmby.IsSome && artwork.StartsWith("emby://"))
        {
            Url url = EmbyUrl.RelativeProxyForArtwork(artwork);
            if (artworkKind is ArtworkKind.Poster or ArtworkKind.Thumbnail)
            {
                url.SetQueryParam("maxHeight", 440);
            }

            artwork = url;
        }

        return(artwork);
    }
コード例 #2
0
    private string GetArtworkUrl(Artwork artwork, ArtworkKind artworkKind)
    {
        string artworkPath = artwork.Path;

        int height = artworkKind switch
        {
            ArtworkKind.Thumbnail => 220,
            _ => 440
        };

        if (artworkPath.StartsWith("jellyfin://"))
        {
            artworkPath = JellyfinUrl.ProxyForArtwork(_scheme, _host, artworkPath, artworkKind)
                          .SetQueryParam("fillHeight", height);
        }
        else if (artworkPath.StartsWith("emby://"))
        {
            artworkPath = EmbyUrl.ProxyForArtwork(_scheme, _host, artworkPath, artworkKind)
                          .SetQueryParam("maxHeight", height);
        }
        else
        {
            string artworkFolder = artworkKind switch
            {
                ArtworkKind.Thumbnail => "thumbnails",
                _ => "posters"
            };

            artworkPath = $"{_scheme}://{_host}/iptv/artwork/{artworkFolder}/{artwork.Path}.jpg";
        }

        return(artworkPath);
    }
コード例 #3
0
        private Option <string> LocateArtwork(Movie movie, ArtworkKind artworkKind)
        {
            string segment = artworkKind switch
            {
                ArtworkKind.Poster => "poster",
                ArtworkKind.FanArt => "fanart",
                _ => throw new ArgumentOutOfRangeException(nameof(artworkKind))
            };

            string path   = movie.MediaVersions.Head().MediaFiles.Head().Path;
            string folder = Path.GetDirectoryName(path) ?? string.Empty;
            IEnumerable <string> possibleMoviePosters = ImageFileExtensions.Collect(
                ext => new[] { $"{segment}.{ext}", Path.GetFileNameWithoutExtension(path) + $"-{segment}.{ext}" })
                                                        .Map(f => Path.Combine(folder, f));
            Option <string> result = possibleMoviePosters.Filter(p => _localFileSystem.FileExists(p)).HeadOrNone();

            if (result.IsNone && artworkKind == ArtworkKind.Poster)
            {
                IEnumerable <string> possibleFolderPosters = ImageFileExtensions.Collect(
                    ext => new[] { $"folder.{ext}" })
                                                             .Map(f => Path.Combine(folder, f));
                result = possibleFolderPosters.Filter(p => _localFileSystem.FileExists(p)).HeadOrNone();
            }

            return(result);
        }
    }
コード例 #4
0
    private Option <string> LocateArtworkForArtist(string artistFolder, ArtworkKind artworkKind)
    {
        string segment = artworkKind switch
        {
            ArtworkKind.Thumbnail => "thumb",
            ArtworkKind.FanArt => "fanart",
            _ => throw new ArgumentOutOfRangeException(nameof(artworkKind))
        };

        return(ImageFileExtensions
               .Map(ext => $"{segment}.{ext}")
               .Map(f => Path.Combine(artistFolder, f))
               .Filter(s => _localFileSystem.FileExists(s))
               .HeadOrNone());
    }
コード例 #5
0
        private Option <string> LocateArtworkForShow(string showFolder, ArtworkKind artworkKind)
        {
            string[] segments = artworkKind switch
            {
                ArtworkKind.Poster => new[] { "poster", "folder" },
                ArtworkKind.FanArt => new[] { "fanart" },
                _ => throw new ArgumentOutOfRangeException(nameof(artworkKind))
            };

            return(ImageFileExtensions
                   .Map(ext => segments.Map(segment => $"{segment}.{ext}"))
                   .Flatten()
                   .Map(f => Path.Combine(showFolder, f))
                   .Filter(s => _localFileSystem.FileExists(s))
                   .HeadOrNone());
        }
コード例 #6
0
    protected async Task <bool> UpdateArtworkIfNeeded(
        Domain.Metadata existingMetadata,
        Domain.Metadata incomingMetadata,
        ArtworkKind artworkKind)
    {
        if (incomingMetadata.DateUpdated > existingMetadata.DateUpdated)
        {
            Option <Artwork> maybeIncomingArtwork = Optional(incomingMetadata.Artwork).Flatten()
                                                    .Find(a => a.ArtworkKind == artworkKind);

            if (maybeIncomingArtwork.IsNone)
            {
                existingMetadata.Artwork ??= new List <Artwork>();
                existingMetadata.Artwork.RemoveAll(a => a.ArtworkKind == artworkKind);
                await _metadataRepository.RemoveArtwork(existingMetadata, artworkKind);
            }

            foreach (Artwork incomingArtwork in maybeIncomingArtwork)
            {
                _logger.LogDebug("Refreshing Plex {Attribute} from {Path}", artworkKind, incomingArtwork.Path);

                Option <Artwork> maybeExistingArtwork = Optional(existingMetadata.Artwork).Flatten()
                                                        .Find(a => a.ArtworkKind == artworkKind);

                if (maybeExistingArtwork.IsNone)
                {
                    existingMetadata.Artwork ??= new List <Artwork>();
                    existingMetadata.Artwork.Add(incomingArtwork);
                    await _metadataRepository.AddArtwork(existingMetadata, incomingArtwork);
                }

                foreach (Artwork existingArtwork in maybeExistingArtwork)
                {
                    existingArtwork.Path        = incomingArtwork.Path;
                    existingArtwork.DateUpdated = incomingArtwork.DateUpdated;
                    await _metadataRepository.UpdateArtworkPath(existingArtwork);
                }
            }

            return(true);
        }

        return(false);
    }
コード例 #7
0
    public static Url ProxyForArtwork(string scheme, string host, string artwork, ArtworkKind artworkKind)
    {
        string[] split = artwork.Replace("jellyfin://", string.Empty).Split('?');
        if (split.Length != 2)
        {
            return(artwork);
        }

        string pathSegment         = split[0];
        QueryParamCollection query = Url.ParseQueryParams(split[1]);

        string artworkFolder = artworkKind switch
        {
            ArtworkKind.Thumbnail => "thumbnails",
            _ => "posters"
        };

        return(Url.Parse($"{scheme}://{host}/iptv/artwork/{artworkFolder}/jellyfin")
               .AppendPathSegment(pathSegment)
               .SetQueryParams(query));
    }
コード例 #8
0
        private async Task <Either <BaseError, MediaItemScanResult <Movie> > > UpdateArtwork(
            MediaItemScanResult <Movie> result,
            ArtworkKind artworkKind)
        {
            try
            {
                Movie movie = result.Item;
                await LocateArtwork(movie, artworkKind).IfSomeAsync(
                    async posterFile =>
                {
                    MovieMetadata metadata = movie.MovieMetadata.Head();
                    await RefreshArtwork(posterFile, metadata, artworkKind);
                });

                return(result);
            }
            catch (Exception ex)
            {
                return(BaseError.New(ex.ToString()));
            }
        }
コード例 #9
0
        private async Task <Either <BaseError, MediaItemScanResult <Show> > > UpdateArtworkForShow(
            MediaItemScanResult <Show> result,
            string showFolder,
            ArtworkKind artworkKind)
        {
            try
            {
                Show show = result.Item;
                await LocateArtworkForShow(showFolder, artworkKind).IfSomeAsync(
                    async posterFile =>
                {
                    ShowMetadata metadata = show.ShowMetadata.Head();
                    await RefreshArtwork(posterFile, metadata, artworkKind);
                });

                return(result);
            }
            catch (Exception ex)
            {
                return(BaseError.New(ex.ToString()));
            }
        }
コード例 #10
0
    private async Task <Either <BaseError, MediaItemScanResult <Movie> > > UpdateArtwork(
        MediaItemScanResult <Movie> result,
        ArtworkKind artworkKind,
        CancellationToken cancellationToken)
    {
        try
        {
            Movie           movie        = result.Item;
            Option <string> maybeArtwork = LocateArtwork(movie, artworkKind);
            foreach (string posterFile in maybeArtwork)
            {
                MovieMetadata metadata = movie.MovieMetadata.Head();
                await RefreshArtwork(posterFile, metadata, artworkKind, None, None, cancellationToken);
            }

            return(result);
        }
        catch (Exception ex)
        {
            _client.Notify(ex);
            return(BaseError.New(ex.ToString()));
        }
    }
コード例 #11
0
    private async Task <Either <BaseError, MediaItemScanResult <Show> > > UpdateArtworkForShow(
        MediaItemScanResult <Show> result,
        string showFolder,
        ArtworkKind artworkKind,
        CancellationToken cancellationToken)
    {
        try
        {
            Show            show         = result.Item;
            Option <string> maybeArtwork = LocateArtworkForShow(showFolder, artworkKind);
            foreach (string artworkFile in maybeArtwork)
            {
                ShowMetadata metadata = show.ShowMetadata.Head();
                await RefreshArtwork(artworkFile, metadata, artworkKind, None, None, cancellationToken);
            }

            return(result);
        }
        catch (Exception ex)
        {
            _client.Notify(ex);
            return(BaseError.New(ex.ToString()));
        }
    }
コード例 #12
0
    private async Task <Either <BaseError, MediaItemScanResult <Artist> > > UpdateArtworkForArtist(
        MediaItemScanResult <Artist> result,
        string artistFolder,
        ArtworkKind artworkKind,
        CancellationToken cancellationToken)
    {
        try
        {
            Artist artist = result.Item;
            await LocateArtworkForArtist(artistFolder, artworkKind).IfSomeAsync(
                async artworkFile =>
            {
                ArtistMetadata metadata = artist.ArtistMetadata.Head();
                await RefreshArtwork(artworkFile, metadata, artworkKind, None, None, cancellationToken);
            });

            return(result);
        }
        catch (Exception ex)
        {
            _client.Notify(ex);
            return(BaseError.New(ex.ToString()));
        }
    }
コード例 #13
0
 private static string Artwork(Metadata metadata, ArtworkKind artworkKind) =>
 Optional(metadata.Artwork.FirstOrDefault(a => a.ArtworkKind == artworkKind))
 .Match(a => a.Path, string.Empty);