From b05d505bceef5a645b4d19aec2c8764fa795b182 Mon Sep 17 00:00:00 2001 From: Leonardo Galli Date: Tue, 2 May 2017 22:15:03 +0200 Subject: [PATCH 1/6] Fixed Final in titles parsing as an edition. --- src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs | 3 +++ src/NzbDrone.Core/Parser/Parser.cs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs index 0ee998579..c7a5e939b 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs @@ -75,6 +75,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("A.I.Artificial.Intelligence.(2001)", "A.I. Artificial Intelligence")] [TestCase("A.Movie.Name.(1998)", "A Movie Name")] [TestCase("Thor: The Dark World 2013", "Thor The Dark World")] + [TestCase("Resident.Evil.The.Final.Chapter.2016", "Resident Evil The Final Chapter")] public void should_parse_movie_title(string postTitle, string title) { Parser.Parser.ParseMovieTitle(postTitle).MovieTitle.Should().Be(title); @@ -123,6 +124,8 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Prometheus 50th Anniversary Edition 2012.mkv", "50th Anniversary Edition")] [TestCase("Movie 2in1 2012.mkv", "2in1")] [TestCase("Movie IMAX 2012.mkv", "IMAX")] + [TestCase("Fake Movie Final Cut 2016", "Final Cut")] + [TestCase("Fake Movie 2016 Final Cut ", "Final Cut")] public void should_parse_edition(string postTitle, string edition) { Parser.Parser.ParseMovieTitle(postTitle).Edition.Should().Be(edition); diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index adbbac553..237ff1471 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -19,11 +19,11 @@ namespace NzbDrone.Core.Parser private static readonly Regex[] ReportMovieTitleRegex = new[] { //Special, Despecialized, etc. Edition Movies, e.g: Mission.Impossible.3.Special.Edition.2011 - new Regex(@"^(?(?![(\[]).+?)?(?:(?:[-_\W](?<![)\[!]))*\(?(?<edition>(((Extended.|Ultimate.)?(Director.?s|Collector.?s|Theatrical|Ultimate|Final|Extended|Rogue|Special|Despecialized|\d{2,3}(th)?.Anniversary)(.(Cut|Edition|Version))?(.(Extended|Uncensored|Remastered|Unrated|Uncut|IMAX|Fan.?Edit))?|((Uncensored|Remastered|Unrated|Uncut|IMAX|Fan.?Edit|Edition|Restored|((2|3|4)in1))))))\)?.+(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)", + new Regex(@"^(?<title>(?![(\[]).+?)?(?:(?:[-_\W](?<![)\[!]))*\(?(?<edition>(((Extended.|Ultimate.)?(Director.?s|Collector.?s|Theatrical|Ultimate|Final(?=(.(Cut|Edition|Version)))|Extended|Rogue|Special|Despecialized|\d{2,3}(th)?.Anniversary)(.(Cut|Edition|Version))?(.(Extended|Uncensored|Remastered|Unrated|Uncut|IMAX|Fan.?Edit))?|((Uncensored|Remastered|Unrated|Uncut|IMAX|Fan.?Edit|Edition|Restored|((2|3|4)in1))))))\)?.+(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), //Special, Despecialized, etc. Edition Movies, e.g: Mission.Impossible.3.2011.Special.Edition //TODO: Seems to slow down parsing heavily! - new Regex(@"^(?<title>(?![(\[]).+?)?(?:(?:[-_\W](?<![)\[!]))*(?<year>(19|20)\d{2}(?!p|i|(19|20)\d{2}|\]|\W(19|20)\d{2})))+(\W+|_|$)(?!\\)\(?(?<edition>(((Extended.|Ultimate.)?(Director.?s|Collector.?s|Theatrical|Ultimate|Final|Extended|Rogue|Special|Despecialized|\d{2,3}(th)?.Anniversary)(.(Cut|Edition|Version))?(.(Extended|Uncensored|Remastered|Unrated|Uncut|IMAX|Fan.?Edit))?|((Uncensored|Remastered|Unrated|Uncut|IMAX|Fan.?Edit|Edition|Restored|((2|3|4)in1))))))\)?", + new Regex(@"^(?<title>(?![(\[]).+?)?(?:(?:[-_\W](?<![)\[!]))*(?<year>(19|20)\d{2}(?!p|i|(19|20)\d{2}|\]|\W(19|20)\d{2})))+(\W+|_|$)(?!\\)\(?(?<edition>(((Extended.|Ultimate.)?(Director.?s|Collector.?s|Theatrical|Ultimate|Final(?=(.(Cut|Edition|Version)))|Extended|Rogue|Special|Despecialized|\d{2,3}(th)?.Anniversary)(.(Cut|Edition|Version))?(.(Extended|Uncensored|Remastered|Unrated|Uncut|IMAX|Fan.?Edit))?|((Uncensored|Remastered|Unrated|Uncut|IMAX|Fan.?Edit|Edition|Restored|((2|3|4)in1))))))\)?", RegexOptions.IgnoreCase | RegexOptions.Compiled), //Normal movie format, e.g: Mission.Impossible.3.2011 From 1eca179b4e8d9c3d4492fd909a51784216473e48 Mon Sep 17 00:00:00 2001 From: hotio <hotio@users.noreply.github.com> Date: Sat, 6 May 2017 12:30:36 +0200 Subject: [PATCH 2/6] Update Kodi icon, fixes #1464 (#1492) --- src/NzbDrone.Core/Notifications/Xbmc/XbmcJsonApiProxy.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NzbDrone.Core/Notifications/Xbmc/XbmcJsonApiProxy.cs b/src/NzbDrone.Core/Notifications/Xbmc/XbmcJsonApiProxy.cs index 943a80cd3..1d46d47cb 100644 --- a/src/NzbDrone.Core/Notifications/Xbmc/XbmcJsonApiProxy.cs +++ b/src/NzbDrone.Core/Notifications/Xbmc/XbmcJsonApiProxy.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Notifications.Xbmc var parameters = new Dictionary<string, object>(); parameters.Add("title", title); parameters.Add("message", message); - parameters.Add("image", "https://raw.github.com/Sonarr/Sonarr/develop/Logo/64.png"); + parameters.Add("image", "https://raw.github.com/Radarr/Radarr/develop/Logo/64.png"); parameters.Add("displaytime", settings.DisplayTime * 1000); ProcessRequest(request, settings, "GUI.ShowNotification", parameters); From 817f48448c698c72c32090708e14c2e6bfcd548b Mon Sep 17 00:00:00 2001 From: PatrickGHanna <patrick.gene.hanna@gmail.com> Date: Sat, 6 May 2017 04:31:41 -0600 Subject: [PATCH 3/6] Fix: A small bug fix for items loading as undefined in organize modal. Movie titles should now show up correctly. (#1424) --- src/UI/Movies/Editor/MovieEditorFooterView.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/UI/Movies/Editor/MovieEditorFooterView.js b/src/UI/Movies/Editor/MovieEditorFooterView.js index ff24b2493..b316c94b9 100644 --- a/src/UI/Movies/Editor/MovieEditorFooterView.js +++ b/src/UI/Movies/Editor/MovieEditorFooterView.js @@ -52,7 +52,6 @@ module.exports = Marionette.ItemView.extend({ this.listenTo(FullMovieCollection, 'save', function() { window.alert(' Done Saving'); - var selected = FullMovieCollection.where({ selected : true }); }); @@ -177,7 +176,7 @@ module.exports = Marionette.ItemView.extend({ }, _organizeFiles : function() { - var selected = this.editorGrid.getSelectedModels(); + var selected = FullMovieCollection.where({ selected : true }); var updateFilesMoviesView = new UpdateFilesMoviesView({ movies : selected }); this.listenToOnce(updateFilesMoviesView, 'updatingFiles', this._afterSave); From 58e81a916ca160abe981b3d613edaa2a5addf283 Mon Sep 17 00:00:00 2001 From: Leonardo Galli <leonardo.galli@bluewin.ch> Date: Sat, 6 May 2017 15:26:35 +0200 Subject: [PATCH 4/6] Fixed error when language is present in title, but has dots instead of spaces. For example The.Danish.Girl.2015 --- src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs | 1 + src/NzbDrone.Core/Parser/Parser.cs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs index c7a5e939b..1feea9f4d 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs @@ -88,6 +88,7 @@ namespace NzbDrone.Core.Test.ParserTests } [TestCase("The Danish Girl 2015")] + [TestCase("The.Danish.Girl.2015.1080p.BluRay.x264.DTS-HD.MA.5.1-RARBG")] public void should_not_parse_language_in_movie_title(string postTitle) { Parser.Parser.ParseMovieTitle(postTitle).Language.Should().Be(Language.English); diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 237ff1471..e9504fd96 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -412,9 +412,9 @@ namespace NzbDrone.Core.Parser if (result != null) { var languageTitle = simpleTitle; - if (result.MovieTitle.IsNotNullOrWhiteSpace() ) + if (match[0].Groups["title"].Success && match[0].Groups["title"].Value.IsNotNullOrWhiteSpace()) { - languageTitle = simpleTitle.Replace(result.MovieTitle, "A Movie"); + languageTitle = simpleTitle.Replace(match[0].Groups["title"].Value, "A Movie"); } result.Language = LanguageParser.ParseLanguage(languageTitle); From d133ee3143d1a3e2f3384d10737b723ab5762351 Mon Sep 17 00:00:00 2001 From: Leonardo Galli <leonardo.galli@bluewin.ch> Date: Mon, 8 May 2017 18:46:03 +0200 Subject: [PATCH 5/6] Hopefully more logging to catch errors better. --- src/NzbDrone.Api/Commands/CommandModule.cs | 14 +++++++-- src/NzbDrone.Api/Series/MovieModule.cs | 33 ++++++++++++++++++---- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/NzbDrone.Api/Commands/CommandModule.cs b/src/NzbDrone.Api/Commands/CommandModule.cs index fcaeef9c4..1395d68ec 100644 --- a/src/NzbDrone.Api/Commands/CommandModule.cs +++ b/src/NzbDrone.Api/Commands/CommandModule.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NLog; using NzbDrone.Api.Extensions; using NzbDrone.Api.Validation; using NzbDrone.Common; @@ -17,14 +18,17 @@ namespace NzbDrone.Api.Commands { private readonly IManageCommandQueue _commandQueueManager; private readonly IServiceFactory _serviceFactory; + private readonly Logger _logger; public CommandModule(IManageCommandQueue commandQueueManager, IBroadcastSignalRMessage signalRBroadcaster, - IServiceFactory serviceFactory) + IServiceFactory serviceFactory, + Logger logger) : base(signalRBroadcaster) { _commandQueueManager = commandQueueManager; _serviceFactory = serviceFactory; + _logger = logger; GetResourceById = GetCommand; CreateResource = StartCommand; @@ -41,7 +45,13 @@ namespace NzbDrone.Api.Commands private int StartCommand(CommandResource commandResource) { var commandType = _serviceFactory.GetImplementations(typeof(Command)) - .Single(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase)); + .SingleOrDefault(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase)); + + if (commandType == null) + { + _logger.Error("Found no matching command for {0}", commandResource.Name); + return 0; + } dynamic command = Request.Body.FromJson(commandType); command.Trigger = CommandTrigger.Manual; diff --git a/src/NzbDrone.Api/Series/MovieModule.cs b/src/NzbDrone.Api/Series/MovieModule.cs index 06e5c7d02..5a6fc28bf 100644 --- a/src/NzbDrone.Api/Series/MovieModule.cs +++ b/src/NzbDrone.Api/Series/MovieModule.cs @@ -17,6 +17,8 @@ using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.Validation; using NzbDrone.SignalR; using NzbDrone.Core.Datastore; +using Microsoft.CSharp.RuntimeBinder; +using Nancy; namespace NzbDrone.Api.Movie { @@ -58,9 +60,12 @@ namespace NzbDrone.Api.Movie GetResourceAll = AllMovie; GetResourcePaged = GetMoviePaged; GetResourceById = GetMovie; - Get[TITLE_SLUG_ROUTE] = (options) => { - return ReqResExtensions.AsResponse(GetByTitleSlug(options.slug)); - }; + Get[TITLE_SLUG_ROUTE] = GetByTitleSlug; /*(options) => { + return ReqResExtensions.AsResponse(GetByTitleSlug(options.slug), Nancy.HttpStatusCode.OK); + };*/ + + + CreateResource = AddMovie; UpdateResource = UpdateMovie; DeleteResource = DeleteMovie; @@ -145,9 +150,27 @@ namespace NzbDrone.Api.Movie return moviesResources; } - private MovieResource GetByTitleSlug(string slug) + private Response GetByTitleSlug(dynamic options) { - return MapToResource(_moviesService.FindByTitleSlug(slug)); + var slug = ""; + try + { + slug = options.slug; + // do stuff with x + } + catch (RuntimeBinderException) + { + return new NotFoundResponse(); + } + + try + { + return MapToResource(_moviesService.FindByTitleSlug(slug)).AsResponse(Nancy.HttpStatusCode.OK); + } + catch (ModelNotFoundException) + { + return new NotFoundResponse(); + } } private int AddMovie(MovieResource moviesResource) From 3ab3fbfd571477638316b80c4c38077103e2bc00 Mon Sep 17 00:00:00 2001 From: Leonardo Galli <leonardo.galli@bluewin.ch> Date: Tue, 9 May 2017 16:46:19 +0200 Subject: [PATCH 6/6] Added ability to discover new movies based on upcoming blurays as well as popular movies (borrowed from steven lu :)) --- .../Series/MovieDiscoverModule.cs | 6 +- .../MetadataSource/IDiscoverNewMovies.cs | 2 +- .../MetadataSource/SkyHook/SkyHookProxy.cs | 58 ++++++++++++++----- src/UI/AddMovies/AddMoviesView.js | 58 +++++++++++++++---- src/UI/AddMovies/AddMoviesViewTemplate.hbs | 15 ++++- src/UI/AddMovies/DiscoverMoviesCollection.js | 6 +- 6 files changed, 109 insertions(+), 36 deletions(-) diff --git a/src/NzbDrone.Api/Series/MovieDiscoverModule.cs b/src/NzbDrone.Api/Series/MovieDiscoverModule.cs index e99de8ecd..7d6400d5c 100644 --- a/src/NzbDrone.Api/Series/MovieDiscoverModule.cs +++ b/src/NzbDrone.Api/Series/MovieDiscoverModule.cs @@ -17,12 +17,12 @@ namespace NzbDrone.Api.Movie : base("/movies/discover") { _searchProxy = searchProxy; - Get["/"] = x => Search(); + Get["/{action?recommendations}"] = x => Search(x.action); } - private Response Search() + private Response Search(string action) { - var imdbResults = _searchProxy.DiscoverNewMovies(); + var imdbResults = _searchProxy.DiscoverNewMovies(action); return MapToResource(imdbResults).AsResponse(); } diff --git a/src/NzbDrone.Core/MetadataSource/IDiscoverNewMovies.cs b/src/NzbDrone.Core/MetadataSource/IDiscoverNewMovies.cs index 4a04e47d9..108d8e1a4 100644 --- a/src/NzbDrone.Core/MetadataSource/IDiscoverNewMovies.cs +++ b/src/NzbDrone.Core/MetadataSource/IDiscoverNewMovies.cs @@ -5,6 +5,6 @@ namespace NzbDrone.Core.MetadataSource { public interface IDiscoverNewMovies { - List<Movie> DiscoverNewMovies(); + List<Movie> DiscoverNewMovies(string action); } } \ No newline at end of file diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs index c656c02a6..d52cbc4b5 100644 --- a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs +++ b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs @@ -349,31 +349,57 @@ namespace NzbDrone.Core.MetadataSource.SkyHook return resources.movie_results.SelectList(MapMovie).FirstOrDefault(); } - public List<Movie> DiscoverNewMovies() + public List<Movie> DiscoverNewMovies(string action) { string allIds = string.Join(",", _movieService.GetAllMovies().Select(m => m.TmdbId)); - var request = new HttpRequestBuilder("https://radarr.video/recommendations/api.php").Build(); - - request.AllowAutoRedirect = true; - request.Method = HttpMethod.POST; - request.Headers.ContentType = "application/x-www-form-urlencoded"; - request.SetContent($"tmdbids={allIds}"); + HttpRequest request; + List<MovieResult> results; - var response = _httpClient.Post<List<MovieResult>>(request); - if (response.StatusCode != HttpStatusCode.OK) + if (action == "upcoming") { - throw new HttpException(request, response); - } + var lastWeek = DateTime.Now.AddDays(-7); + var threeWeeks = DateTime.Now.AddDays(7 * 3); - if (response.Headers.ContentType != HttpAccept.Json.Value) - { - throw new HttpException(request, response); + request = _movieBuilder.Create().SetSegment("route", "discover") + .SetSegment("id", "movie") + .SetSegment("secondaryRoute", "") + .AddQueryParam("region", "us") + .AddQueryParam("with_release_type", "5|4|6") + .AddQueryParam("release_date.gte", lastWeek.ToString("yyyy-MM-dd")) + .AddQueryParam("sort_by", "popularity.desc") + .AddQueryParam("release_date.lte", threeWeeks.ToString("yyyy-MM-dd")).Build(); + + + var response = _httpClient.Get<MovieSearchRoot>(request); + + if (response.StatusCode != HttpStatusCode.OK) + { + throw new HttpException(request, response); + } + + results = response.Resource.results.ToList(); } + else + { + request = new HttpRequestBuilder("https://radarr.video/api/{action}/").SetSegment("action", action).Build(); - var movieResults = response.Resource; + request.AllowAutoRedirect = true; + request.Method = HttpMethod.POST; + request.Headers.ContentType = "application/x-www-form-urlencoded"; + request.SetContent($"tmdbids={allIds}"); - return movieResults.SelectList(MapMovie); + var response = _httpClient.Post<List<MovieResult>>(request); + + if (response.StatusCode != HttpStatusCode.OK) + { + throw new HttpException(request, response); + } + + results = response.Resource; + } + + return results.SelectList(MapMovie); } private string StripTrailingTheFromTitle(string title) diff --git a/src/UI/AddMovies/AddMoviesView.js b/src/UI/AddMovies/AddMoviesView.js index 51dda6128..c5f583803 100644 --- a/src/UI/AddMovies/AddMoviesView.js +++ b/src/UI/AddMovies/AddMoviesView.js @@ -21,11 +21,18 @@ module.exports = Marionette.Layout.extend({ moviesSearch : '.x-movies-search', searchBar : '.x-search-bar', loadMore : '.x-load-more', - discoverHeader : ".x-discover-header" + discoverHeader : ".x-discover-header", + discoverBefore : ".x-discover-before", + discoverRecos : ".x-recommendations-tab", + discoverPopular : ".x-popular-tab" , + discoverUpcoming : ".x-upcoming-tab" }, events : { - 'click .x-load-more' : '_onLoadMore' + 'click .x-load-more' : '_onLoadMore', + "click .x-recommendations-tab" : "_discoverRecos", + "click .x-popular-tab" : "_discoverPopular", + "click .x-upcoming-tab" : "_discoverUpcoming" }, initialize : function(options) { @@ -56,11 +63,6 @@ module.exports = Marionette.Layout.extend({ this.search({term: options.query}); } else if (options.action == "discover") { this.isDiscover = true; - if (FullMovieCollection.length > 0) { - this._discover(); - } else { - this.listenTo(FullMovieCollection, "sync", this._discover); - } } }, @@ -110,6 +112,11 @@ module.exports = Marionette.Layout.extend({ if (this.isDiscover) { this.ui.searchBar.hide(); + if (FullMovieCollection.length > 0) { + this._discoverRecos(); + } else { + this.listenTo(FullMovieCollection, "sync", this._discover); + } if (this.collection.length == 0) { this.searchResult.show(new LoadingView()); } @@ -117,10 +124,10 @@ module.exports = Marionette.Layout.extend({ }, onShow : function() { - this.ui.discoverHeader.hide(); + this.ui.discoverBefore.hide(); this.ui.moviesSearch.focus(); if (this.isDiscover) { - this.ui.discoverHeader.show(); + this.ui.discoverBefore.show(); } }, @@ -213,7 +220,34 @@ module.exports = Marionette.Layout.extend({ } }, - _discover : function() { - this.collection.fetch() - } + _discover : function(action) { + if (this.collection.action === action) { + return + } + this.searchResult.show(new LoadingView()); + this.collection.action = action; + this.collection.fetch({ + data : { action : action } + }); + }, + + _discoverRecos : function() { + this.ui.discoverRecos.tab("show"); + this.ui.discoverHeader.html("Recommendations by The Movie Database for you"); + this._discover("recommendations"); + }, + + _discoverPopular : function() { + this.ui.discoverPopular.tab("show"); + this.ui.discoverHeader.html("Currently Popular Movies"); + this._discover("popular"); + }, + + _discoverUpcoming : function() { + this.ui.discoverUpcoming.tab("show"); + this.ui.discoverHeader.html("Movies coming to Blu-Ray in the next weeks"); + this._discover("upcoming"); + }, + + }); diff --git a/src/UI/AddMovies/AddMoviesViewTemplate.hbs b/src/UI/AddMovies/AddMoviesViewTemplate.hbs index 2fc612744..6fb4e54b2 100644 --- a/src/UI/AddMovies/AddMoviesViewTemplate.hbs +++ b/src/UI/AddMovies/AddMoviesViewTemplate.hbs @@ -4,9 +4,18 @@ {{folder.path}} </div> </div>{{/if}} -<h2 class="x-discover-header"> - Recommendations by The Movie Database based on your library: -</h2> + +<div class="x-discover-before"> + <ul class="nav nav-tabs nav-justified settings-tabs"> + <li><a href="#media-management" class="x-recommendations-tab no-router">Recommendations</a></li> + <li><a href="#popular" class="x-popular-tab no-router">Popular</a></li> + <li><a href="#upcoming" class="x-upcoming-tab no-router">Upcoming</a></li> + </ul> + <h2 class="x-discover-header"> + Recommendations by The Movie Database based on your library: + </h2> +</div> + <div class="x-search-bar"> <div class="input-group input-group-lg add-movies-search"> <span class="input-group-addon"><i class="icon-sonarr-search"/></span> diff --git a/src/UI/AddMovies/DiscoverMoviesCollection.js b/src/UI/AddMovies/DiscoverMoviesCollection.js index 962d758ba..bc90bc702 100644 --- a/src/UI/AddMovies/DiscoverMoviesCollection.js +++ b/src/UI/AddMovies/DiscoverMoviesCollection.js @@ -3,7 +3,11 @@ var MovieModel = require('../Movies/MovieModel'); var _ = require('underscore'); module.exports = Backbone.Collection.extend({ - url : window.NzbDrone.ApiRoot + "/movies/discover", + url : function() { + var route = this.action || ""; + return window.NzbDrone.ApiRoot + "/movies/discover/" + route; + }, + model : MovieModel, parse : function(response) {