diff options
Diffstat (limited to 'MediaBrowser.Providers/Movies')
12 files changed, 646 insertions, 294 deletions
diff --git a/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs b/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs index e697738fe..0b2502ba9 100644 --- a/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs +++ b/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.IO; @@ -18,10 +19,12 @@ namespace MediaBrowser.Providers.Movies public class BoxSetProviderFromXml : BaseMetadataProvider { public static BoxSetProviderFromXml Current; + private readonly IFileSystem _fileSystem; - public BoxSetProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) + public BoxSetProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { + _fileSystem = fileSystem; Current = this; } @@ -54,7 +57,7 @@ namespace MediaBrowser.Providers.Movies return false; } - return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; } /// <summary> diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs index f34988481..30fb8c659 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs @@ -8,13 +8,13 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using System; -using System.Globalization; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Xml; namespace MediaBrowser.Providers.Movies { @@ -34,12 +34,8 @@ namespace MediaBrowser.Providers.Movies /// </summary> private readonly IProviderManager _providerManager; - /// <summary> - /// The us culture - /// </summary> - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - internal static FanArtMovieProvider Current { get; private set; } + private readonly IFileSystem _fileSystem; /// <summary> /// Initializes a new instance of the <see cref="FanArtMovieProvider" /> class. @@ -49,7 +45,7 @@ namespace MediaBrowser.Providers.Movies /// <param name="configurationManager">The configuration manager.</param> /// <param name="providerManager">The provider manager.</param> /// <exception cref="System.ArgumentNullException">httpClient</exception> - public FanArtMovieProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager) + public FanArtMovieProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem) : base(logManager, configurationManager) { if (httpClient == null) @@ -58,6 +54,7 @@ namespace MediaBrowser.Providers.Movies } HttpClient = httpClient; _providerManager = providerManager; + _fileSystem = fileSystem; Current = this; } @@ -136,28 +133,6 @@ namespace MediaBrowser.Providers.Movies return false; } - if (!ConfigurationManager.Configuration.DownloadMovieImages.Art && - !ConfigurationManager.Configuration.DownloadMovieImages.Logo && - !ConfigurationManager.Configuration.DownloadMovieImages.Disc && - !ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && - !ConfigurationManager.Configuration.DownloadMovieImages.Banner && - !ConfigurationManager.Configuration.DownloadMovieImages.Thumb && - !ConfigurationManager.Configuration.DownloadMovieImages.Primary) - { - return false; - } - - if (item.HasImage(ImageType.Primary) && - item.HasImage(ImageType.Art) && - item.HasImage(ImageType.Logo) && - item.HasImage(ImageType.Disc) && - item.HasImage(ImageType.Banner) && - item.HasImage(ImageType.Thumb) && - item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops) - { - return false; - } - return base.NeedsRefreshInternal(item, providerInfo); } @@ -168,24 +143,11 @@ namespace MediaBrowser.Providers.Movies if (!string.IsNullOrEmpty(id)) { // Process images - var path = GetMovieDataPath(ConfigurationManager.ApplicationPaths, id); + var xmlPath = GetFanartXmlPath(id); - try - { - var files = new DirectoryInfo(path) - .EnumerateFiles("*.xml", SearchOption.TopDirectoryOnly) - .Select(i => i.LastWriteTimeUtc) - .ToList(); - - if (files.Count > 0) - { - return files.Max() > providerInfo.LastRefreshed; - } - } - catch (DirectoryNotFoundException) - { - return true; - } + var fileInfo = new FileInfo(xmlPath); + + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed; } return base.NeedsRefreshBasedOnCompareDate(item, providerInfo); @@ -231,18 +193,19 @@ namespace MediaBrowser.Providers.Movies if (!string.IsNullOrEmpty(movieId)) { - var movieDataPath = GetMovieDataPath(ConfigurationManager.ApplicationPaths, movieId); - var xmlPath = Path.Combine(movieDataPath, "fanart.xml"); + var xmlPath = GetFanartXmlPath(movieId); // Only download the xml if it doesn't already exist. The prescan task will take care of getting updates if (!File.Exists(xmlPath)) { - await DownloadMovieXml(movieDataPath, movieId, cancellationToken).ConfigureAwait(false); + await DownloadMovieXml(movieId, cancellationToken).ConfigureAwait(false); } if (File.Exists(xmlPath)) { - await FetchFromXml(item, xmlPath, cancellationToken).ConfigureAwait(false); + var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualFanartMovieImageProvider.ProviderName).ConfigureAwait(false); + + await FetchImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); } } @@ -250,22 +213,27 @@ namespace MediaBrowser.Providers.Movies return true; } + public string GetFanartXmlPath(string tmdbId) + { + var movieDataPath = GetMovieDataPath(ConfigurationManager.ApplicationPaths, tmdbId); + return Path.Combine(movieDataPath, "fanart.xml"); + } + /// <summary> /// Downloads the movie XML. /// </summary> - /// <param name="movieDataPath">The movie data path.</param> /// <param name="tmdbId">The TMDB id.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - internal async Task DownloadMovieXml(string movieDataPath, string tmdbId, CancellationToken cancellationToken) + internal async Task DownloadMovieXml(string tmdbId, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - string url = string.Format(FanArtBaseUrl, ApiKey, tmdbId); + var url = string.Format(FanArtBaseUrl, ApiKey, tmdbId); - var xmlPath = Path.Combine(movieDataPath, "fanart.xml"); + var xmlPath = GetFanartXmlPath(tmdbId); - Directory.CreateDirectory(movieDataPath); + Directory.CreateDirectory(Path.GetDirectoryName(xmlPath)); using (var response = await HttpClient.Get(new HttpRequestOptions { @@ -275,89 +243,60 @@ namespace MediaBrowser.Providers.Movies }).ConfigureAwait(false)) { - using (var xmlFileStream = new FileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous)) + using (var xmlFileStream = _fileSystem.GetFileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) { await response.CopyToAsync(xmlFileStream).ConfigureAwait(false); } } } - /// <summary> - /// Fetches from XML. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="xmlFilePath">The XML file path.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - private async Task FetchFromXml(BaseItem item, string xmlFilePath, CancellationToken cancellationToken) + private async Task FetchImages(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken) { - var doc = new XmlDocument(); - doc.Load(xmlFilePath); - - var language = ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower(); - cancellationToken.ThrowIfCancellationRequested(); - string path; - - if (ConfigurationManager.Configuration.DownloadMovieImages.Disc && !item.HasImage(ImageType.Disc)) + if (ConfigurationManager.Configuration.DownloadMovieImages.Primary && !item.HasImage(ImageType.Primary)) { - var node = doc.SelectSingleNode("//fanart/movie/movieposters/movieposter[@lang = \"" + language + "\"]/@url") ?? - doc.SelectSingleNode("//fanart/movie/movieposters/movieposter/@url"); - path = node != null ? node.Value : null; - if (!string.IsNullOrEmpty(path)) + var image = images.FirstOrDefault(i => i.Type == ImageType.Primary); + + if (image != null) { - await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Disc, null, cancellationToken) - .ConfigureAwait(false); + await _providerManager.SaveImage(item, image.Url, FanArtResourcePool, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); } } cancellationToken.ThrowIfCancellationRequested(); - + if (ConfigurationManager.Configuration.DownloadMovieImages.Logo && !item.HasImage(ImageType.Logo)) { - var node = - doc.SelectSingleNode("//fanart/movie/hdmovielogos/hdmovielogo[@lang = \"" + language + "\"]/@url") ?? - doc.SelectSingleNode("//fanart/movie/movielogos/movielogo[@lang = \"" + language + "\"]/@url"); - if (node == null && language != "en") - { - //maybe just couldn't find language - try just first one - node = doc.SelectSingleNode("//fanart/movie/hdmovielogos/hdmovielogo/@url") ?? - doc.SelectSingleNode("//fanart/movie/movielogos/movielogo/@url"); - } - path = node != null ? node.Value : null; - if (!string.IsNullOrEmpty(path)) + var image = images.FirstOrDefault(i => i.Type == ImageType.Logo); + + if (image != null) { - await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Logo, null, cancellationToken).ConfigureAwait(false); + await _providerManager.SaveImage(item, image.Url, FanArtResourcePool, ImageType.Logo, null, cancellationToken).ConfigureAwait(false); } } + cancellationToken.ThrowIfCancellationRequested(); if (ConfigurationManager.Configuration.DownloadMovieImages.Art && !item.HasImage(ImageType.Art)) { - var node = - doc.SelectSingleNode("//fanart/movie/hdmoviecleararts/hdmovieclearart[@lang = \"" + language + "\"]/@url") ?? - doc.SelectSingleNode("//fanart/movie/hdmoviecleararts/hdmovieclearart/@url") ?? - doc.SelectSingleNode("//fanart/movie/moviearts/movieart[@lang = \"" + language + "\"]/@url") ?? - doc.SelectSingleNode("//fanart/movie/moviearts/movieart/@url"); - path = node != null ? node.Value : null; - if (!string.IsNullOrEmpty(path)) + var image = images.FirstOrDefault(i => i.Type == ImageType.Art); + + if (image != null) { - await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Art, null, cancellationToken) - .ConfigureAwait(false); + await _providerManager.SaveImage(item, image.Url, FanArtResourcePool, ImageType.Art, null, cancellationToken).ConfigureAwait(false); } } + cancellationToken.ThrowIfCancellationRequested(); if (ConfigurationManager.Configuration.DownloadMovieImages.Disc && !item.HasImage(ImageType.Disc)) { - var node = doc.SelectSingleNode("//fanart/movie/moviediscs/moviedisc[@lang = \"" + language + "\"]/@url") ?? - doc.SelectSingleNode("//fanart/movie/moviediscs/moviedisc/@url"); - path = node != null ? node.Value : null; - if (!string.IsNullOrEmpty(path)) + var image = images.FirstOrDefault(i => i.Type == ImageType.Disc); + + if (image != null) { - await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Disc, null, cancellationToken) - .ConfigureAwait(false); + await _providerManager.SaveImage(item, image.Url, FanArtResourcePool, ImageType.Disc, null, cancellationToken).ConfigureAwait(false); } } @@ -365,13 +304,11 @@ namespace MediaBrowser.Providers.Movies if (ConfigurationManager.Configuration.DownloadMovieImages.Banner && !item.HasImage(ImageType.Banner)) { - var node = doc.SelectSingleNode("//fanart/movie/moviebanners/moviebanner[@lang = \"" + language + "\"]/@url") ?? - doc.SelectSingleNode("//fanart/movie/moviebanners/moviebanner/@url"); - path = node != null ? node.Value : null; - if (!string.IsNullOrEmpty(path)) + var image = images.FirstOrDefault(i => i.Type == ImageType.Banner); + + if (image != null) { - await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Banner, null, cancellationToken) - .ConfigureAwait(false); + await _providerManager.SaveImage(item, image.Url, FanArtResourcePool, ImageType.Banner, null, cancellationToken).ConfigureAwait(false); } } @@ -379,40 +316,30 @@ namespace MediaBrowser.Providers.Movies if (ConfigurationManager.Configuration.DownloadMovieImages.Thumb && !item.HasImage(ImageType.Thumb)) { - var node = doc.SelectSingleNode("//fanart/movie/moviethumbs/moviethumb[@lang = \"" + language + "\"]/@url") ?? - doc.SelectSingleNode("//fanart/movie/moviethumbs/moviethumb/@url"); - path = node != null ? node.Value : null; - if (!string.IsNullOrEmpty(path)) + var image = images.FirstOrDefault(i => i.Type == ImageType.Thumb); + + if (image != null) { - await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Thumb, null, cancellationToken) - .ConfigureAwait(false); + await _providerManager.SaveImage(item, image.Url, FanArtResourcePool, ImageType.Thumb, null, cancellationToken).ConfigureAwait(false); } } + cancellationToken.ThrowIfCancellationRequested(); + var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops; - if (ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit) + if (ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && + item.BackdropImagePaths.Count < backdropLimit) { - var nodes = doc.SelectNodes("//fanart/movie/moviebackgrounds//@url"); + var numBackdrops = item.BackdropImagePaths.Count; - if (nodes != null) + foreach (var image in images.Where(i => i.Type == ImageType.Backdrop)) { - var numBackdrops = item.BackdropImagePaths.Count; - - foreach (XmlNode node in nodes) - { - path = node.Value; - - if (!string.IsNullOrEmpty(path) && !item.ContainsImageWithSourceUrl(path)) - { - await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Backdrop, numBackdrops, cancellationToken) - .ConfigureAwait(false); - - numBackdrops++; + await _providerManager.SaveImage(item, image.Url, FanArtResourcePool, ImageType.Backdrop, numBackdrops, cancellationToken) + .ConfigureAwait(false); - if (item.BackdropImagePaths.Count >= backdropLimit) break; - } - } + numBackdrops++; + if (item.BackdropImagePaths.Count >= backdropLimit) break; } } } diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs index 51b77599e..cc2293968 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Net; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; @@ -32,15 +33,17 @@ namespace MediaBrowser.Providers.Movies /// </summary> private readonly IServerConfigurationManager _config; private readonly IJsonSerializer _jsonSerializer; + private readonly IFileSystem _fileSystem; private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public FanArtMovieUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient) + public FanArtMovieUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem) { _jsonSerializer = jsonSerializer; _config = config; _logger = logger; _httpClient = httpClient; + _fileSystem = fileSystem; } /// <summary> @@ -66,7 +69,7 @@ namespace MediaBrowser.Providers.Movies var timestampFileInfo = new FileInfo(timestampFile); // Don't check for tvdb updates anymore frequently than 24 hours - if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < 1) + if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1) { return; } @@ -83,7 +86,7 @@ namespace MediaBrowser.Providers.Movies progress.Report(5); - await UpdateMovies(moviesToUpdate, path, progress, cancellationToken).ConfigureAwait(false); + await UpdateMovies(moviesToUpdate, progress, cancellationToken).ConfigureAwait(false); } var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture); @@ -124,14 +127,16 @@ namespace MediaBrowser.Providers.Movies } } - private async Task UpdateMovies(IEnumerable<string> idList, string moviesDataPath, IProgress<double> progress, CancellationToken cancellationToken) + private async Task UpdateMovies(IEnumerable<string> idList, IProgress<double> progress, CancellationToken cancellationToken) { var list = idList.ToList(); var numComplete = 0; foreach (var id in list) { - await UpdateMovie(id, moviesDataPath, cancellationToken).ConfigureAwait(false); + _logger.Info("Updating movie " + id); + + await FanArtMovieProvider.Current.DownloadMovieXml(id, cancellationToken).ConfigureAwait(false); numComplete++; double percent = numComplete; @@ -142,17 +147,6 @@ namespace MediaBrowser.Providers.Movies } } - private Task UpdateMovie(string tmdbId, string movieDataPath, CancellationToken cancellationToken) - { - _logger.Info("Updating movie " + tmdbId); - - movieDataPath = Path.Combine(movieDataPath, tmdbId); - - Directory.CreateDirectory(movieDataPath); - - return FanArtMovieProvider.Current.DownloadMovieXml(movieDataPath, tmdbId, cancellationToken); - } - /// <summary> /// Dates the time to unix timestamp. /// </summary> diff --git a/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs new file mode 100644 index 000000000..64843de99 --- /dev/null +++ b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs @@ -0,0 +1,297 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; + +namespace MediaBrowser.Providers.Movies +{ + public class ManualFanartMovieImageProvider : IImageProvider + { + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly IServerConfigurationManager _config; + + public ManualFanartMovieImageProvider(IServerConfigurationManager config) + { + _config = config; + } + + public string Name + { + get { return ProviderName; } + } + + public static string ProviderName + { + get { return "FanArt"; } + } + + public bool Supports(BaseItem item) + { + return FanArtMovieProvider.Current.Supports(item); + } + + public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + { + var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); + + return images.Where(i => i.Type == imageType); + } + + public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) + { + var list = new List<RemoteImageInfo>(); + + var movieId = item.GetProviderId(MetadataProviders.Tmdb); + + if (!string.IsNullOrEmpty(movieId)) + { + var xmlPath = FanArtMovieProvider.Current.GetFanartXmlPath(movieId); + + try + { + AddImages(list, xmlPath, cancellationToken); + } + catch (FileNotFoundException) + { + // No biggie. Don't blow up + } + } + + var language = _config.Configuration.PreferredMetadataLanguage; + + var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); + + // Sort first by width to prioritize HD versions + list = list.OrderByDescending(i => i.Width ?? 0) + .ThenByDescending(i => + { + if (string.Equals(language, 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) + .ToList(); + + return Task.FromResult<IEnumerable<RemoteImageInfo>>(list); + } + + private void AddImages(List<RemoteImageInfo> list, string xmlPath, CancellationToken cancellationToken) + { + using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8)) + { + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings + { + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true, + ValidationType = ValidationType.None + })) + { + reader.MoveToContent(); + + // Loop through each element + while (reader.Read()) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "movie": + { + using (var subReader = reader.ReadSubtree()) + { + AddImages(list, subReader, cancellationToken); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + } + } + + private void AddImages(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "hdmoviecleararts": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Art, 1000, 562); + } + break; + } + case "hdmovielogos": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Logo, 800, 310); + } + break; + } + case "moviediscs": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Disc, 1000, 1000); + } + break; + } + case "movieposters": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Primary, 1000, 1426); + } + break; + } + case "movielogos": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Logo, 400, 155); + } + break; + } + case "moviearts": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Art, 500, 281); + } + break; + } + case "moviethumbs": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Thumb, 1000, 562); + } + break; + } + case "moviebanners": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Banner, 1000, 185); + } + break; + } + case "moviebackgrounds": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Backdrop, 1920, 1080); + } + break; + } + default: + reader.Skip(); + break; + } + } + } + } + + private void PopulateImageCategory(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height) + { + reader.MoveToContent(); + + while (reader.Read()) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "hdmovielogo": + case "moviedisc": + case "hdmovieclearart": + case "movieposter": + case "movielogo": + case "movieart": + case "moviethumb": + case "moviebanner": + case "moviebackground": + { + var url = reader.GetAttribute("url"); + + if (!string.IsNullOrEmpty(url)) + { + 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 int Priority + { + get { return 1; } + } + } +} diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs new file mode 100644 index 000000000..4ae15e91f --- /dev/null +++ b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs @@ -0,0 +1,177 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using MediaBrowser.Model.Serialization; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.Movies +{ + class ManualMovieDbImageProvider : IImageProvider + { + private readonly IJsonSerializer _jsonSerializer; + private readonly IServerConfigurationManager _config; + + public ManualMovieDbImageProvider(IJsonSerializer jsonSerializer, IServerConfigurationManager config) + { + _jsonSerializer = jsonSerializer; + _config = config; + } + + public string Name + { + get { return ProviderName; } + } + + public static string ProviderName + { + get { return "TheMovieDb"; } + } + + public bool Supports(BaseItem item) + { + return MovieDbImagesProvider.SupportsItem(item); + } + + public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + { + var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); + + return images.Where(i => i.Type == imageType); + } + + public async Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) + { + var list = new List<RemoteImageInfo>(); + + var results = FetchImages(item, _jsonSerializer); + + if (results == null) + { + return list; + } + + var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); + + var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + + list.AddRange(GetPosters(results, item).Select(i => new RemoteImageInfo + { + Url = tmdbImageUrl + i.file_path, + CommunityRating = i.vote_average, + VoteCount = i.vote_count, + Width = i.width, + Height = i.height, + Language = i.iso_639_1, + ProviderName = Name, + Type = ImageType.Primary, + RatingType = RatingType.Score + })); + + list.AddRange(GetBackdrops(results, item).Select(i => new RemoteImageInfo + { + Url = tmdbImageUrl + i.file_path, + CommunityRating = i.vote_average, + VoteCount = i.vote_count, + Width = i.width, + Height = i.height, + ProviderName = Name, + Type = ImageType.Backdrop, + RatingType = RatingType.Score + })); + + return list; + } + + /// <summary> + /// Gets the posters. + /// </summary> + /// <param name="images">The images.</param> + /// <param name="item">The item.</param> + /// <returns>IEnumerable{MovieDbProvider.Poster}.</returns> + private IEnumerable<MovieDbProvider.Poster> GetPosters(MovieDbProvider.Images images, BaseItem item) + { + var language = _config.Configuration.PreferredMetadataLanguage; + + var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); + + var eligiblePosters = images.posters == null ? + new List<MovieDbProvider.Poster>() : + images.posters + .ToList(); + + return eligiblePosters.OrderByDescending(i => + { + if (string.Equals(language, i.iso_639_1, StringComparison.OrdinalIgnoreCase)) + { + return 3; + } + if (!isLanguageEn) + { + if (string.Equals("en", i.iso_639_1, StringComparison.OrdinalIgnoreCase)) + { + return 2; + } + } + if (string.IsNullOrEmpty(i.iso_639_1)) + { + return isLanguageEn ? 3 : 2; + } + return 0; + }) + .ThenByDescending(i => i.vote_average) + .ThenByDescending(i => i.vote_count) + .ToList(); + } + + /// <summary> + /// Gets the backdrops. + /// </summary> + /// <param name="images">The images.</param> + /// <param name="item">The item.</param> + /// <returns>IEnumerable{MovieDbProvider.Backdrop}.</returns> + private IEnumerable<MovieDbProvider.Backdrop> GetBackdrops(MovieDbProvider.Images images, BaseItem item) + { + var eligibleBackdrops = images.backdrops == null ? new List<MovieDbProvider.Backdrop>() : + images.backdrops + .ToList(); + + return eligibleBackdrops.OrderByDescending(i => i.vote_average).ThenByDescending(i => i.vote_count); + } + + /// <summary> + /// Fetches the images. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="jsonSerializer">The json serializer.</param> + /// <returns>Task{MovieImages}.</returns> + private MovieDbProvider.Images FetchImages(BaseItem item, IJsonSerializer jsonSerializer) + { + var path = MovieDbProvider.Current.GetImagesDataFilePath(item); + + if (!string.IsNullOrEmpty(path)) + { + var fileInfo = new FileInfo(path); + + if (fileInfo.Exists) + { + return jsonSerializer.DeserializeFromFile<MovieDbProvider.CompleteMovieData>(path).images; + } + } + + return null; + } + + public int Priority + { + get { return 2; } + } + } +} diff --git a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs index 52e6c214f..6c503ad3a 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Net; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -6,7 +7,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; using System.IO; @@ -22,19 +23,11 @@ namespace MediaBrowser.Providers.Movies public class MovieDbImagesProvider : BaseMetadataProvider { /// <summary> - /// The get images - /// </summary> - private const string GetImages = @"http://api.themoviedb.org/3/{2}/{0}/images?api_key={1}"; - - /// <summary> /// The _provider manager /// </summary> private readonly IProviderManager _providerManager; - /// <summary> - /// The _json serializer - /// </summary> - private readonly IJsonSerializer _jsonSerializer; + private readonly IFileSystem _fileSystem; /// <summary> /// Initializes a new instance of the <see cref="MovieDbImagesProvider"/> class. @@ -42,12 +35,11 @@ namespace MediaBrowser.Providers.Movies /// <param name="logManager">The log manager.</param> /// <param name="configurationManager">The configuration manager.</param> /// <param name="providerManager">The provider manager.</param> - /// <param name="jsonSerializer">The json serializer.</param> - public MovieDbImagesProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IJsonSerializer jsonSerializer) + public MovieDbImagesProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _providerManager = providerManager; - _jsonSerializer = jsonSerializer; + _fileSystem = fileSystem; } /// <summary> @@ -66,6 +58,11 @@ namespace MediaBrowser.Providers.Movies /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> public override bool Supports(BaseItem item) { + return SupportsItem(item); + } + + public static bool SupportsItem(BaseItem item) + { var trailer = item as Trailer; if (trailer != null) @@ -145,12 +142,7 @@ namespace MediaBrowser.Providers.Movies protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo) { - if (string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tmdb))) - { - return false; - } - - var path = MovieDbProvider.Current.GetDataFilePath(item, "default"); + var path = MovieDbProvider.Current.GetImagesDataFilePath(item); if (!string.IsNullOrEmpty(path)) { @@ -158,7 +150,7 @@ namespace MediaBrowser.Providers.Movies if (fileInfo.Exists) { - return fileInfo.LastWriteTimeUtc > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed; } } @@ -176,113 +168,54 @@ namespace MediaBrowser.Providers.Movies { var id = item.GetProviderId(MetadataProviders.Tmdb); - var status = ProviderRefreshStatus.Success; - if (!string.IsNullOrEmpty(id)) { - var images = FetchImages(item); + var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualMovieDbImageProvider.ProviderName).ConfigureAwait(false); - if (images != null) - { - status = await ProcessImages(item, images, cancellationToken).ConfigureAwait(false); - } + await ProcessImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); } - SetLastRefreshed(item, DateTime.UtcNow, status); + SetLastRefreshed(item, DateTime.UtcNow); return true; } /// <summary> - /// Fetches the images. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>Task{MovieImages}.</returns> - private MovieDbProvider.Images FetchImages(BaseItem item) - { - var path = MovieDbProvider.Current.GetDataFilePath(item, "default"); - - if (!string.IsNullOrEmpty(path)) - { - var fileInfo = new FileInfo(path); - - if (fileInfo.Exists) - { - return _jsonSerializer.DeserializeFromFile<MovieDbProvider.CompleteMovieData>(path).images; - } - } - - return null; - } - - /// <summary> /// Processes the images. /// </summary> /// <param name="item">The item.</param> /// <param name="images">The images.</param> /// <param name="cancellationToken">The cancellation token</param> /// <returns>Task.</returns> - private async Task<ProviderRefreshStatus> ProcessImages(BaseItem item, MovieDbProvider.Images images, CancellationToken cancellationToken) + private async Task ProcessImages(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - var status = ProviderRefreshStatus.Success; - - var eligiblePosters = images.posters == null ? - new List<MovieDbProvider.Poster>() : - images.posters.Where(i => i.width >= ConfigurationManager.Configuration.MinMoviePosterWidth) + var eligiblePosters = images + .Where(i => i.Type == ImageType.Primary && i.Width.HasValue && i.Width.Value >= ConfigurationManager.Configuration.MinMoviePosterWidth) .ToList(); - eligiblePosters = eligiblePosters.OrderByDescending(i => i.vote_average).ToList(); - // poster if (eligiblePosters.Count > 0 && !item.HasImage(ImageType.Primary)) { - var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; - // get highest rated poster for our language + var poster = eligiblePosters[0]; - var poster = eligiblePosters.FirstOrDefault(p => string.Equals(p.iso_639_1, ConfigurationManager.Configuration.PreferredMetadataLanguage, StringComparison.OrdinalIgnoreCase)); + var url = poster.Url; - if (poster == null) + var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions { - // couldn't find our specific language, find english - poster = eligiblePosters.FirstOrDefault(p => string.Equals(p.iso_639_1, "en", StringComparison.OrdinalIgnoreCase)); - } + Url = url, + CancellationToken = cancellationToken - if (poster == null) - { - //still couldn't find it - try highest rated null one - poster = eligiblePosters.FirstOrDefault(p => p.iso_639_1 == null); - } + }).ConfigureAwait(false); - if (poster == null) - { - //finally - just get the highest rated one - poster = eligiblePosters.FirstOrDefault(); - } - - if (poster != null) - { - var url = tmdbImageUrl + poster.file_path; - - var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken - - }).ConfigureAwait(false); - - await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(poster.file_path), ImageType.Primary, null, url, cancellationToken) - .ConfigureAwait(false); - - } + await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(url), ImageType.Primary, null, url, cancellationToken) + .ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - var eligibleBackdrops = images.backdrops == null ? new List<MovieDbProvider.Backdrop>() : - images.backdrops.Where(i => i.width >= ConfigurationManager.Configuration.MinMovieBackdropWidth) + var eligibleBackdrops = images + .Where(i => i.Type == ImageType.Backdrop && i.Width.HasValue && i.Width.Value >= ConfigurationManager.Configuration.MinMovieBackdropWidth) .ToList(); var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops; @@ -290,13 +223,9 @@ namespace MediaBrowser.Providers.Movies // backdrops - only download if earlier providers didn't find any (fanart) if (eligibleBackdrops.Count > 0 && ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit) { - var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; - for (var i = 0; i < eligibleBackdrops.Count; i++) { - var url = tmdbImageUrl + eligibleBackdrops[i].file_path; + var url = eligibleBackdrops[i].Url; if (!item.ContainsImageWithSourceUrl(url)) { @@ -307,7 +236,7 @@ namespace MediaBrowser.Providers.Movies }).ConfigureAwait(false); - await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(eligibleBackdrops[i].file_path), ImageType.Backdrop, item.BackdropImagePaths.Count, url, cancellationToken) + await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(url), ImageType.Backdrop, item.BackdropImagePaths.Count, url, cancellationToken) .ConfigureAwait(false); } @@ -317,8 +246,6 @@ namespace MediaBrowser.Providers.Movies } } } - - return status; } } } diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 9ed0860b2..67cec7498 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -47,6 +48,7 @@ namespace MediaBrowser.Providers.Movies /// </summary> /// <value>The HTTP client.</value> protected IHttpClient HttpClient { get; private set; } + private readonly IFileSystem _fileSystem; /// <summary> /// Initializes a new instance of the <see cref="MovieDbProvider" /> class. @@ -56,12 +58,13 @@ namespace MediaBrowser.Providers.Movies /// <param name="jsonSerializer">The json serializer.</param> /// <param name="httpClient">The HTTP client.</param> /// <param name="providerManager">The provider manager.</param> - public MovieDbProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, IProviderManager providerManager) + public MovieDbProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, IProviderManager providerManager, IFileSystem fileSystem) : base(logManager, configurationManager) { JsonSerializer = jsonSerializer; HttpClient = httpClient; ProviderManager = providerManager; + _fileSystem = fileSystem; Current = this; } @@ -189,6 +192,7 @@ namespace MediaBrowser.Providers.Movies static readonly Regex[] NameMatches = new[] { new Regex(@"(?<name>.*)\((?<year>\d{4})\)"), // matches "My Movie (2001)" and gives us the name and the year + new Regex(@"(?<name>.*)(\.(?<year>\d{4})(\.|$)).*$"), new Regex(@"(?<name>.*)") // last resort matches the whole string as the name }; @@ -205,23 +209,20 @@ namespace MediaBrowser.Providers.Movies protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo) { - var language = ConfigurationManager.Configuration.PreferredMetadataLanguage; - - var path = GetDataFilePath(item, language); + var path = GetDataFilePath(item); if (!string.IsNullOrEmpty(path)) { - var fileInfo = new FileInfo(path); + var imagesFilePath = GetImagesDataFilePath(item); - if (fileInfo.Exists) - { - return fileInfo.LastWriteTimeUtc > providerInfo.LastRefreshed; - } + var fileInfo = new FileInfo(path); + var imagesFileInfo = new FileInfo(imagesFilePath); - return true; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed || + !imagesFileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(imagesFileInfo) > providerInfo.LastRefreshed; } - return base.NeedsRefreshBasedOnCompareDate(item, providerInfo); + return true; } /// <summary> @@ -320,7 +321,7 @@ namespace MediaBrowser.Providers.Movies /// <param name="name">The name.</param> /// <param name="justName">Name of the just.</param> /// <param name="year">The year.</param> - protected void ParseName(string name, out string justName, out int? year) + public static void ParseName(string name, out string justName, out int? year) { justName = null; year = null; @@ -504,9 +505,9 @@ namespace MediaBrowser.Providers.Movies var language = ConfigurationManager.Configuration.PreferredMetadataLanguage; - var dataFilePath = GetDataFilePath(item, language); + var dataFilePath = GetDataFilePath(item); - if (string.IsNullOrEmpty(dataFilePath) || !File.Exists(dataFilePath)) + if (string.IsNullOrEmpty(dataFilePath) || !File.Exists(dataFilePath) || !File.Exists(GetImagesDataFilePath(item))) { var isBoxSet = item is BoxSet; @@ -534,7 +535,7 @@ namespace MediaBrowser.Providers.Movies if (isForcedRefresh || ConfigurationManager.Configuration.EnableTmdbUpdates || !HasAltMeta(item)) { - dataFilePath = GetDataFilePath(item, language); + dataFilePath = GetDataFilePath(item); var mainResult = JsonSerializer.DeserializeFromFile<CompleteMovieData>(dataFilePath); @@ -576,10 +577,11 @@ namespace MediaBrowser.Providers.Movies /// Gets the data file path. /// </summary> /// <param name="item">The item.</param> - /// <param name="language">The language.</param> /// <returns>System.String.</returns> - internal string GetDataFilePath(BaseItem item, string language) + internal string GetDataFilePath(BaseItem item) { + var language = ConfigurationManager.Configuration.PreferredMetadataLanguage; + var id = item.GetProviderId(MetadataProviders.Tmdb); if (string.IsNullOrEmpty(id)) @@ -594,6 +596,18 @@ namespace MediaBrowser.Providers.Movies return path; } + internal string GetImagesDataFilePath(BaseItem item) + { + var path = GetDataFilePath(item); + + if (!string.IsNullOrEmpty(path)) + { + path = Path.Combine(Path.GetDirectoryName(path), "default.json"); + } + + return path; + } + /// <summary> /// Fetches the main result. /// </summary> diff --git a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs index ed92151c7..dfab655f1 100644 --- a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs +++ b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs @@ -1,7 +1,7 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -21,11 +21,13 @@ namespace MediaBrowser.Providers.Movies { internal static MovieProviderFromXml Current { get; private set; } private readonly IItemRepository _itemRepo; + private readonly IFileSystem _fileSystem; - public MovieProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IItemRepository itemRepo) + public MovieProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IItemRepository itemRepo, IFileSystem fileSystem) : base(logManager, configurationManager) { _itemRepo = itemRepo; + _fileSystem = fileSystem; Current = this; } @@ -71,7 +73,7 @@ namespace MediaBrowser.Providers.Movies return false; } - return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; } /// <summary> diff --git a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs index b5d264682..4c1838cfc 100644 --- a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs +++ b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Net; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; @@ -35,6 +36,7 @@ namespace MediaBrowser.Providers.Movies /// </summary> private readonly IServerConfigurationManager _config; private readonly IJsonSerializer _json; + private readonly IFileSystem _fileSystem; /// <summary> /// Initializes a new instance of the <see cref="MovieUpdatesPreScanTask"/> class. @@ -43,12 +45,13 @@ namespace MediaBrowser.Providers.Movies /// <param name="httpClient">The HTTP client.</param> /// <param name="config">The config.</param> /// <param name="json">The json.</param> - public MovieUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json) + public MovieUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json, IFileSystem fileSystem) { _logger = logger; _httpClient = httpClient; _config = config; _json = json; + _fileSystem = fileSystem; } protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); @@ -100,7 +103,7 @@ namespace MediaBrowser.Providers.Movies var refreshDays = _config.Configuration.EnableTmdbUpdates ? 1 : 7; // Don't check for tvdb updates anymore frequently than 24 hours - if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < refreshDays) + if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < refreshDays) { return; } diff --git a/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs b/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs index ab90675fd..8de061b99 100644 --- a/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs +++ b/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; @@ -13,10 +14,12 @@ namespace MediaBrowser.Providers.Movies class PersonProviderFromXml : BaseMetadataProvider { internal static PersonProviderFromXml Current { get; private set; } + private readonly IFileSystem _fileSystem; - public PersonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) + public PersonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) : base(logManager, configurationManager) { + _fileSystem = fileSystem; Current = this; } @@ -49,7 +52,7 @@ namespace MediaBrowser.Providers.Movies return false; } - return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed; } /// <summary> diff --git a/MediaBrowser.Providers/Movies/PersonUpdatesPreScanTask.cs b/MediaBrowser.Providers/Movies/PersonUpdatesPreScanTask.cs index d6cc39c86..8a5e6bd9d 100644 --- a/MediaBrowser.Providers/Movies/PersonUpdatesPreScanTask.cs +++ b/MediaBrowser.Providers/Movies/PersonUpdatesPreScanTask.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Net; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; @@ -34,6 +35,7 @@ namespace MediaBrowser.Providers.Movies /// </summary> private readonly IServerConfigurationManager _config; private readonly IJsonSerializer _json; + private readonly IFileSystem _fileSystem; /// <summary> /// Initializes a new instance of the <see cref="PersonUpdatesPreScanTask"/> class. @@ -41,12 +43,13 @@ namespace MediaBrowser.Providers.Movies /// <param name="logger">The logger.</param> /// <param name="httpClient">The HTTP client.</param> /// <param name="config">The config.</param> - public PersonUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json) + public PersonUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json, IFileSystem fileSystem) { _logger = logger; _httpClient = httpClient; _config = config; _json = json; + _fileSystem = fileSystem; } protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); @@ -74,7 +77,7 @@ namespace MediaBrowser.Providers.Movies var timestampFileInfo = new FileInfo(timestampFile); // Don't check for tvdb updates anymore frequently than 24 hours - if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < 1) + if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1) { return; } diff --git a/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs b/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs index 4a5db1d81..7c38eb97b 100644 --- a/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs @@ -30,8 +30,9 @@ namespace MediaBrowser.Providers.Movies internal static TmdbPersonProvider Current { get; private set; } const string DataFileName = "info.json"; + private readonly IFileSystem _fileSystem; - public TmdbPersonProvider(IJsonSerializer jsonSerializer, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager) + public TmdbPersonProvider(IJsonSerializer jsonSerializer, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem) : base(logManager, configurationManager) { if (jsonSerializer == null) @@ -40,6 +41,7 @@ namespace MediaBrowser.Providers.Movies } JsonSerializer = jsonSerializer; ProviderManager = providerManager; + _fileSystem = fileSystem; Current = this; } @@ -105,7 +107,7 @@ namespace MediaBrowser.Providers.Movies if (fileInfo.Exists) { - return fileInfo.LastWriteTimeUtc > providerInfo.LastRefreshed; + return _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed; } return true; @@ -270,7 +272,7 @@ namespace MediaBrowser.Providers.Movies { Directory.CreateDirectory(personDataPath); - using (var fs = new FileStream(Path.Combine(personDataPath, DataFileName), FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true)) + using (var fs = _fileSystem.GetFileStream(Path.Combine(personDataPath, DataFileName), FileMode.Create, FileAccess.Write, FileShare.Read, true)) { await json.CopyToAsync(fs).ConfigureAwait(false); } |
