mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
a start to the lookup feature
This commit is contained in:
parent
d537826d81
commit
6c5cf81752
252
MediaBrowser.Api/ItemLookupService.cs
Normal file
252
MediaBrowser.Api/ItemLookupService.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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" />
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 =>
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user