private void PopulateImages(List <RemoteImageInfo> list, List <Image> images, ImageType type, int width, int height) { if (images == null) { return; } list.AddRange(images.Select(i => { var url = i.url; if (!string.IsNullOrEmpty(url)) { var likesString = i.likes; var info = new RemoteImageInfo { RatingType = RatingType.Likes, Type = type, Width = width, Height = height, ProviderName = Name, Url = url, Language = i.lang }; if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Integer, CultureInfo.InvariantCulture, out var likes)) { info.CommunityRating = likes; } return(info); } return(null); }).Where(i => i != null)); }
private void PopulateImages(List <RemoteImageInfo> list, List <Image> images, ImageType type, int width, int height) { if (images == null) { return; } list.AddRange(images.Select(i => { var url = i.url; if (!string.IsNullOrEmpty(url)) { var likesString = i.likes; int likes; var info = new RemoteImageInfo { RatingType = RatingType.Likes, Type = type, Width = width, Height = height, ProviderName = Name, Url = url.Replace("http://", "https://", StringComparison.OrdinalIgnoreCase), Language = i.lang }; if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes)) { info.CommunityRating = likes; } return(info); } return(null); }).Where(i => i != null)); }
/// <summary> /// Adds the image. /// </summary> /// <param name="list">The list.</param> /// <param name="reader">The reader.</param> /// <param name="type">The type.</param> /// <param name="width">The width.</param> /// <param name="height">The height.</param> private void AddImage(List <RemoteImageInfo> list, XmlReader reader, ImageType type, int width, int height) { var url = reader.GetAttribute("url"); var size = reader.GetAttribute("size"); if (!String.IsNullOrEmpty(size)) { int sizeNum; if (Int32.TryParse(size, NumberStyles.Any, _usCulture, out sizeNum)) { width = sizeNum; height = sizeNum; } } var likesString = reader.GetAttribute("likes"); int likes; var info = new RemoteImageInfo { RatingType = RatingType.Likes, Type = type, Width = width, Height = height, ProviderName = Name, Url = url, Language = reader.GetAttribute("lang") }; if (!String.IsNullOrEmpty(likesString) && Int32.TryParse(likesString, NumberStyles.Any, _usCulture, out likes)) { info.CommunityRating = likes; } list.Add(info); }
private void AddImage(XmlReader reader, List <RemoteImageInfo> images) { reader.MoveToContent(); string bannerType = null; string url = null; int? bannerSeason = null; int? width = null; int? height = null; string language = null; double?rating = null; int? voteCount = null; string thumbnailUrl = null; while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case "Rating": { var val = reader.ReadElementContentAsString() ?? string.Empty; double rval; if (double.TryParse(val, NumberStyles.Any, _usCulture, out rval)) { rating = rval; } break; } case "RatingCount": { var val = reader.ReadElementContentAsString() ?? string.Empty; int rval; if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval)) { voteCount = rval; } break; } case "Language": { language = reader.ReadElementContentAsString() ?? string.Empty; break; } case "ThumbnailPath": { thumbnailUrl = reader.ReadElementContentAsString() ?? string.Empty; break; } case "BannerType": { bannerType = reader.ReadElementContentAsString() ?? string.Empty; break; } case "BannerPath": { url = reader.ReadElementContentAsString() ?? string.Empty; break; } case "BannerType2": { var bannerType2 = reader.ReadElementContentAsString() ?? string.Empty; // Sometimes the resolution is stuffed in here var resolutionParts = bannerType2.Split('x'); if (resolutionParts.Length == 2) { int rval; if (int.TryParse(resolutionParts[0], NumberStyles.Integer, _usCulture, out rval)) { width = rval; } if (int.TryParse(resolutionParts[1], NumberStyles.Integer, _usCulture, out rval)) { height = rval; } } break; } case "Season": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { bannerSeason = int.Parse(val); } break; } default: reader.Skip(); break; } } } if (!string.IsNullOrEmpty(url) && !bannerSeason.HasValue) { var imageInfo = new RemoteImageInfo { RatingType = RatingType.Score, CommunityRating = rating, VoteCount = voteCount, Url = TVUtils.BannerUrl + url, ProviderName = Name, Language = language, Width = width, Height = height }; if (!string.IsNullOrEmpty(thumbnailUrl)) { imageInfo.ThumbnailUrl = TVUtils.BannerUrl + thumbnailUrl; } if (string.Equals(bannerType, "poster", StringComparison.OrdinalIgnoreCase)) { imageInfo.Type = ImageType.Primary; images.Add(imageInfo); } else if (string.Equals(bannerType, "series", StringComparison.OrdinalIgnoreCase)) { imageInfo.Type = ImageType.Banner; images.Add(imageInfo); } else if (string.Equals(bannerType, "fanart", StringComparison.OrdinalIgnoreCase)) { imageInfo.Type = ImageType.Backdrop; images.Add(imageInfo); } } }
[InlineData(ImageType.Backdrop, 1, true)] // populated item, forced to download public async void RefreshImages_NonStubItemPopulatedProviderRemote_DownloadsIfNecessary(ImageType imageType, int initialImageCount, bool fullRefresh) { var targetImageCount = 1; // Set path and media source manager so images will be downloaded (EnableImageStub will return false) var item = GetItemWithImages(imageType, initialImageCount, false); item.Path = "non-empty path"; BaseItem.MediaSourceManager = Mock.Of <IMediaSourceManager>(); // seek 2 so it won't short-circuit out of downloading when populated var libraryOptions = GetLibraryOptions(item, imageType, 2); const string Content = "Content"; var remoteProvider = new Mock <IRemoteImageProvider>(MockBehavior.Strict); remoteProvider.Setup(rp => rp.Name).Returns("MockRemoteProvider"); remoteProvider.Setup(rp => rp.GetSupportedImages(item)) .Returns(new[] { imageType }); remoteProvider.Setup(rp => rp.GetImageResponse(It.IsAny <string>(), It.IsAny <CancellationToken>())) .ReturnsAsync((string url, CancellationToken _) => new HttpResponseMessage { ReasonPhrase = url, StatusCode = HttpStatusCode.OK, Content = new StringContent(Content, Encoding.UTF8, "image/jpeg") }); var refreshOptions = fullRefresh ? new ImageRefreshOptions(Mock.Of <IDirectoryService>()) { ImageRefreshMode = MetadataRefreshMode.FullRefresh, ReplaceAllImages = true } : new ImageRefreshOptions(Mock.Of <IDirectoryService>()); var remoteInfo = new RemoteImageInfo[targetImageCount]; for (int i = 0; i < targetImageCount; i++) { remoteInfo[i] = new RemoteImageInfo { Type = imageType, Url = "image url " + i }; } var providerManager = new Mock <IProviderManager>(MockBehavior.Strict); providerManager.Setup(pm => pm.GetAvailableRemoteImages(It.IsAny <BaseItem>(), It.IsAny <RemoteImageQuery>(), It.IsAny <CancellationToken>())) .ReturnsAsync(remoteInfo); providerManager.Setup(pm => pm.SaveImage(item, It.IsAny <Stream>(), It.IsAny <string>(), imageType, null, It.IsAny <CancellationToken>())) .Callback <BaseItem, Stream, string, ImageType, int?, CancellationToken>((callbackItem, _, _, callbackType, _, _) => callbackItem.SetImagePath(callbackType, callbackItem.AllowsMultipleImages(callbackType) ? callbackItem.GetImages(callbackType).Count() : 0, new FileSystemMetadata())) .Returns(Task.CompletedTask); var fileSystem = new Mock <IFileSystem>(); // match reported file size to image content length - condition for skipping already downloaded multi-images fileSystem.Setup(fs => fs.GetFileInfo(It.IsAny <string>())) .Returns(new FileSystemMetadata { Length = Content.Length }); var itemImageProvider = GetItemImageProvider(providerManager.Object, fileSystem); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List <IImageProvider> { remoteProvider.Object }, refreshOptions, CancellationToken.None); Assert.Equal(initialImageCount == 0 || fullRefresh, result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); Assert.Equal(targetImageCount, item.GetImages(imageType).Count()); }
public async Task <IEnumerable <RemoteImageInfo> > GetImages(BaseItem item, LibraryOptions libraryOptions, CancellationToken cancellationToken) { _logger?.Info($"{Name}-{nameof(JavImageProvider)}-{nameof(GetImages)} name:{item.Name}"); var list = new List <RemoteImageInfo>(); JavVideoIndex index = null; if ((index = item.GetJavVideoIndex(_jsonSerializer)) == null) { _logger?.Info($"{Name}-{nameof(JavImageProvider)}-{nameof(GetImages)} name:{item.Name} JavVideoIndex not found."); return(list); } JavVideo m = null; try { var cachePath = Path.Combine(_appPaths.CachePath, Name, index.Provider, $"{index.Num}.json"); m = _jsonSerializer.DeserializeFromFile <JavVideo>(cachePath); } catch { _logger?.Info($"{Name}-{nameof(JavImageProvider)}-{nameof(GetImages)} name:{item.Name} JavVideo not found."); } if (m == null) { return(list); } if (string.IsNullOrWhiteSpace(m.Cover) && m.Samples?.Any() == true) { m.Cover = m.Samples.FirstOrDefault(); } if (string.IsNullOrWhiteSpace(m.Cover) == false) { async Task SaveImage(ImageType type) { //有的就跳过了 if (item.ImageInfos?.Any(o => o.Type == type) == true) { return; } try { var url = ImageProxyService.BuildUrl(m.Cover, type == ImageType.Primary ? 1 : 0); var resp = await ImageProxyService.GetImageResponse(url, cancellationToken); if (resp?.ContentLength > 0) { #if __JELLYFIN__ await providerManager.SaveImage(item, resp.Content, resp.ContentType, type, 0, cancellationToken); #else await providerManager.SaveImage(item, libraryOptions, resp.Content, resp.ContentType.ToArray(), type, 0, cancellationToken); #endif } } catch (Exception ex) { _logger?.Warn($"Save image error: {type} {m.Cover} {ex.Message}"); } } await SaveImage(ImageType.Primary); await SaveImage(ImageType.Backdrop); //await SaveImage(ImageType.Art); var b = new RemoteImageInfo() { ProviderName = Name, Type = ImageType.Backdrop, Url = Plugin.Instance.Configuration.BuildProxyUrl(m.Cover), }; list.Add(b); } if (m.Samples?.Any() == true) { list.AddRange(m.Samples.Select(o => new RemoteImageInfo() { ProviderName = Name, Type = ImageType.Art, Url = Plugin.Instance.Configuration.BuildProxyUrl(o), })); } return(list); }
private IEnumerable <RemoteImageInfo> GetImages(Image[] images, string seasonNumber, string preferredLanguage) { var list = new List <RemoteImageInfo>(); // any languages with null ids are ignored var languages = _tvdbClientManager.GetLanguagesAsync(CancellationToken.None).Result.Data.Where(x => x.Id.HasValue).ToArray(); foreach (Image image in images) { // The API returns everything that contains the subkey eg. 2 matches 20, 21, 22, 23 etc. if (!string.Equals(image.SubKey, seasonNumber, StringComparison.Ordinal)) { continue; } var imageInfo = new RemoteImageInfo { RatingType = RatingType.Score, CommunityRating = (double?)image.RatingsInfo.Average, VoteCount = image.RatingsInfo.Count, Url = TvdbUtils.BannerUrl + image.FileName, ProviderName = Name, Language = languages.FirstOrDefault(lang => lang.Id == image.LanguageId)?.Abbreviation, ThumbnailUrl = TvdbUtils.BannerUrl + image.Thumbnail }; var resolution = image.Resolution.Split('x'); if (resolution.Length == 2) { imageInfo.Width = Convert.ToInt32(resolution[0], CultureInfo.InvariantCulture); imageInfo.Height = Convert.ToInt32(resolution[1], CultureInfo.InvariantCulture); } imageInfo.Type = TvdbUtils.GetImageTypeFromKeyType(image.KeyType); list.Add(imageInfo); } var isLanguageEn = string.Equals(preferredLanguage, "en", StringComparison.OrdinalIgnoreCase); return(list.OrderByDescending(i => { if (string.Equals(preferredLanguage, i.Language, StringComparison.OrdinalIgnoreCase)) { return 3; } if (!isLanguageEn) { if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase)) { return 2; } } if (string.IsNullOrEmpty(i.Language)) { return isLanguageEn ? 3 : 2; } return 0; }) .ThenByDescending(i => i.CommunityRating ?? 0) .ThenByDescending(i => i.VoteCount ?? 0)); }
private void PopulateImageCategory(List <RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height, bool allowSeasonAll = false) { reader.MoveToContent(); while (reader.Read()) { cancellationToken.ThrowIfCancellationRequested(); if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case "hdtvlogo": case "hdclearart": case "clearlogo": case "clearart": case "showbackground": case "seasonthumb": case "tvthumb": case "tvbanner": case "tvposter": { var url = reader.GetAttribute("url"); var season = reader.GetAttribute("season"); var isSeasonValid = string.IsNullOrEmpty(season) || (allowSeasonAll && string.Equals(season, "all", StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrEmpty(url) && isSeasonValid) { var likesString = reader.GetAttribute("likes"); int likes; var info = new RemoteImageInfo { RatingType = RatingType.Likes, Type = type, Width = width, Height = height, ProviderName = Name, Url = url, Language = reader.GetAttribute("lang") }; if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes)) { info.CommunityRating = likes; } list.Add(info); } break; } default: reader.Skip(); break; } } } }
public async Task <IEnumerable <RemoteImageInfo> > GetImages(BaseItem item, CancellationToken cancellationToken) { var tmdbId = item.GetProviderId(MetadataProvider.Tmdb); if (string.IsNullOrEmpty(tmdbId)) { return(null); } var language = item.GetPreferredMetadataLanguage(); // TODO use image languages if All Languages isn't toggled, but there's currently no way to get that value in here var series = await _tmdbClientManager .GetSeriesAsync(Convert.ToInt32(tmdbId, CultureInfo.InvariantCulture), null, null, cancellationToken) .ConfigureAwait(false); if (series?.Images == null) { return(Enumerable.Empty <RemoteImageInfo>()); } var posters = series.Images.Posters; var backdrops = series.Images.Backdrops; var remoteImages = new RemoteImageInfo[posters.Count + backdrops.Count]; for (var i = 0; i < posters.Count; i++) { var poster = posters[i]; remoteImages[i] = new RemoteImageInfo { Url = _tmdbClientManager.GetPosterUrl(poster.FilePath), CommunityRating = poster.VoteAverage, VoteCount = poster.VoteCount, Width = poster.Width, Height = poster.Height, Language = TmdbUtils.AdjustImageLanguage(poster.Iso_639_1, language), ProviderName = Name, Type = ImageType.Primary, RatingType = RatingType.Score }; } for (var i = 0; i < backdrops.Count; i++) { var backdrop = series.Images.Backdrops[i]; remoteImages[posters.Count + i] = new RemoteImageInfo { Url = _tmdbClientManager.GetBackdropUrl(backdrop.FilePath), CommunityRating = backdrop.VoteAverage, VoteCount = backdrop.VoteCount, Width = backdrop.Width, Height = backdrop.Height, ProviderName = Name, Type = ImageType.Backdrop, RatingType = RatingType.Score }; } return(remoteImages.OrderByLanguageDescending(language)); }