PreDB Integration. Update Library is advisable

pull/1117/head
Leonardo Galli 8 years ago committed by GitHub
parent 3cf5301e46
commit 149c5292f1

@ -29,7 +29,7 @@ namespace NzbDrone.Api.Movie
int tmdbId = -1;
if(Int32.TryParse(Request.Query.tmdbId, out tmdbId))
{
var result = _movieInfo.GetMovieInfo(tmdbId, null);
var result = _movieInfo.GetMovieInfo(tmdbId, null, true);
return result.ToResource().AsResponse();
}

@ -0,0 +1,15 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(135)]
public class add_haspredbentry_to_movies : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Movies").AddColumn("HasPreDBEntry").AsBoolean().WithDefaultValue(false);
}
}
}

@ -17,6 +17,7 @@ using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.NetImport;
using NzbDrone.Core.Tv.Commands;
using NzbDrone.Core.Update.Commands;
using NzbDrone.Core.MetadataSource.PreDB;
namespace NzbDrone.Core.Jobs
{
@ -72,6 +73,7 @@ namespace NzbDrone.Core.Jobs
var defaultTasks = new[]
{
new ScheduledTask{ Interval = 0.25f, TypeName = typeof(CheckForFinishedDownloadCommand).FullName},
new ScheduledTask{ Interval = 1*60, TypeName = typeof(PreDBSyncCommand).FullName},
new ScheduledTask{ Interval = 5, TypeName = typeof(MessagingCleanupCommand).FullName},
new ScheduledTask{ Interval = updateInterval, TypeName = typeof(ApplicationUpdateCommand).FullName},
// new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},

@ -8,6 +8,6 @@ namespace NzbDrone.Core.MetadataSource
public interface IProvideMovieInfo
{
Movie GetMovieInfo(string ImdbId);
Movie GetMovieInfo(int TmdbId, Profile profile);
Movie GetMovieInfo(int TmdbId, Profile profile, bool hasPreDBEntry);
}
}

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.MetadataSource.PreDB
{
class PreDBResult
{
public string Title { get; set; }
public string Link { get; set; }
}
}

@ -0,0 +1,194 @@
using System.Linq;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Pending;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Indexers;
using System.ServiceModel.Syndication;
using System.Xml;
using NzbDrone.Common.Http;
using NzbDrone.Core.Tv;
using System;
using System.IO;
using NzbDrone.Core.Parser;
using NzbDrone.Core.IndexerSearch;
using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.MetadataSource.PreDB
{
public interface IPreDBService
{
bool HasReleases(Movie movie);
}
public class PreDBService : IPreDBService, IExecute<PreDBSyncCommand>
{
private readonly IFetchAndParseRss _rssFetcherAndParser;
private readonly IMakeDownloadDecision _downloadDecisionMaker;
private readonly IProcessDownloadDecisions _processDownloadDecisions;
private readonly IPendingReleaseService _pendingReleaseService;
private readonly IEventAggregator _eventAggregator;
private readonly IMovieService _movieService;
private readonly IHttpClient _httpClient;
private readonly IParsingService _parsingService;
private readonly Logger _logger;
public PreDBService(
IFetchAndParseRss rssFetcherAndParser,
IMakeDownloadDecision downloadDecisionMaker,
IProcessDownloadDecisions processDownloadDecisions,
IPendingReleaseService pendingReleaseService,
IEventAggregator eventAggregator,
IMovieService movieService,
IHttpClient httpClient,
IParsingService parsingService,
Logger logger)
{
_rssFetcherAndParser = rssFetcherAndParser;
_downloadDecisionMaker = downloadDecisionMaker;
_processDownloadDecisions = processDownloadDecisions;
_pendingReleaseService = pendingReleaseService;
_eventAggregator = eventAggregator;
_movieService = movieService;
_httpClient = httpClient;
_parsingService = parsingService;
_logger = logger;
}
private List<PreDBResult> GetResults(string category = "", string search = "")
{
var builder = new HttpRequestBuilder("http://predb.me").AddQueryParam("rss", "1");
if (category.IsNotNullOrWhiteSpace())
{
builder.AddQueryParam("cats", category);
}
if (search.IsNotNullOrWhiteSpace())
{
builder.AddQueryParam("search", search);
}
var request = builder.Build();
request.AllowAutoRedirect = true;
request.SuppressHttpError = true;
var response = _httpClient.Get(request);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
_logger.Warn("Non 200 StatusCode {0} encountered while searching PreDB.", response.StatusCode);
return new List<PreDBResult>();
}
try
{
var reader = XmlReader.Create(new StringReader(response.Content));
var items = SyndicationFeed.Load(reader);
var results = new List<PreDBResult>();
foreach (SyndicationItem item in items.Items)
{
var result = new PreDBResult();
result.Title = item.Title.Text;
result.Link = item.Links[0].Uri.ToString();
results.Add(result);
}
return results;
}
catch (Exception ex)
{
_logger.Error(ex, "Error while searching PreDB.");
}
return new List<PreDBResult>();
}
private List<Movie> FindMatchesToResults(List<PreDBResult> results)
{
var matches = new List<Movie>();
foreach (PreDBResult result in results)
{
var parsedInfo = Parser.Parser.ParseMovieTitle(result.Title);
if (parsedInfo != null)
{
var movie = _movieService.FindByTitle(parsedInfo.MovieTitle, parsedInfo.Year);
if (movie != null)
{
matches.Add(movie);
}
}
}
return matches;
}
private List<Movie> Sync()
{
_logger.ProgressInfo("Starting PreDB Sync");
var results = GetResults("movies");
var matches = FindMatchesToResults(results);
return matches;
}
public void Execute(PreDBSyncCommand message)
{
var haveNewReleases = Sync();
foreach (Movie movie in haveNewReleases)
{
if (!movie.HasPreDBEntry)
{
movie.HasPreDBEntry = true;
_movieService.UpdateMovie(movie);
}
if (movie.Monitored)
{
//Maybe auto search each movie once?
}
}
_eventAggregator.PublishEvent(new PreDBSyncCompleteEvent(haveNewReleases));
}
public bool HasReleases(Movie movie)
{
var results = GetResults("movies", movie.Title);
foreach (PreDBResult result in results)
{
var parsed = Parser.Parser.ParseMovieTitle(result.Title);
if (parsed == null)
{
parsed = new Parser.Model.ParsedMovieInfo { MovieTitle = result.Title, Year = 0 };
}
var match = _parsingService.Map(parsed, "", new MovieSearchCriteria { Movie = movie });
if (match != null && match.Movie != null && match.Movie.Id == movie.Id)
{
return true;
}
}
return false;
}
}
}

@ -0,0 +1,10 @@
using NzbDrone.Core.Messaging.Commands;
namespace NzbDrone.Core.MetadataSource.PreDB
{
public class PreDBSyncCommand : Command
{
public override bool SendUpdatesToClient => true;
}
}

@ -0,0 +1,19 @@
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Download;
using System;
using System.Linq;
using System.Collections.Generic;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.MetadataSource.PreDB
{
public class PreDBSyncCompleteEvent : IEvent
{
public List<Movie> NewlyReleased { get; private set; }
public PreDBSyncCompleteEvent(List<Movie> newlyReleased)
{
NewlyReleased = newlyReleased;
}
}
}

@ -9,6 +9,8 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.MetadataSource.PreDB;
using NzbDrone.Core.Tv;
using System.Threading;
using NzbDrone.Core.Parser;
@ -25,14 +27,16 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
private readonly IHttpRequestBuilderFactory _movieBuilder;
private readonly ITmdbConfigService _configService;
private readonly IMovieService _movieService;
private readonly IPreDBService _predbService;
public SkyHookProxy(IHttpClient httpClient, ISonarrCloudRequestBuilder requestBuilder, ITmdbConfigService configService, IMovieService movieService, Logger logger)
public SkyHookProxy(IHttpClient httpClient, ISonarrCloudRequestBuilder requestBuilder, ITmdbConfigService configService, IMovieService movieService, IPreDBService predbService, Logger logger)
{
_httpClient = httpClient;
_requestBuilder = requestBuilder.SkyHookTvdb;
_movieBuilder = requestBuilder.TMDB;
_configService = configService;
_movieService = movieService;
_predbService = predbService;
_logger = logger;
}
@ -66,7 +70,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return new Tuple<Series, List<Episode>>(series, episodes.ToList());
}
public Movie GetMovieInfo(int TmdbId, Profile profile = null)
public Movie GetMovieInfo(int TmdbId, Profile profile = null, bool hasPreDBEntry = false)
{
var langCode = profile != null ? IsoLanguages.Get(profile.Language).TwoLetterCode : "us";
@ -235,12 +239,25 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
{
movie.Status = MovieStatusType.Announced;
}
//since TMDB lacks alot of information lets assume that stuff is released if its been in cinemas for longer than 3 months.
if (!movie.PhysicalRelease.HasValue && (movie.Status == MovieStatusType.InCinemas) && (((DateTime.Now).Subtract(movie.InCinemas.Value)).TotalSeconds > 60*60*24*30*3))
{
movie.Status = MovieStatusType.Released;
}
if (!hasPreDBEntry)
{
if (_predbService.HasReleases(movie))
{
movie.HasPreDBEntry = true;
}
else
{
movie.HasPreDBEntry = false;
}
}
//this matches with the old behavior before the creation of the MovieStatusType.InCinemas
/*if (resource.status == "Released")
{

@ -99,6 +99,7 @@
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
@ -890,6 +891,10 @@
<Compile Include="Messaging\IProcessMessage.cs" />
<Compile Include="MetadataSource\IProvideMovieInfo.cs" />
<Compile Include="MetadataSource\ISearchForNewMovie.cs" />
<Compile Include="MetadataSource\PreDB\PreDBResult.cs" />
<Compile Include="MetadataSource\PreDB\PreDBSyncCommand.cs" />
<Compile Include="MetadataSource\PreDB\PreDBSyncEvent.cs" />
<Compile Include="MetadataSource\PreDB\PreDBService.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ActorResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ConfigurationResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\EpisodeResource.cs" />
@ -1260,6 +1265,7 @@
<Compile Include="Validation\UrlValidator.cs" />
<Compile Include="Datastore\Migration\131_make_parsed_episode_info_nullable.cs" />
<Compile Include="Housekeeping\Housekeepers\FixWronglyMatchedMovieFiles.cs" />
<Compile Include="Datastore\Migration\135_add_haspredbentry_to_movies.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">

@ -47,6 +47,7 @@ namespace NzbDrone.Core.Tv
public HashSet<int> Tags { get; set; }
public AddMovieOptions AddOptions { get; set; }
public LazyLoaded<MovieFile> MovieFile { get; set; }
public bool HasPreDBEntry { get; set; }
public int MovieFileId { get; set; }
public List<string> AlternativeTitles { get; set; }
public string YouTubeTrailerId{ get; set; }
@ -73,13 +74,19 @@ namespace NzbDrone.Core.Tv
else
MinimumAvailabilityDate = DateTime.MaxValue;
break;
//TODO: might need to handle PreDB but for now treat the same as Released
case MovieStatusType.Released:
case MovieStatusType.PreDB:
default:
MinimumAvailabilityDate = PhysicalRelease.HasValue ? PhysicalRelease.Value : (InCinemas.HasValue ? InCinemas.Value.AddDays(90) : DateTime.MaxValue);
break;
}
if (HasPreDBEntry && MinimumAvailability == MovieStatusType.PreDB)
{
return true;
}
return DateTime.Now >= MinimumAvailabilityDate.AddDays(delay);
}

@ -101,7 +101,7 @@ namespace NzbDrone.Core.Tv
((v.MinimumAvailability == MovieStatusType.Released && v.Status >= MovieStatusType.Released) ||
(v.MinimumAvailability == MovieStatusType.InCinemas && v.Status >= MovieStatusType.InCinemas) ||
(v.MinimumAvailability == MovieStatusType.Announced && v.Status >= MovieStatusType.Announced) ||
(v.MinimumAvailability == MovieStatusType.PreDB && v.Status >= MovieStatusType.Released));
(v.MinimumAvailability == MovieStatusType.PreDB && v.Status >= MovieStatusType.Released || v.HasPreDBEntry == true));
break;
}
}

@ -51,7 +51,7 @@ namespace NzbDrone.Core.Tv
try
{
movieInfo = _movieInfo.GetMovieInfo(movie.TmdbId, movie.Profile);
movieInfo = _movieInfo.GetMovieInfo(movie.TmdbId, movie.Profile, movie.HasPreDBEntry);
}
catch (MovieNotFoundException)
{
@ -86,6 +86,7 @@ namespace NzbDrone.Core.Tv
movie.PhysicalRelease = movieInfo.PhysicalRelease;
movie.YouTubeTrailerId = movieInfo.YouTubeTrailerId;
movie.Studio = movieInfo.Studio;
movie.HasPreDBEntry = movieInfo.HasPreDBEntry;
try
{

@ -12,10 +12,6 @@ module.exports = NzbDroneCell.extend({
var timeSince = new Date().getTime() - date.getTime();
var numOfMonths = timeSince / 1000 / 60 / 60 / 24 / 30;
if (status === 'released') {
this.$el.html('<i class="icon-sonarr-movie-released grid-icon" title="Released"></i>');
this._setStatusWeight(3);
}
if (status === 'inCinemas') {
this.$el.html('<i class="icon-sonarr-movie-cinemas grid-icon" title="In Cinemas"></i>');

@ -92,7 +92,7 @@ Handlebars.registerHelper('GetStatus', function() {
return new Handlebars.SafeString('<i class="icon-sonarr-movie-released grid-icon" title=""></i>&nbsp;Released');
}
else if (!monitored) {
if (!monitored) {
return new Handlebars.SafeString('<i class="icon-sonarr-series-unmonitored grid-icon" title=""></i>&nbsp;Not Monitored');
}
});
@ -105,16 +105,13 @@ Handlebars.registerHelper('GetBannerStatus', function() {
//var timeSince = new Date().getTime() - date.getTime();
//var numOfMonths = timeSince / 1000 / 60 / 60 / 24 / 30;
if (status === "announced") {
return new Handlebars.SafeString('<div class="announced-banner"><i class="icon-sonarr-movie-announced grid-icon" title=""></i>&nbsp;Announced</div>');
}
if (status === "inCinemas") {
return new Handlebars.SafeString('<div class="cinemas-banner"><i class="icon-sonarr-movie-cinemas grid-icon" title=""></i>&nbsp;In Cinemas</div>');
}
if (status === 'released') {
return new Handlebars.SafeString('<div class="released-banner"><i class="icon-sonarr-movie-released grid-icon" title=""></i>&nbsp;Released</div>');
if (status === "announced") {
return new Handlebars.SafeString('<div class="announced-banner"><i class="icon-sonarr-movie-announced grid-icon" title=""></i>&nbsp;Announced</div>');
}
else if (!monitored) {
return new Handlebars.SafeString('<div class="announced-banner"><i class="icon-sonarr-series-unmonitored grid-icon" title=""></i>&nbsp;Not Monitored</div>');

@ -126,6 +126,12 @@ module.exports = Marionette.Layout.extend({
command : 'rsssync',
errorMessage : 'RSS Sync Failed!'
},
{
title : "PreDB Sync",
icon : "icon-sonarr-refresh",
command : "predbsync",
errorMessage : "PreDB Sync Failed!"
},
{
title : 'Update Library',
icon : 'icon-sonarr-refresh',

Loading…
Cancel
Save