Onedr0p/3 8 17 (#1087)

* Move ToUrlSlug to Parser, fix issue with trakt lists that have non-alphanumeric characters

* Move "Add movies" link in nav to the first link

* String interpolation!

* Add Limit to Trakt List Settings to limit the amount of movies returned, 50 by default

* Updates to FailedDownload

* Update DownloadService and CompleteDownloadService
pull/2/head
Devin Buhl 8 years ago committed by GitHub
parent 5c22d0b61d
commit 571730ddec

@ -19,7 +19,7 @@ namespace NzbDrone.Core.Datastore.Migration
using (IDbCommand getSeriesCmd = conn.CreateCommand()) using (IDbCommand getSeriesCmd = conn.CreateCommand())
{ {
getSeriesCmd.Transaction = tran; getSeriesCmd.Transaction = tran;
getSeriesCmd.CommandText = @"SELECT Id, Title, Year FROM Movies"; getSeriesCmd.CommandText = @"SELECT Id, Title, Year, TmdbId FROM Movies";
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader()) using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
{ {
while (seriesReader.Read()) while (seriesReader.Read())
@ -27,8 +27,9 @@ namespace NzbDrone.Core.Datastore.Migration
var id = seriesReader.GetInt32(0); var id = seriesReader.GetInt32(0);
var title = seriesReader.GetString(1); var title = seriesReader.GetString(1);
var year = seriesReader.GetInt32(2); var year = seriesReader.GetInt32(2);
var tmdbId = seriesReader.GetInt32(3);
var titleSlug = ToUrlSlug(title + "-" + year); var titleSlug = Parser.Parser.ToUrlSlug(title + "-" + tmdbId);
using (IDbCommand updateCmd = conn.CreateCommand()) using (IDbCommand updateCmd = conn.CreateCommand())
{ {
@ -43,29 +44,5 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
} }
public static string ToUrlSlug(string value)
{
//First to lower case
value = value.ToLowerInvariant();
//Remove all accents
var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(value);
value = Encoding.ASCII.GetString(bytes);
//Replace spaces
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
//Remove invalid chars
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
//Trim dashes from end
value = value.Trim('-', '_');
//Replace double occurences of - or _
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
return value;
}
} }
} }

@ -30,14 +30,12 @@ namespace NzbDrone.Core.Download
private readonly IParsingService _parsingService; private readonly IParsingService _parsingService;
private readonly IMovieService _movieService; private readonly IMovieService _movieService;
private readonly Logger _logger; private readonly Logger _logger;
private readonly ISeriesService _seriesService;
public CompletedDownloadService(IConfigService configService, public CompletedDownloadService(IConfigService configService,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IHistoryService historyService, IHistoryService historyService,
IDownloadedMovieImportService downloadedMovieImportService, IDownloadedMovieImportService downloadedMovieImportService,
IParsingService parsingService, IParsingService parsingService,
ISeriesService seriesService,
IMovieService movieService, IMovieService movieService,
Logger logger) Logger logger)
{ {
@ -48,7 +46,6 @@ namespace NzbDrone.Core.Download
_parsingService = parsingService; _parsingService = parsingService;
_movieService = movieService; _movieService = movieService;
_logger = logger; _logger = logger;
_seriesService = seriesService;
} }
public void Process(TrackedDownload trackedDownload, bool ignoreWarnings = false) public void Process(TrackedDownload trackedDownload, bool ignoreWarnings = false)

@ -137,16 +137,16 @@ namespace NzbDrone.Core.Download
throw; throw;
} }
var episodeGrabbedEvent = new MovieGrabbedEvent(remoteMovie); var movieGrabbedEvent = new MovieGrabbedEvent(remoteMovie);
episodeGrabbedEvent.DownloadClient = downloadClient.GetType().Name; movieGrabbedEvent.DownloadClient = downloadClient.GetType().Name;
if (!string.IsNullOrWhiteSpace(downloadClientId)) if (!string.IsNullOrWhiteSpace(downloadClientId))
{ {
episodeGrabbedEvent.DownloadId = downloadClientId; movieGrabbedEvent.DownloadId = downloadClientId;
} }
_logger.ProgressInfo("Report sent to {0}. {1}", downloadClient.Definition.Name, downloadTitle); _logger.ProgressInfo("Report sent to {0}. {1}", downloadClient.Definition.Name, downloadTitle);
_eventAggregator.PublishEvent(episodeGrabbedEvent); _eventAggregator.PublishEvent(movieGrabbedEvent);
} }
} }
} }

@ -87,9 +87,9 @@ namespace NzbDrone.Core.Download
var downloadFailedEvent = new DownloadFailedEvent var downloadFailedEvent = new DownloadFailedEvent
{ {
SeriesId = historyItem.SeriesId, SeriesId = 0,
MovieId = historyItem.MovieId, MovieId = historyItem.MovieId,
EpisodeIds = historyItems.Select(h => h.EpisodeId).ToList(), EpisodeIds = null,
Quality = historyItem.Quality, Quality = historyItem.Quality,
SourceTitle = historyItem.SourceTitle, SourceTitle = historyItem.SourceTitle,
DownloadClient = historyItem.Data.GetValueOrDefault(History.History.DOWNLOAD_CLIENT), DownloadClient = historyItem.Data.GetValueOrDefault(History.History.DOWNLOAD_CLIENT),

@ -12,17 +12,17 @@ namespace NzbDrone.Core.Download
public class RedownloadFailedDownloadService : IHandleAsync<DownloadFailedEvent> public class RedownloadFailedDownloadService : IHandleAsync<DownloadFailedEvent>
{ {
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly IEpisodeService _episodeService; private readonly IMovieService _movieService;
private readonly IManageCommandQueue _commandQueueManager; private readonly IManageCommandQueue _commandQueueManager;
private readonly Logger _logger; private readonly Logger _logger;
public RedownloadFailedDownloadService(IConfigService configService, public RedownloadFailedDownloadService(IConfigService configService,
IEpisodeService episodeService, IMovieService movieService,
IManageCommandQueue commandQueueManager, IManageCommandQueue commandQueueManager,
Logger logger) Logger logger)
{ {
_configService = configService; _configService = configService;
_episodeService = episodeService; _movieService = movieService;
_commandQueueManager = commandQueueManager; _commandQueueManager = commandQueueManager;
_logger = logger; _logger = logger;
} }
@ -38,40 +38,8 @@ namespace NzbDrone.Core.Download
if (message.MovieId != 0) if (message.MovieId != 0)
{ {
_logger.Debug("Failed download contains a movie, searching again."); _logger.Debug("Failed download contains a movie, searching again.");
_commandQueueManager.Push(new MoviesSearchCommand { MovieIds = new List<int> { message.MovieId } }); _commandQueueManager.Push(new MoviesSearchCommand { MovieIds = new List<int> { message.MovieId } });
return;
}
if (message.EpisodeIds.Count == 1)
{
_logger.Debug("Failed download only contains one episode, searching again");
_commandQueueManager.Push(new EpisodeSearchCommand(message.EpisodeIds));
return;
} }
var seasonNumber = _episodeService.GetEpisode(message.EpisodeIds.First()).SeasonNumber;
var episodesInSeason = _episodeService.GetEpisodesBySeason(message.SeriesId, seasonNumber);
if (message.EpisodeIds.Count == episodesInSeason.Count)
{
_logger.Debug("Failed download was entire season, searching again");
_commandQueueManager.Push(new SeasonSearchCommand
{
SeriesId = message.SeriesId,
SeasonNumber = seasonNumber
});
return;
}
_logger.Debug("Failed download contains multiple episodes, probably a double episode, searching again");
_commandQueueManager.Push(new EpisodeSearchCommand(message.EpisodeIds));
} }
} }
} }

@ -135,7 +135,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
} }
catch (Exception e) catch (Exception e)
{ {
_logger.Error(e, "Couldn't process tracked download " + downloadItem.Title); _logger.Error(e, $"Couldn't process tracked download {downloadItem.Title}");
} }
return trackedDownloads; return trackedDownloads;

@ -9,11 +9,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Exceptions; using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MetadataSource.SkyHook.Resource; using NzbDrone.Core.MetadataSource.SkyHook.Resource;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using System.Text;
using System.Threading; using System.Threading;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Profiles; using NzbDrone.Core.Profiles;
@ -133,7 +129,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
movie.TmdbId = TmdbId; movie.TmdbId = TmdbId;
movie.ImdbId = resource.imdb_id; movie.ImdbId = resource.imdb_id;
movie.Title = resource.title; movie.Title = resource.title;
movie.TitleSlug = ToUrlSlug(resource.title); movie.TitleSlug = Parser.Parser.ToUrlSlug(resource.title);
movie.CleanTitle = Parser.Parser.CleanSeriesTitle(resource.title); movie.CleanTitle = Parser.Parser.CleanSeriesTitle(resource.title);
movie.SortTitle = Parser.Parser.NormalizeTitle(resource.title); movie.SortTitle = Parser.Parser.NormalizeTitle(resource.title);
movie.Overview = resource.overview; movie.Overview = resource.overview;
@ -475,7 +471,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
{ {
imdbMovie.SortTitle = Parser.Parser.NormalizeTitle(result.title); imdbMovie.SortTitle = Parser.Parser.NormalizeTitle(result.title);
imdbMovie.Title = result.title; imdbMovie.Title = result.title;
imdbMovie.TitleSlug = ToUrlSlug(result.title); imdbMovie.TitleSlug = Parser.Parser.ToUrlSlug(result.title);
if (result.release_date.IsNotNullOrWhiteSpace()) if (result.release_date.IsNotNullOrWhiteSpace())
{ {
@ -662,30 +658,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
} }
} }
public static string ToUrlSlug(string value)
{
//First to lower case
value = value.ToLowerInvariant();
//Remove all accents
var bytes = Encoding.GetEncoding("ISO-8859-8").GetBytes(value);
value = Encoding.ASCII.GetString(bytes);
//Replace spaces
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
//Remove invalid chars
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
//Trim dashes from end
value = value.Trim('-', '_');
//Replace double occurences of - or _
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
return value;
}
public Movie MapMovieToTmdbMovie(Movie movie) public Movie MapMovieToTmdbMovie(Movie movie)
{ {
Movie newMovie = movie; Movie newMovie = movie;

@ -1,6 +1,8 @@
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
@ -87,42 +89,43 @@ namespace NzbDrone.Core.NetImport.Trakt
{ {
var link = Settings.Link.Trim(); var link = Settings.Link.Trim();
var filters = $"?years={Settings.Years}&genres={Settings.Genres.ToLower()}&ratings={Settings.Rating}&certifications={Settings.Ceritification.ToLower()}"; var filtersAndLimit = $"?years={Settings.Years}&genres={Settings.Genres.ToLower()}&ratings={Settings.Rating}&certifications={Settings.Ceritification.ToLower()}&limit={Settings.Limit}";
switch (Settings.ListType) switch (Settings.ListType)
{ {
case (int)TraktListType.UserCustomList: case (int)TraktListType.UserCustomList:
link = link + $"/users/{Settings.Username.Trim()}/lists/{Settings.Listname.Trim()}/items/movies"; var listName = Parser.Parser.ToUrlSlug(Settings.Listname.Trim());
link = link + $"/users/{Settings.Username.Trim()}/lists/{listName}/items/movies?limit={Settings.Limit}";
break; break;
case (int)TraktListType.UserWatchList: case (int)TraktListType.UserWatchList:
link = link + $"/users/{Settings.Username.Trim()}/watchlist/movies"; link = link + $"/users/{Settings.Username.Trim()}/watchlist/movies?limit={Settings.Limit}";
break; break;
case (int)TraktListType.UserWatchedList: case (int)TraktListType.UserWatchedList:
link = link + $"/users/{Settings.Username.Trim()}/watched/movies"; link = link + $"/users/{Settings.Username.Trim()}/watched/movies?limit={Settings.Limit}";
break; break;
case (int)TraktListType.Trending: case (int)TraktListType.Trending:
link = link + "/movies/trending" + filters; link = link + "/movies/trending" + filtersAndLimit;
break; break;
case (int)TraktListType.Popular: case (int)TraktListType.Popular:
link = link + "/movies/popular" + filters; link = link + "/movies/popular" + filtersAndLimit;
break; break;
case (int)TraktListType.Anticipated: case (int)TraktListType.Anticipated:
link = link + "/movies/anticipated" + filters; link = link + "/movies/anticipated" + filtersAndLimit;
break; break;
case (int)TraktListType.BoxOffice: case (int)TraktListType.BoxOffice:
link = link + "/movies/boxoffice" + filters; link = link + "/movies/boxoffice" + filtersAndLimit;
break; break;
case (int)TraktListType.TopWatchedByWeek: case (int)TraktListType.TopWatchedByWeek:
link = link + "/movies/watched/weekly" + filters; link = link + "/movies/watched/weekly" + filtersAndLimit;
break; break;
case (int)TraktListType.TopWatchedByMonth: case (int)TraktListType.TopWatchedByMonth:
link = link + "/movies/watched/monthly" + filters; link = link + "/movies/watched/monthly" + filtersAndLimit;
break; break;
case (int)TraktListType.TopWatchedByYear: case (int)TraktListType.TopWatchedByYear:
link = link + "/movies/watched/yearly" + filters; link = link + "/movies/watched/yearly" + filtersAndLimit;
break; break;
case (int)TraktListType.TopWatchedByAllTime: case (int)TraktListType.TopWatchedByAllTime:
link = link + "/movies/watched/all" + filters; link = link + "/movies/watched/all" + filtersAndLimit;
break; break;
} }
@ -131,7 +134,7 @@ namespace NzbDrone.Core.NetImport.Trakt
var request = new NetImportRequest($"{link}", HttpAccept.Json); var request = new NetImportRequest($"{link}", HttpAccept.Json);
request.HttpRequest.Headers.Add("trakt-api-version", "2"); request.HttpRequest.Headers.Add("trakt-api-version", "2");
request.HttpRequest.Headers.Add("trakt-api-key", "964f67b126ade0112c4ae1f0aea3a8fb03190f71117bd83af6a0560a99bc52e6"); //aeon request.HttpRequest.Headers.Add("trakt-api-key", "964f67b126ade0112c4ae1f0aea3a8fb03190f71117bd83af6a0560a99bc52e6"); //aeon
if (_configService.TraktAuthToken != null) if (_configService.TraktAuthToken.IsNotNullOrWhiteSpace())
{ {
request.HttpRequest.Headers.Add("Authorization", "Bearer " + _configService.TraktAuthToken); request.HttpRequest.Headers.Add("Authorization", "Bearer " + _configService.TraktAuthToken);
} }

@ -43,6 +43,11 @@ namespace NzbDrone.Core.NetImport.Trakt
.Matches(@"^\d+(\-\d+)?$", RegexOptions.IgnoreCase) .Matches(@"^\d+(\-\d+)?$", RegexOptions.IgnoreCase)
.When(c => c.Years.IsNotNullOrWhiteSpace()) .When(c => c.Years.IsNotNullOrWhiteSpace())
.WithMessage("Not a valid year or range of years"); .WithMessage("Not a valid year or range of years");
// Limit not smaller than 1 and not larger than 100
RuleFor(c => c.Limit)
.InclusiveBetween(1, 500)
.WithMessage("Must be 1 thru 500");
} }
} }
@ -60,6 +65,7 @@ namespace NzbDrone.Core.NetImport.Trakt
Ceritification = "NR,G,PG,PG-13,R,NC-17"; Ceritification = "NR,G,PG,PG-13,R,NC-17";
Genres = ""; Genres = "";
Years = ""; Years = "";
Limit = 100;
} }
[FieldDefinition(0, Label = "Trakt API URL", HelpText = "Link to to Trakt API URL, do not change unless you know what you are doing.")] [FieldDefinition(0, Label = "Trakt API URL", HelpText = "Link to to Trakt API URL, do not change unless you know what you are doing.")]
@ -86,6 +92,9 @@ namespace NzbDrone.Core.NetImport.Trakt
[FieldDefinition(7, Label = "Years", HelpText = "Filter movies by year or year range")] [FieldDefinition(7, Label = "Years", HelpText = "Filter movies by year or year range")]
public string Years { get; set; } public string Years { get; set; }
[FieldDefinition(8, Label = "Limit", HelpText = "Limit the number of movies to get")]
public int Limit { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NLog; using NLog;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
@ -608,6 +609,30 @@ namespace NzbDrone.Core.Parser
return null; return null;
} }
public static string ToUrlSlug(string value)
{
//First to lower case
value = value.ToLowerInvariant();
//Remove all accents
var bytes = Encoding.GetEncoding("ISO-8859-8").GetBytes(value);
value = Encoding.ASCII.GetString(bytes);
//Replace spaces
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
//Remove invalid chars
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
//Trim dashes from end
value = value.Trim('-', '_');
//Replace double occurences of - or _
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
return value;
}
public static string ParseSeriesName(string title) public static string ParseSeriesName(string title)
{ {
Logger.Debug("Parsing string '{0}'", title); Logger.Debug("Parsing string '{0}'", title);

@ -19,8 +19,9 @@
</div> </div>
<div class="navbar-collapse collapse x-navbar-collapse"> <div class="navbar-collapse collapse x-navbar-collapse">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li><a href="{{UrlBase}}/" class="x-series-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-series"></i> Movies</a></li>
<li><a href="{{UrlBase}}/addmovies" class="x-series-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-add"></i> Add Movies</a></li> <li><a href="{{UrlBase}}/addmovies" class="x-series-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-add"></i> Add Movies</a></li>
<li><a href="{{UrlBase}}/" class="x-series-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-series"></i> Movies</a></li>
<li><a href="{{UrlBase}}/calendar" class="x-calendar-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-calendar"></i> Calendar</a></li> <li><a href="{{UrlBase}}/calendar" class="x-calendar-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-calendar"></i> Calendar</a></li>
<li><a href="{{UrlBase}}/activity" class="x-activity-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-activity"></i> Activity<span id="x-queue-count" class="navbar-info"></span></a></li> <li><a href="{{UrlBase}}/activity" class="x-activity-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-activity"></i> Activity<span id="x-queue-count" class="navbar-info"></span></a></li>
<li><a href="{{UrlBase}}/wanted" class="x-wanted-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-wanted"></i> Wanted</a></li> <li><a href="{{UrlBase}}/wanted" class="x-wanted-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-wanted"></i> Wanted</a></li>

Loading…
Cancel
Save