mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-19 16:01:46 +02:00
Added: Ability to see TMDB and lists going through the Radarr API on the discovery page.
Added: More lists (specifically presets for IMDB Top 250 and IMDB Popular) Added: Ability to set Radarr API endpoint as list.
This commit is contained in:
parent
b70ed720c5
commit
accf8a9efa
@ -6,17 +6,22 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System;
|
using System;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Api.NetImport;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Movie
|
namespace NzbDrone.Api.Movie
|
||||||
{
|
{
|
||||||
public class MovieDiscoverModule : NzbDroneRestModule<MovieResource>
|
public class MovieDiscoverModule : NzbDroneRestModule<MovieResource>
|
||||||
{
|
{
|
||||||
private readonly IDiscoverNewMovies _searchProxy;
|
private readonly IDiscoverNewMovies _searchProxy;
|
||||||
|
private readonly INetImportFactory _netImportFactory;
|
||||||
|
|
||||||
public MovieDiscoverModule(IDiscoverNewMovies searchProxy)
|
public MovieDiscoverModule(IDiscoverNewMovies searchProxy, INetImportFactory netImportFactory)
|
||||||
: base("/movies/discover")
|
: base("/movies/discover")
|
||||||
{
|
{
|
||||||
_searchProxy = searchProxy;
|
_searchProxy = searchProxy;
|
||||||
|
_netImportFactory = netImportFactory;
|
||||||
|
Get["/lists"] = x => GetLists();
|
||||||
Get["/{action?recommendations}"] = x => Search(x.action);
|
Get["/{action?recommendations}"] = x => Search(x.action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +31,20 @@ private Response Search(string action)
|
|||||||
return MapToResource(imdbResults).AsResponse();
|
return MapToResource(imdbResults).AsResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response GetLists()
|
||||||
|
{
|
||||||
|
var lists = _netImportFactory.Discoverable();
|
||||||
|
|
||||||
|
return lists.Select(definition => {
|
||||||
|
var resource = new NetImportResource();
|
||||||
|
resource.Id = definition.Definition.Id;
|
||||||
|
|
||||||
|
resource.Name = definition.Definition.Name;
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}).AsResponse();
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
||||||
{
|
{
|
||||||
foreach (var currentSeries in movies)
|
foreach (var currentSeries in movies)
|
||||||
|
@ -20,7 +20,7 @@ public class RSSImportFixture : CoreTest<RSSImport>
|
|||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Subject.Definition = Subject.DefaultDefinitions.First();
|
Subject.Definition = Subject.GetDefaultDefinitions().First();
|
||||||
}
|
}
|
||||||
private void GivenRecentFeedResponse(string rssXmlFile)
|
private void GivenRecentFeedResponse(string rssXmlFile)
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,10 @@ public abstract class DownloadClientBase<TSettings> : IDownloadClient
|
|||||||
|
|
||||||
public virtual ProviderMessage Message => null;
|
public virtual ProviderMessage Message => null;
|
||||||
|
|
||||||
public IEnumerable<ProviderDefinition> DefaultDefinitions => new List<ProviderDefinition>();
|
public IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
|
{
|
||||||
|
return new List<ProviderDefinition>();
|
||||||
|
}
|
||||||
|
|
||||||
public ProviderDefinition Definition { get; set; }
|
public ProviderDefinition Definition { get; set; }
|
||||||
|
|
||||||
|
@ -17,7 +17,10 @@ namespace NzbDrone.Core.Extras.Metadata
|
|||||||
|
|
||||||
public virtual ProviderMessage Message => null;
|
public virtual ProviderMessage Message => null;
|
||||||
|
|
||||||
public IEnumerable<ProviderDefinition> DefaultDefinitions => new List<ProviderDefinition>();
|
public IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
|
{
|
||||||
|
return new List<ProviderDefinition>();
|
||||||
|
}
|
||||||
|
|
||||||
public ProviderDefinition Definition { get; set; }
|
public ProviderDefinition Definition { get; set; }
|
||||||
|
|
||||||
|
@ -38,9 +38,7 @@ public IndexerBase(IIndexerStatusService indexerStatusService, IConfigService co
|
|||||||
|
|
||||||
public virtual ProviderMessage Message => null;
|
public virtual ProviderMessage Message => null;
|
||||||
|
|
||||||
public virtual IEnumerable<ProviderDefinition> DefaultDefinitions
|
public virtual IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
{
|
||||||
var config = (IProviderConfig)new TSettings();
|
var config = (IProviderConfig)new TSettings();
|
||||||
|
|
||||||
@ -53,7 +51,6 @@ public virtual IEnumerable<ProviderDefinition> DefaultDefinitions
|
|||||||
Settings = config
|
Settings = config
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public virtual ProviderDefinition Definition { get; set; }
|
public virtual ProviderDefinition Definition { get; set; }
|
||||||
|
|
||||||
|
@ -35,9 +35,7 @@ public override IParseIndexerResponse GetParser()
|
|||||||
return new NewznabRssParser(Settings);
|
return new NewznabRssParser(Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<ProviderDefinition> DefaultDefinitions
|
public override IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
{
|
||||||
yield return GetDefinition("DOGnzb", GetSettings("https://api.dognzb.cr"));
|
yield return GetDefinition("DOGnzb", GetSettings("https://api.dognzb.cr"));
|
||||||
yield return GetDefinition("DrunkenSlug", GetSettings("https://api.drunkenslug.com"));
|
yield return GetDefinition("DrunkenSlug", GetSettings("https://api.drunkenslug.com"));
|
||||||
@ -54,7 +52,6 @@ public override IEnumerable<ProviderDefinition> DefaultDefinitions
|
|||||||
yield return GetDefinition("SimplyNZBs", GetSettings("https://simplynzbs.com"));
|
yield return GetDefinition("SimplyNZBs", GetSettings("https://simplynzbs.com"));
|
||||||
yield return GetDefinition("Usenet Crawler", GetSettings("https://www.usenet-crawler.com"));
|
yield return GetDefinition("Usenet Crawler", GetSettings("https://www.usenet-crawler.com"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Newznab(INewznabCapabilitiesProvider capabilitiesProvider, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
public Newznab(INewznabCapabilitiesProvider capabilitiesProvider, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
||||||
: base(httpClient, indexerStatusService, configService, parsingService, logger)
|
: base(httpClient, indexerStatusService, configService, parsingService, logger)
|
||||||
|
@ -37,14 +37,11 @@ public override IParseIndexerResponse GetParser()
|
|||||||
return new TorznabRssParser();
|
return new TorznabRssParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<ProviderDefinition> DefaultDefinitions
|
public override IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
{
|
||||||
yield return GetDefinition("Jackett", GetSettings("http://localhost:9117/torznab/YOURINDEXER"));
|
yield return GetDefinition("Jackett", GetSettings("http://localhost:9117/torznab/YOURINDEXER"));
|
||||||
yield return GetDefinition("HD4Free.xyz", GetSettings("http://hd4free.xyz"));
|
yield return GetDefinition("HD4Free.xyz", GetSettings("http://hd4free.xyz"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Torznab(INewznabCapabilitiesProvider capabilitiesProvider, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
public Torznab(INewznabCapabilitiesProvider capabilitiesProvider, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
||||||
: base(httpClient, indexerStatusService, configService, parsingService, logger)
|
: base(httpClient, indexerStatusService, configService, parsingService, logger)
|
||||||
|
@ -8,5 +8,7 @@ public interface ISearchForNewMovie
|
|||||||
List<Movie> SearchForNewMovie(string title);
|
List<Movie> SearchForNewMovie(string title);
|
||||||
|
|
||||||
Movie MapMovieToTmdbMovie(Movie movie);
|
Movie MapMovieToTmdbMovie(Movie movie);
|
||||||
|
|
||||||
|
Movie MapMovie(SkyHook.Resource.MovieResult result);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,27 +11,30 @@ public interface IRadarrAPIClient
|
|||||||
{
|
{
|
||||||
IHttpRequestBuilderFactory RadarrAPI { get; }
|
IHttpRequestBuilderFactory RadarrAPI { get; }
|
||||||
List<MovieResult> DiscoverMovies(string action, Func<HttpRequest, HttpRequest> enhanceRequest);
|
List<MovieResult> DiscoverMovies(string action, Func<HttpRequest, HttpRequest> enhanceRequest);
|
||||||
|
string APIURL { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RadarrAPIClient : IRadarrAPIClient
|
public class RadarrAPIClient : IRadarrAPIClient
|
||||||
{
|
{
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
|
|
||||||
|
public string APIURL { get; private set; }
|
||||||
|
|
||||||
public RadarrAPIClient(IConfigFileProvider configFile, IHttpClient httpClient)
|
public RadarrAPIClient(IConfigFileProvider configFile, IHttpClient httpClient)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
|
|
||||||
if (configFile.Branch == "nightly")
|
if (configFile.Branch == "nightly")
|
||||||
{
|
{
|
||||||
RadarrAPI = new HttpRequestBuilder("https://staging.api.radarr.video/{route}/{action}")
|
APIURL = "https://staging.api.radarr.video";
|
||||||
.CreateFactory();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RadarrAPI = new HttpRequestBuilder("https://api.radarr.video/v2/{route}/{action}")
|
APIURL = "https://api.radarr.video/v2";
|
||||||
.CreateFactory();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RadarrAPI = new HttpRequestBuilder(APIURL+"/{route}/{action}")
|
||||||
|
.CreateFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpResponse Execute(HttpRequest request)
|
private HttpResponse Execute(HttpRequest request)
|
||||||
|
@ -168,23 +168,9 @@ public class ListResponseRoot
|
|||||||
public object poster_path { get; set; }
|
public object poster_path { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Item
|
public class Item : MovieResult
|
||||||
{
|
{
|
||||||
public string poster_path { get; set; }
|
|
||||||
public bool adult { get; set; }
|
|
||||||
public string overview { get; set; }
|
|
||||||
public string release_date { get; set; }
|
|
||||||
public string original_title { get; set; }
|
|
||||||
public int[] genre_ids { get; set; }
|
|
||||||
public int id { get; set; }
|
|
||||||
public string media_type { get; set; }
|
public string media_type { get; set; }
|
||||||
public string original_language { get; set; }
|
|
||||||
public string title { get; set; }
|
|
||||||
public string backdrop_path { get; set; }
|
|
||||||
public float popularity { get; set; }
|
|
||||||
public int vote_count { get; set; }
|
|
||||||
public bool video { get; set; }
|
|
||||||
public float vote_average { get; set; }
|
|
||||||
public string first_air_date { get; set; }
|
public string first_air_date { get; set; }
|
||||||
public string[] origin_country { get; set; }
|
public string[] origin_country { get; set; }
|
||||||
public string name { get; set; }
|
public string name { get; set; }
|
||||||
|
@ -546,7 +546,7 @@ public List<Series> SearchForNewSeries(string title)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Movie MapMovie(MovieResult result)
|
public Movie MapMovie(MovieResult result)
|
||||||
{
|
{
|
||||||
var imdbMovie = new Movie();
|
var imdbMovie = new Movie();
|
||||||
imdbMovie.TmdbId = result.id;
|
imdbMovie.TmdbId = result.id;
|
||||||
|
@ -32,9 +32,8 @@ public NetImportBase(IConfigService configService, IParsingService parsingServic
|
|||||||
public Type ConfigContract => typeof(TSettings);
|
public Type ConfigContract => typeof(TSettings);
|
||||||
|
|
||||||
public virtual ProviderMessage Message => null;
|
public virtual ProviderMessage Message => null;
|
||||||
public virtual IEnumerable<ProviderDefinition> DefaultDefinitions
|
|
||||||
{
|
public virtual IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
get
|
|
||||||
{
|
{
|
||||||
var config = (IProviderConfig)new TSettings();
|
var config = (IProviderConfig)new TSettings();
|
||||||
|
|
||||||
@ -49,7 +48,6 @@ public virtual IEnumerable<ProviderDefinition> DefaultDefinitions
|
|||||||
Settings = config
|
Settings = config
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public virtual ProviderDefinition Definition { get; set; }
|
public virtual ProviderDefinition Definition { get; set; }
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ namespace NzbDrone.Core.NetImport
|
|||||||
public interface INetImportFactory : IProviderFactory<INetImport, NetImportDefinition>
|
public interface INetImportFactory : IProviderFactory<INetImport, NetImportDefinition>
|
||||||
{
|
{
|
||||||
List<INetImport> Enabled();
|
List<INetImport> Enabled();
|
||||||
|
|
||||||
|
List<INetImport> Discoverable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NetImportFactory : ProviderFactory<INetImport, NetImportDefinition>, INetImportFactory
|
public class NetImportFactory : ProviderFactory<INetImport, NetImportDefinition>, INetImportFactory
|
||||||
@ -46,6 +48,13 @@ public List<INetImport> Enabled()
|
|||||||
return indexers.ToList();
|
return indexers.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<INetImport> Discoverable()
|
||||||
|
{
|
||||||
|
var enabledImporters = GetAvailableProviders().Where(n => (n.GetType() == typeof(Radarr.RadarrProxied) || n.GetType() == typeof(TMDb.TMDbImport)));
|
||||||
|
var indexers = FilterBlockedIndexers(enabledImporters);
|
||||||
|
return indexers.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
private IEnumerable<INetImport> FilterBlockedIndexers(IEnumerable<INetImport> importers)
|
private IEnumerable<INetImport> FilterBlockedIndexers(IEnumerable<INetImport> importers)
|
||||||
{
|
{
|
||||||
foreach (var importer in importers)
|
foreach (var importer in importers)
|
||||||
|
@ -17,11 +17,9 @@ public RSSImport(IHttpClient httpClient, IConfigService configService, IParsingS
|
|||||||
: base(httpClient, configService, parsingService, logger)
|
: base(httpClient, configService, parsingService, logger)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override IEnumerable<ProviderDefinition> DefaultDefinitions
|
public override IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
{
|
{
|
||||||
get
|
foreach (var def in base.GetDefaultDefinitions())
|
||||||
{
|
|
||||||
foreach (var def in base.DefaultDefinitions)
|
|
||||||
{
|
{
|
||||||
yield return def;
|
yield return def;
|
||||||
}
|
}
|
||||||
@ -44,7 +42,6 @@ public override IEnumerable<ProviderDefinition> DefaultDefinitions
|
|||||||
Settings = new RSSImportSettings { Link = "http://rss.imdb.com/user/IMDBUSERID/watchlist" },
|
Settings = new RSSImportSettings { Link = "http://rss.imdb.com/user/IMDBUSERID/watchlist" },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public override INetImportRequestGenerator GetRequestGenerator()
|
public override INetImportRequestGenerator GetRequestGenerator()
|
||||||
{
|
{
|
||||||
|
78
src/NzbDrone.Core/NetImport/Radarr/RadarrParser.cs
Normal file
78
src/NzbDrone.Core/NetImport/Radarr/RadarrParser.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using NzbDrone.Core.NetImport.Exceptions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
using NzbDrone.Core.MetadataSource.RadarrAPI;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.NetImport.Radarr
|
||||||
|
{
|
||||||
|
public class RadarrParser : IParseNetImportResponse
|
||||||
|
{
|
||||||
|
private readonly RadarrSettings _settings;
|
||||||
|
private NetImportResponse _importResponse;
|
||||||
|
private readonly ISearchForNewMovie _skyhookProxy;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public RadarrParser(RadarrSettings settings, ISearchForNewMovie skyhookProxy)
|
||||||
|
{
|
||||||
|
_skyhookProxy = skyhookProxy;//TinyIoC.TinyIoCContainer.Current.Resolve<ISearchForNewMovie>();
|
||||||
|
_settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<Tv.Movie> ParseResponse(NetImportResponse importResponse)
|
||||||
|
{
|
||||||
|
_importResponse = importResponse;
|
||||||
|
|
||||||
|
var movies = new List<Tv.Movie>();
|
||||||
|
|
||||||
|
if (!PreProcess(_importResponse))
|
||||||
|
{
|
||||||
|
return movies;
|
||||||
|
}
|
||||||
|
|
||||||
|
var jsonResponse = JsonConvert.DeserializeObject<List<MovieResult>>(_importResponse.Content);
|
||||||
|
|
||||||
|
// no movies were return
|
||||||
|
if (jsonResponse == null)
|
||||||
|
{
|
||||||
|
return movies;
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonResponse.SelectList(_skyhookProxy.MapMovie);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual bool PreProcess(NetImportResponse indexerResponse)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var error = JsonConvert.DeserializeObject<RadarrError>(indexerResponse.HttpResponse.Content);
|
||||||
|
|
||||||
|
if (error != null && error.Errors != null && error.Errors.Count != 0)
|
||||||
|
{
|
||||||
|
throw new RadarrAPIException(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JsonSerializationException)
|
||||||
|
{
|
||||||
|
//No error!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (indexerResponse.HttpResponse.StatusCode != System.Net.HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
throw new HttpException(indexerResponse.HttpRequest, indexerResponse.HttpResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
84
src/NzbDrone.Core/NetImport/Radarr/RadarrProxied.cs
Normal file
84
src/NzbDrone.Core/NetImport/Radarr/RadarrProxied.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.NetImport.Radarr
|
||||||
|
{
|
||||||
|
public class RadarrProxied : HttpNetImportBase<RadarrSettings>
|
||||||
|
{
|
||||||
|
public override string Name => "Radarr Proxied Lists";
|
||||||
|
public override bool Enabled => true;
|
||||||
|
public override bool EnableAuto => false;
|
||||||
|
|
||||||
|
private readonly IHttpClient _httpClient;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
private readonly ISearchForNewMovie _skyhookProxy;
|
||||||
|
|
||||||
|
public RadarrProxied(IHttpClient httpClient, IConfigService configService, IParsingService parsingService, ISearchForNewMovie skyhookProxy,
|
||||||
|
Logger logger)
|
||||||
|
: base(httpClient, configService, parsingService, logger)
|
||||||
|
{
|
||||||
|
_skyhookProxy = skyhookProxy;
|
||||||
|
_logger = logger;
|
||||||
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
|
{
|
||||||
|
foreach (var def in base.GetDefaultDefinitions())
|
||||||
|
{
|
||||||
|
yield return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return new NetImportDefinition
|
||||||
|
{
|
||||||
|
Name = "IMDb Top 250",
|
||||||
|
Enabled = Enabled,
|
||||||
|
EnableAuto = true,
|
||||||
|
ProfileId = 1,
|
||||||
|
Implementation = GetType().Name,
|
||||||
|
Settings = new RadarrSettings { Path = "/imdb/top250" },
|
||||||
|
};
|
||||||
|
yield return new NetImportDefinition
|
||||||
|
{
|
||||||
|
Name = "IMDb Popular Movies",
|
||||||
|
Enabled = Enabled,
|
||||||
|
EnableAuto = true,
|
||||||
|
ProfileId = 1,
|
||||||
|
Implementation = GetType().Name,
|
||||||
|
Settings = new RadarrSettings { Path = "/imdb/popular" },
|
||||||
|
};
|
||||||
|
yield return new NetImportDefinition
|
||||||
|
{
|
||||||
|
Name = "IMDb List",
|
||||||
|
Enabled = Enabled,
|
||||||
|
EnableAuto = true,
|
||||||
|
ProfileId = 1,
|
||||||
|
Implementation = GetType().Name,
|
||||||
|
Settings = new RadarrSettings { Path = "/imdb/list?listId=LISTID" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override INetImportRequestGenerator GetRequestGenerator()
|
||||||
|
{
|
||||||
|
return new RadarrRequestGenerator()
|
||||||
|
{
|
||||||
|
Settings = Settings,
|
||||||
|
Logger = _logger,
|
||||||
|
HttpClient = _httpClient
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IParseNetImportResponse GetParser()
|
||||||
|
{
|
||||||
|
return new RadarrParser(Settings, _skyhookProxy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
src/NzbDrone.Core/NetImport/Radarr/RadarrRequestGenerator.cs
Normal file
38
src/NzbDrone.Core/NetImport/Radarr/RadarrRequestGenerator.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.NetImport.Radarr
|
||||||
|
{
|
||||||
|
public class RadarrRequestGenerator : INetImportRequestGenerator
|
||||||
|
{
|
||||||
|
public RadarrSettings Settings { get; set; }
|
||||||
|
public IHttpClient HttpClient { get; set; }
|
||||||
|
public Logger Logger { get; set; }
|
||||||
|
|
||||||
|
public int MaxPages { get; set; }
|
||||||
|
|
||||||
|
public RadarrRequestGenerator()
|
||||||
|
{
|
||||||
|
MaxPages = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual NetImportPageableRequestChain GetMovies()
|
||||||
|
{
|
||||||
|
var pageableRequests = new NetImportPageableRequestChain();
|
||||||
|
|
||||||
|
var baseUrl = $"{Settings.APIURL.TrimEnd("/")}";
|
||||||
|
|
||||||
|
var request = new NetImportRequest($"{baseUrl}{Settings.Path}", HttpAccept.Json);
|
||||||
|
|
||||||
|
request.HttpRequest.SuppressHttpError = true;
|
||||||
|
|
||||||
|
pageableRequests.Add(new List<NetImportRequest> { request });
|
||||||
|
return pageableRequests;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
src/NzbDrone.Core/NetImport/Radarr/RadarrSettings.cs
Normal file
42
src/NzbDrone.Core/NetImport/Radarr/RadarrSettings.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Annotations;
|
||||||
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
using NzbDrone.Core.Validation;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using NzbDrone.Core.MetadataSource.RadarrAPI;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.NetImport.Radarr
|
||||||
|
{
|
||||||
|
|
||||||
|
public class RadarrSettingsValidator : AbstractValidator<RadarrSettings>
|
||||||
|
{
|
||||||
|
public RadarrSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.APIURL).ValidRootUrl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RadarrSettings : IProviderConfig
|
||||||
|
{
|
||||||
|
private static readonly RadarrSettingsValidator Validator = new RadarrSettingsValidator();
|
||||||
|
|
||||||
|
public RadarrSettings()
|
||||||
|
{
|
||||||
|
APIURL = "https://api.radarr.video";
|
||||||
|
Path = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
[FieldDefinition(0, Label = "Radarr API URL", HelpText = "Link to to Radarr API URL.Use https://staging.api.radarr.video if you are on nightly.")]
|
||||||
|
public string APIURL { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(1, Label = "Path to list", HelpText = "Path to the list proxied by the Radarr API. Check the wiki for available lists.")]
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
public NzbDroneValidationResult Validate()
|
||||||
|
{
|
||||||
|
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
|
|
||||||
|
|
||||||
@ -14,13 +15,15 @@ public class TMDbImport : HttpNetImportBase<TMDbSettings>
|
|||||||
|
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
private readonly ISearchForNewMovie _skyhookProxy;
|
||||||
|
|
||||||
public TMDbImport(IHttpClient httpClient, IConfigService configService, IParsingService parsingService,
|
public TMDbImport(IHttpClient httpClient, IConfigService configService, IParsingService parsingService, ISearchForNewMovie skyhookProxy,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(httpClient, configService, parsingService, logger)
|
: base(httpClient, configService, parsingService, logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
|
_skyhookProxy = skyhookProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override INetImportRequestGenerator GetRequestGenerator()
|
public override INetImportRequestGenerator GetRequestGenerator()
|
||||||
@ -35,7 +38,7 @@ public override INetImportRequestGenerator GetRequestGenerator()
|
|||||||
|
|
||||||
public override IParseNetImportResponse GetParser()
|
public override IParseNetImportResponse GetParser()
|
||||||
{
|
{
|
||||||
return new TMDbParser(Settings);
|
return new TMDbParser(Settings, _skyhookProxy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,8 @@
|
|||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
using TinyIoC;
|
||||||
|
|
||||||
namespace NzbDrone.Core.NetImport.TMDb
|
namespace NzbDrone.Core.NetImport.TMDb
|
||||||
{
|
{
|
||||||
@ -13,10 +15,12 @@ public class TMDbParser : IParseNetImportResponse
|
|||||||
{
|
{
|
||||||
private readonly TMDbSettings _settings;
|
private readonly TMDbSettings _settings;
|
||||||
private NetImportResponse _importResponse;
|
private NetImportResponse _importResponse;
|
||||||
|
private readonly ISearchForNewMovie _skyhookProxy;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public TMDbParser(TMDbSettings settings)
|
public TMDbParser(TMDbSettings settings, ISearchForNewMovie skyhookProxy)
|
||||||
{
|
{
|
||||||
|
_skyhookProxy = skyhookProxy;
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,22 +45,7 @@ public TMDbParser(TMDbSettings settings)
|
|||||||
return movies;
|
return movies;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var movie in jsonResponse.results)
|
return jsonResponse.results.SelectList(_skyhookProxy.MapMovie);
|
||||||
{
|
|
||||||
// Movies with no Year Fix
|
|
||||||
if (string.IsNullOrWhiteSpace(movie.release_date))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
movies.AddIfNotNull(new Tv.Movie()
|
|
||||||
{
|
|
||||||
Title = movie.title,
|
|
||||||
TmdbId = movie.id,
|
|
||||||
ImdbId = null,
|
|
||||||
Year = DateTime.Parse(movie.release_date).Year
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -82,13 +71,7 @@ public TMDbParser(TMDbSettings settings)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
movies.AddIfNotNull(new Tv.Movie()
|
movies.AddIfNotNull(_skyhookProxy.MapMovie(movie));
|
||||||
{
|
|
||||||
Title = movie.title,
|
|
||||||
TmdbId = movie.id,
|
|
||||||
ImdbId = null,
|
|
||||||
Year = DateTime.Parse(movie.release_date).Year
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,10 @@ namespace NzbDrone.Core.Notifications
|
|||||||
|
|
||||||
public virtual ProviderMessage Message => null;
|
public virtual ProviderMessage Message => null;
|
||||||
|
|
||||||
public IEnumerable<ProviderDefinition> DefaultDefinitions => new List<ProviderDefinition>();
|
public IEnumerable<ProviderDefinition> GetDefaultDefinitions()
|
||||||
|
{
|
||||||
|
return new List<ProviderDefinition>();
|
||||||
|
}
|
||||||
|
|
||||||
public ProviderDefinition Definition { get; set; }
|
public ProviderDefinition Definition { get; set; }
|
||||||
public abstract ValidationResult Test();
|
public abstract ValidationResult Test();
|
||||||
|
@ -1285,6 +1285,10 @@
|
|||||||
<Compile Include="NetImport\ImportExclusions\ImportExclusionsRepository.cs" />
|
<Compile Include="NetImport\ImportExclusions\ImportExclusionsRepository.cs" />
|
||||||
<Compile Include="NetImport\ImportExclusions\ImportExclusionsService.cs" />
|
<Compile Include="NetImport\ImportExclusions\ImportExclusionsService.cs" />
|
||||||
<Compile Include="Datastore\Migration\138_add_physical_release_note.cs" />
|
<Compile Include="Datastore\Migration\138_add_physical_release_note.cs" />
|
||||||
|
<Compile Include="NetImport\Radarr\RadarrProxied.cs" />
|
||||||
|
<Compile Include="NetImport\Radarr\RadarrParser.cs" />
|
||||||
|
<Compile Include="NetImport\Radarr\RadarrRequestGenerator.cs" />
|
||||||
|
<Compile Include="NetImport\Radarr\RadarrSettings.cs" />
|
||||||
<Compile Include="MetadataSource\RadarrAPI\RadarrResources.cs" />
|
<Compile Include="MetadataSource\RadarrAPI\RadarrResources.cs" />
|
||||||
<Compile Include="MetadataSource\RadarrAPI\RadarrAPIClient.cs" />
|
<Compile Include="MetadataSource\RadarrAPI\RadarrAPIClient.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -1358,6 +1362,7 @@
|
|||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="NetImport\ImportExclusions\" />
|
<Folder Include="NetImport\ImportExclusions\" />
|
||||||
|
<Folder Include="NetImport\Radarr\" />
|
||||||
<Folder Include="MetadataSource\RadarrAPI\" />
|
<Folder Include="MetadataSource\RadarrAPI\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
@ -9,7 +9,9 @@ public interface IProvider
|
|||||||
string Name { get; }
|
string Name { get; }
|
||||||
Type ConfigContract { get; }
|
Type ConfigContract { get; }
|
||||||
ProviderMessage Message { get; }
|
ProviderMessage Message { get; }
|
||||||
IEnumerable<ProviderDefinition> DefaultDefinitions { get; }
|
|
||||||
|
IEnumerable<ProviderDefinition> GetDefaultDefinitions();
|
||||||
|
|
||||||
ProviderDefinition Definition { get; set; }
|
ProviderDefinition Definition { get; set; }
|
||||||
ValidationResult Test();
|
ValidationResult Test();
|
||||||
object RequestAction(string stage, IDictionary<string, string> query);
|
object RequestAction(string stage, IDictionary<string, string> query);
|
||||||
|
@ -43,7 +43,7 @@ public IEnumerable<TProviderDefinition> GetDefaultDefinitions()
|
|||||||
{
|
{
|
||||||
foreach (var provider in _providers)
|
foreach (var provider in _providers)
|
||||||
{
|
{
|
||||||
var definition = provider.DefaultDefinitions
|
var definition = provider.GetDefaultDefinitions()
|
||||||
.OfType<TProviderDefinition>()
|
.OfType<TProviderDefinition>()
|
||||||
.FirstOrDefault(v => v.Name == null || v.Name == provider.Name);
|
.FirstOrDefault(v => v.Name == null || v.Name == provider.Name);
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ public IEnumerable<TProviderDefinition> GetPresetDefinitions(TProviderDefinition
|
|||||||
{
|
{
|
||||||
var provider = _providers.First(v => v.GetType().Name == providerDefinition.Implementation);
|
var provider = _providers.First(v => v.GetType().Name == providerDefinition.Implementation);
|
||||||
|
|
||||||
var definitions = provider.DefaultDefinitions
|
var definitions = provider.GetDefaultDefinitions()
|
||||||
.OfType<TProviderDefinition>()
|
.OfType<TProviderDefinition>()
|
||||||
.Where(v => v.Name != null && v.Name != provider.Name)
|
.Where(v => v.Name != null && v.Name != provider.Name)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -3,7 +3,12 @@ var $ = require('jquery');
|
|||||||
var vent = require('vent');
|
var vent = require('vent');
|
||||||
var Marionette = require('marionette');
|
var Marionette = require('marionette');
|
||||||
var AddMoviesCollection = require('./AddMoviesCollection');
|
var AddMoviesCollection = require('./AddMoviesCollection');
|
||||||
|
var AddFromListCollection = require('./List/AddFromListCollection');
|
||||||
var SearchResultCollectionView = require('./SearchResultCollectionView');
|
var SearchResultCollectionView = require('./SearchResultCollectionView');
|
||||||
|
var DiscoverableListDropdownView = require("./DiscoverableListDropdownView");
|
||||||
|
var DiscoverableListCollection = require("./DiscoverableListCollection");
|
||||||
|
var DiscoverableListCollectionView = require("./DiscoverableListCollectionView");
|
||||||
|
var DiscoverMoviesCollection = require("./DiscoverMoviesCollection");
|
||||||
var EmptyView = require('./EmptyView');
|
var EmptyView = require('./EmptyView');
|
||||||
var NotFoundView = require('./NotFoundView');
|
var NotFoundView = require('./NotFoundView');
|
||||||
var DiscoverEmptyView = require('./DiscoverEmptyView');
|
var DiscoverEmptyView = require('./DiscoverEmptyView');
|
||||||
@ -15,7 +20,8 @@ module.exports = Marionette.Layout.extend({
|
|||||||
template : 'AddMovies/AddMoviesViewTemplate',
|
template : 'AddMovies/AddMoviesViewTemplate',
|
||||||
|
|
||||||
regions : {
|
regions : {
|
||||||
searchResult : '#search-result'
|
myRegion : '#my-region',
|
||||||
|
searchResult : '#search-result',
|
||||||
},
|
},
|
||||||
|
|
||||||
ui : {
|
ui : {
|
||||||
@ -26,14 +32,17 @@ module.exports = Marionette.Layout.extend({
|
|||||||
discoverBefore : ".x-discover-before",
|
discoverBefore : ".x-discover-before",
|
||||||
discoverRecos : ".x-recommendations-tab",
|
discoverRecos : ".x-recommendations-tab",
|
||||||
discoverPopular : ".x-popular-tab" ,
|
discoverPopular : ".x-popular-tab" ,
|
||||||
discoverUpcoming : ".x-upcoming-tab"
|
discoverUpcoming : ".x-upcoming-tab",
|
||||||
|
discoverLists : ".x-lists-tab"
|
||||||
},
|
},
|
||||||
|
|
||||||
events : {
|
events : {
|
||||||
'click .x-load-more' : '_onLoadMore',
|
'click .x-load-more' : '_onLoadMore',
|
||||||
"click .x-recommendations-tab" : "_discoverRecos",
|
"click .x-recommendations-tab" : "_discoverRecos",
|
||||||
"click .x-popular-tab" : "_discoverPopular",
|
"click .x-popular-tab" : "_discoverPopular",
|
||||||
"click .x-upcoming-tab" : "_discoverUpcoming"
|
"click .x-upcoming-tab" : "_discoverUpcoming",
|
||||||
|
"click .x-lists-tab" : "_discoverLists",
|
||||||
|
"click .discoverable-list-item" : "_discoverList"
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize : function(options) {
|
initialize : function(options) {
|
||||||
@ -58,6 +67,15 @@ module.exports = Marionette.Layout.extend({
|
|||||||
isExisting : this.isExisting
|
isExisting : this.isExisting
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*this.listsDropdown = new DiscoverableListCollectionView({
|
||||||
|
collection : DiscoverableListCollection
|
||||||
|
});*/
|
||||||
|
|
||||||
|
this.listenTo(DiscoverableListCollection, 'sync', this._showListDropdown);
|
||||||
|
this.listsDropdown = new DiscoverableListCollectionView({
|
||||||
|
collection : DiscoverableListCollection
|
||||||
|
})
|
||||||
|
|
||||||
this.throttledSearch = _.debounce(this.search, 1000, { trailing : true }).bind(this);
|
this.throttledSearch = _.debounce(this.search, 1000, { trailing : true }).bind(this);
|
||||||
|
|
||||||
if (options.action === "search") {
|
if (options.action === "search") {
|
||||||
@ -125,6 +143,8 @@ module.exports = Marionette.Layout.extend({
|
|||||||
this.ui.moviesSearch.focus();
|
this.ui.moviesSearch.focus();
|
||||||
this.ui.loadMore.hide();
|
this.ui.loadMore.hide();
|
||||||
|
|
||||||
|
this._showListDropdown();
|
||||||
|
|
||||||
if (this.isDiscover) {
|
if (this.isDiscover) {
|
||||||
this.ui.discoverBefore.show();
|
this.ui.discoverBefore.show();
|
||||||
}
|
}
|
||||||
@ -208,6 +228,14 @@ module.exports = Marionette.Layout.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_showListDropdown : function() {
|
||||||
|
this.listsDropdown = new DiscoverableListDropdownView(DiscoverableListCollection.toJSON());
|
||||||
|
this.listsDropdown.render();
|
||||||
|
$("#list-dropdown").html(this.listsDropdown.$el.html());
|
||||||
|
//debugger;
|
||||||
|
//this.myRegion.show(new DiscoverableListDropdownView(DiscoverableListCollection.toJSON()));
|
||||||
|
},
|
||||||
|
|
||||||
_abortExistingSearch : function() {
|
_abortExistingSearch : function() {
|
||||||
if (this.currentSearchPromise && this.currentSearchPromise.readyState > 0 && this.currentSearchPromise.readyState < 4) {
|
if (this.currentSearchPromise && this.currentSearchPromise.readyState > 0 && this.currentSearchPromise.readyState < 4) {
|
||||||
console.log('aborting previous pending search request.');
|
console.log('aborting previous pending search request.');
|
||||||
@ -229,7 +257,14 @@ module.exports = Marionette.Layout.extend({
|
|||||||
if (this.collection.action === action) {
|
if (this.collection.action === action) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.collection.specialProperty === "special") {
|
||||||
this.collection.reset();
|
this.collection.reset();
|
||||||
|
this.collection = new DiscoverMoviesCollection();
|
||||||
|
this.resultCollectionView.collection = this.collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.listenTo(this.collection, 'sync', this._showResults);
|
||||||
this.searchResult.show(new LoadingView());
|
this.searchResult.show(new LoadingView());
|
||||||
this.collection.action = action;
|
this.collection.action = action;
|
||||||
this.currentSearchPromise = this.collection.fetch();
|
this.currentSearchPromise = this.collection.fetch();
|
||||||
@ -253,5 +288,22 @@ module.exports = Marionette.Layout.extend({
|
|||||||
this._discover("upcoming");
|
this._discover("upcoming");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_discoverLists : function() {
|
||||||
|
/*this.ui.discoverLists.tab("show");
|
||||||
|
this.ui.discoverHeader.html("");*/
|
||||||
|
},
|
||||||
|
|
||||||
|
_discoverList : function(options) {
|
||||||
|
this.ui.discoverLists.tab("show");
|
||||||
|
this.ui.discoverHeader.html("Showing movies from list: "+options.target.textContent);
|
||||||
|
|
||||||
|
this.collection.reset();
|
||||||
|
this.collection = new AddFromListCollection();
|
||||||
|
this.listenTo(this.collection, 'sync', this._showResults);
|
||||||
|
this.searchResult.show(new LoadingView());
|
||||||
|
this.currentSearchPromise = this.collection.fetch({ data: { listId: options.target.value } });
|
||||||
|
this.resultCollectionView.collection = this.collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -10,6 +10,13 @@
|
|||||||
<li><a href="#media-management" class="x-recommendations-tab no-router">Recommendations</a></li>
|
<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="#popular" class="x-popular-tab no-router">Popular</a></li>
|
||||||
<li><a href="#upcoming" class="x-upcoming-tab no-router">Upcoming</a></li>
|
<li><a href="#upcoming" class="x-upcoming-tab no-router">Upcoming</a></li>
|
||||||
|
<li role="presentation" class="dropdown">
|
||||||
|
<a class="dropdown-toggle x-lists-tab" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
|
||||||
|
Lists <span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul id="list-dropdown" class="dropdown-menu">
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2 class="x-discover-header">
|
<h2 class="x-discover-header">
|
||||||
Recommendations by The Movie Database based on your library:
|
Recommendations by The Movie Database based on your library:
|
||||||
|
13
src/UI/AddMovies/DiscoverableListDropdownView.js
Normal file
13
src/UI/AddMovies/DiscoverableListDropdownView.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
var Marionette = require('marionette');
|
||||||
|
|
||||||
|
module.exports = Marionette.CompositeView.extend({
|
||||||
|
template : 'AddMovies/DiscoverableListDropdownViewTemplate',
|
||||||
|
|
||||||
|
initialize : function(lists) {
|
||||||
|
this.lists = lists;
|
||||||
|
},
|
||||||
|
|
||||||
|
templateHelpers : function() {
|
||||||
|
return this.lists;
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,3 @@
|
|||||||
|
{{#each this}}
|
||||||
|
<li value="{{id}}" class="clickable discoverable-list-item">{{name}}</option>
|
||||||
|
{{/each}}
|
@ -5,6 +5,7 @@ var _ = require('underscore');
|
|||||||
module.exports = Backbone.Collection.extend({
|
module.exports = Backbone.Collection.extend({
|
||||||
url : window.NzbDrone.ApiRoot + '/netimport/movies',
|
url : window.NzbDrone.ApiRoot + '/netimport/movies',
|
||||||
model : MovieModel,
|
model : MovieModel,
|
||||||
|
specialProperty: "special",
|
||||||
|
|
||||||
parse : function(response) {
|
parse : function(response) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -148,6 +148,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#list-dropdown {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discoverable-list-item {
|
||||||
|
font-size: 14px;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discoverable-list-item:hover {
|
||||||
|
background-color: rgb(237, 237, 237);
|
||||||
|
}
|
||||||
|
|
||||||
li.add-new {
|
li.add-new {
|
||||||
.clickable;
|
.clickable;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user