a start to the lookup feature

This commit is contained in:
Luke Pulverenti 2014-03-01 17:34:27 -05:00
parent d537826d81
commit 6c5cf81752
14 changed files with 484 additions and 94 deletions

View file

@ -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);
}
}
}

View file

@ -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)

View file

@ -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" />

View file

@ -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);
}
}

View file

@ -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

View file

@ -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
});
}
}
}

View file

@ -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 =>

View file

@ -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)
{

View file

@ -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
});
}
}
}

View file

@ -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
}
if (results.Count == 0)
{
// 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("?", " ");
name = name.Trim();
// Search again if the new name is different
if (!string.Equals(name, originalName))
{
// try with dot and _ turned to space
var originalName = name;
results = await GetSearchResults(name, searchType, year, language, cancellationToken).ConfigureAwait(false);
name = name.Replace(",", " ");
name = name.Replace(".", " ");
name = name.Replace("_", " ");
name = name.Replace("-", " ");
name = name.Replace("!", " ");
name = name.Replace("?", " ");
name = name.Trim();
// Search again if the new name is different
if (!string.Equals(name, originalName))
if (results.Count == 0 && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
{
id = await AttemptFindId(name, searchType, year, language, cancellationToken).ConfigureAwait(false);
//one more time, in english
results = await GetSearchResults(name, searchType, year, "en", cancellationToken).ConfigureAwait(false);
if (id == null && language != "en")
{
//one more time, in english
id = await AttemptFindId(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,11 +114,36 @@ 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)
{
if (year.HasValue)

View file

@ -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
});
}
}
}

View file

@ -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
});
}
}
}

View file

@ -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
});
}
}
}

View file

@ -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;
//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);
}
//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)
{