< Summary - Jellyfin

Information
Class: MediaBrowser.Providers.Plugins.StudioImages.StudiosImageProvider
Assembly: MediaBrowser.Providers
File(s): /srv/git/jellyfin/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs
Line coverage
15%
Covered lines: 5
Uncovered lines: 27
Coverable lines: 32
Total lines: 192
Line coverage: 15.6%
Branch coverage
0%
Covered branches: 0
Total branches: 2
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Name()100%210%
Supports(...)100%11100%
GetSupportedImages(...)100%210%
GetImage(...)0%620%
GetUrl(...)100%210%
EnsureThumbsList(...)100%210%
GetImageResponse(...)100%210%
FindMatch(...)100%210%
GetComparableName(...)100%210%
GetRepositoryUrl()100%210%

File(s)

/srv/git/jellyfin/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs

#LineLine coverage
 1#nullable disable
 2
 3using System;
 4using System.Collections.Generic;
 5using System.Globalization;
 6using System.IO;
 7using System.Linq;
 8using System.Net.Http;
 9using System.Threading;
 10using System.Threading.Tasks;
 11using Jellyfin.Extensions;
 12using MediaBrowser.Common.Net;
 13using MediaBrowser.Controller.Configuration;
 14using MediaBrowser.Controller.Entities;
 15using MediaBrowser.Controller.Providers;
 16using MediaBrowser.Model.Entities;
 17using MediaBrowser.Model.IO;
 18using MediaBrowser.Model.Providers;
 19
 20namespace MediaBrowser.Providers.Plugins.StudioImages
 21{
 22    /// <summary>
 23    /// Studio image provider.
 24    /// </summary>
 25    public class StudiosImageProvider : IRemoteImageProvider
 26    {
 27        private readonly IServerConfigurationManager _config;
 28        private readonly IHttpClientFactory _httpClientFactory;
 29        private readonly IFileSystem _fileSystem;
 30
 31        /// <summary>
 32        /// Initializes a new instance of the <see cref="StudiosImageProvider"/> class.
 33        /// </summary>
 34        /// <param name="config">The <see cref="IServerConfigurationManager"/>.</param>
 35        /// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/>.</param>
 36        /// <param name="fileSystem">The <see cref="IFileSystem"/>.</param>
 37        public StudiosImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory, IFileSyste
 38        {
 2239            _config = config;
 2240            _httpClientFactory = httpClientFactory;
 2241            _fileSystem = fileSystem;
 2242        }
 43
 44        /// <inheritdoc />
 045        public string Name => "Artwork Repository";
 46
 47        /// <inheritdoc />
 48        public bool Supports(BaseItem item)
 49        {
 4650            return item is Studio;
 51        }
 52
 53        /// <inheritdoc />
 54        public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
 55        {
 056            return [ImageType.Thumb];
 57        }
 58
 59        /// <inheritdoc />
 60        public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
 61        {
 62            var thumbsPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotestudiothumbs.txt");
 63
 64            await EnsureThumbsList(thumbsPath, cancellationToken).ConfigureAwait(false);
 65
 66            cancellationToken.ThrowIfCancellationRequested();
 67
 68            var imageInfo = GetImage(item, thumbsPath, ImageType.Thumb, "thumb");
 69
 70            if (imageInfo is null)
 71            {
 72                return [];
 73            }
 74
 75            return [imageInfo];
 76        }
 77
 78        private RemoteImageInfo GetImage(BaseItem item, string filename, ImageType type, string remoteFilename)
 79        {
 080            var list = GetAvailableImages(filename);
 81
 082            var match = FindMatch(item, list);
 83
 084            if (!string.IsNullOrEmpty(match))
 85            {
 086                var url = GetUrl(match, remoteFilename);
 87
 088                return new RemoteImageInfo
 089                {
 090                    ProviderName = Name,
 091                    Type = type,
 092                    Url = url
 093                };
 94            }
 95
 096            return null;
 97        }
 98
 99        private string GetUrl(string image, string filename)
 100        {
 0101            return string.Format(CultureInfo.InvariantCulture, "{0}/images/{1}/{2}.jpg", GetRepositoryUrl(), image, file
 102        }
 103
 104        private Task EnsureThumbsList(string file, CancellationToken cancellationToken)
 105        {
 0106            string url = string.Format(CultureInfo.InvariantCulture, "{0}/thumbs.txt", GetRepositoryUrl());
 107
 0108            return EnsureList(url, file, _fileSystem, cancellationToken);
 109        }
 110
 111        /// <inheritdoc />
 112        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
 113        {
 0114            var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
 0115            return httpClient.GetAsync(url, cancellationToken);
 116        }
 117
 118        /// <summary>
 119        /// Ensures the existence of a file listing.
 120        /// </summary>
 121        /// <param name="url">The URL.</param>
 122        /// <param name="file">The file.</param>
 123        /// <param name="fileSystem">The file system.</param>
 124        /// <param name="cancellationToken">The cancellation token.</param>
 125        /// <returns>A Task to ensure existence of a file listing.</returns>
 126        public async Task EnsureList(string url, string file, IFileSystem fileSystem, CancellationToken cancellationToke
 127        {
 128            var fileInfo = fileSystem.GetFileInfo(file);
 129
 130            if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1)
 131            {
 132                var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
 133
 134                Directory.CreateDirectory(Path.GetDirectoryName(file));
 135                var response = await httpClient.GetStreamAsync(url, cancellationToken).ConfigureAwait(false);
 136                await using (response.ConfigureAwait(false))
 137                {
 138                    var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.
 139                    await using (fileStream.ConfigureAwait(false))
 140                    {
 141                        await response.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
 142                    }
 143                }
 144            }
 145        }
 146
 147        /// <summary>
 148        /// Get matching image for an item.
 149        /// </summary>
 150        /// <param name="item">The <see cref="BaseItem"/>.</param>
 151        /// <param name="images">The enumerable of image strings.</param>
 152        /// <returns>The matching image string.</returns>
 153        public string FindMatch(BaseItem item, IEnumerable<string> images)
 154        {
 0155            var name = GetComparableName(item.Name);
 156
 0157            return images.FirstOrDefault(i => string.Equals(name, GetComparableName(i), StringComparison.OrdinalIgnoreCa
 158        }
 159
 160        private string GetComparableName(string name)
 161        {
 0162            return name.Replace(" ", string.Empty, StringComparison.Ordinal)
 0163                .Replace(".", string.Empty, StringComparison.Ordinal)
 0164                .Replace("&", string.Empty, StringComparison.Ordinal)
 0165                .Replace("!", string.Empty, StringComparison.Ordinal)
 0166                .Replace(",", string.Empty, StringComparison.Ordinal)
 0167                .Replace("/", string.Empty, StringComparison.Ordinal);
 168        }
 169
 170        /// <summary>
 171        /// Get available image strings for a file.
 172        /// </summary>
 173        /// <param name="file">The file.</param>
 174        /// <returns>All images strings of a file.</returns>
 175        public IEnumerable<string> GetAvailableImages(string file)
 176        {
 177            using var fileStream = File.OpenRead(file);
 178            using var reader = new StreamReader(fileStream);
 179
 180            foreach (var line in reader.ReadAllLines())
 181            {
 182                if (!string.IsNullOrWhiteSpace(line))
 183                {
 184                    yield return line;
 185                }
 186            }
 187        }
 188
 189        private string GetRepositoryUrl()
 0190            => Plugin.Instance.Configuration.RepositoryUrl;
 191    }
 192}