aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs252
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs27
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj1
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs12
-rw-r--r--MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs11
-rw-r--r--MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs73
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs23
-rw-r--r--MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs4
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs7
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbSearch.cs96
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs14
-rw-r--r--MediaBrowser.Providers/People/MovieDbPersonProvider.cs15
-rw-r--r--MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs15
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs28
14 files changed, 484 insertions, 94 deletions
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
new file mode 100644
index 000000000..25782f8c1
--- /dev/null
+++ b/MediaBrowser.Api/ItemLookupService.cs
@@ -0,0 +1,252 @@
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Providers;
+using ServiceStack;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Api
+{
+ [Route("/Items/{Id}/ExternalIdInfos", "GET")]
+ [Api(Description = "Gets external id infos for an item")]
+ public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>>
+ {
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Id { get; set; }
+ }
+
+ [Route("/Items/RemoteSearch/Movie", "POST")]
+ [Api(Description = "Gets external id infos for an item")]
+ public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
+ {
+ }
+
+ [Route("/Items/RemoteSearch/Trailer", "POST")]
+ [Api(Description = "Gets external id infos for an item")]
+ public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
+ {
+ }
+
+ [Route("/Items/RemoteSearch/AdultVideo", "POST")]
+ [Api(Description = "Gets external id infos for an item")]
+ public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>>
+ {
+ }
+
+ [Route("/Items/RemoteSearch/Series", "POST")]
+ [Api(Description = "Gets external id infos for an item")]
+ public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>>
+ {
+ }
+
+ [Route("/Items/RemoteSearch/Game", "POST")]
+ [Api(Description = "Gets external id infos for an item")]
+ public class GetGameRemoteSearchResults : RemoteSearchQuery<GameInfo>, IReturn<List<RemoteSearchResult>>
+ {
+ }
+
+ [Route("/Items/RemoteSearch/BoxSet", "POST")]
+ [Api(Description = "Gets external id infos for an item")]
+ public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>>
+ {
+ }
+
+ [Route("/Items/RemoteSearch/Person", "POST")]
+ [Api(Description = "Gets external id infos for an item")]
+ public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>>
+ {
+ }
+
+ [Route("/Items/RemoteSearch/Image", "GET")]
+ [Api(Description = "Gets a remote image")]
+ public class GetRemoteSearchImage
+ {
+ [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string ImageUrl { get; set; }
+
+ [ApiMember(Name = "ProviderName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string ProviderName { get; set; }
+ }
+
+ public class ItemLookupService : BaseApiService
+ {
+ private readonly IDtoService _dtoService;
+ private readonly IProviderManager _providerManager;
+ private readonly IServerApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
+
+ public ItemLookupService(IDtoService dtoService, IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem)
+ {
+ _dtoService = dtoService;
+ _providerManager = providerManager;
+ _appPaths = appPaths;
+ _fileSystem = fileSystem;
+ }
+
+ public object Get(GetExternalIdInfos request)
+ {
+ var item = _dtoService.GetItemByDtoId(request.Id);
+
+ var infos = _providerManager.GetExternalIdInfos(item).ToList();
+
+ return ToOptimizedResult(infos);
+ }
+
+ public object Post(GetMovieRemoteSearchResults request)
+ {
+ var result = _providerManager.GetRemoteSearchResults<Movie, MovieInfo>(request, CancellationToken.None).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Post(GetAdultVideoRemoteSearchResults request)
+ {
+ var result = _providerManager.GetRemoteSearchResults<AdultVideo, ItemLookupInfo>(request, CancellationToken.None).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Post(GetSeriesRemoteSearchResults request)
+ {
+ var result = _providerManager.GetRemoteSearchResults<Series, SeriesInfo>(request, CancellationToken.None).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Post(GetGameRemoteSearchResults request)
+ {
+ var result = _providerManager.GetRemoteSearchResults<Game, GameInfo>(request, CancellationToken.None).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Post(GetBoxSetRemoteSearchResults request)
+ {
+ var result = _providerManager.GetRemoteSearchResults<BoxSet, BoxSetInfo>(request, CancellationToken.None).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Post(GetPersonRemoteSearchResults request)
+ {
+ var result = _providerManager.GetRemoteSearchResults<Person, PersonLookupInfo>(request, CancellationToken.None).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Post(GetTrailerRemoteSearchResults request)
+ {
+ var result = _providerManager.GetRemoteSearchResults<Trailer, TrailerInfo>(request, CancellationToken.None).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Get(GetRemoteSearchImage request)
+ {
+ var result = GetRemoteImage(request).Result;
+
+ return result;
+ }
+
+ /// <summary>
+ /// Gets the remote image.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <returns>Task{System.Object}.</returns>
+ private async Task<object> GetRemoteImage(GetRemoteSearchImage request)
+ {
+ var urlHash = request.ImageUrl.GetMD5();
+ var pointerCachePath = GetFullCachePath(urlHash.ToString());
+
+ string contentPath;
+
+ try
+ {
+ using (var reader = new StreamReader(pointerCachePath))
+ {
+ contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
+ }
+
+ if (File.Exists(contentPath))
+ {
+ return ToStaticFileResult(contentPath);
+ }
+ }
+ catch (DirectoryNotFoundException)
+ {
+ // Means the file isn't cached yet
+ }
+ catch (FileNotFoundException)
+ {
+ // Means the file isn't cached yet
+ }
+
+ await DownloadImage(request.ProviderName, request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
+
+ // Read the pointer file again
+ using (var reader = new StreamReader(pointerCachePath))
+ {
+ contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
+ }
+
+ return ToStaticFileResult(contentPath);
+ }
+
+ /// <summary>
+ /// Downloads the image.
+ /// </summary>
+ /// <param name="providerName">Name of the provider.</param>
+ /// <param name="url">The URL.</param>
+ /// <param name="urlHash">The URL hash.</param>
+ /// <param name="pointerCachePath">The pointer cache path.</param>
+ /// <returns>Task.</returns>
+ private async Task DownloadImage(string providerName, string url, Guid urlHash, string pointerCachePath)
+ {
+ var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false);
+
+ var ext = result.ContentType.Split('/').Last();
+
+ var fullCachePath = GetFullCachePath(urlHash + "." + ext);
+
+ Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
+ using (var stream = result.Content)
+ {
+ using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ {
+ await stream.CopyToAsync(filestream).ConfigureAwait(false);
+ }
+ }
+
+ Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
+ using (var writer = new StreamWriter(pointerCachePath))
+ {
+ await writer.WriteAsync(fullCachePath).ConfigureAwait(false);
+ }
+ }
+
+ /// <summary>
+ /// Gets the full cache path.
+ /// </summary>
+ /// <param name="filename">The filename.</param>
+ /// <returns>System.String.</returns>
+ private string GetFullCachePath(string filename)
+ {
+ return Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename);
+ }
+
+ }
+}
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 4cb20273f..c3fdbb9a0 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -6,10 +6,8 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System;
@@ -50,18 +48,6 @@ namespace MediaBrowser.Api.Library
public int Index { get; set; }
}
- [Route("/Items/{Id}/ExternalIdInfos", "GET")]
- [Api(Description = "Gets external id infos for an item")]
- public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
/// <summary>
/// Class GetCriticReviews
/// </summary>
@@ -256,29 +242,18 @@ namespace MediaBrowser.Api.Library
private readonly IUserDataManager _userDataManager;
private readonly IDtoService _dtoService;
- private readonly IProviderManager _providerManager;
/// <summary>
/// Initializes a new instance of the <see cref="LibraryService" /> class.
/// </summary>
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
- IDtoService dtoService, IUserDataManager userDataManager, IProviderManager providerManager)
+ IDtoService dtoService, IUserDataManager userDataManager)
{
_itemRepo = itemRepo;
_libraryManager = libraryManager;
_userManager = userManager;
_dtoService = dtoService;
_userDataManager = userDataManager;
- _providerManager = providerManager;
- }
-
- public object Get(GetExternalIdInfos request)
- {
- var item = _dtoService.GetItemByDtoId(request.Id);
-
- var infos = _providerManager.GetExternalIdInfos(item).ToList();
-
- return ToOptimizedResult(infos);
}
public object Get(GetMediaFolders request)
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index ee2a7eafc..bcc487a5d 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -82,6 +82,7 @@
<Compile Include="Images\ImageService.cs" />
<Compile Include="Images\ImageWriter.cs" />
<Compile Include="InstantMixService.cs" />
+ <Compile Include="ItemLookupService.cs" />
<Compile Include="ItemRefreshService.cs" />
<Compile Include="ItemUpdateService.cs" />
<Compile Include="Library\LibraryService.cs" />
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 83ee6ae83..94b19498a 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
@@ -126,5 +127,14 @@ namespace MediaBrowser.Controller.Providers
CancellationToken cancellationToken)
where TItemType : BaseItem, new()
where TLookupType : ItemLookupInfo;
+
+ /// <summary>
+ /// Gets the search image.
+ /// </summary>
+ /// <param name="providerName">Name of the provider.</param>
+ /// <param name="url">The URL.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{HttpResponseInfo}.</returns>
+ Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs
index f00a22a3a..0ff7ee5a9 100644
--- a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs
+++ b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs
@@ -18,11 +18,8 @@ namespace MediaBrowser.Controller.Providers
Task<MetadataResult<TItemType>> GetMetadata(TLookupInfoType info, CancellationToken cancellationToken);
}
- public interface IRemoteSearchProvider<in TLookupInfoType> : IMetadataProvider
- where TLookupInfoType : ItemLookupInfo
+ public interface IRemoteSearchProvider : IMetadataProvider
{
- Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken);
-
/// <summary>
/// Gets the image response.
/// </summary>
@@ -31,6 +28,12 @@ namespace MediaBrowser.Controller.Providers
/// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken);
}
+
+ public interface IRemoteSearchProvider<in TLookupInfoType> : IRemoteSearchProvider
+ where TLookupInfoType : ItemLookupInfo
+ {
+ Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken);
+ }
public class RemoteSearchQuery<T>
where T : ItemLookupInfo
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
index 09939f2d6..d698b4ce0 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
+++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
@@ -32,20 +32,71 @@ namespace MediaBrowser.Providers.BoxSets
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private readonly ILocalizationManager _localization;
+ private readonly IHttpClient _httpClient;
- public MovieDbBoxSetProvider(ILogger logger, IJsonSerializer json, IServerConfigurationManager config, IFileSystem fileSystem, ILocalizationManager localization)
+ public MovieDbBoxSetProvider(ILogger logger, IJsonSerializer json, IServerConfigurationManager config, IFileSystem fileSystem, ILocalizationManager localization, IHttpClient httpClient)
{
_logger = logger;
_json = json;
_config = config;
_fileSystem = fileSystem;
_localization = localization;
+ _httpClient = httpClient;
Current = this;
}
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(BoxSetInfo searchInfo, CancellationToken cancellationToken)
{
- return new List<RemoteSearchResult>();
+ var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb);
+
+ var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+
+ var tmdbImageUrl = tmdbSettings.images.base_url + "original";
+
+ if (!string.IsNullOrEmpty(tmdbId))
+ {
+ await EnsureInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
+
+ var dataFilePath = GetDataFilePath(_config.ApplicationPaths, tmdbId, searchInfo.MetadataLanguage);
+ var info = _json.DeserializeFromFile<RootObject>(dataFilePath);
+
+ var images = (info.images ?? new Images()).posters ?? new List<Poster>();
+
+ var result = new RemoteSearchResult
+ {
+ Name = info.name,
+
+ SearchProviderName = Name,
+
+ ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path)
+ };
+
+ result.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
+
+ return new[] { result };
+ }
+
+ var results = await new MovieDbSearch(_logger, _json).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
+
+ return results.Select(i => GetRemoteSearchResult(i, tmdbImageUrl));
+ }
+
+ private RemoteSearchResult GetRemoteSearchResult(MovieDbSearch.TmdbMovieSearchResult tmdbResult, string baseImageUrl)
+ {
+ var result = new RemoteSearchResult
+ {
+ Name = tmdbResult.name,
+
+ SearchProviderName = Name,
+
+ ImageUrl = string.IsNullOrEmpty(tmdbResult.poster_path) ? null : (baseImageUrl + tmdbResult.poster_path)
+ };
+
+ result.SetProviderId(MetadataProviders.Tmdb, tmdbResult.id.ToString(_usCulture));
+
+ return result;
}
public async Task<MetadataResult<BoxSet>> GetMetadata(BoxSetInfo id, CancellationToken cancellationToken)
@@ -55,7 +106,9 @@ namespace MediaBrowser.Providers.BoxSets
// We don't already have an Id, need to fetch it
if (string.IsNullOrEmpty(tmdbId))
{
- var searchResult = await new MovieDbSearch(_logger, _json).FindCollectionId(id, cancellationToken).ConfigureAwait(false);
+ var searchResults = await new MovieDbSearch(_logger, _json).GetSearchResults(id, cancellationToken).ConfigureAwait(false);
+
+ var searchResult = searchResults.FirstOrDefault();
if (searchResult != null)
{
@@ -219,10 +272,15 @@ namespace MediaBrowser.Providers.BoxSets
private static string GetDataFilePath(IApplicationPaths appPaths, string tmdbId, string preferredLanguage)
{
+ if (string.IsNullOrWhiteSpace(preferredLanguage))
+ {
+ throw new ArgumentNullException("preferredLanguage");
+ }
+
var path = GetDataPath(appPaths, tmdbId);
var filename = string.Format("all-{0}.json",
- preferredLanguage ?? string.Empty);
+ preferredLanguage);
return Path.Combine(path, filename);
}
@@ -291,7 +349,12 @@ namespace MediaBrowser.Providers.BoxSets
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
- throw new NotImplementedException();
+ return _httpClient.GetResponse(new HttpRequestOptions
+ {
+ CancellationToken = cancellationToken,
+ Url = url,
+ ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ });
}
}
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 942f414b6..b35c4887c 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -657,6 +657,15 @@ namespace MediaBrowser.Providers.Manager
providers = providers.Where(i => string.Equals(i.Name, searchInfo.SearchProviderName, StringComparison.OrdinalIgnoreCase));
}
+ if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataLanguage))
+ {
+ searchInfo.SearchInfo.MetadataLanguage = ConfigurationManager.Configuration.PreferredMetadataLanguage;
+ }
+ if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataCountryCode))
+ {
+ searchInfo.SearchInfo.MetadataCountryCode = ConfigurationManager.Configuration.MetadataCountryCode;
+ }
+
foreach (var provider in providers)
{
var results = await provider.GetSearchResults(searchInfo.SearchInfo, cancellationToken).ConfigureAwait(false);
@@ -665,7 +674,7 @@ namespace MediaBrowser.Providers.Manager
if (list.Count > 0)
{
- return list;
+ return list.Take(10);
}
}
@@ -673,6 +682,18 @@ namespace MediaBrowser.Providers.Manager
return new List<RemoteSearchResult>();
}
+ public Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken)
+ {
+ var provider = _metadataProviders.OfType<IRemoteSearchProvider>().FirstOrDefault(i => string.Equals(i.Name, providerName, StringComparison.OrdinalIgnoreCase));
+
+ if (provider == null)
+ {
+ throw new ArgumentException("Search provider not found.");
+ }
+
+ return provider.GetImageResponse(url, cancellationToken);
+ }
+
public IEnumerable<IExternalId> GetExternalIds(IHasProviderIds item)
{
return _externalIds.Where(i =>
diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
index abd48e37c..b6dca5b7d 100644
--- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
+++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
@@ -39,7 +39,9 @@ namespace MediaBrowser.Providers.Movies
// Don't search for music video id's because it is very easy to misidentify.
if (string.IsNullOrEmpty(tmdbId) && string.IsNullOrEmpty(imdbId) && typeof(T) != typeof(MusicVideo))
{
- var searchResult = await new MovieDbSearch(_logger, _jsonSerializer).FindMovieId(itemId, cancellationToken).ConfigureAwait(false);
+ var searchResults = await new MovieDbSearch(_logger, _jsonSerializer).GetMovieSearchResults(itemId, cancellationToken).ConfigureAwait(false);
+
+ var searchResult = searchResults.FirstOrDefault();
if (searchResult != null)
{
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index 32a77a8a6..2c47dbc2f 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -558,7 +558,12 @@ namespace MediaBrowser.Providers.Movies
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
- throw new NotImplementedException();
+ return _httpClient.GetResponse(new HttpRequestOptions
+ {
+ CancellationToken = cancellationToken,
+ Url = url,
+ ResourcePool = MovieDbResourcePool
+ });
}
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs
index 383705e0a..ad7335009 100644
--- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs
@@ -29,22 +29,22 @@ namespace MediaBrowser.Providers.Movies
_json = json;
}
- public Task<TmdbMovieSearchResult> FindSeriesId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
+ public Task<IEnumerable<TmdbMovieSearchResult>> GetSearchResults(SeriesInfo idInfo, CancellationToken cancellationToken)
{
- return FindId(idInfo, "tv", cancellationToken);
+ return GetSearchResults(idInfo, "tv", cancellationToken);
}
- public Task<TmdbMovieSearchResult> FindMovieId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
+ public Task<IEnumerable<TmdbMovieSearchResult>> GetMovieSearchResults(ItemLookupInfo idInfo, CancellationToken cancellationToken)
{
- return FindId(idInfo, "movie", cancellationToken);
+ return GetSearchResults(idInfo, "movie", cancellationToken);
}
- public Task<TmdbMovieSearchResult> FindCollectionId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
+ public Task<IEnumerable<TmdbMovieSearchResult>> GetSearchResults(BoxSetInfo idInfo, CancellationToken cancellationToken)
{
- return FindId(idInfo, "collection", cancellationToken);
+ return GetSearchResults(idInfo, "collection", cancellationToken);
}
- private async Task<TmdbMovieSearchResult> FindId(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken)
+ private async Task<IEnumerable<TmdbMovieSearchResult>> GetSearchResults(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken)
{
var name = idInfo.Name;
var year = idInfo.Year;
@@ -60,48 +60,49 @@ namespace MediaBrowser.Providers.Movies
//nope - search for it
//var searchType = item is BoxSet ? "collection" : "movie";
- var id = await AttemptFindId(name, searchType, year, language, cancellationToken).ConfigureAwait(false);
+ var results = await GetSearchResults(name, searchType, year, language, cancellationToken).ConfigureAwait(false);
- if (id == null)
+ if (results.Count == 0)
{
//try in english if wasn't before
- if (language != "en")
+ if (!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
{
- id = await AttemptFindId(name, searchType, year, "en", cancellationToken).ConfigureAwait(false);
+ results = await GetSearchResults(name, searchType, year, "en", cancellationToken).ConfigureAwait(false);
}
- else
- {
- // try with dot and _ turned to space
- var originalName = name;
+ }
- name = name.Replace(",", " ");
- name = name.Replace(".", " ");
- name = name.Replace("_", " ");
- name = name.Replace("-", " ");
- name = name.Replace("!", " ");
- name = name.Replace("?", " ");
+ if (results.Count == 0)
+ {
+ // try with dot and _ turned to space
+ var originalName = name;
- name = name.Trim();
+ name = name.Replace(",", " ");
+ name = name.Replace(".", " ");
+ name = name.Replace("_", " ");
+ name = name.Replace("-", " ");
+ name = name.Replace("!", " ");
+ name = name.Replace("?", " ");
- // Search again if the new name is different
- if (!string.Equals(name, originalName))
- {
- id = await AttemptFindId(name, searchType, year, language, cancellationToken).ConfigureAwait(false);
+ name = name.Trim();
- if (id == null && language != "en")
- {
- //one more time, in english
- id = await AttemptFindId(name, searchType, year, "en", cancellationToken).ConfigureAwait(false);
+ // Search again if the new name is different
+ if (!string.Equals(name, originalName))
+ {
+ results = await GetSearchResults(name, searchType, year, language, cancellationToken).ConfigureAwait(false);
+
+ if (results.Count == 0 && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
+ {
+ //one more time, in english
+ results = await GetSearchResults(name, searchType, year, "en", cancellationToken).ConfigureAwait(false);
- }
}
}
}
- return id;
+ return results;
}
- private async Task<TmdbMovieSearchResult> AttemptFindId(string name, string type, int? year, string language, CancellationToken cancellationToken)
+ private async Task<List<TmdbMovieSearchResult>> GetSearchResults(string name, string type, int? year, string language, CancellationToken cancellationToken)
{
var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, type);
@@ -113,9 +114,34 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false))
{
- var searchResult = _json.DeserializeFromStream<TmdbMovieSearchResults>(json);
- return FindBestResult(searchResult.results, name, year);
+ var searchResults = _json.DeserializeFromStream<TmdbMovieSearchResults>(json);
+
+ var results = searchResults.results ?? new List<TmdbMovieSearchResult>();
+
+ var index = 0;
+ var resultTuples = results.Select(result => new Tuple<TmdbMovieSearchResult, int>(result, index++)).ToList();
+
+ return resultTuples.OrderBy(i => GetSearchResultOrder(i.Item1, year))
+ .ThenBy(i => i.Item2)
+ .Select(i => i.Item1)
+ .ToList();
+ }
+ }
+
+ private int GetSearchResultOrder(TmdbMovieSearchResult result, int? year)
+ {
+ if (year.HasValue)
+ {
+ DateTime r;
+
+ // These dates are always in this exact format
+ if (DateTime.TryParseExact(result.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
+ {
+ return Math.Abs(r.Year - year.Value);
+ }
}
+
+ return 0;
}
private TmdbMovieSearchResult FindBestResult(List<TmdbMovieSearchResult> results, string name, int? year)
diff --git a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
index 8c981e2d8..512fee8f8 100644
--- a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
@@ -11,6 +11,13 @@ namespace MediaBrowser.Providers.Movies
{
public class MovieDbTrailerProvider : IRemoteMetadataProvider<Trailer, TrailerInfo>, IHasOrder
{
+ private readonly IHttpClient _httpClient;
+
+ public MovieDbTrailerProvider(IHttpClient httpClient)
+ {
+ _httpClient = httpClient;
+ }
+
public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
{
return MovieDbProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken);
@@ -42,7 +49,12 @@ namespace MediaBrowser.Providers.Movies
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
- throw new NotImplementedException();
+ return _httpClient.GetResponse(new HttpRequestOptions
+ {
+ CancellationToken = cancellationToken,
+ Url = url,
+ ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ });
}
}
}
diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
index 01be6bf91..b5bf445bf 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
+++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
@@ -29,12 +29,14 @@ namespace MediaBrowser.Providers.People
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _configurationManager;
+ private readonly IHttpClient _httpClient;
- public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer)
+ public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient)
{
_fileSystem = fileSystem;
_configurationManager = configurationManager;
_jsonSerializer = jsonSerializer;
+ _httpClient = httpClient;
Current = this;
}
@@ -64,6 +66,8 @@ namespace MediaBrowser.Providers.People
{
Name = info.name,
+ SearchProviderName = Name,
+
ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path)
};
@@ -94,6 +98,8 @@ namespace MediaBrowser.Providers.People
{
var result = new RemoteSearchResult
{
+ SearchProviderName = Name,
+
Name = i.Name,
ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : (baseImageUrl + i.Profile_Path)
@@ -349,7 +355,12 @@ namespace MediaBrowser.Providers.People
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
- throw new NotImplementedException();
+ return _httpClient.GetResponse(new HttpRequestOptions
+ {
+ CancellationToken = cancellationToken,
+ Url = url,
+ ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ });
}
}
}
diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
index b46336e90..9f1d5f021 100644
--- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
@@ -33,14 +33,16 @@ namespace MediaBrowser.Providers.TV
private readonly IServerConfigurationManager _configurationManager;
private readonly ILogger _logger;
private readonly ILocalizationManager _localization;
+ private readonly IHttpClient _httpClient;
- public MovieDbSeriesProvider(IJsonSerializer jsonSerializer, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization)
+ public MovieDbSeriesProvider(IJsonSerializer jsonSerializer, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, IHttpClient httpClient)
{
_jsonSerializer = jsonSerializer;
_fileSystem = fileSystem;
_configurationManager = configurationManager;
_logger = logger;
_localization = localization;
+ _httpClient = httpClient;
Current = this;
}
@@ -82,7 +84,9 @@ namespace MediaBrowser.Providers.TV
if (string.IsNullOrEmpty(tmdbId))
{
- var searchResult = await new MovieDbSearch(_logger, _jsonSerializer).FindSeriesId(info, cancellationToken).ConfigureAwait(false);
+ var searchResults = await new MovieDbSearch(_logger, _jsonSerializer).GetSearchResults(info, cancellationToken).ConfigureAwait(false);
+
+ var searchResult = searchResults.FirstOrDefault();
if (searchResult != null)
{
@@ -462,7 +466,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 = MovieDbProvider.Current.MovieDbResourcePool
+ });
}
}
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
index 43037d6ce..c0d784fcc 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
public void Run()
{
- NatUtility.Logger = new LogWriter(_logger);
+ //NatUtility.Logger = new LogWriter(_logger);
Reload();
}
@@ -64,17 +64,17 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
- var ex = e.ExceptionObject as Exception;
-
- if (ex == null)
- {
- _logger.Error("Unidentified error reported by Mono.Nat");
- }
- else
- {
- // Seeing some blank exceptions coming through here
- _logger.ErrorException("Error reported by Mono.Nat: ", ex);
- }
+ //var ex = e.ExceptionObject as Exception;
+
+ //if (ex == null)
+ //{
+ // _logger.Error("Unidentified error reported by Mono.Nat");
+ //}
+ //else
+ //{
+ // // Seeing some blank exceptions coming through here
+ // _logger.ErrorException("Error reported by Mono.Nat: ", ex);
+ //}
}
void NatUtility_DeviceFound(object sender, DeviceEventArgs e)
@@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
}
catch (Exception ex)
{
- _logger.ErrorException("Error creating port forwarding rules", ex);
+ //_logger.ErrorException("Error creating port forwarding rules", ex);
}
}
@@ -106,7 +106,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private void CreatePortMap(INatDevice device, int port)
{
- _logger.Info("Creating port map on port {0}", port);
+ _logger.Debug("Creating port map on port {0}", port);
device.CreatePortMap(new Mapping(Protocol.Tcp, port, port)
{