using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.TV; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Controller.Providers { /// /// Class SortNameProvider /// public class SortNameProvider : BaseMetadataProvider { /// /// Supportses the specified item. /// /// The item. /// true if XXXX, false otherwise public override bool Supports(BaseItem item) { return true; } /// /// 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) { return !string.IsNullOrEmpty(item.Name) && string.IsNullOrEmpty(item.SortName); } /// /// 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}. protected override Task FetchAsyncInternal(BaseItem item, bool force, CancellationToken cancellationToken) { return SetSortName(item, cancellationToken) ? TrueTaskResult : FalseTaskResult; } /// /// Sets the name of the sort. /// /// The item. /// The cancellation token. /// true if XXXX, false otherwise protected bool SetSortName(BaseItem item, CancellationToken cancellationToken) { if (!string.IsNullOrWhiteSpace(item.SortName)) return false; //let the earlier provider win cancellationToken.ThrowIfCancellationRequested(); if (item is Episode) { //special handling for TV episodes season and episode number item.SortName = (item.ParentIndexNumber != null ? item.ParentIndexNumber.Value.ToString("000-") : "") + (item.IndexNumber != null ? item.IndexNumber.Value.ToString("0000 - ") : "") + item.Name; } else if (item is Season) { //sort seasons by season number - numerically item.SortName = item.IndexNumber != null ? item.IndexNumber.Value.ToString("0000") : item.Name; } else if (item is Audio) { //sort tracks by production year and index no so they will sort in order if in a multi-album list item.SortName = (item.ProductionYear != null ? item.ProductionYear.Value.ToString("000-") : "") + (item.IndexNumber != null ? item.IndexNumber.Value.ToString("0000 - ") : "") + item.Name; } else if (item is MusicAlbum) { //sort albums by year item.SortName = item.ProductionYear != null ? item.ProductionYear.Value.ToString("0000") : item.Name; } else { if (item.Name == null) return false; //some items may not have name filled in properly var sortable = item.Name.Trim().ToLower(); sortable = Kernel.Instance.Configuration.SortRemoveCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), string.Empty)); sortable = Kernel.Instance.Configuration.SortReplaceCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), " ")); foreach (var search in Kernel.Instance.Configuration.SortRemoveWords) { cancellationToken.ThrowIfCancellationRequested(); var searchLower = search.ToLower(); // Remove from beginning if a space follows if (sortable.StartsWith(searchLower + " ")) { sortable = sortable.Remove(0, searchLower.Length + 1); } // Remove from middle if surrounded by spaces sortable = sortable.Replace(" " + searchLower + " ", " "); // Remove from end if followed by a space if (sortable.EndsWith(" " + searchLower)) { sortable = sortable.Remove(sortable.Length - (searchLower.Length + 1)); } } item.SortName = sortable; } return true; } } }