From 0ee8b75b54eee04d16c47b7417db76ab245c5f6d Mon Sep 17 00:00:00 2001 From: Devin Buhl Date: Wed, 11 Jan 2017 15:42:37 -0500 Subject: [PATCH] initial autoimporter commit --- .../AutoImport.derp/AutoImportBase.cs | 35 +++++++ .../AutoImport.derp/AutoImportDefinition.cs | 18 ++++ .../AutoImport.derp/AutoImportRepository.cs | 20 ++++ .../AutoImport.derp/IAutoImport.cs | 12 +++ .../IMDbWatchList/IMDbWatchList.cs | 43 +++++++++ .../IMDbWatchList/IMDbWatchListProxy.cs | 79 ++++++++++++++++ .../IMDbWatchList/IMDbWatchListSettings.cs | 30 ++++++ .../AutoImporter/AutoImporterBase.cs | 91 +++++++++++++++++++ .../AutoImporter/AutoImporterDefinition.cs | 17 ++++ .../AutoImporter/IAutoImporter.cs | 15 +++ src/NzbDrone.Core/NzbDrone.Core.csproj | 10 ++ 11 files changed, 370 insertions(+) create mode 100644 src/NzbDrone.Core/AutoImport.derp/AutoImportBase.cs create mode 100644 src/NzbDrone.Core/AutoImport.derp/AutoImportDefinition.cs create mode 100644 src/NzbDrone.Core/AutoImport.derp/AutoImportRepository.cs create mode 100644 src/NzbDrone.Core/AutoImport.derp/IAutoImport.cs create mode 100644 src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchList.cs create mode 100644 src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchListProxy.cs create mode 100644 src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchListSettings.cs create mode 100644 src/NzbDrone.Core/AutoImporter/AutoImporterBase.cs create mode 100644 src/NzbDrone.Core/AutoImporter/AutoImporterDefinition.cs create mode 100644 src/NzbDrone.Core/AutoImporter/IAutoImporter.cs diff --git a/src/NzbDrone.Core/AutoImport.derp/AutoImportBase.cs b/src/NzbDrone.Core/AutoImport.derp/AutoImportBase.cs new file mode 100644 index 000000000..9dc51714c --- /dev/null +++ b/src/NzbDrone.Core/AutoImport.derp/AutoImportBase.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using FluentValidation.Results; +using NzbDrone.Core.ThingiProvider; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.AutoImport +{ + public abstract class AutoImportBase : IAutoImport where TSettings : IProviderConfig, new() + { + public abstract string Name { get; } + + public Type ConfigContract => typeof(TSettings); + + public virtual ProviderMessage Message => null; + + public IEnumerable DefaultDefinitions => new List(); + + public ProviderDefinition Definition { get; set; } + public abstract ValidationResult Test(); + + public abstract string Link { get; } + + protected TSettings Settings => (TSettings)Definition.Settings; + + public override string ToString() + { + return GetType().Name; + } + + public abstract bool Enabled { get; } + + public virtual object RequestAction(string action, IDictionary query) { return null; } + } +} diff --git a/src/NzbDrone.Core/AutoImport.derp/AutoImportDefinition.cs b/src/NzbDrone.Core/AutoImport.derp/AutoImportDefinition.cs new file mode 100644 index 000000000..f1d53e72e --- /dev/null +++ b/src/NzbDrone.Core/AutoImport.derp/AutoImportDefinition.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.AutoImport +{ + public class AutoImportDefinition : ProviderDefinition + { + public AutoImportDefinition() + { + Tags = new HashSet(); + } + + public bool Enabled { get; set; } + public HashSet Tags { get; set; } + + public override bool Enable => Enabled; + } +} diff --git a/src/NzbDrone.Core/AutoImport.derp/AutoImportRepository.cs b/src/NzbDrone.Core/AutoImport.derp/AutoImportRepository.cs new file mode 100644 index 000000000..398bcaf99 --- /dev/null +++ b/src/NzbDrone.Core/AutoImport.derp/AutoImportRepository.cs @@ -0,0 +1,20 @@ +using NzbDrone.Core.Datastore; +using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.ThingiProvider; + + +namespace NzbDrone.Core.AutoImport +{ + public interface IAutoImportRepository : IProviderRepository + { + + } + + public class AutoImportRepository : ProviderRepository, IAutoImportRepository + { + public AutoImportRepository(IMainDatabase database, IEventAggregator eventAggregator) + : base(database, eventAggregator) + { + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/AutoImport.derp/IAutoImport.cs b/src/NzbDrone.Core/AutoImport.derp/IAutoImport.cs new file mode 100644 index 000000000..5597ddee8 --- /dev/null +++ b/src/NzbDrone.Core/AutoImport.derp/IAutoImport.cs @@ -0,0 +1,12 @@ +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.AutoImport +{ + public interface IAutoImport : IProvider + { + string Link { get; } + bool Enabled { get; } + + // void OnGrab(GrabMessage grabMessage); + } +} diff --git a/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchList.cs b/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchList.cs new file mode 100644 index 000000000..d060e1362 --- /dev/null +++ b/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchList.cs @@ -0,0 +1,43 @@ + +using System.Collections.Generic; +using FluentValidation.Results; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.Tv; +using NzbDrone.Core.AutoImport; +using NzbDrone.Core.AutoImport.IMDbWatchList; +using System; + +namespace NzbDrone.Core.AutoImpoter.IMDbWatchList +{ + public class IMDbWatchList : AutoImportBase + { + public override bool Enabled + { + get + { + throw new NotImplementedException(); + } + } + + //private readonly INotifyMyAndroidProxy _proxy; + + //public NotifyMyAndroid(INotifyMyAndroidProxy proxy) + //{ + // _proxy = proxy; + //} + + public override string Link => "http://rss.imdb.com/"; + + public override string Name => "IMDb Public Watchlist"; + + + public override ValidationResult Test() + { + var failures = new List(); + + // failures.AddIfNotNull(_proxy.Test(Settings)); + + return new ValidationResult(failures); + } + } +} diff --git a/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchListProxy.cs b/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchListProxy.cs new file mode 100644 index 000000000..28561ef66 --- /dev/null +++ b/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchListProxy.cs @@ -0,0 +1,79 @@ +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.AutoImport.IMDbWatchList +{ + public interface IIMDbWatchListProxy + { + void ImportMovies(string url); + ValidationFailure Test(IMDbWatchListSettings 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(IMDbWatchListSettings settings) + { + try + { + Verify(settings.IMDbWatchListId); + ImportMovies(settings.IMDbWatchListId); + } + catch (Exception ex) + { + _logger.Error(ex, "Unable to import movies: " + ex.Message); + return new ValidationFailure("IMDbWatchListId", "Unable to import movies"); + } + + return null; + } + } +} diff --git a/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchListSettings.cs b/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchListSettings.cs new file mode 100644 index 000000000..4ecd75c72 --- /dev/null +++ b/src/NzbDrone.Core/AutoImport.derp/IMDbWatchList/IMDbWatchListSettings.cs @@ -0,0 +1,30 @@ +using FluentValidation; +using NzbDrone.Core.Annotations; +using NzbDrone.Core.ThingiProvider; +using NzbDrone.Core.Validation; + +namespace NzbDrone.Core.AutoImport.IMDbWatchList +{ + public class IMDbWatchListSettingsValidator : AbstractValidator + { + public IMDbWatchListSettingsValidator() + { + RuleFor(c => c.IMDbWatchListId).NotEmpty(); + } + } + + public class IMDbWatchListSettings : IProviderConfig + { + private static readonly IMDbWatchListSettingsValidator Validator = new IMDbWatchListSettingsValidator(); + + [FieldDefinition(0, Label = "Watch List Id", HelpLink = "http://rss.imdb.com/list/")] + public string IMDbWatchListId { get; set; } + + public bool IsValid => !string.IsNullOrWhiteSpace(IMDbWatchListId); + + public NzbDroneValidationResult Validate() + { + return new NzbDroneValidationResult(Validator.Validate(this)); + } + } +} diff --git a/src/NzbDrone.Core/AutoImporter/AutoImporterBase.cs b/src/NzbDrone.Core/AutoImporter/AutoImporterBase.cs new file mode 100644 index 000000000..23f6c4aba --- /dev/null +++ b/src/NzbDrone.Core/AutoImporter/AutoImporterBase.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FluentValidation.Results; +using NLog; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.IndexerSearch.Definitions; +using NzbDrone.Core.Parser; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.AutoImporter +{ + public abstract class AutoImporterBase : IAutoImporter + where TSettings : IProviderConfig, new() + { + // protected readonly IAutoImporterStatusService _autoImporterStatusService; + protected readonly IConfigService _configService; + protected readonly IParsingService _parsingService; + protected readonly Logger _logger; + + public abstract string Name { get; } + // public abstract DownloadProtocol Protocol { get; } + public abstract string Link { get; } + + public abstract bool Enabled { get; } + // public abstract bool SupportsSearch { get; } + + public AutoImporterBase(/*IAutoImporterStatusService autoImporterStatusService, */IConfigService configService, IParsingService parsingService, Logger logger) + { + //_autoImporterStatusService = autoImporterStatusService; + _configService = configService; + _parsingService = parsingService; + _logger = logger; + } + + public Type ConfigContract => typeof(TSettings); + + public virtual ProviderMessage Message => null; + + public virtual IEnumerable DefaultDefinitions + { + get + { + var config = (IProviderConfig)new TSettings(); + + yield return new AutoImporterDefinition + { + Name = GetType().Name, + Link = Link, + Enabled = config.Validate().IsValid && Enabled, + Implementation = GetType().Name, + Settings = config + }; + } + } + + public virtual ProviderDefinition Definition { get; set; } + + public virtual object RequestAction(string action, IDictionary query) { return null; } + + protected TSettings Settings => (TSettings)Definition.Settings; + + public abstract IList Fetch(); + + public ValidationResult Test() + { + var failures = new List(); + + try + { + Test(failures); + } + catch (Exception ex) + { + _logger.Error(ex, "Test aborted due to exception"); + failures.Add(new ValidationFailure(string.Empty, "Test was aborted due to an error: " + ex.Message)); + } + + return new ValidationResult(failures); + } + + protected abstract void Test(List failures); + + public override string ToString() + { + return Definition.Name; + } + } +} diff --git a/src/NzbDrone.Core/AutoImporter/AutoImporterDefinition.cs b/src/NzbDrone.Core/AutoImporter/AutoImporterDefinition.cs new file mode 100644 index 000000000..2446fb817 --- /dev/null +++ b/src/NzbDrone.Core/AutoImporter/AutoImporterDefinition.cs @@ -0,0 +1,17 @@ +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.AutoImporter +{ + public class AutoImporterDefinition : ProviderDefinition + { + public bool Enabled { get; set; } + public string Link { get; set; } + //public DownloadProtocol Protocol { get; set; } + //public bool SupportsRss { get; set; } + //public bool SupportsSearch { get; set; } + + public override bool Enable => Enabled; + + // public IndexerStatus Status { get; set; } + } +} diff --git a/src/NzbDrone.Core/AutoImporter/IAutoImporter.cs b/src/NzbDrone.Core/AutoImporter/IAutoImporter.cs new file mode 100644 index 000000000..246e94f92 --- /dev/null +++ b/src/NzbDrone.Core/AutoImporter/IAutoImporter.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using NzbDrone.Core.IndexerSearch.Definitions; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.AutoImporter +{ + public interface IAutoImporter : IProvider + { + string Link { get; } + bool Enabled { get; } + + IList Fetch(); + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 3ea6a0a76..3a6153c86 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -122,6 +122,16 @@ + + + + + + + + + +