using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.IO; using MediaBrowser.Model.Logging; using System; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Controller.Providers { /// /// Provides images for generic types by looking for standard images in the IBN /// public class ImagesByNameProvider : ImageFromMediaLocationProvider { public ImagesByNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager) { } /// /// Supportses the specified item. /// /// The item. /// true if XXXX, false otherwise public override bool Supports(BaseItem item) { //only run for these generic types since we are expensive in file i/o return item is IndexFolder || item is BasePluginFolder || item is CollectionFolder; } /// /// Gets the priority. /// /// The priority. public override MetadataProviderPriority Priority { get { return MetadataProviderPriority.Last; } } /// /// Needses the refresh internal. /// /// The item. /// The provider info. /// true if XXXX, false otherwise protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) { // Force a refresh if the IBN path changed if (!string.Equals(providerInfo.CustomData, ConfigurationManager.ApplicationPaths.ItemsByNamePath, StringComparison.OrdinalIgnoreCase)) { return true; } return base.NeedsRefreshInternal(item, providerInfo); } /// /// Gets a value indicating whether [refresh on file system stamp change]. /// /// true if [refresh on file system stamp change]; otherwise, false. protected override bool RefreshOnFileSystemStampChange { get { return false; } } /// /// Override this to return the date that should be compared to the last refresh date /// to determine if this provider should be re-fetched. /// /// The item. /// DateTime. protected override DateTime CompareDate(BaseItem item) { // If the IBN location exists return the last modified date of any file in it var location = GetLocation(item); if (!Directory.Exists(location)) { return DateTime.MinValue; } var files = new DirectoryInfo(location).EnumerateFiles("*", SearchOption.TopDirectoryOnly).ToList(); if (files.Count == 0) { return DateTime.MinValue; } return files.Select(f => { var lastWriteTime = GetLastWriteTimeUtc(f); var creationTime = GetCreationTimeUtc(f); return creationTime > lastWriteTime ? creationTime : lastWriteTime; }).Max(); } /// /// Gets the creation time UTC. /// /// The info. /// DateTime. private DateTime GetLastWriteTimeUtc(FileSystemInfo info) { // This could throw an error on some file systems that have dates out of range try { return info.LastAccessTimeUtc; } catch (Exception ex) { Logger.ErrorException("Error determining LastAccessTimeUtc for {0}", ex, info.FullName); return DateTime.MinValue; } } /// /// Gets the creation time UTC. /// /// The info. /// DateTime. private DateTime GetCreationTimeUtc(FileSystemInfo info) { // This could throw an error on some file systems that have dates out of range try { return info.CreationTimeUtc; } catch (Exception ex) { Logger.ErrorException("Error determining CreationTimeUtc for {0}", ex, info.FullName); return DateTime.MinValue; } } /// /// Fetches metadata and returns true or false indicating if any work that requires persistence was done /// /// The item. /// if set to true [force]. /// The cancellation token. /// Task{System.Boolean}. public override async Task FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) { var result = await base.FetchAsync(item, force, cancellationToken).ConfigureAwait(false); BaseProviderInfo data; if (item.ProviderData.TryGetValue(Id, out data)) { data.CustomData = ConfigurationManager.ApplicationPaths.ItemsByNamePath; } return result; } /// /// Gets the location. /// /// The item. /// System.String. protected string GetLocation(BaseItem item) { var name = FileSystem.GetValidFilename(item.Name); return Path.Combine(ConfigurationManager.ApplicationPaths.GeneralPath, name); } /// /// Gets the image. /// /// The item. /// The filename without extension. /// System.Nullable{WIN32_FIND_DATA}. protected override WIN32_FIND_DATA? GetImage(BaseItem item, string filenameWithoutExtension) { var location = GetLocation(item); var result = FileSystem.GetFileData(Path.Combine(location, filenameWithoutExtension + ".png")); if (!result.HasValue) result = FileSystem.GetFileData(Path.Combine(location, filenameWithoutExtension + ".jpg")); return result; } } }