Async skyhook, movie lookup and media cover proxy

pull/9173/head
Bogdan 1 year ago
parent f41ce21d7f
commit 9e1d4fe6fc

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
@ -39,7 +40,7 @@ namespace NzbDrone.Core.Test.ImportListTests
Mocker.GetMock<ISearchForNewMovie>() Mocker.GetMock<ISearchForNewMovie>()
.Setup(v => v.MapMovieToTmdbMovie(It.IsAny<MovieMetadata>())) .Setup(v => v.MapMovieToTmdbMovie(It.IsAny<MovieMetadata>()))
.Returns<MovieMetadata>(m => new MovieMetadata { TmdbId = m.TmdbId }); .Returns<MovieMetadata>(m => Task.FromResult(new MovieMetadata { TmdbId = m.TmdbId }));
} }
private void GivenList(int id, bool enabled, bool enabledAuto, ImportListFetchResult fetchResult) private void GivenList(int id, bool enabled, bool enabledAuto, ImportListFetchResult fetchResult)

@ -1,4 +1,5 @@
using System.Net; using System.Net;
using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
@ -19,7 +20,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
{ {
_httpResponse = new HttpResponse(null, new HttpHeader(), "", HttpStatusCode.OK); _httpResponse = new HttpResponse(null, new HttpHeader(), "", HttpStatusCode.OK);
Mocker.GetMock<IDiskProvider>().Setup(c => c.GetFileSize(It.IsAny<string>())).Returns(100); Mocker.GetMock<IDiskProvider>().Setup(c => c.GetFileSize(It.IsAny<string>())).Returns(100);
Mocker.GetMock<IHttpClient>().Setup(c => c.Head(It.IsAny<HttpRequest>())).Returns(_httpResponse); Mocker.GetMock<IHttpClient>().Setup(c => c.HeadAsync(It.IsAny<HttpRequest>())).Returns(Task.FromResult(_httpResponse));
} }
private void GivenFileExistsOnDisk() private void GivenFileExistsOnDisk()
@ -34,33 +35,37 @@ namespace NzbDrone.Core.Test.MediaCoverTests
} }
[Test] [Test]
public void should_return_false_if_file_not_exists() public async Task should_return_false_if_file_not_exists()
{ {
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse(); var result = await Subject.AlreadyExists("http://url", "c:\\file.exe");
result.Should().BeFalse();
} }
[Test] [Test]
public void should_return_false_if_file_exists_but_diffrent_size() public async Task should_return_false_if_file_exists_but_diffrent_size()
{ {
GivenExistingFileSize(100); GivenExistingFileSize(100);
_httpResponse.Headers.ContentLength = 200; _httpResponse.Headers.ContentLength = 200;
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse(); var result = await Subject.AlreadyExists("http://url", "c:\\file.exe");
result.Should().BeFalse();
} }
[Test] [Test]
public void should_return_true_if_file_exists_and_same_size_and_not_corrupt() public async Task should_return_true_if_file_exists_and_same_size_and_not_corrupt()
{ {
GivenExistingFileSize(100); GivenExistingFileSize(100);
_httpResponse.Headers.ContentLength = 100; _httpResponse.Headers.ContentLength = 100;
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeTrue(); var result = await Subject.AlreadyExists("http://url", "c:\\file.exe");
result.Should().BeTrue();
} }
[Test] [Test]
public void should_return_true_if_there_is_no_size_header_and_file_exist() public async Task should_return_true_if_there_is_no_size_header_and_file_exist()
{ {
GivenExistingFileSize(100); GivenExistingFileSize(100);
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse(); var result = await Subject.AlreadyExists("http://url", "c:\\file.exe");
result.Should().BeFalse();
} }
} }
} }

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
@ -78,7 +79,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
{ {
Mocker.GetMock<ICoverExistsSpecification>() Mocker.GetMock<ICoverExistsSpecification>()
.Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>())) .Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>()))
.Returns(false); .Returns(Task.FromResult(false));
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.IsAny<string>())) .Setup(v => v.FileExists(It.IsAny<string>()))
@ -95,7 +96,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
{ {
Mocker.GetMock<ICoverExistsSpecification>() Mocker.GetMock<ICoverExistsSpecification>()
.Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>())) .Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>()))
.Returns(true); .Returns(Task.FromResult(true));
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.IsAny<string>())) .Setup(v => v.FileExists(It.IsAny<string>()))
@ -112,7 +113,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
{ {
Mocker.GetMock<ICoverExistsSpecification>() Mocker.GetMock<ICoverExistsSpecification>()
.Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>())) .Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>()))
.Returns(true); .Returns(Task.FromResult(true));
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.IsAny<string>())) .Setup(v => v.FileExists(It.IsAny<string>()))
@ -133,7 +134,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
{ {
Mocker.GetMock<ICoverExistsSpecification>() Mocker.GetMock<ICoverExistsSpecification>()
.Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>())) .Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>()))
.Returns(true); .Returns(Task.FromResult(true));
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.IsAny<string>())) .Setup(v => v.FileExists(It.IsAny<string>()))
@ -154,7 +155,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
{ {
Mocker.GetMock<ICoverExistsSpecification>() Mocker.GetMock<ICoverExistsSpecification>()
.Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>())) .Setup(v => v.AlreadyExists(It.IsAny<string>(), It.IsAny<string>()))
.Returns(true); .Returns(Task.FromResult(true));
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.IsAny<string>())) .Setup(v => v.FileExists(It.IsAny<string>()))

@ -1,3 +1,4 @@
using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.MetadataSource.SkyHook; using NzbDrone.Core.MetadataSource.SkyHook;
@ -20,9 +21,10 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
[TestCase(11, "Star Wars")] [TestCase(11, "Star Wars")]
[TestCase(2, "Ariel")] [TestCase(2, "Ariel")]
[TestCase(70981, "Prometheus")] [TestCase(70981, "Prometheus")]
public void should_be_able_to_get_movie_detail(int tmdbId, string title) public async Task should_be_able_to_get_movie_detail(int tmdbId, string title)
{ {
var details = Subject.GetMovieInfo(tmdbId).Item1; var movieInfo = await Subject.GetMovieInfo(tmdbId);
var details = movieInfo.Item1;
ValidateMovie(details); ValidateMovie(details);

@ -1,3 +1,4 @@
using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.MetadataSource.SkyHook; using NzbDrone.Core.MetadataSource.SkyHook;
@ -23,9 +24,9 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
// [TestCase("The Man from U.N.C.L.E.", "The Man from U.N.C.L.E.")] // [TestCase("The Man from U.N.C.L.E.", "The Man from U.N.C.L.E.")]
[TestCase("imdb:tt2527336", "Star Wars: The Last Jedi")] [TestCase("imdb:tt2527336", "Star Wars: The Last Jedi")]
[TestCase("imdb:tt2798920", "Annihilation")] [TestCase("imdb:tt2798920", "Annihilation")]
public void successful_search(string title, string expected) public async Task successful_search(string title, string expected)
{ {
var result = Subject.SearchForNewMovie(title); var result = await Subject.SearchForNewMovie(title);
result.Should().NotBeEmpty(); result.Should().NotBeEmpty();
@ -41,9 +42,9 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
[TestCase("tmdbid:1")] [TestCase("tmdbid:1")]
[TestCase("adjalkwdjkalwdjklawjdlKAJD;EF")] [TestCase("adjalkwdjkalwdjklawjdlKAJD;EF")]
[TestCase("imdb: tt9805708")] [TestCase("imdb: tt9805708")]
public void no_search_result(string term) public async Task no_search_result(string term)
{ {
var result = Subject.SearchForNewMovie(term); var result = await Subject.SearchForNewMovie(term);
result.Should().BeEmpty(); result.Should().BeEmpty();
ExceptionVerification.IgnoreWarns(); ExceptionVerification.IgnoreWarns();

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using FluentValidation; using FluentValidation;
@ -36,7 +37,7 @@ namespace NzbDrone.Core.Test.MovieTests
{ {
Mocker.GetMock<IProvideMovieInfo>() Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(tmdbId)) .Setup(s => s.GetMovieInfo(tmdbId))
.Returns(new Tuple<MovieMetadata, List<Credit>>(_fakeMovie, new List<Credit>())); .Returns(Task.FromResult(new Tuple<MovieMetadata, List<Credit>>(_fakeMovie, new List<Credit>())));
} }
private void GivenValidPath() private void GivenValidPath()
@ -51,7 +52,7 @@ namespace NzbDrone.Core.Test.MovieTests
} }
[Test] [Test]
public void should_be_able_to_add_a_movie_without_passing_in_title() public async Task should_be_able_to_add_a_movie_without_passing_in_title()
{ {
var newMovie = new Movie var newMovie = new Movie
{ {
@ -62,13 +63,13 @@ namespace NzbDrone.Core.Test.MovieTests
GivenValidMovie(newMovie.TmdbId); GivenValidMovie(newMovie.TmdbId);
GivenValidPath(); GivenValidPath();
var series = Subject.AddMovie(newMovie); var series = await Subject.AddMovie(newMovie);
series.Title.Should().Be(_fakeMovie.Title); series.Title.Should().Be(_fakeMovie.Title);
} }
[Test] [Test]
public void should_have_proper_path() public async Task should_have_proper_path()
{ {
var newMovie = new Movie var newMovie = new Movie
{ {
@ -79,7 +80,7 @@ namespace NzbDrone.Core.Test.MovieTests
GivenValidMovie(newMovie.TmdbId); GivenValidMovie(newMovie.TmdbId);
GivenValidPath(); GivenValidPath();
var series = Subject.AddMovie(newMovie); var series = await Subject.AddMovie(newMovie);
series.Path.Should().Be(Path.Combine(newMovie.RootFolderPath, _fakeMovie.Title)); series.Path.Should().Be(Path.Combine(newMovie.RootFolderPath, _fakeMovie.Title));
} }
@ -102,7 +103,7 @@ namespace NzbDrone.Core.Test.MovieTests
new ValidationFailure("Path", "Test validation failure") new ValidationFailure("Path", "Test validation failure")
})); }));
Assert.Throws<ValidationException>(() => Subject.AddMovie(newMovie)); Assert.ThrowsAsync<ValidationException>(async () => await Subject.AddMovie(newMovie));
} }
[Test] [Test]
@ -125,7 +126,7 @@ namespace NzbDrone.Core.Test.MovieTests
new ValidationFailure("Path", "Test validation failure") new ValidationFailure("Path", "Test validation failure")
})); }));
Assert.Throws<ValidationException>(() => Subject.AddMovie(newMovie)); Assert.ThrowsAsync<ValidationException>(async () => await Subject.AddMovie(newMovie));
ExceptionVerification.ExpectedErrors(1); ExceptionVerification.ExpectedErrors(1);
} }

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
@ -67,7 +68,7 @@ namespace NzbDrone.Core.Test.MovieTests
{ {
Mocker.GetMock<IProvideMovieInfo>() Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(_movie.TmdbId)) .Setup(s => s.GetMovieInfo(_movie.TmdbId))
.Returns(new Tuple<MovieMetadata, List<Credit>>(movie, new List<Credit>())); .Returns(Task.FromResult(new Tuple<MovieMetadata, List<Credit>>(movie, new List<Credit>())));
} }
[Test] [Test]

@ -190,7 +190,7 @@ namespace NzbDrone.Core.ImportLists
private List<ImportListMovie> MapMovieReports(IEnumerable<ImportListMovie> reports) private List<ImportListMovie> MapMovieReports(IEnumerable<ImportListMovie> reports)
{ {
var mappedMovies = reports.Select(m => _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = m.Title, TmdbId = m.TmdbId, ImdbId = m.ImdbId, Year = m.Year })) var mappedMovies = reports.Select(m => _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = m.Title, TmdbId = m.TmdbId, ImdbId = m.ImdbId, Year = m.Year }).GetAwaiter().GetResult())
.Where(x => x != null) .Where(x => x != null)
.DistinctBy(x => x.TmdbId) .DistinctBy(x => x.TmdbId)
.ToList(); .ToList();

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using NLog; using NLog;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.Instrumentation.Extensions;
@ -41,7 +42,7 @@ namespace NzbDrone.Core.ImportLists
_configService = configService; _configService = configService;
} }
private void SyncAll() private async Task SyncAll()
{ {
if (_importListFactory.Enabled().Empty()) if (_importListFactory.Enabled().Empty())
{ {
@ -62,16 +63,16 @@ namespace NzbDrone.Core.ImportLists
CleanLibrary(); CleanLibrary();
} }
ProcessListItems(listItemsResult); await ProcessListItems(listItemsResult);
} }
private void SyncList(ImportListDefinition definition) private async Task SyncList(ImportListDefinition definition)
{ {
_logger.ProgressInfo("Starting Import List Refresh for List {0}", definition.Name); _logger.ProgressInfo("Starting Import List Refresh for List {0}", definition.Name);
var listItemsResult = _listFetcherAndParser.FetchSingleList(definition); var listItemsResult = _listFetcherAndParser.FetchSingleList(definition);
ProcessListItems(listItemsResult); await ProcessListItems(listItemsResult);
} }
private void ProcessMovieReport(ImportListDefinition importList, ImportListMovie report, List<ImportExclusion> listExclusions, List<int> dbMovies, List<Movie> moviesToAdd) private void ProcessMovieReport(ImportListDefinition importList, ImportListMovie report, List<ImportExclusion> listExclusions, List<int> dbMovies, List<Movie> moviesToAdd)
@ -123,7 +124,7 @@ namespace NzbDrone.Core.ImportLists
} }
} }
private void ProcessListItems(ImportListFetchResult listFetchResult) private async Task ProcessListItems(ImportListFetchResult listFetchResult)
{ {
listFetchResult.Movies = listFetchResult.Movies.DistinctBy(x => listFetchResult.Movies = listFetchResult.Movies.DistinctBy(x =>
{ {
@ -164,7 +165,7 @@ namespace NzbDrone.Core.ImportLists
if (moviesToAdd.Any()) if (moviesToAdd.Any())
{ {
_logger.ProgressInfo("Adding {0} movies from your auto enabled lists to library", moviesToAdd.Count); _logger.ProgressInfo("Adding {0} movies from your auto enabled lists to library", moviesToAdd.Count);
_addMovieService.AddMovies(moviesToAdd, true); await _addMovieService.AddMovies(moviesToAdd, true);
} }
} }
@ -172,11 +173,11 @@ namespace NzbDrone.Core.ImportLists
{ {
if (message.DefinitionId.HasValue) if (message.DefinitionId.HasValue)
{ {
SyncList(_importListFactory.Get(message.DefinitionId.Value)); SyncList(_importListFactory.Get(message.DefinitionId.Value)).GetAwaiter().GetResult();
} }
else else
{ {
SyncAll(); SyncAll().GetAwaiter().GetResult();
} }
} }

@ -1,4 +1,5 @@
using NLog; using System.Threading.Tasks;
using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
@ -6,7 +7,7 @@ namespace NzbDrone.Core.MediaCover
{ {
public interface ICoverExistsSpecification public interface ICoverExistsSpecification
{ {
bool AlreadyExists(string url, string path); Task<bool> AlreadyExists(string url, string path);
} }
public class CoverAlreadyExistsSpecification : ICoverExistsSpecification public class CoverAlreadyExistsSpecification : ICoverExistsSpecification
@ -22,16 +23,17 @@ namespace NzbDrone.Core.MediaCover
_logger = logger; _logger = logger;
} }
public bool AlreadyExists(string url, string path) public async Task<bool> AlreadyExists(string url, string path)
{ {
if (!_diskProvider.FileExists(path)) if (!_diskProvider.FileExists(path))
{ {
return false; return false;
} }
var headers = _httpClient.Head(new HttpRequest(url)).Headers; var response = await _httpClient.HeadAsync(new HttpRequest(url));
var fileSize = _diskProvider.GetFileSize(path); var fileSize = _diskProvider.GetFileSize(path);
return fileSize == headers.ContentLength;
return fileSize == response.Headers.ContentLength;
} }
} }
} }

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using NLog; using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
@ -143,7 +144,7 @@ namespace NzbDrone.Core.MediaCover
return Path.Combine(_coverRootFolder, movieId.ToString()); return Path.Combine(_coverRootFolder, movieId.ToString());
} }
private bool EnsureCovers(Movie movie) private async Task<bool> EnsureCovers(Movie movie)
{ {
var updated = false; var updated = false;
var toResize = new List<Tuple<MediaCover, bool>>(); var toResize = new List<Tuple<MediaCover, bool>>();
@ -160,11 +161,11 @@ namespace NzbDrone.Core.MediaCover
try try
{ {
alreadyExists = _coverExistsSpecification.AlreadyExists(cover.RemoteUrl, fileName); alreadyExists = await _coverExistsSpecification.AlreadyExists(cover.RemoteUrl, fileName);
if (!alreadyExists) if (!alreadyExists)
{ {
DownloadCover(movie, cover); await DownloadCover(movie, cover);
updated = true; updated = true;
} }
} }
@ -186,7 +187,7 @@ namespace NzbDrone.Core.MediaCover
try try
{ {
_semaphore.Wait(); await _semaphore.WaitAsync();
foreach (var tuple in toResize) foreach (var tuple in toResize)
{ {
@ -201,12 +202,12 @@ namespace NzbDrone.Core.MediaCover
return updated; return updated;
} }
private void DownloadCover(Movie movie, MediaCover cover) private async Task DownloadCover(Movie movie, MediaCover cover)
{ {
var fileName = GetCoverPath(movie.Id, cover.CoverType); var fileName = GetCoverPath(movie.Id, cover.CoverType);
_logger.Info("Downloading {0} for {1} {2}", cover.CoverType, movie, cover.RemoteUrl); _logger.Info("Downloading {0} for {1} {2}", cover.CoverType, movie, cover.RemoteUrl);
_httpClient.DownloadFile(cover.RemoteUrl, fileName); await _httpClient.DownloadFileAsync(cover.RemoteUrl, fileName);
} }
private void EnsureResizedCovers(Movie movie, MediaCover cover, bool forceResize) private void EnsureResizedCovers(Movie movie, MediaCover cover, bool forceResize)
@ -265,7 +266,7 @@ namespace NzbDrone.Core.MediaCover
public void HandleAsync(MovieUpdatedEvent message) public void HandleAsync(MovieUpdatedEvent message)
{ {
var updated = EnsureCovers(message.Movie); var updated = EnsureCovers(message.Movie).GetAwaiter().GetResult();
_eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Movie, updated)); _eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Movie, updated));
} }

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Collections; using NzbDrone.Core.Movies.Collections;
using NzbDrone.Core.Movies.Credits; using NzbDrone.Core.Movies.Credits;
@ -8,8 +9,8 @@ namespace NzbDrone.Core.MetadataSource
{ {
public interface IProvideMovieInfo public interface IProvideMovieInfo
{ {
MovieMetadata GetMovieByImdbId(string imdbId); Task<MovieMetadata> GetMovieByImdbId(string imdbId);
Tuple<MovieMetadata, List<Credit>> GetMovieInfo(int tmdbId); Task<Tuple<MovieMetadata, List<Credit>>> GetMovieInfo(int tmdbId);
MovieCollection GetCollectionInfo(int tmdbId); MovieCollection GetCollectionInfo(int tmdbId);
List<MovieMetadata> GetBulkMovieInfo(List<int> tmdbIds); List<MovieMetadata> GetBulkMovieInfo(List<int> tmdbIds);

@ -1,12 +1,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
namespace NzbDrone.Core.MetadataSource namespace NzbDrone.Core.MetadataSource
{ {
public interface ISearchForNewMovie public interface ISearchForNewMovie
{ {
List<Movie> SearchForNewMovie(string title); Task<List<Movie>> SearchForNewMovie(string title);
MovieMetadata MapMovieToTmdbMovie(MovieMetadata movie); Task<MovieMetadata> MapMovieToTmdbMovie(MovieMetadata movie);
} }
} }

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using NzbDrone.Common.Cloud; using NzbDrone.Common.Cloud;
@ -70,7 +71,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return new HashSet<int>(response.Resource); return new HashSet<int>(response.Resource);
} }
public Tuple<MovieMetadata, List<Credit>> GetMovieInfo(int tmdbId) public async Task<Tuple<MovieMetadata, List<Credit>>> GetMovieInfo(int tmdbId)
{ {
var httpRequest = _radarrMetadata.Create() var httpRequest = _radarrMetadata.Create()
.SetSegment("route", "movie") .SetSegment("route", "movie")
@ -80,7 +81,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
httpRequest.AllowAutoRedirect = true; httpRequest.AllowAutoRedirect = true;
httpRequest.SuppressHttpError = true; httpRequest.SuppressHttpError = true;
var httpResponse = _httpClient.Get<MovieResource>(httpRequest); var httpResponse = await _httpClient.GetAsync<MovieResource>(httpRequest);
if (httpResponse.HasHttpError) if (httpResponse.HasHttpError)
{ {
@ -158,7 +159,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return movies; return movies;
} }
public MovieMetadata GetMovieByImdbId(string imdbId) public async Task<MovieMetadata> GetMovieByImdbId(string imdbId)
{ {
imdbId = Parser.Parser.NormalizeImdbId(imdbId); imdbId = Parser.Parser.NormalizeImdbId(imdbId);
@ -175,7 +176,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
httpRequest.AllowAutoRedirect = true; httpRequest.AllowAutoRedirect = true;
httpRequest.SuppressHttpError = true; httpRequest.SuppressHttpError = true;
var httpResponse = _httpClient.Get<List<MovieResource>>(httpRequest); var httpResponse = await _httpClient.GetAsync<List<MovieResource>>(httpRequest);
if (httpResponse.HasHttpError) if (httpResponse.HasHttpError)
{ {
@ -310,7 +311,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return title; return title;
} }
public MovieMetadata MapMovieToTmdbMovie(MovieMetadata movie) public async Task<MovieMetadata> MapMovieToTmdbMovie(MovieMetadata movie)
{ {
try try
{ {
@ -325,7 +326,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return newMovie; return newMovie;
} }
newMovie = GetMovieInfo(movie.TmdbId).Item1; var movieInfo = await GetMovieInfo(movie.TmdbId);
newMovie = movieInfo.Item1;
} }
else if (movie.ImdbId.IsNotNullOrWhiteSpace()) else if (movie.ImdbId.IsNotNullOrWhiteSpace())
{ {
@ -336,7 +338,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return newMovie; return newMovie;
} }
newMovie = GetMovieByImdbId(movie.ImdbId); newMovie = await GetMovieByImdbId(movie.ImdbId);
} }
else else
{ {
@ -346,7 +348,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
yearStr = $" {movie.Year}"; yearStr = $" {movie.Year}";
} }
var newMovieObject = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault(); var searchedNewMovies = await SearchForNewMovie(movie.Title + yearStr);
var newMovieObject = searchedNewMovies.FirstOrDefault();
if (newMovieObject == null) if (newMovieObject == null)
{ {
@ -373,7 +376,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
} }
} }
public List<Movie> SearchForNewMovie(string title) public async Task<List<Movie>> SearchForNewMovie(string title)
{ {
try try
{ {
@ -400,7 +403,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
{ {
try try
{ {
var movieLookup = GetMovieByImdbId(parserResult.ImdbId); var movieLookup = await GetMovieByImdbId(parserResult.ImdbId);
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } }; return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } };
} }
catch (Exception) catch (Exception)
@ -413,7 +416,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
{ {
try try
{ {
var movieLookup = GetMovieInfo(parserResult.TmdbId).Item1; var movieInfo = await GetMovieInfo(parserResult.TmdbId);
var movieLookup = movieInfo.Item1;
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } }; return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } };
} }
catch (Exception) catch (Exception)
@ -438,7 +442,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
try try
{ {
var movieLookup = GetMovieByImdbId(imdbid); var movieLookup = await GetMovieByImdbId(imdbid);
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } }; return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } };
} }
catch (MovieNotFoundException) catch (MovieNotFoundException)
@ -460,7 +464,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
try try
{ {
var movieLookup = GetMovieInfo(tmdbid).Item1; var movieInfo = await GetMovieInfo(tmdbid);
var movieLookup = movieInfo.Item1;
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } }; return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } };
} }
catch (MovieNotFoundException) catch (MovieNotFoundException)
@ -482,7 +487,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
request.AllowAutoRedirect = true; request.AllowAutoRedirect = true;
request.SuppressHttpError = true; request.SuppressHttpError = true;
var httpResponse = _httpClient.Get<List<MovieResource>>(request); var httpResponse = await _httpClient.GetAsync<List<MovieResource>>(request);
return httpResponse.Resource.SelectList(MapSearchResult); return httpResponse.Resource.SelectList(MapSearchResult);
} }

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using FluentValidation; using FluentValidation;
using FluentValidation.Results; using FluentValidation.Results;
using NLog; using NLog;
@ -15,8 +16,8 @@ namespace NzbDrone.Core.Movies
{ {
public interface IAddMovieService public interface IAddMovieService
{ {
Movie AddMovie(Movie newMovie); Task<Movie> AddMovie(Movie newMovie);
List<Movie> AddMovies(List<Movie> newMovies, bool ignoreErrors = false); Task<List<Movie>> AddMovies(List<Movie> newMovies, bool ignoreErrors = false);
} }
public class AddMovieService : IAddMovieService public class AddMovieService : IAddMovieService
@ -43,11 +44,11 @@ namespace NzbDrone.Core.Movies
_logger = logger; _logger = logger;
} }
public Movie AddMovie(Movie newMovie) public async Task<Movie> AddMovie(Movie newMovie)
{ {
Ensure.That(newMovie, () => newMovie).IsNotNull(); Ensure.That(newMovie, () => newMovie).IsNotNull();
newMovie = AddSkyhookData(newMovie); newMovie = await AddSkyhookData(newMovie);
newMovie = SetPropertiesAndValidate(newMovie); newMovie = SetPropertiesAndValidate(newMovie);
_logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path); _logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path);
@ -60,7 +61,7 @@ namespace NzbDrone.Core.Movies
return newMovie; return newMovie;
} }
public List<Movie> AddMovies(List<Movie> newMovies, bool ignoreErrors = false) public async Task<List<Movie>> AddMovies(List<Movie> newMovies, bool ignoreErrors = false)
{ {
var added = DateTime.UtcNow; var added = DateTime.UtcNow;
var moviesToAdd = new List<Movie>(); var moviesToAdd = new List<Movie>();
@ -71,7 +72,7 @@ namespace NzbDrone.Core.Movies
try try
{ {
var movie = AddSkyhookData(m); var movie = await AddSkyhookData(m);
movie = SetPropertiesAndValidate(movie); movie = SetPropertiesAndValidate(movie);
movie.Added = added; movie.Added = added;
@ -95,13 +96,14 @@ namespace NzbDrone.Core.Movies
return _movieService.AddMovies(moviesToAdd); return _movieService.AddMovies(moviesToAdd);
} }
private Movie AddSkyhookData(Movie newMovie) private async Task<Movie> AddSkyhookData(Movie newMovie)
{ {
var movie = new Movie(); var movie = new Movie();
try try
{ {
movie.MovieMetadata = _movieInfo.GetMovieInfo(newMovie.TmdbId).Item1; var movieInfo = await _movieInfo.GetMovieInfo(newMovie.TmdbId);
movie.MovieMetadata = movieInfo.Item1;
} }
catch (MovieNotFoundException) catch (MovieNotFoundException)
{ {

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using NLog; using NLog;
using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Core.Exceptions; using NzbDrone.Core.Exceptions;
@ -116,7 +117,7 @@ namespace NzbDrone.Core.Movies
return false; return false;
} }
private void SyncCollectionMovies(MovieCollection collection) private async Task SyncCollectionMovies(MovieCollection collection)
{ {
if (collection.Monitored) if (collection.Monitored)
{ {
@ -127,7 +128,7 @@ namespace NzbDrone.Core.Movies
if (moviesToAdd.Any()) if (moviesToAdd.Any())
{ {
_addMovieService.AddMovies(moviesToAdd.Select(m => new Movie await _addMovieService.AddMovies(moviesToAdd.Select(m => new Movie
{ {
TmdbId = m.TmdbId, TmdbId = m.TmdbId,
Title = m.Title, Title = m.Title,
@ -153,7 +154,7 @@ namespace NzbDrone.Core.Movies
foreach (var collectionId in message.CollectionIds) foreach (var collectionId in message.CollectionIds)
{ {
var newCollection = RefreshCollectionInfo(collectionId); var newCollection = RefreshCollectionInfo(collectionId);
SyncCollectionMovies(newCollection); SyncCollectionMovies(newCollection).GetAwaiter().GetResult();
} }
} }
else else
@ -171,7 +172,7 @@ namespace NzbDrone.Core.Movies
newCollection = RefreshCollectionInfo(collection.Id); newCollection = RefreshCollectionInfo(collection.Id);
} }
SyncCollectionMovies(newCollection); SyncCollectionMovies(newCollection).GetAwaiter().GetResult();
} }
catch (MovieNotFoundException) catch (MovieNotFoundException)
{ {

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using NLog; using NLog;
using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Core.AutoTagging; using NzbDrone.Core.AutoTagging;
@ -69,7 +70,7 @@ namespace NzbDrone.Core.Movies
_logger = logger; _logger = logger;
} }
private Movie RefreshMovieInfo(int movieId) private async Task<Movie> RefreshMovieInfo(int movieId)
{ {
// Get the movie before updating, that way any changes made to the movie after the refresh started, // Get the movie before updating, that way any changes made to the movie after the refresh started,
// but before this movie was refreshed won't be lost. // but before this movie was refreshed won't be lost.
@ -83,7 +84,7 @@ namespace NzbDrone.Core.Movies
try try
{ {
var tuple = _movieInfo.GetMovieInfo(movie.TmdbId); var tuple = await _movieInfo.GetMovieInfo(movie.TmdbId);
movieInfo = tuple.Item1; movieInfo = tuple.Item1;
credits = tuple.Item2; credits = tuple.Item2;
} }
@ -250,7 +251,7 @@ namespace NzbDrone.Core.Movies
try try
{ {
movie = RefreshMovieInfo(movieId); movie = RefreshMovieInfo(movieId).GetAwaiter().GetResult();
UpdateTags(movie); UpdateTags(movie);
RescanMovie(movie, isNew, trigger); RescanMovie(movie, isNew, trigger);
} }
@ -286,7 +287,7 @@ namespace NzbDrone.Core.Movies
{ {
try try
{ {
movieLocal = RefreshMovieInfo(movieLocal.Id); movieLocal = RefreshMovieInfo(movieLocal.Id).GetAwaiter().GetResult();
} }
catch (MovieNotFoundException) catch (MovieNotFoundException)
{ {

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.ImportLists; using NzbDrone.Core.ImportLists;
@ -54,6 +55,7 @@ namespace Radarr.Api.V3.ImportLists
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public object GetDiscoverMovies(bool includeRecommendations = false) public object GetDiscoverMovies(bool includeRecommendations = false)
{ {
var movieLanguage = (Language)_configService.MovieInfoLanguage; var movieLanguage = (Language)_configService.MovieInfoLanguage;
@ -100,11 +102,14 @@ namespace Radarr.Api.V3.ImportLists
} }
[HttpPost] [HttpPost]
public object AddMovies([FromBody] List<MovieResource> resource) [Consumes("application/json")]
[Produces("application/json")]
public async Task<List<MovieResource>> AddMovies([FromBody] List<MovieResource> resource)
{ {
var newMovies = resource.ToModel(); var newMovies = resource.ToModel();
var addedMovies = await _addMovieService.AddMovies(newMovies, true);
return _addMovieService.AddMovies(newMovies, true).ToResource(0); return addedMovies.ToResource(0);
} }
private IEnumerable<ImportListMoviesResource> MapToResource(IEnumerable<Movie> movies, Language language) private IEnumerable<ImportListMoviesResource> MapToResource(IEnumerable<Movie> movies, Language language)

@ -219,9 +219,9 @@ namespace Radarr.Api.V3.Movies
} }
[RestPostById] [RestPostById]
public ActionResult<MovieResource> AddMovie(MovieResource moviesResource) public async Task<ActionResult<MovieResource>> AddMovie(MovieResource moviesResource)
{ {
var movie = _addMovieService.AddMovie(moviesResource.ToModel()); var movie = await _addMovieService.AddMovie(moviesResource.ToModel());
return Created(movie.Id); return Created(movie.Id);
} }

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using Radarr.Http; using Radarr.Http;
@ -24,11 +25,14 @@ namespace Radarr.Api.V3.Movies
} }
[HttpPost] [HttpPost]
public object Import([FromBody] List<MovieResource> resource) [Consumes("application/json")]
[Produces("application/json")]
public async Task<List<MovieResource>> Import([FromBody] List<MovieResource> resource)
{ {
var newMovies = resource.ToModel(); var newMovies = resource.ToModel();
var addedMovies = await _addMovieService.AddMovies(newMovies);
return _addMovieService.AddMovies(newMovies).ToResource(0); return addedMovies.ToResource(0);
} }
} }
} }

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Languages; using NzbDrone.Core.Languages;
@ -45,28 +46,34 @@ namespace Radarr.Api.V3.Movies
} }
[HttpGet("tmdb")] [HttpGet("tmdb")]
public object SearchByTmdbId(int tmdbId) [Produces("application/json")]
public async Task<MovieResource> SearchByTmdbId(int tmdbId)
{ {
var availDelay = _configService.AvailabilityDelay; var availDelay = _configService.AvailabilityDelay;
var result = new Movie { MovieMetadata = _movieInfo.GetMovieInfo(tmdbId).Item1 }; var movieInfo = await _movieInfo.GetMovieInfo(tmdbId);
var result = new Movie { MovieMetadata = movieInfo.Item1 };
var translation = result.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage); var translation = result.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
return result.ToResource(availDelay, translation); return result.ToResource(availDelay, translation);
} }
[HttpGet("imdb")] [HttpGet("imdb")]
public object SearchByImdbId(string imdbId) [Produces("application/json")]
public async Task<MovieResource> SearchByImdbId(string imdbId)
{ {
var result = new Movie { MovieMetadata = _movieInfo.GetMovieByImdbId(imdbId) }; var result = new Movie { MovieMetadata = await _movieInfo.GetMovieByImdbId(imdbId) };
var availDelay = _configService.AvailabilityDelay; var availDelay = _configService.AvailabilityDelay;
var translation = result.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage); var translation = result.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
return result.ToResource(availDelay, translation); return result.ToResource(availDelay, translation);
} }
[HttpGet] [HttpGet]
public object Search([FromQuery] string term) [Produces("application/json")]
public async Task<IEnumerable<MovieResource>> Search([FromQuery] string term)
{ {
var searchResults = _searchProxy.SearchForNewMovie(term); var searchResults = await _searchProxy.SearchForNewMovie(term);
return MapToResource(searchResults); return MapToResource(searchResults);
} }

Loading…
Cancel
Save