瀏覽代碼

implement series searching

Luke Pulverenti 11 年之前
父節點
當前提交
e1387a24c1

+ 39 - 2
MediaBrowser.Api/ItemLookupService.cs

@@ -5,7 +5,9 @@ using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Providers;
 using ServiceStack;
 using System;
@@ -81,20 +83,30 @@ namespace MediaBrowser.Api
         [ApiMember(Name = "ProviderName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string ProviderName { get; set; }
     }
-    
+
+    [Route("/Items/RemoteSearch/Apply/{Id}", "POST")]
+    [Api(Description = "Applies search criteria to an item and refreshes metadata")]
+    public class ApplySearchCriteria : RemoteSearchResult, IReturnVoid
+    {
+        [ApiMember(Name = "Id", Description = "The item id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public string Id { get; set; }
+    }
+
     public class ItemLookupService : BaseApiService
     {
         private readonly IDtoService _dtoService;
         private readonly IProviderManager _providerManager;
         private readonly IServerApplicationPaths _appPaths;
         private readonly IFileSystem _fileSystem;
+        private readonly ILibraryManager _libraryManager;
 
-        public ItemLookupService(IDtoService dtoService, IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem)
+        public ItemLookupService(IDtoService dtoService, IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager)
         {
             _dtoService = dtoService;
             _providerManager = providerManager;
             _appPaths = appPaths;
             _fileSystem = fileSystem;
+            _libraryManager = libraryManager;
         }
 
         public object Get(GetExternalIdInfos request)
@@ -162,6 +174,31 @@ namespace MediaBrowser.Api
             return result;
         }
 
+        public void Post(ApplySearchCriteria request)
+        {
+            var item = _libraryManager.GetItemById(new Guid(request.Id));
+
+            foreach (var key in request.ProviderIds)
+            {
+                var value = key.Value;
+
+                if (!string.IsNullOrWhiteSpace(value))
+                {
+                    item.SetProviderId(key.Key, value);
+                }
+            }
+
+            var task = item.RefreshMetadata(new MetadataRefreshOptions
+            {
+                MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
+                ImageRefreshMode = ImageRefreshMode.FullRefresh,
+                ReplaceAllMetadata = true
+
+            }, CancellationToken.None);
+
+            Task.WaitAll(task);
+        }
+
         /// <summary>
         /// Gets the remote image.
         /// </summary>

+ 18 - 2
MediaBrowser.Providers/Manager/ProviderManager.cs

@@ -492,7 +492,7 @@ namespace MediaBrowser.Providers.Manager
                     Type = MetadataPluginType.MetadataFetcher
                 }));
             }
-            
+
             if (item.IsSaveLocalMetadataEnabled())
             {
                 // Savers
@@ -668,7 +668,7 @@ namespace MediaBrowser.Providers.Manager
 
             foreach (var provider in providers)
             {
-                var results = await provider.GetSearchResults(searchInfo.SearchInfo, cancellationToken).ConfigureAwait(false);
+                var results = await GetSearchResults(provider, searchInfo.SearchInfo, cancellationToken).ConfigureAwait(false);
 
                 var list = results.ToList();
 
@@ -682,6 +682,22 @@ namespace MediaBrowser.Providers.Manager
             return new List<RemoteSearchResult>();
         }
 
+        private async Task<IEnumerable<RemoteSearchResult>> GetSearchResults<TLookupType>(IRemoteSearchProvider<TLookupType> provider, TLookupType searchInfo,
+            CancellationToken cancellationToken)
+            where TLookupType : ItemLookupInfo
+        {
+            var results = await provider.GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
+
+            var list = results.ToList();
+
+            foreach (var item in list)
+            {
+                item.SearchProviderName = provider.Name;
+            }
+
+            return list;
+        }
+
         public Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken)
         {
             var provider = _metadataProviders.OfType<IRemoteSearchProvider>().FirstOrDefault(i => string.Equals(i.Name, providerName, StringComparison.OrdinalIgnoreCase));

+ 0 - 56
MediaBrowser.Providers/Movies/MovieDbSearch.cs

@@ -144,62 +144,6 @@ namespace MediaBrowser.Providers.Movies
             return 0;
         }
 
-        private TmdbMovieSearchResult FindBestResult(List<TmdbMovieSearchResult> results, string name, int? year)
-        {
-            if (year.HasValue)
-            {
-                // Take the first result from the same year
-                var result = results.FirstOrDefault(i =>
-                {
-                    // Make sure it has a name
-                    if (!string.IsNullOrEmpty(i.title ?? i.name))
-                    {
-                        DateTime r;
-
-                        // These dates are always in this exact format
-                        if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
-                        {
-                            return r.Year == year.Value;
-                        }
-                    }
-
-                    return false;
-                });
-
-                if (result != null)
-                {
-                    return result;
-                }
-
-                // Take the first result within one year
-                result = results.FirstOrDefault(i =>
-                {
-                    // Make sure it has a name
-                    if (!string.IsNullOrEmpty(i.title ?? i.name))
-                    {
-                        DateTime r;
-
-                        // These dates are always in this exact format
-                        if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
-                        {
-                            return Math.Abs(r.Year - year.Value) <= 1;
-                        }
-                    }
-
-                    return false;
-                });
-
-                if (result != null)
-                {
-                    return result;
-                }
-            }
-
-            // Just take the first one
-            return results.FirstOrDefault(i => !string.IsNullOrEmpty(i.title ?? i.name));
-        }
-
-
         /// <summary>
         /// Class TmdbMovieSearchResult
         /// </summary>

+ 8 - 5
MediaBrowser.Providers/TV/MissingEpisodeProvider.cs

@@ -105,12 +105,15 @@ namespace MediaBrowser.Providers.TV
                 hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
             }
 
-            var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase));
-
-            if (seriesConfig == null || !seriesConfig.DisabledMetadataFetchers.Contains(TvdbSeriesProvider.Current.Name, StringComparer.OrdinalIgnoreCase))
+            if (_config.Configuration.EnableInternetProviders)
             {
-                hasNewEpisodes = await AddMissingEpisodes(group.ToList(), seriesDataPath, episodeLookup, cancellationToken)
-                    .ConfigureAwait(false);
+                var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase));
+
+                if (seriesConfig == null || !seriesConfig.DisabledMetadataFetchers.Contains(TvdbSeriesProvider.Current.Name, StringComparer.OrdinalIgnoreCase))
+                {
+                    hasNewEpisodes = await AddMissingEpisodes(group.ToList(), seriesDataPath, episodeLookup, cancellationToken)
+                        .ConfigureAwait(false);
+                }
             }
 
             if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)

+ 126 - 14
MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs

@@ -4,6 +4,7 @@ using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
@@ -21,7 +22,7 @@ using System.Threading.Tasks;
 
 namespace MediaBrowser.Providers.TV
 {
-    public class MovieDbSeriesProvider : IRemoteMetadataProvider<Series,SeriesInfo>, IHasOrder
+    public class MovieDbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
     {
         private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}?api_key={1}&append_to_response=casts,images,keywords,external_ids";
         private readonly CultureInfo _usCulture = new CultureInfo("en-US");
@@ -53,7 +54,108 @@ namespace MediaBrowser.Providers.TV
 
         public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
         {
-            return new List<RemoteSearchResult>();
+            var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+
+            var tmdbImageUrl = tmdbSettings.images.base_url + "original";
+            
+            var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb);
+
+            if (!string.IsNullOrEmpty(tmdbId))
+            {
+                cancellationToken.ThrowIfCancellationRequested();
+
+                await EnsureSeriesInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
+                
+                var dataFilePath = GetDataFilePath(tmdbId, searchInfo.MetadataLanguage);
+
+                var obj = _jsonSerializer.DeserializeFromFile<RootObject>(dataFilePath);
+
+                var remoteResult = new RemoteSearchResult
+                {
+                    Name = obj.name,
+                    SearchProviderName = Name,
+                    ImageUrl = string.IsNullOrWhiteSpace(obj.poster_path) ? null : tmdbImageUrl + obj.poster_path
+                };
+
+                remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture));
+                remoteResult.SetProviderId(MetadataProviders.Imdb, obj.external_ids.imdb_id);
+
+                if (obj.external_ids.tvdb_id > 0)
+                {
+                    remoteResult.SetProviderId(MetadataProviders.Tvdb, obj.external_ids.tvdb_id.ToString(_usCulture));
+                }
+                
+                return new[] { remoteResult };
+            }
+
+            var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb);
+
+            if (!string.IsNullOrEmpty(imdbId))
+            {
+                var searchResult = await FindByExternalId(imdbId, "imdb_id", cancellationToken).ConfigureAwait(false);
+
+                if (searchResult != null)
+                {
+                    var remoteResult = new RemoteSearchResult
+                    {
+                        Name = searchResult.name,
+                        SearchProviderName = Name,
+                        ImageUrl = string.IsNullOrWhiteSpace(searchResult.poster_path) ? null : tmdbImageUrl + searchResult.poster_path
+                    };
+
+                    remoteResult.SetProviderId(MetadataProviders.Tmdb, searchResult.id.ToString(_usCulture));
+
+                    return new[] { remoteResult };
+                }
+            }
+
+            var tvdbId = searchInfo.GetProviderId(MetadataProviders.Tvdb);
+
+            if (!string.IsNullOrEmpty(tvdbId))
+            {
+                var searchResult = await FindByExternalId(tvdbId, "tvdb_id", cancellationToken).ConfigureAwait(false);
+
+                if (searchResult != null)
+                {
+                    var remoteResult = new RemoteSearchResult
+                    {
+                        Name = searchResult.name,
+                        SearchProviderName = Name,
+                        ImageUrl = string.IsNullOrWhiteSpace(searchResult.poster_path) ? null : tmdbImageUrl + searchResult.poster_path
+                    };
+
+                    remoteResult.SetProviderId(MetadataProviders.Tmdb, searchResult.id.ToString(_usCulture));
+
+                    return new[] { remoteResult };
+                }
+            }
+
+            var searchResults = await new MovieDbSearch(_logger, _jsonSerializer).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
+
+            return searchResults.Select(i =>
+            {
+                var remoteResult = new RemoteSearchResult
+                {
+                    SearchProviderName = Name,
+                    Name = i.name,
+                    ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : tmdbImageUrl + i.poster_path
+                };
+
+                if (!string.IsNullOrWhiteSpace(i.release_date))
+                {
+                    DateTime r;
+
+                    // These dates are always in this exact format
+                    if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", _usCulture, DateTimeStyles.None, out r))
+                    {
+                        remoteResult.PremiereDate = r.ToUniversalTime();
+                    }
+                }
+
+                remoteResult.SetProviderId(MetadataProviders.Tmdb, i.id.ToString(_usCulture));
+
+                return remoteResult;
+            });
         }
 
         public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
@@ -68,7 +170,12 @@ namespace MediaBrowser.Providers.TV
 
                 if (!string.IsNullOrEmpty(imdbId))
                 {
-                    tmdbId = await FindIdByExternalId(imdbId, "imdb_id", cancellationToken).ConfigureAwait(false);
+                    var searchResult = await FindByExternalId(imdbId, "imdb_id", cancellationToken).ConfigureAwait(false);
+
+                    if (searchResult != null)
+                    {
+                        tmdbId = searchResult.id.ToString(_usCulture);
+                    }
                 }
             }
 
@@ -78,7 +185,12 @@ namespace MediaBrowser.Providers.TV
 
                 if (!string.IsNullOrEmpty(tvdbId))
                 {
-                    tmdbId = await FindIdByExternalId(tvdbId, "tvdb_id", cancellationToken).ConfigureAwait(false);
+                    var searchResult = await FindByExternalId(tvdbId, "tvdb_id", cancellationToken).ConfigureAwait(false);
+
+                    if (searchResult != null)
+                    {
+                        tmdbId = searchResult.id.ToString(_usCulture);
+                    }
                 }
             }
 
@@ -102,7 +214,7 @@ namespace MediaBrowser.Providers.TV
 
                 result.HasMetadata = result.Item != null;
             }
-            
+
             return result;
         }
 
@@ -123,7 +235,7 @@ namespace MediaBrowser.Providers.TV
 
             tmdbId = seriesInfo.id.ToString(_usCulture);
 
-            dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language);
+            dataFilePath = GetDataFilePath(tmdbId, language);
             Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
             _jsonSerializer.SerializeToFile(seriesInfo, dataFilePath);
 
@@ -151,7 +263,7 @@ namespace MediaBrowser.Providers.TV
                 series.CommunityRating = rating;
             }
 
-           series.Overview =  seriesInfo.overview;
+            series.Overview = seriesInfo.overview;
 
             if (seriesInfo.networks != null)
             {
@@ -210,7 +322,7 @@ namespace MediaBrowser.Providers.TV
 
             return dataPath;
         }
-        
+
         internal async Task DownloadSeriesInfo(string id, string preferredMetadataLanguage, CancellationToken cancellationToken)
         {
             var mainResult = await FetchMainResult(id, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
@@ -245,7 +357,7 @@ namespace MediaBrowser.Providers.TV
 
                 url += string.Format("&language={0}", language);
             }
-            
+
             // Get images in english and with no language
             url += "&include_image_language=" + string.Join(",", imageLanguages.ToArray());
 
@@ -262,7 +374,7 @@ namespace MediaBrowser.Providers.TV
                 return _jsonSerializer.DeserializeFromStream<RootObject>(json);
             }
         }
-        
+
         private readonly Task _cachedTask = Task.FromResult(true);
         internal Task EnsureSeriesInfo(string tmdbId, string language, CancellationToken cancellationToken)
         {
@@ -332,10 +444,10 @@ namespace MediaBrowser.Providers.TV
             return false;
         }
 
-        private async Task<string> FindIdByExternalId(string id, string externalSource, CancellationToken cancellationToken)
+        private async Task<MovieDbSearch.TvResult> FindByExternalId(string id, string externalSource, CancellationToken cancellationToken)
         {
-            var url = string.Format("http://api.themoviedb.org/3/tv/find/{0}?api_key={1}&external_source={2}", 
-                id, 
+            var url = string.Format("http://api.themoviedb.org/3/tv/find/{0}?api_key={1}&external_source={2}",
+                id,
                 MovieDbProvider.ApiKey,
                 externalSource);
 
@@ -355,7 +467,7 @@ namespace MediaBrowser.Providers.TV
 
                     if (tv != null)
                     {
-                        return tv.id.ToString(_usCulture);
+                        return tv;
                     }
                 }
             }

+ 12 - 1
MediaBrowser.Providers/TV/TvdbSeriesProvider.cs

@@ -50,6 +50,12 @@ namespace MediaBrowser.Providers.TV
 
         public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
         {
+            var seriesId = searchInfo.GetProviderId(MetadataProviders.Tvdb);
+
+            if (!string.IsNullOrEmpty(seriesId))
+            {
+            }
+            
             return new List<RemoteSearchResult>();
         }
 
@@ -1092,7 +1098,12 @@ namespace MediaBrowser.Providers.TV
 
         public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            throw new NotImplementedException();
+            return _httpClient.GetResponse(new HttpRequestOptions
+            {
+                CancellationToken = cancellationToken,
+                Url = url,
+                ResourcePool = TvDbResourcePool
+            });
         }
     }
 }

+ 3 - 0
MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj

@@ -196,6 +196,9 @@
     <Content Include="dashboard-ui\css\images\items\detail\tv.png">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="dashboard-ui\css\images\items\list\remotesearch.png">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="dashboard-ui\css\images\media\tvflyout.png">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>

+ 2 - 2
Nuget/MediaBrowser.Common.Internal.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common.Internal</id>
-        <version>3.0.333</version>
+        <version>3.0.334</version>
         <title>MediaBrowser.Common.Internal</title>
         <authors>Luke</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.333" />
+            <dependency id="MediaBrowser.Common" version="3.0.334" />
             <dependency id="NLog" version="2.1.0" />
             <dependency id="SimpleInjector" version="2.4.1" />
             <dependency id="sharpcompress" version="0.10.2" />

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common</id>
-        <version>3.0.333</version>
+        <version>3.0.334</version>
         <title>MediaBrowser.Common</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>

+ 2 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.333</version>
+        <version>3.0.334</version>
         <title>Media Browser.Server.Core</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.333" />
+            <dependency id="MediaBrowser.Common" version="3.0.334" />
         </dependencies>
     </metadata>
     <files>