mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-23 22:25:14 -04:00
Added couchpotato, and added a test
This commit is contained in:
@@ -3,91 +3,88 @@ using System.Xml.Serialization;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.CouchPotato
|
||||
{
|
||||
class CouchPotatoAPI
|
||||
public class CouchPotatoResponse
|
||||
{
|
||||
public class CouchPotatoResponse
|
||||
{
|
||||
public Movie[] movies { get; set; }
|
||||
public int total { get; set; }
|
||||
public bool empty { get; set; }
|
||||
public bool success { get; set; }
|
||||
}
|
||||
public Movie[] movies { get; set; }
|
||||
public int total { get; set; }
|
||||
public bool empty { get; set; }
|
||||
public bool success { get; set; }
|
||||
}
|
||||
|
||||
public class Movie
|
||||
{
|
||||
public string status { get; set; }
|
||||
public Info info { get; set; }
|
||||
public string _t { get; set; }
|
||||
public List<Release> releases { get; set; }
|
||||
public string title { get; set; }
|
||||
public string _rev { get; set; }
|
||||
public string profile_id { get; set; }
|
||||
public string _id { get; set; }
|
||||
public object category_id { get; set; }
|
||||
public string type { get; set; }
|
||||
}
|
||||
public class Movie
|
||||
{
|
||||
public string status { get; set; }
|
||||
public Info info { get; set; }
|
||||
public string _t { get; set; }
|
||||
public List<Release> releases { get; set; }
|
||||
public string title { get; set; }
|
||||
public string _rev { get; set; }
|
||||
public string profile_id { get; set; }
|
||||
public string _id { get; set; }
|
||||
public object category_id { get; set; }
|
||||
public string type { get; set; }
|
||||
}
|
||||
|
||||
public class Info
|
||||
{
|
||||
public string[] genres { get; set; }
|
||||
public int tmdb_id { get; set; }
|
||||
public string plot { get; set; }
|
||||
public string tagline { get; set; }
|
||||
public int year { get; set; }
|
||||
public string original_title { get; set; }
|
||||
public bool via_imdb { get; set; }
|
||||
public string[] directors { get; set; }
|
||||
public string[] titles { get; set; }
|
||||
public string imdb { get; set; }
|
||||
public string mpaa { get; set; }
|
||||
public bool via_tmdb { get; set; }
|
||||
public string[] actors { get; set; }
|
||||
public string[] writers { get; set; }
|
||||
public int runtime { get; set; }
|
||||
public string type { get; set; }
|
||||
public string released { get; set; }
|
||||
}
|
||||
public class Info
|
||||
{
|
||||
public string[] genres { get; set; }
|
||||
public int tmdb_id { get; set; }
|
||||
public string plot { get; set; }
|
||||
public string tagline { get; set; }
|
||||
public int year { get; set; }
|
||||
public string original_title { get; set; }
|
||||
public bool via_imdb { get; set; }
|
||||
public string[] directors { get; set; }
|
||||
public string[] titles { get; set; }
|
||||
public string imdb { get; set; }
|
||||
public string mpaa { get; set; }
|
||||
public bool via_tmdb { get; set; }
|
||||
public string[] actors { get; set; }
|
||||
public string[] writers { get; set; }
|
||||
public int runtime { get; set; }
|
||||
public string type { get; set; }
|
||||
public string released { get; set; }
|
||||
}
|
||||
|
||||
public class ReleaseInfo
|
||||
{
|
||||
public int size { get; set; }
|
||||
public int seeders { get; set; }
|
||||
public string protocol { get; set; }
|
||||
public string description { get; set; }
|
||||
public string url { get; set; }
|
||||
public int age { get; set; }
|
||||
public string id { get; set; }
|
||||
public int leechers { get; set; }
|
||||
public int score { get; set; }
|
||||
public string provider { get; set; }
|
||||
public int seed_time { get; set; }
|
||||
public string provider_extra { get; set; }
|
||||
public string detail_url { get; set; }
|
||||
public string type { get; set; }
|
||||
public double seed_ratio { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
public class ReleaseInfo
|
||||
{
|
||||
public int size { get; set; }
|
||||
public int seeders { get; set; }
|
||||
public string protocol { get; set; }
|
||||
public string description { get; set; }
|
||||
public string url { get; set; }
|
||||
public int age { get; set; }
|
||||
public string id { get; set; }
|
||||
public int leechers { get; set; }
|
||||
public int score { get; set; }
|
||||
public string provider { get; set; }
|
||||
public int seed_time { get; set; }
|
||||
public string provider_extra { get; set; }
|
||||
public string detail_url { get; set; }
|
||||
public string type { get; set; }
|
||||
public double seed_ratio { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
|
||||
public class DownloadInfo
|
||||
{
|
||||
public bool status_support { get; set; }
|
||||
public string id { get; set; }
|
||||
public string downloader { get; set; }
|
||||
}
|
||||
public class DownloadInfo
|
||||
{
|
||||
public bool status_support { get; set; }
|
||||
public string id { get; set; }
|
||||
public string downloader { get; set; }
|
||||
}
|
||||
|
||||
public class Release
|
||||
{
|
||||
public string status { get; set; }
|
||||
public ReleaseInfo info { get; set; }
|
||||
public DownloadInfo download_info { get; set; }
|
||||
public string _id { get; set; }
|
||||
public string media_id { get; set; }
|
||||
public string _rev { get; set; }
|
||||
public string _t { get; set; }
|
||||
public bool is_3d { get; set; }
|
||||
public int last_edit { get; set; }
|
||||
public string identifier { get; set; }
|
||||
public string quality { get; set; }
|
||||
}
|
||||
public class Release
|
||||
{
|
||||
public string status { get; set; }
|
||||
public ReleaseInfo info { get; set; }
|
||||
public DownloadInfo download_info { get; set; }
|
||||
public string _id { get; set; }
|
||||
public string media_id { get; set; }
|
||||
public string _rev { get; set; }
|
||||
public string _t { get; set; }
|
||||
public bool is_3d { get; set; }
|
||||
public int last_edit { get; set; }
|
||||
public string identifier { get; set; }
|
||||
public string quality { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.NetImport.Exceptions;
|
||||
using NzbDrone.Core.Tv;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.Exceptions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.CouchPotato
|
||||
{
|
||||
public class CouchPotatoParser : IParseNetImportResponse
|
||||
{
|
||||
private readonly CouchPotatoSettings _settings;
|
||||
private NetImportResponse _importResponse;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private static readonly Regex ReplaceEntities = new Regex("&[a-z]+;", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public CouchPotatoParser(CouchPotatoSettings settings)
|
||||
{
|
||||
_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<CouchPotatoResponse>(_importResponse.Content);
|
||||
|
||||
// no movies were return
|
||||
if (jsonResponse.total == 0)
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
var responseData = jsonResponse.movies;
|
||||
|
||||
foreach (var item in responseData)
|
||||
{
|
||||
// if there are no releases at all the movie wasn't found on CP, so return movies
|
||||
if (!item.releases.Any() && item.type == "movie")
|
||||
{
|
||||
movies.AddIfNotNull(new Tv.Movie()
|
||||
{
|
||||
Title = item.title,
|
||||
ImdbId = item.info.imdb,
|
||||
TmdbId = item.info.tmdb_id
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// snatched,missing,available,downloaded
|
||||
// done,seeding
|
||||
bool isCompleted = item.releases.Any(rel => (rel.status == "done" || rel.status == "seeding"));
|
||||
if (!isCompleted)
|
||||
{
|
||||
movies.AddIfNotNull(new Tv.Movie()
|
||||
{
|
||||
Title = item.title,
|
||||
ImdbId = item.info.imdb,
|
||||
TmdbId = item.info.tmdb_id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return movies;
|
||||
}
|
||||
|
||||
protected virtual bool PreProcess(NetImportResponse indexerResponse)
|
||||
{
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new NetImportException(indexerResponse, "Indexer API call resulted in an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
if (indexerResponse.HttpResponse.Headers.ContentType != null && indexerResponse.HttpResponse.Headers.ContentType.Contains("text/json") &&
|
||||
indexerResponse.HttpRequest.Headers.Accept != null && !indexerResponse.HttpRequest.Headers.Accept.Contains("text/json"))
|
||||
{
|
||||
throw new NetImportException(indexerResponse, "Indexer responded with html content. Site is likely blocked or unavailable.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using NzbDrone.Common.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.CouchPotato
|
||||
{
|
||||
public class CouchPotatoRequestGenerator : INetImportRequestGenerator
|
||||
{
|
||||
public CouchPotatoSettings Settings { get; set; }
|
||||
|
||||
public virtual NetImportPageableRequestChain GetMovies()
|
||||
{
|
||||
var pageableRequests = new NetImportPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetMovies(null));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<NetImportRequest> GetMovies(string searchParameters)
|
||||
{
|
||||
var request = new NetImportRequest($"{Settings.Link.Trim()}:{Settings.Port}/api/{Settings.ApiKey}/movie.list/?status=active", HttpAccept.Json);
|
||||
yield return request;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.CouchPotato
|
||||
{
|
||||
|
||||
public class CouchPotatoSettings : NetImportBaseSettings
|
||||
{
|
||||
public CouchPotatoSettings()
|
||||
{
|
||||
Link = "http://localhost";
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "CouchPotato URL", HelpText = "Link to your CoouchPootato.")]
|
||||
public new string Link { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "CouchPotato Port", HelpText = "Port your CoouchPootato uses.")]
|
||||
public string Port { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "CouchPotato API Key", HelpText = "CoouchPootato API Key.")]
|
||||
public string ApiKey { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.RSSImport
|
||||
{
|
||||
class IMDbWatchListAPI
|
||||
{
|
||||
[XmlRoot(ElementName = "item")]
|
||||
public class Movie
|
||||
{
|
||||
[XmlElement(ElementName = "pubDate")]
|
||||
public string PublishDate { get; set; }
|
||||
[XmlElement(ElementName = "title")]
|
||||
public string Title { get; set; }
|
||||
[XmlElement(ElementName = "link")]
|
||||
public string Link { get; set; }
|
||||
[XmlElement(ElementName = "guid")]
|
||||
public string Guid { get; set; }
|
||||
[XmlElement(ElementName = "description")]
|
||||
public string Description { get; set; }
|
||||
}
|
||||
|
||||
[XmlRoot(ElementName = "channel")]
|
||||
public class Channel
|
||||
{
|
||||
[XmlElement(ElementName = "title")]
|
||||
public string Title { get; set; }
|
||||
[XmlElement(ElementName = "link")]
|
||||
public string Link { get; set; }
|
||||
[XmlElement(ElementName = "description")]
|
||||
public string Description { get; set; }
|
||||
[XmlElement(ElementName = "pubDate")]
|
||||
public string PublishDate { get; set; }
|
||||
[XmlElement(ElementName = "lastBuildDate")]
|
||||
public string LastBuildDate { get; set; }
|
||||
[XmlElement(ElementName = "item")]
|
||||
public List<Movie> Movie { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Xml.Linq;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
using RestSharp;
|
||||
using NzbDrone.Core.Rest;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.RSSImport
|
||||
{
|
||||
public interface IIMDbWatchListProxy
|
||||
{
|
||||
void ImportMovies(string url);
|
||||
ValidationFailure Test(RSSImportSettings settings);
|
||||
}
|
||||
|
||||
public class IMDbWatchListProxy : IIMDbWatchListProxy
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private const string URL = "http://rss.imdb.com";
|
||||
|
||||
public IMDbWatchListProxy(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void ImportMovies(string id)
|
||||
{
|
||||
var client = RestClientFactory.BuildClient(URL);
|
||||
var request = new RestRequest("/list/{id}", Method.GET);
|
||||
request.RequestFormat = DataFormat.Xml;
|
||||
request.AddParameter("id", id, ParameterType.UrlSegment);
|
||||
|
||||
var response = client.ExecuteAndValidate(request);
|
||||
ValidateResponse(response);
|
||||
}
|
||||
|
||||
private void Verify(string id)
|
||||
{
|
||||
var client = RestClientFactory.BuildClient(URL);
|
||||
var request = new RestRequest("/list/{id}", Method.GET);
|
||||
request.RequestFormat = DataFormat.Xml;
|
||||
request.AddParameter("id", id, ParameterType.UrlSegment);
|
||||
|
||||
var response = client.ExecuteAndValidate(request);
|
||||
ValidateResponse(response);
|
||||
}
|
||||
|
||||
private void ValidateResponse(IRestResponse response)
|
||||
{
|
||||
var xDoc = XDocument.Parse(response.Content);
|
||||
var nma = xDoc.Descendants("nma").Single();
|
||||
var error = nma.Descendants("error").SingleOrDefault();
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
((HttpStatusCode)Convert.ToInt32(error.Attribute("code").Value)).VerifyStatusCode(error.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public ValidationFailure Test(RSSImportSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
Verify(settings.Link);
|
||||
ImportMovies(settings.Link);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to import movies: " + ex.Message);
|
||||
return new ValidationFailure("IMDbWatchListId", "Unable to import movies");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,10 @@ namespace NzbDrone.Core.NetImport.RSSImport
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public NetImportPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||
{
|
||||
return new NetImportPageableRequestChain();
|
||||
}
|
||||
//public NetImportPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||
//{
|
||||
// return new NetImportPageableRequestChain();
|
||||
//}
|
||||
|
||||
private IEnumerable<NetImportRequest> GetMovies(string searchParameters)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,6 @@ namespace NzbDrone.Core.NetImport.RSSImport
|
||||
public RSSImportSettings()
|
||||
{
|
||||
Link = "http://rss.yoursite.com";
|
||||
ProfileId = 1;
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "RSS Link", HelpText = "Link to the rss feed of movies.")]
|
||||
|
||||
Reference in New Issue
Block a user