mirror of
https://github.com/Radarr/Radarr
synced 2025-03-15 08:29:08 +00:00
Fixed: Posters not always showing when searching for movie
Fixes #4729 Fixes #4704
This commit is contained in:
parent
863252d7e9
commit
77036ac3ef
8 changed files with 155 additions and 11 deletions
|
@ -160,6 +160,7 @@ class MovieImage extends Component {
|
|||
src={url}
|
||||
onError={this.onError}
|
||||
onLoad={this.onLoad}
|
||||
rel="noreferrer"
|
||||
/>
|
||||
</LazyLoad>
|
||||
);
|
||||
|
|
|
@ -280,6 +280,10 @@ namespace NzbDrone.Core.Extras.Metadata
|
|||
|
||||
_mediaFileAttributeService.SetFilePermissions(fullPath);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
_logger.Warn(ex, "Couldn't download image {0} for {1}. {2}", image.Url, movie, ex.Message);
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
_logger.Warn(ex, "Couldn't download image {0} for {1}. {2}", image.Url, movie, ex.Message);
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.MediaCover
|
|||
{
|
||||
public MediaCoverTypes CoverType { get; set; }
|
||||
public string Url { get; set; }
|
||||
public string RemoteUrl { get; set; }
|
||||
|
||||
public MediaCover()
|
||||
{
|
||||
|
|
64
src/NzbDrone.Core/MediaCover/MediaCoverProxy.cs
Normal file
64
src/NzbDrone.Core/MediaCover/MediaCoverProxy.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.MediaCover
|
||||
{
|
||||
public interface IMediaCoverProxy
|
||||
{
|
||||
string RegisterUrl(string url);
|
||||
|
||||
string GetUrl(string hash);
|
||||
byte[] GetImage(string hash);
|
||||
}
|
||||
|
||||
public class MediaCoverProxy : IMediaCoverProxy
|
||||
{
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
private readonly ICached<string> _cache;
|
||||
|
||||
public MediaCoverProxy(IHttpClient httpClient, IConfigFileProvider configFileProvider, ICacheManager cacheManager)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_configFileProvider = configFileProvider;
|
||||
_cache = cacheManager.GetCache<string>(GetType());
|
||||
}
|
||||
|
||||
public string RegisterUrl(string url)
|
||||
{
|
||||
var hash = url.SHA256Hash();
|
||||
|
||||
_cache.Set(hash, url, TimeSpan.FromHours(24));
|
||||
|
||||
_cache.ClearExpired();
|
||||
|
||||
var fileName = Path.GetFileName(url);
|
||||
return _configFileProvider.UrlBase + @"/MediaCoverProxy/" + hash + "/" + fileName;
|
||||
}
|
||||
|
||||
public string GetUrl(string hash)
|
||||
{
|
||||
var result = _cache.Find(hash);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
throw new KeyNotFoundException("Url no longer in cache");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] GetImage(string hash)
|
||||
{
|
||||
var url = GetUrl(hash);
|
||||
|
||||
var request = new HttpRequest(url);
|
||||
|
||||
return _httpClient.Get(request).ResponseData;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ namespace NzbDrone.Core.MediaCover
|
|||
IHandleAsync<MoviesDeletedEvent>,
|
||||
IMapCoversToLocal
|
||||
{
|
||||
private readonly IMediaCoverProxy _mediaCoverProxy;
|
||||
private readonly IImageResizer _resizer;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
|
@ -40,7 +41,8 @@ namespace NzbDrone.Core.MediaCover
|
|||
// So limit the number of concurrent resizing tasks
|
||||
private static SemaphoreSlim _semaphore = new SemaphoreSlim((int)Math.Ceiling(Environment.ProcessorCount / 2.0));
|
||||
|
||||
public MediaCoverService(IImageResizer resizer,
|
||||
public MediaCoverService(IMediaCoverProxy mediaCoverProxy,
|
||||
IImageResizer resizer,
|
||||
IHttpClient httpClient,
|
||||
IDiskProvider diskProvider,
|
||||
IAppFolderInfo appFolderInfo,
|
||||
|
@ -49,6 +51,7 @@ namespace NzbDrone.Core.MediaCover
|
|||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
{
|
||||
_mediaCoverProxy = mediaCoverProxy;
|
||||
_resizer = resizer;
|
||||
_httpClient = httpClient;
|
||||
_diskProvider = diskProvider;
|
||||
|
@ -69,16 +72,29 @@ namespace NzbDrone.Core.MediaCover
|
|||
|
||||
public void ConvertToLocalUrls(int movieId, IEnumerable<MediaCover> covers)
|
||||
{
|
||||
foreach (var mediaCover in covers)
|
||||
if (movieId == 0)
|
||||
{
|
||||
var filePath = GetCoverPath(movieId, mediaCover.CoverType);
|
||||
|
||||
mediaCover.Url = _configFileProvider.UrlBase + @"/MediaCover/" + movieId + "/" + mediaCover.CoverType.ToString().ToLower() + ".jpg";
|
||||
|
||||
if (_diskProvider.FileExists(filePath))
|
||||
// Movie isn't in Radarr yet, map via a proxy to circument referrer issues
|
||||
foreach (var mediaCover in covers)
|
||||
{
|
||||
var lastWrite = _diskProvider.FileGetLastWrite(filePath);
|
||||
mediaCover.Url += "?lastWrite=" + lastWrite.Ticks;
|
||||
mediaCover.RemoteUrl = mediaCover.Url;
|
||||
mediaCover.Url = _mediaCoverProxy.RegisterUrl(mediaCover.RemoteUrl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var mediaCover in covers)
|
||||
{
|
||||
var filePath = GetCoverPath(movieId, mediaCover.CoverType);
|
||||
|
||||
mediaCover.RemoteUrl = mediaCover.Url;
|
||||
mediaCover.Url = _configFileProvider.UrlBase + @"/MediaCover/" + movieId + "/" + mediaCover.CoverType.ToString().ToLower() + ".jpg";
|
||||
|
||||
if (_diskProvider.FileExists(filePath))
|
||||
{
|
||||
var lastWrite = _diskProvider.FileGetLastWrite(filePath);
|
||||
mediaCover.Url += "?lastWrite=" + lastWrite.Ticks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +122,10 @@ namespace NzbDrone.Core.MediaCover
|
|||
updated = true;
|
||||
}
|
||||
}
|
||||
catch (HttpException e)
|
||||
{
|
||||
_logger.Warn("Couldn't download media cover for {0}. {1}", movie, e.Message);
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
_logger.Warn("Couldn't download media cover for {0}. {1}", movie, e.Message);
|
||||
|
|
|
@ -17,17 +17,20 @@ namespace Radarr.Api.V3.Movies
|
|||
private readonly ISearchForNewMovie _searchProxy;
|
||||
private readonly IProvideMovieInfo _movieInfo;
|
||||
private readonly IBuildFileNames _fileNameBuilder;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
private readonly IConfigService _configService;
|
||||
|
||||
public MovieLookupModule(ISearchForNewMovie searchProxy,
|
||||
IProvideMovieInfo movieInfo,
|
||||
IBuildFileNames fileNameBuilder,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IConfigService configService)
|
||||
: base("/movie/lookup")
|
||||
{
|
||||
_movieInfo = movieInfo;
|
||||
_searchProxy = searchProxy;
|
||||
_fileNameBuilder = fileNameBuilder;
|
||||
_coverMapper = coverMapper;
|
||||
_configService = configService;
|
||||
Get("/", x => Search());
|
||||
Get("/tmdb", x => SearchByTmdbId());
|
||||
|
@ -69,10 +72,13 @@ namespace Radarr.Api.V3.Movies
|
|||
{
|
||||
var translation = currentMovie.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||
var resource = currentMovie.ToResource(translation);
|
||||
|
||||
_coverMapper.ConvertToLocalUrls(resource.Id, resource.Images);
|
||||
|
||||
var poster = currentMovie.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
if (poster != null)
|
||||
{
|
||||
resource.RemotePoster = poster.Url;
|
||||
resource.RemotePoster = poster.RemoteUrl;
|
||||
}
|
||||
|
||||
resource.Folder = _fileNameBuilder.GetMovieFolder(currentMovie);
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace Radarr.Http.Frontend.Mappers
|
|||
|
||||
public override bool CanHandle(string resourceUrl)
|
||||
{
|
||||
return resourceUrl.StartsWith("/MediaCover", StringComparison.InvariantCultureIgnoreCase);
|
||||
return resourceUrl.StartsWith("/MediaCover/", StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
48
src/Radarr.Http/Frontend/Mappers/MediaCoverProxyMapper.cs
Normal file
48
src/Radarr.Http/Frontend/Mappers/MediaCoverProxyMapper.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using Nancy;
|
||||
using Nancy.Responses;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
|
||||
namespace Radarr.Http.Frontend.Mappers
|
||||
{
|
||||
public class MediaCoverProxyMapper : IMapHttpRequestsToDisk
|
||||
{
|
||||
private readonly Regex _regex = new Regex(@"/MediaCoverProxy/(?<hash>\w+)/(?<filename>(.+)\.(jpg|png|gif))");
|
||||
|
||||
private readonly IMediaCoverProxy _mediaCoverProxy;
|
||||
|
||||
public MediaCoverProxyMapper(IMediaCoverProxy mediaCoverProxy)
|
||||
{
|
||||
_mediaCoverProxy = mediaCoverProxy;
|
||||
}
|
||||
|
||||
public string Map(string resourceUrl)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool CanHandle(string resourceUrl)
|
||||
{
|
||||
return resourceUrl.StartsWith("/MediaCoverProxy/", StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public Response GetResponse(string resourceUrl)
|
||||
{
|
||||
var match = _regex.Match(resourceUrl);
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
return new NotFoundResponse();
|
||||
}
|
||||
|
||||
var hash = match.Groups["hash"].Value;
|
||||
var filename = match.Groups["filename"].Value;
|
||||
|
||||
var imageData = _mediaCoverProxy.GetImage(hash);
|
||||
|
||||
return new StreamResponse(() => new MemoryStream(imageData), MimeTypes.GetMimeType(filename));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue