diff options
| -rw-r--r-- | MediaBrowser.Controller/Entities/BaseItem.cs | 4 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Entities/IHasMetadata.cs | 6 | ||||
| -rw-r--r-- | MediaBrowser.Controller/MediaBrowser.Controller.csproj | 2 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Providers/IProviderManager.cs | 11 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Providers/ItemIdentifier.cs | 73 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Providers/ItemIdentities.cs | 43 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Providers/ItemLookupInfo.cs | 76 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Manager/MetadataService.cs | 51 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Manager/ProviderManager.cs | 26 | ||||
| -rw-r--r-- | MediaBrowser.Providers/MediaBrowser.Providers.csproj | 1 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs | 64 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs | 29 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs | 5 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/TvdbSeriesProvider.cs | 26 | ||||
| -rw-r--r-- | MediaBrowser.ServerApplication/ApplicationHost.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.sln | 4 |
16 files changed, 381 insertions, 52 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index b7edbfc60..a2ff1b4fd 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -32,6 +32,7 @@ namespace MediaBrowser.Controller.Entities ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); LockedFields = new List<MetadataFields>(); ImageInfos = new List<ItemImageInfo>(); + Identities = new List<IItemIdentity>(); } /// <summary> @@ -244,6 +245,9 @@ namespace MediaBrowser.Controller.Entities public bool IsUnidentified { get; set; } + [IgnoreDataMember] + public List<IItemIdentity> Identities { get; set; } + /// <summary> /// Gets or sets the locked fields. /// </summary> diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 91f37135f..4e90fb155 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; @@ -55,5 +56,10 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value><c>true</c> if this instance is unidentified; otherwise, <c>false</c>.</value> bool IsUnidentified { get; set; } + + /// <summary> + /// Gets the item identities. + /// </summary> + List<IItemIdentity> Identities { get; set; } } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 7bc82f76d..addcaea8d 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -225,6 +225,8 @@ <Compile Include="Security\IEncryptionManager.cs" /> <Compile Include="Subtitles\ISubtitleManager.cs" /> <Compile Include="Subtitles\ISubtitleProvider.cs" /> + <Compile Include="Providers\ItemIdentifier.cs" /> + <Compile Include="Providers\ItemIdentities.cs" /> <Compile Include="Providers\ItemLookupInfo.cs" /> <Compile Include="Providers\MetadataRefreshOptions.cs" /> <Compile Include="Providers\NameParser.cs" /> diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 94b19498a..883fa12b4 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -54,11 +54,13 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="imageProviders">The image providers.</param> /// <param name="metadataServices">The metadata services.</param> + /// <param name="identityProviders">The identity providers.</param> + /// <param name="identityConverters">The identity converters.</param> /// <param name="metadataProviders">The metadata providers.</param> /// <param name="savers">The savers.</param> /// <param name="imageSavers">The image savers.</param> /// <param name="externalIds">The external ids.</param> - void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, + void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> savers, IEnumerable<IImageSaver> imageSavers, IEnumerable<IExternalId> externalIds); @@ -136,5 +138,12 @@ namespace MediaBrowser.Controller.Providers /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{HttpResponseInfo}.</returns> Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken); + + IEnumerable<IItemIdentityProvider<TLookupInfo, TIdentity>> GetItemIdentityProviders<TLookupInfo, TIdentity>() + where TLookupInfo : ItemLookupInfo + where TIdentity : IItemIdentity; + + IEnumerable<IItemIdentityConverter<TIdentity>> GetItemIdentityConverters<TIdentity>() + where TIdentity : IItemIdentity; } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemIdentifier.cs b/MediaBrowser.Controller/Providers/ItemIdentifier.cs new file mode 100644 index 000000000..13e4f137f --- /dev/null +++ b/MediaBrowser.Controller/Providers/ItemIdentifier.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Providers +{ + public class ItemIdentifier<TLookupInfo, TIdentity> + where TLookupInfo : ItemLookupInfo + where TIdentity : IItemIdentity + { + public async Task<IEnumerable<TIdentity>> FindIdentities(TLookupInfo item, IProviderManager providerManager, CancellationToken cancellationToken) + { + var providers = providerManager.GetItemIdentityProviders<TLookupInfo, TIdentity>(); + var converters = providerManager.GetItemIdentityConverters<TIdentity>(); + + var identities = new List<IdentityPair>(); + + foreach (var provider in providers) + { + var result = new IdentityPair + { + Identity = await provider.FindIdentity(item), + Order = provider.Order + }; + + if (!Equals(result.Identity, default(TIdentity))) + { + identities.Add(result); + } + } + + var convertersAvailable = new List<IItemIdentityConverter<TIdentity>>(converters); + bool changesMade; + + do + { + changesMade = false; + + for (int i = convertersAvailable.Count - 1; i >= 0; i--) + { + var converter = convertersAvailable[i]; + var input = identities.FirstOrDefault(id => id.Identity.Type == converter.SourceType); + var existing = identities.Where(id => id.Identity.Type == converter.ResultType); + + if (input != null && !existing.Any(id => id.Order <= converter.Order)) + { + var result = new IdentityPair + { + Identity = await converter.Convert(input.Identity).ConfigureAwait(false), + Order = converter.Order + }; + + if (!Equals(result.Identity, default(TIdentity))) + { + identities.Add(result); + convertersAvailable.RemoveAt(i); + changesMade = true; + } + } + } + } while (changesMade); + + return identities.OrderBy(id => id.Order).Select(id => id.Identity); + } + + private class IdentityPair + { + public TIdentity Identity; + public int Order; + } + } +}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemIdentities.cs b/MediaBrowser.Controller/Providers/ItemIdentities.cs new file mode 100644 index 000000000..93d468af0 --- /dev/null +++ b/MediaBrowser.Controller/Providers/ItemIdentities.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Providers +{ + public interface IItemIdentity + { + string Type { get; } + } + + public interface IHasIdentities<out TIdentity> + where TIdentity : IItemIdentity + { + IEnumerable<TIdentity> Identities { get; } + + Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken); + } + + public interface IItemIdentityProvider : IHasOrder { } + + public interface IItemIdentityProvider<in TLookupInfo, TIdentity> : IItemIdentityProvider + where TLookupInfo : ItemLookupInfo + where TIdentity : IItemIdentity + { + Task<TIdentity> FindIdentity(TLookupInfo info); + } + + public interface IItemIdentityConverter : IHasOrder { } + + public interface IItemIdentityConverter<TIdentity> : IItemIdentityConverter + where TIdentity : IItemIdentity + { + Task<TIdentity> Convert(TIdentity identity); + + string SourceType { get; } + + string ResultType { get; } + } +}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs index 65ee94556..20bc572b4 100644 --- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs @@ -1,4 +1,7 @@ -using MediaBrowser.Model.Entities; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; @@ -96,8 +99,10 @@ namespace MediaBrowser.Controller.Providers public string Path { get; set; } } - public class EpisodeInfo : ItemLookupInfo + public class EpisodeInfo : ItemLookupInfo, IHasIdentities<EpisodeIdentity> { + private List<EpisodeIdentity> _identities = new List<EpisodeIdentity>(); + public Dictionary<string, string> SeriesProviderIds { get; set; } public int? IndexNumberEnd { get; set; } @@ -107,6 +112,27 @@ namespace MediaBrowser.Controller.Providers { SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } + + public IEnumerable<EpisodeIdentity> Identities + { + get { return _identities; } + } + + public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) + { + var identifier = new ItemIdentifier<EpisodeInfo, EpisodeIdentity>(); + _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); + } + } + + public class EpisodeIdentity : IItemIdentity + { + public string Type { get; set; } + + public string SeriesId { get; set; } + public int? SeasonIndex { get; set; } + public int IndexNumber { get; set; } + public int? IndexNumberEnd { get; set; } } public class SongInfo : ItemLookupInfo @@ -116,9 +142,29 @@ namespace MediaBrowser.Controller.Providers public List<string> Artists { get; set; } } - public class SeriesInfo : ItemLookupInfo + public class SeriesInfo : ItemLookupInfo, IHasIdentities<SeriesIdentity> { + private List<SeriesIdentity> _identities = new List<SeriesIdentity>(); + public int? AnimeSeriesIndex { get; set; } + + public IEnumerable<SeriesIdentity> Identities + { + get { return _identities; } + } + + public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) + { + var identifier = new ItemIdentifier<SeriesInfo, SeriesIdentity>(); + _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); + } + } + + public class SeriesIdentity : IItemIdentity + { + public string Type { get; set; } + + public string Id { get; set; } } public class PersonLookupInfo : ItemLookupInfo @@ -151,8 +197,10 @@ namespace MediaBrowser.Controller.Providers public string SeriesName { get; set; } } - public class SeasonInfo : ItemLookupInfo + public class SeasonInfo : ItemLookupInfo, IHasIdentities<SeasonIdentity> { + private List<SeasonIdentity> _identities = new List<SeasonIdentity>(); + public Dictionary<string, string> SeriesProviderIds { get; set; } public int? AnimeSeriesIndex { get; set; } @@ -160,5 +208,25 @@ namespace MediaBrowser.Controller.Providers { SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } + + public IEnumerable<SeasonIdentity> Identities + { + get { return _identities; } + } + + public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) + { + var identifier = new ItemIdentifier<SeasonInfo, SeasonIdentity>(); + _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); + } + } + + public class SeasonIdentity : IItemIdentity + { + public string Type { get; set; } + + public string SeriesId { get; set; } + + public int SeasonIndex { get; set; } } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index e40f49acf..717b93524 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -104,6 +104,9 @@ namespace MediaBrowser.Providers.Manager refreshResult.AddStatus(ProviderRefreshStatus.Failure, ex.Message); } + // Identify item + TIdType id = null; + // Next run metadata providers if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) { @@ -120,7 +123,8 @@ namespace MediaBrowser.Providers.Manager if (providers.Count > 0) { - var result = await RefreshWithProviders(itemOfType, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false); + id = await CreateInitialLookupInfo(itemOfType, cancellationToken).ConfigureAwait(false); + var result = await RefreshWithProviders(itemOfType, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false); updateType = updateType | result.UpdateType; refreshResult.AddStatus(result.Status, result.ErrorMessage); @@ -129,6 +133,13 @@ namespace MediaBrowser.Providers.Manager } } + if (id == null) + { + id = await CreateInitialLookupInfo(itemOfType, cancellationToken).ConfigureAwait(false); + } + + MergeIdentities(itemOfType, id); + // Next run remote image providers, but only if local image providers didn't throw an exception if (!localImagesFailed && refreshOptions.ImageRefreshMode != ImageRefreshMode.ValidationOnly) { @@ -162,6 +173,15 @@ namespace MediaBrowser.Providers.Manager } } + private void MergeIdentities(TItemType item, TIdType id) + { + var hasIdentity = id as IHasIdentities<IItemIdentity>; + if (hasIdentity != null) + { + item.Identities = hasIdentity.Identities.ToList(); + } + } + /// <summary> /// Befores the save. /// </summary> @@ -259,7 +279,7 @@ namespace MediaBrowser.Providers.Manager return item is TItemType; } - protected virtual async Task<RefreshResult> RefreshWithProviders(TItemType item, MetadataRefreshOptions options, List<IMetadataProvider> providers, ItemImageProvider imageService, CancellationToken cancellationToken) + protected virtual async Task<RefreshResult> RefreshWithProviders(TItemType item, TIdType id, MetadataRefreshOptions options, List<IMetadataProvider> providers, ItemImageProvider imageService, CancellationToken cancellationToken) { var refreshResult = new RefreshResult { @@ -280,7 +300,7 @@ namespace MediaBrowser.Providers.Manager // If replacing all metadata, run internet providers first if (options.ReplaceAllMetadata) { - await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false); + await ExecuteRemoteProviders(item, temp, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false); } var hasLocalMetadata = false; @@ -333,7 +353,7 @@ namespace MediaBrowser.Providers.Manager // Local metadata is king - if any is found don't run remote providers if (!options.ReplaceAllMetadata && (!hasLocalMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh)) { - await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false); + await ExecuteRemoteProviders(item, temp, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false); } if (refreshResult.UpdateType > ItemUpdateType.None) @@ -374,10 +394,8 @@ namespace MediaBrowser.Providers.Manager return new TItemType(); } - private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, IEnumerable<IRemoteMetadataProvider<TItemType, TIdType>> providers, RefreshResult refreshResult, CancellationToken cancellationToken) + private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, TIdType id, IEnumerable<IRemoteMetadataProvider<TItemType, TIdType>> providers, RefreshResult refreshResult, CancellationToken cancellationToken) { - TIdType id = null; - var unidentifiedCount = 0; var identifiedCount = 0; @@ -386,11 +404,7 @@ namespace MediaBrowser.Providers.Manager var providerName = provider.GetType().Name; Logger.Debug("Running {0} for {1}", providerName, item.Path ?? item.Name); - if (id == null) - { - id = item.GetLookupInfo(); - } - else + if (id != null) { MergeNewData(temp, id); } @@ -435,6 +449,19 @@ namespace MediaBrowser.Providers.Manager } } + private async Task<TIdType> CreateInitialLookupInfo(TItemType item, CancellationToken cancellationToken) + { + var info = item.GetLookupInfo(); + + var hasIdentity = info as IHasIdentities<IItemIdentity>; + if (hasIdentity != null) + { + await hasIdentity.FindIdentities(ProviderManager, cancellationToken).ConfigureAwait(false); + } + + return info; + } + private void MergeNewData(TItemType source, TIdType lookupInfo) { // Copy new provider id's that may have been obtained diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 864435e40..6f33de67f 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -53,6 +53,8 @@ namespace MediaBrowser.Providers.Manager private readonly IFileSystem _fileSystem; private IMetadataService[] _metadataServices = { }; + private IItemIdentityProvider[] _identityProviders = { }; + private IItemIdentityConverter[] _identityConverters = { }; private IMetadataProvider[] _metadataProviders = { }; private IEnumerable<IMetadataSaver> _savers; private IImageSaver[] _imageSavers; @@ -81,17 +83,22 @@ namespace MediaBrowser.Providers.Manager /// </summary> /// <param name="imageProviders">The image providers.</param> /// <param name="metadataServices">The metadata services.</param> + /// <param name="identityProviders">The identity providers.</param> + /// <param name="identityConverters">The identity converters.</param> /// <param name="metadataProviders">The metadata providers.</param> /// <param name="metadataSavers">The metadata savers.</param> /// <param name="imageSavers">The image savers.</param> /// <param name="externalIds">The external ids.</param> - public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers, - IEnumerable<IImageSaver> imageSavers, - IEnumerable<IExternalId> externalIds) + public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, + IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters, + IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers, + IEnumerable<IImageSaver> imageSavers, IEnumerable<IExternalId> externalIds) { ImageProviders = imageProviders.ToArray(); _metadataServices = metadataServices.OrderBy(i => i.Order).ToArray(); + _identityProviders = identityProviders.ToArray(); + _identityConverters = identityConverters.ToArray(); _metadataProviders = metadataProviders.ToArray(); _savers = metadataSavers.ToArray(); _imageSavers = imageSavers.ToArray(); @@ -257,6 +264,19 @@ namespace MediaBrowser.Providers.Manager .ThenBy(GetDefaultOrder); } + public IEnumerable<IItemIdentityProvider<TLookupInfo, TIdentity>> GetItemIdentityProviders<TLookupInfo, TIdentity>() + where TLookupInfo : ItemLookupInfo + where TIdentity : IItemIdentity + { + return _identityProviders.OfType<IItemIdentityProvider<TLookupInfo, TIdentity>>(); + } + + public IEnumerable<IItemIdentityConverter<TIdentity>> GetItemIdentityConverters<TIdentity>() + where TIdentity : IItemIdentity + { + return _identityConverters.OfType<IItemIdentityConverter<TIdentity>>(); + } + private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(IHasImages item, bool includeDisabled) { var options = GetMetadataOptions(item); diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 3ad4a608a..3978b36bb 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -205,6 +205,7 @@ <Compile Include="TV\SeriesMetadataService.cs" /> <Compile Include="TV\TvdbEpisodeImageProvider.cs" /> <Compile Include="People\TvdbPersonImageProvider.cs" /> + <Compile Include="TV\TvdbSeasonIdentityProvider.cs" /> <Compile Include="TV\TvdbSeasonImageProvider.cs" /> <Compile Include="TV\TvdbSeriesImageProvider.cs" /> <Compile Include="TV\SeasonMetadataService.cs" /> diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index ba7455e23..dd9f3af8b 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.TV /// <summary> /// Class RemoteEpisodeProvider /// </summary> - class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IHasChangeMonitor + class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IItemIdentityProvider<EpisodeInfo, EpisodeIdentity>, IHasChangeMonitor { internal static TvdbEpisodeProvider Current; private readonly IFileSystem _fileSystem; @@ -40,19 +40,18 @@ namespace MediaBrowser.Providers.TV { var list = new List<RemoteSearchResult>(); - string seriesTvdbId; - searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId); + var identity = searchInfo.Identities.FirstOrDefault(id => id.Type == MetadataProviders.Tvdb.ToString()) ?? await FindIdentity(searchInfo).ConfigureAwait(false); - if (!string.IsNullOrEmpty(seriesTvdbId)) + if (identity != null) { - await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesTvdbId, searchInfo.MetadataLanguage, + await TvdbSeriesProvider.Current.EnsureSeriesInfo(identity.SeriesId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false); - var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesTvdbId); + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, identity.SeriesId); try { - var item = FetchEpisodeData(searchInfo, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken); + var item = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken); if (item != null) { @@ -83,20 +82,19 @@ namespace MediaBrowser.Providers.TV get { return "TheTVDB"; } } - public Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, CancellationToken cancellationToken) + public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, CancellationToken cancellationToken) { - string seriesTvdbId; - searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId); + var identity = searchInfo.Identities.FirstOrDefault(id => id.Type == MetadataProviders.Tvdb.ToString()) ?? await FindIdentity(searchInfo).ConfigureAwait(false); var result = new MetadataResult<Episode>(); - if (!string.IsNullOrEmpty(seriesTvdbId)) + if (identity != null) { - var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesTvdbId); + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, identity.SeriesId); try { - result.Item = FetchEpisodeData(searchInfo, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken); + result.Item = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken); result.HasMetadata = result.Item != null; } catch (FileNotFoundException) @@ -105,7 +103,7 @@ namespace MediaBrowser.Providers.TV } } - return Task.FromResult(result); + return result; } public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) @@ -211,18 +209,14 @@ namespace MediaBrowser.Providers.TV /// </summary> /// <param name="id">The identifier.</param> /// <param name="seriesDataPath">The series data path.</param> + /// <param name="seriesProviderIds"></param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{System.Boolean}.</returns> - private Episode FetchEpisodeData(EpisodeInfo id, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken) + private Episode FetchEpisodeData(EpisodeInfo id, EpisodeIdentity identity, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken) { - if (id.IndexNumber == null) - { - return null; - } - - var episodeNumber = id.IndexNumber.Value; + var episodeNumber = identity.IndexNumber; var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(seriesProviderIds) ?? 0; - var seasonNumber = id.ParentIndexNumber + seasonOffset; + var seasonNumber = identity.SeasonIndex + seasonOffset; if (seasonNumber == null) { @@ -263,7 +257,7 @@ namespace MediaBrowser.Providers.TV usingAbsoluteData = true; } - var end = id.IndexNumberEnd ?? episodeNumber; + var end = identity.IndexNumberEnd ?? episodeNumber; episodeNumber++; while (episodeNumber <= end) @@ -726,5 +720,29 @@ namespace MediaBrowser.Providers.TV { throw new NotImplementedException(); } + + public Task<EpisodeIdentity> FindIdentity(EpisodeInfo info) + { + string seriesTvdbId; + info.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId); + + if (string.IsNullOrEmpty(seriesTvdbId) || info.IndexNumber == null) + { + return Task.FromResult<EpisodeIdentity>(null); + } + + var id = new EpisodeIdentity + { + Type = MetadataProviders.Tvdb.ToString(), + SeriesId = seriesTvdbId, + SeasonIndex = info.ParentIndexNumber, + IndexNumber = info.IndexNumber.Value, + IndexNumberEnd = info.IndexNumberEnd + }; + + return Task.FromResult(id); + } + + public int Order { get { return 0; } } } } diff --git a/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs new file mode 100644 index 000000000..5876c9998 --- /dev/null +++ b/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Providers.TV +{ + public class TvdbSeasonIdentityProvider : IItemIdentityProvider<SeasonInfo, SeasonIdentity> + { + public Task<SeasonIdentity> FindIdentity(SeasonInfo info) + { + string tvdbSeriesId; + if (!info.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out tvdbSeriesId) || string.IsNullOrEmpty(tvdbSeriesId) || info.IndexNumber == null) + { + return Task.FromResult<SeasonIdentity>(null); + } + + var result = new SeasonIdentity + { + Type = MetadataProviders.Tvdb.ToString(), + SeriesId = tvdbSeriesId, + SeasonIndex = info.IndexNumber.Value + }; + + return Task.FromResult(result); + } + + public int Order { get { return 0; } } + } +}
\ No newline at end of file diff --git a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs index 5a9981c6e..af1edeed0 100644 --- a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs @@ -65,7 +65,8 @@ namespace MediaBrowser.Providers.TV var season = (Season)item; var series = season.Series; - var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tvdb) : null; + var identity = season.Identities.OfType<SeasonIdentity>().FirstOrDefault(id => id.Type == MetadataProviders.Tvdb.ToString()); + var seriesId = identity != null ? identity.SeriesId : null; if (!string.IsNullOrEmpty(seriesId) && season.IndexNumber.HasValue) { @@ -78,7 +79,7 @@ namespace MediaBrowser.Providers.TV try { - int seasonNumber = AdjustForSeriesOffset(series, season.IndexNumber.Value); + int seasonNumber = AdjustForSeriesOffset(series, identity.SeasonIndex); return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, cancellationToken); } catch (FileNotFoundException) diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index f9ebaddf8..6ca548829 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -23,7 +23,7 @@ using System.Xml; namespace MediaBrowser.Providers.TV { - public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder + public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IItemIdentityProvider<SeriesInfo, SeriesIdentity>, IHasOrder { private const string TvdbSeriesOffset = "TvdbSeriesOffset"; private const string TvdbSeriesOffsetFormat = "{0}-{1}"; @@ -72,7 +72,15 @@ namespace MediaBrowser.Providers.TV if (string.IsNullOrEmpty(seriesId)) { - seriesId = await FindSeries(itemId.Name, cancellationToken).ConfigureAwait(false); + seriesId = itemId.Identities + .Where(id => id.Type == MetadataProviders.Tvdb.ToString()) + .Select(id => id.Id) + .FirstOrDefault(); + + if (string.IsNullOrEmpty(seriesId)) + { + seriesId = await FindSeries(itemId.Name, cancellationToken).ConfigureAwait(false); + } if (string.IsNullOrEmpty(seriesId)) { @@ -1121,6 +1129,20 @@ namespace MediaBrowser.Providers.TV get { return "TheTVDB"; } } + public async Task<SeriesIdentity> FindIdentity(SeriesInfo info) + { + string tvdbId; + if (!info.ProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out tvdbId)) + tvdbId = await FindSeries(info.Name, CancellationToken.None); + + if (!string.IsNullOrEmpty(tvdbId)) + { + return new SeriesIdentity {Type = MetadataProviders.Tvdb.ToString(), Id = tvdbId}; + } + + return null; + } + public int Order { get diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 675e67041..1c1595093 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -722,10 +722,14 @@ namespace MediaBrowser.ServerApplication GetExports<IBaseItemComparer>(), GetExports<ILibraryPostScanTask>()); - ProviderManager.AddParts(GetExports<IImageProvider>(), GetExports<IMetadataService>(), GetExports<IMetadataProvider>(), - GetExports<IMetadataSaver>(), - GetExports<IImageSaver>(), - GetExports<IExternalId>()); + ProviderManager.AddParts(GetExports<IImageProvider>(), + GetExports<IMetadataService>(), + GetExports<IItemIdentityProvider>(), + GetExports<IItemIdentityConverter>(), + GetExports<IMetadataProvider>(), + GetExports<IMetadataSaver>(), + GetExports<IImageSaver>(), + GetExports<IExternalId>()); SeriesOrderManager.AddParts(GetExports<ISeriesOrderProvider>()); diff --git a/MediaBrowser.sln b/MediaBrowser.sln index f2b7a612c..1b132e07f 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -1,6 +1,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}" |
