mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-17 15:02:34 +02:00
Automatically downloading the best movie release works now.
This commit is contained in:
parent
cde1217356
commit
4f6380a73c
@ -21,11 +21,12 @@ protected override void MainDbUpgrade()
|
|||||||
|
|
||||||
//Add HeldReleases
|
//Add HeldReleases
|
||||||
Create.TableForModel("PendingReleases")
|
Create.TableForModel("PendingReleases")
|
||||||
.WithColumn("SeriesId").AsInt32()
|
.WithColumn("SeriesId").AsInt32().WithDefaultValue(0)
|
||||||
.WithColumn("Title").AsString()
|
.WithColumn("Title").AsString()
|
||||||
.WithColumn("Added").AsDateTime()
|
.WithColumn("Added").AsDateTime()
|
||||||
.WithColumn("ParsedEpisodeInfo").AsString()
|
.WithColumn("ParsedEpisodeInfo").AsString()
|
||||||
.WithColumn("Release").AsString();
|
.WithColumn("Release").AsString()
|
||||||
|
.WithColumn("MovieId").AsInt32().WithDefaultValue(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ public class CompletedDownloadService : ICompletedDownloadService
|
|||||||
private readonly IHistoryService _historyService;
|
private readonly IHistoryService _historyService;
|
||||||
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
|
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
|
||||||
private readonly IParsingService _parsingService;
|
private readonly IParsingService _parsingService;
|
||||||
|
private readonly IMovieService _movieService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
private readonly ISeriesService _seriesService;
|
private readonly ISeriesService _seriesService;
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ public CompletedDownloadService(IConfigService configService,
|
|||||||
IDownloadedEpisodesImportService downloadedEpisodesImportService,
|
IDownloadedEpisodesImportService downloadedEpisodesImportService,
|
||||||
IParsingService parsingService,
|
IParsingService parsingService,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
|
IMovieService movieService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
@ -44,6 +46,7 @@ public CompletedDownloadService(IConfigService configService,
|
|||||||
_historyService = historyService;
|
_historyService = historyService;
|
||||||
_downloadedEpisodesImportService = downloadedEpisodesImportService;
|
_downloadedEpisodesImportService = downloadedEpisodesImportService;
|
||||||
_parsingService = parsingService;
|
_parsingService = parsingService;
|
||||||
|
_movieService = movieService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_seriesService = seriesService;
|
_seriesService = seriesService;
|
||||||
}
|
}
|
||||||
@ -88,19 +91,31 @@ public void Process(TrackedDownload trackedDownload, bool ignoreWarnings = false
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title);
|
var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title);
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
{
|
{
|
||||||
if (historyItem != null)
|
if (historyItem != null)
|
||||||
{
|
{
|
||||||
series = _seriesService.GetSeries(historyItem.SeriesId);
|
//series = _seriesService.GetSeries(historyItem.SeriesId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
{
|
{
|
||||||
trackedDownload.Warn("Series title mismatch, automatic import is not possible.");
|
var movie = _parsingService.GetMovie(trackedDownload.DownloadItem.Title);
|
||||||
return;
|
|
||||||
|
if (movie == null)
|
||||||
|
{
|
||||||
|
movie = _movieService.GetMovie(historyItem.MovieId);
|
||||||
|
|
||||||
|
if (movie == null)
|
||||||
|
{
|
||||||
|
trackedDownload.Warn("Movie title mismatch, automatic import is not possible.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//trackedDownload.Warn("Series title mismatch, automatic import is not possible.");
|
||||||
|
//return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ namespace NzbDrone.Core.Download.Pending
|
|||||||
public class PendingRelease : ModelBase
|
public class PendingRelease : ModelBase
|
||||||
{
|
{
|
||||||
public int SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
|
public int MovieId { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public DateTime Added { get; set; }
|
public DateTime Added { get; set; }
|
||||||
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
|
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
|
||||||
@ -14,5 +15,6 @@ public class PendingRelease : ModelBase
|
|||||||
|
|
||||||
//Not persisted
|
//Not persisted
|
||||||
public RemoteEpisode RemoteEpisode { get; set; }
|
public RemoteEpisode RemoteEpisode { get; set; }
|
||||||
|
public RemoteMovie RemoteMovie { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,7 +344,7 @@ public void Handle(EpisodeGrabbedEvent message)
|
|||||||
|
|
||||||
public void Handle(MovieGrabbedEvent message)
|
public void Handle(MovieGrabbedEvent message)
|
||||||
{
|
{
|
||||||
|
//RemoveGrabbed(message.Movie);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(RssSyncCompleteEvent message)
|
public void Handle(RssSyncCompleteEvent message)
|
||||||
|
@ -32,53 +32,112 @@ public ProcessDownloadDecisions(IDownloadService downloadService,
|
|||||||
|
|
||||||
public ProcessedDecisions ProcessDecisions(List<DownloadDecision> decisions)
|
public ProcessedDecisions ProcessDecisions(List<DownloadDecision> decisions)
|
||||||
{
|
{
|
||||||
var qualifiedReports = GetQualifiedReports(decisions);
|
//var qualifiedReports = GetQualifiedReports(decisions);
|
||||||
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(qualifiedReports);
|
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions);
|
||||||
var grabbed = new List<DownloadDecision>();
|
var grabbed = new List<DownloadDecision>();
|
||||||
var pending = new List<DownloadDecision>();
|
var pending = new List<DownloadDecision>();
|
||||||
|
|
||||||
foreach (var report in prioritizedDecisions)
|
foreach (var report in prioritizedDecisions)
|
||||||
{
|
{
|
||||||
var remoteEpisode = report.RemoteEpisode;
|
|
||||||
|
|
||||||
var episodeIds = remoteEpisode.Episodes.Select(e => e.Id).ToList();
|
if (report.IsForMovie)
|
||||||
|
|
||||||
//Skip if already grabbed
|
|
||||||
if (grabbed.SelectMany(r => r.RemoteEpisode.Episodes)
|
|
||||||
.Select(e => e.Id)
|
|
||||||
.ToList()
|
|
||||||
.Intersect(episodeIds)
|
|
||||||
.Any())
|
|
||||||
{
|
{
|
||||||
continue;
|
var remoteMovie = report.RemoteMovie;
|
||||||
|
|
||||||
|
if (report.TemporarilyRejected)
|
||||||
|
{
|
||||||
|
_pendingReleaseService.Add(report);
|
||||||
|
pending.Add(report);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remoteMovie == null || remoteMovie.Movie == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> movieIds = new List<int> { remoteMovie.Movie.Id };
|
||||||
|
|
||||||
|
|
||||||
|
//Skip if already grabbed
|
||||||
|
if (grabbed.Select(r => r.RemoteMovie.Movie)
|
||||||
|
.Select(e => e.Id)
|
||||||
|
.ToList()
|
||||||
|
.Intersect(movieIds)
|
||||||
|
.Any())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pending.Select(r => r.RemoteMovie.Movie)
|
||||||
|
.Select(e => e.Id)
|
||||||
|
.ToList()
|
||||||
|
.Intersect(movieIds)
|
||||||
|
.Any())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_downloadService.DownloadReport(remoteMovie);
|
||||||
|
grabbed.Add(report);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//TODO: support for store & forward
|
||||||
|
//We'll need to differentiate between a download client error and an indexer error
|
||||||
|
_logger.Warn(e, "Couldn't add report to download queue. " + remoteMovie);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var remoteEpisode = report.RemoteEpisode;
|
||||||
|
|
||||||
if (report.TemporarilyRejected)
|
if (remoteEpisode == null || remoteEpisode.Episodes == null)
|
||||||
{
|
{
|
||||||
_pendingReleaseService.Add(report);
|
continue;
|
||||||
pending.Add(report);
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pending.SelectMany(r => r.RemoteEpisode.Episodes)
|
var episodeIds = remoteEpisode.Episodes.Select(e => e.Id).ToList();
|
||||||
.Select(e => e.Id)
|
|
||||||
.ToList()
|
|
||||||
.Intersect(episodeIds)
|
|
||||||
.Any())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
//Skip if already grabbed
|
||||||
{
|
if (grabbed.SelectMany(r => r.RemoteEpisode.Episodes)
|
||||||
_downloadService.DownloadReport(remoteEpisode);
|
.Select(e => e.Id)
|
||||||
grabbed.Add(report);
|
.ToList()
|
||||||
}
|
.Intersect(episodeIds)
|
||||||
catch (Exception e)
|
.Any())
|
||||||
{
|
{
|
||||||
//TODO: support for store & forward
|
continue;
|
||||||
//We'll need to differentiate between a download client error and an indexer error
|
}
|
||||||
_logger.Warn(e, "Couldn't add report to download queue. " + remoteEpisode);
|
|
||||||
|
if (report.TemporarilyRejected)
|
||||||
|
{
|
||||||
|
_pendingReleaseService.Add(report);
|
||||||
|
pending.Add(report);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pending.SelectMany(r => r.RemoteEpisode.Episodes)
|
||||||
|
.Select(e => e.Id)
|
||||||
|
.ToList()
|
||||||
|
.Intersect(episodeIds)
|
||||||
|
.Any())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_downloadService.DownloadReport(remoteEpisode);
|
||||||
|
grabbed.Add(report);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//TODO: support for store & forward
|
||||||
|
//We'll need to differentiate between a download client error and an indexer error
|
||||||
|
_logger.Warn(e, "Couldn't add report to download queue. " + remoteEpisode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
src/NzbDrone.Core/IndexerSearch/MoviesSearchCommand.cs
Normal file
11
src/NzbDrone.Core/IndexerSearch/MoviesSearchCommand.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.IndexerSearch
|
||||||
|
{
|
||||||
|
public class MoviesSearchCommand : Command
|
||||||
|
{
|
||||||
|
public int MovieId { get; set; }
|
||||||
|
|
||||||
|
public override bool SendUpdatesToClient => true;
|
||||||
|
}
|
||||||
|
}
|
46
src/NzbDrone.Core/IndexerSearch/MoviesSearchService.cs
Normal file
46
src/NzbDrone.Core/IndexerSearch/MoviesSearchService.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.IndexerSearch
|
||||||
|
{
|
||||||
|
public class MovieSearchService : IExecute<MoviesSearchCommand>
|
||||||
|
{
|
||||||
|
private readonly IMovieService _seriesService;
|
||||||
|
private readonly ISearchForNzb _nzbSearchService;
|
||||||
|
private readonly IProcessDownloadDecisions _processDownloadDecisions;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public MovieSearchService(IMovieService seriesService,
|
||||||
|
ISearchForNzb nzbSearchService,
|
||||||
|
IProcessDownloadDecisions processDownloadDecisions,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_seriesService = seriesService;
|
||||||
|
_nzbSearchService = nzbSearchService;
|
||||||
|
_processDownloadDecisions = processDownloadDecisions;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(MoviesSearchCommand message)
|
||||||
|
{
|
||||||
|
var series = _seriesService.GetMovie(message.MovieId);
|
||||||
|
|
||||||
|
var downloadedCount = 0;
|
||||||
|
|
||||||
|
if (!series.Monitored)
|
||||||
|
{
|
||||||
|
_logger.Debug("Movie {0} is not monitored, skipping search", series.Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
var decisions = _nzbSearchService.MovieSearch(message.MovieId, false);//_nzbSearchService.SeasonSearch(message.MovieId, season.SeasonNumber, false, message.Trigger == CommandTrigger.Manual);
|
||||||
|
downloadedCount += _processDownloadDecisions.ProcessDecisions(decisions).Grabbed.Count;
|
||||||
|
|
||||||
|
|
||||||
|
_logger.ProgressInfo("Movie search completed. {0} reports downloaded.", downloadedCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -564,6 +564,8 @@
|
|||||||
<Compile Include="Http\HttpProxySettingsProvider.cs" />
|
<Compile Include="Http\HttpProxySettingsProvider.cs" />
|
||||||
<Compile Include="Http\TorcacheHttpInterceptor.cs" />
|
<Compile Include="Http\TorcacheHttpInterceptor.cs" />
|
||||||
<Compile Include="IndexerSearch\Definitions\MovieSearchCriteria.cs" />
|
<Compile Include="IndexerSearch\Definitions\MovieSearchCriteria.cs" />
|
||||||
|
<Compile Include="IndexerSearch\MoviesSearchCommand.cs" />
|
||||||
|
<Compile Include="IndexerSearch\MoviesSearchService.cs" />
|
||||||
<Compile Include="Indexers\BitMeTv\BitMeTv.cs" />
|
<Compile Include="Indexers\BitMeTv\BitMeTv.cs" />
|
||||||
<Compile Include="Indexers\BitMeTv\BitMeTvSettings.cs" />
|
<Compile Include="Indexers\BitMeTv\BitMeTvSettings.cs" />
|
||||||
<Compile Include="Indexers\BitMeTv\BitMeTvRequestGenerator.cs" />
|
<Compile Include="Indexers\BitMeTv\BitMeTvRequestGenerator.cs" />
|
||||||
|
@ -16,6 +16,7 @@ public interface IParsingService
|
|||||||
LocalEpisode GetLocalEpisode(string filename, Series series);
|
LocalEpisode GetLocalEpisode(string filename, Series series);
|
||||||
LocalEpisode GetLocalEpisode(string filename, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource);
|
LocalEpisode GetLocalEpisode(string filename, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource);
|
||||||
Series GetSeries(string title);
|
Series GetSeries(string title);
|
||||||
|
Movie GetMovie(string title);
|
||||||
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null);
|
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null);
|
||||||
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int seriesId, IEnumerable<int> episodeIds);
|
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int seriesId, IEnumerable<int> episodeIds);
|
||||||
RemoteMovie Map(ParsedEpisodeInfo parsedEpisodeInfo, string imdbId, SearchCriteriaBase searchCriteria = null);
|
RemoteMovie Map(ParsedEpisodeInfo parsedEpisodeInfo, string imdbId, SearchCriteriaBase searchCriteria = null);
|
||||||
@ -104,7 +105,7 @@ public Series GetSeries(string title)
|
|||||||
|
|
||||||
if (parsedEpisodeInfo == null)
|
if (parsedEpisodeInfo == null)
|
||||||
{
|
{
|
||||||
return _seriesService.FindByTitle(title); //Here we have a problem since it is not possible for movies to find a scene mapping, so these releases are always rejected :(
|
return _seriesService.FindByTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
||||||
@ -118,6 +119,26 @@ public Series GetSeries(string title)
|
|||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Movie GetMovie(string title)
|
||||||
|
{
|
||||||
|
var parsedEpisodeInfo = Parser.ParseTitle(title);
|
||||||
|
|
||||||
|
if (parsedEpisodeInfo == null)
|
||||||
|
{
|
||||||
|
return _movieService.FindByTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
var series = _movieService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
||||||
|
|
||||||
|
if (series == null)
|
||||||
|
{
|
||||||
|
series = _movieService.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear,
|
||||||
|
parsedEpisodeInfo.SeriesTitleInfo.Year);
|
||||||
|
}
|
||||||
|
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null)
|
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null)
|
||||||
{
|
{
|
||||||
var remoteEpisode = new RemoteEpisode
|
var remoteEpisode = new RemoteEpisode
|
||||||
|
@ -86,7 +86,7 @@ var singleton = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
console.warn(options)
|
||||||
options.element.startSpin();
|
options.element.startSpin();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,7 @@ module.exports = Marionette.Layout.extend({
|
|||||||
edit : '.x-edit',
|
edit : '.x-edit',
|
||||||
refresh : '.x-refresh',
|
refresh : '.x-refresh',
|
||||||
rename : '.x-rename',
|
rename : '.x-rename',
|
||||||
search : '.x-search',
|
searchAuto : '.x-search',
|
||||||
poster : '.x-movie-poster',
|
poster : '.x-movie-poster',
|
||||||
manualSearch : '.x-manual-search',
|
manualSearch : '.x-manual-search',
|
||||||
history : '.x-movie-history',
|
history : '.x-movie-history',
|
||||||
@ -86,8 +86,9 @@ module.exports = Marionette.Layout.extend({
|
|||||||
name : 'refreshMovie'
|
name : 'refreshMovie'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CommandController.bindToCommand({
|
CommandController.bindToCommand({
|
||||||
element : this.ui.search,
|
element : this.ui.searchAuto,
|
||||||
command : {
|
command : {
|
||||||
name : 'moviesSearch'
|
name : 'moviesSearch'
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user