initial autoimporter commit

This commit is contained in:
Devin Buhl 2017-01-11 15:42:37 -05:00
parent 99012d8a40
commit 0ee8b75b54
11 changed files with 370 additions and 0 deletions

View File

@ -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<TSettings> : IAutoImport where TSettings : IProviderConfig, new()
{
public abstract string Name { get; }
public Type ConfigContract => typeof(TSettings);
public virtual ProviderMessage Message => null;
public IEnumerable<ProviderDefinition> DefaultDefinitions => new List<ProviderDefinition>();
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<string, string> query) { return null; }
}
}

View File

@ -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<int>();
}
public bool Enabled { get; set; }
public HashSet<int> Tags { get; set; }
public override bool Enable => Enabled;
}
}

View File

@ -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<AutoImportDefinition>
{
}
public class AutoImportRepository : ProviderRepository<AutoImportDefinition>, IAutoImportRepository
{
public AutoImportRepository(IMainDatabase database, IEventAggregator eventAggregator)
: base(database, eventAggregator)
{
}
}
}

View File

@ -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);
}
}

View File

@ -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<IMDbWatchListSettings>
{
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<ValidationFailure>();
// failures.AddIfNotNull(_proxy.Test(Settings));
return new ValidationResult(failures);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<IMDbWatchListSettings>
{
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));
}
}
}

View File

@ -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<TSettings> : 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<ProviderDefinition> 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<string, string> query) { return null; }
protected TSettings Settings => (TSettings)Definition.Settings;
public abstract IList<ReleaseInfo> Fetch();
public ValidationResult Test()
{
var failures = new List<ValidationFailure>();
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<ValidationFailure> failures);
public override string ToString()
{
return Definition.Name;
}
}
}

View File

@ -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; }
}
}

View File

@ -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<ReleaseInfo> Fetch();
}
}

View File

@ -122,6 +122,16 @@
<Compile Include="Authentication\User.cs" />
<Compile Include="Authentication\UserRepository.cs" />
<Compile Include="Authentication\UserService.cs" />
<Compile Include="AutoImport.derp\AutoImportBase.cs" />
<Compile Include="AutoImport.derp\IAutoImport.cs" />
<Compile Include="AutoImport.derp\IMDbWatchList\IMDbWatchList.cs" />
<Compile Include="AutoImport.derp\IMDbWatchList\IMDbWatchListSettings.cs" />
<Compile Include="AutoImport.derp\IMDbWatchList\IMDbWatchListProxy.cs" />
<Compile Include="AutoImport.derp\AutoImportRepository.cs" />
<Compile Include="AutoImport.derp\AutoImportDefinition.cs" />
<Compile Include="AutoImporter\AutoImporterBase.cs" />
<Compile Include="AutoImporter\IAutoImporter.cs" />
<Compile Include="AutoImporter\AutoImporterDefinition.cs" />
<Compile Include="Backup\Backup.cs" />
<Compile Include="Backup\BackupCommand.cs" />
<Compile Include="Backup\BackupService.cs" />