diff --git a/Marr.Data/Converters/BooleanIntConverter.cs b/Marr.Data/Converters/BooleanIntConverter.cs
index 9dc9b41d3..18c964d15 100644
--- a/Marr.Data/Converters/BooleanIntConverter.cs
+++ b/Marr.Data/Converters/BooleanIntConverter.cs
@@ -20,14 +20,14 @@ namespace Marr.Data.Converters
{
public class BooleanIntConverter : IConverter
{
- public object FromDB(ColumnMap map, object dbValue)
+ public object FromDB(ConverterContext context)
{
- if (dbValue == DBNull.Value)
+ if (context.DbValue == DBNull.Value)
{
return DBNull.Value;
}
- int val = (int)dbValue;
+ int val = (int)context.DbValue;
if (val == 1)
{
@@ -40,7 +40,12 @@ namespace Marr.Data.Converters
throw new ConversionException(
string.Format(
"The BooleanCharConverter could not convert the value '{0}' to a boolean.",
- dbValue));
+ context.DbValue));
+ }
+
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
}
public object ToDB(object clrValue)
diff --git a/Marr.Data/Converters/BooleanYNConverter.cs b/Marr.Data/Converters/BooleanYNConverter.cs
index b116bdeaf..38003939c 100644
--- a/Marr.Data/Converters/BooleanYNConverter.cs
+++ b/Marr.Data/Converters/BooleanYNConverter.cs
@@ -20,14 +20,14 @@ namespace Marr.Data.Converters
{
public class BooleanYNConverter : IConverter
{
- public object FromDB(ColumnMap map, object dbValue)
+ public object FromDB(ConverterContext context)
{
- if (dbValue == DBNull.Value)
+ if (context.DbValue == DBNull.Value)
{
return DBNull.Value;
}
- string val = dbValue.ToString();
+ string val = context.DbValue.ToString();
if (val == "Y")
{
@@ -40,7 +40,12 @@ namespace Marr.Data.Converters
throw new ConversionException(
string.Format(
"The BooleanYNConverter could not convert the value '{0}' to a boolean.",
- dbValue));
+ context.DbValue));
+ }
+
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext {ColumnMap = map, DbValue = dbValue});
}
public object ToDB(object clrValue)
diff --git a/Marr.Data/Converters/CastConverter.cs b/Marr.Data/Converters/CastConverter.cs
index 4253357ed..2fa3b8eca 100644
--- a/Marr.Data/Converters/CastConverter.cs
+++ b/Marr.Data/Converters/CastConverter.cs
@@ -30,12 +30,17 @@ namespace Marr.Data.Converters
get { return typeof(TDb); }
}
- public object FromDB(ColumnMap map, object dbValue)
+ public object FromDB(ConverterContext context)
{
- TDb val = (TDb)dbValue;
+ TDb val = (TDb)context.DbValue;
return val.ToType(typeof(TClr), CultureInfo.InvariantCulture);
}
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
+ }
+
public object ToDB(object clrValue)
{
TClr val = (TClr)clrValue;
diff --git a/Marr.Data/Converters/ConverterContext.cs b/Marr.Data/Converters/ConverterContext.cs
new file mode 100644
index 000000000..341925077
--- /dev/null
+++ b/Marr.Data/Converters/ConverterContext.cs
@@ -0,0 +1,13 @@
+using System.Data;
+using Marr.Data.Mapping;
+
+namespace Marr.Data.Converters
+{
+ public class ConverterContext
+ {
+ public ColumnMap ColumnMap { get; set; }
+ public object DbValue { get; set; }
+ public ColumnMapCollection MapCollection { get; set; }
+ public IDataRecord DataRecord { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Marr.Data/Converters/EnumIntConverter.cs b/Marr.Data/Converters/EnumIntConverter.cs
index a7d528d16..5fe88a411 100644
--- a/Marr.Data/Converters/EnumIntConverter.cs
+++ b/Marr.Data/Converters/EnumIntConverter.cs
@@ -20,11 +20,16 @@ namespace Marr.Data.Converters
{
public class EnumIntConverter : IConverter
{
- public object FromDB(ColumnMap map, object dbValue)
+ public object FromDB(ConverterContext context)
{
- if (dbValue == null || dbValue == DBNull.Value)
+ if (context.DbValue == null || context.DbValue == DBNull.Value)
return null;
- return Enum.ToObject(map.FieldType, (int)dbValue);
+ return Enum.ToObject(context.ColumnMap.FieldType, (int)context.DbValue);
+ }
+
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
}
public object ToDB(object clrValue)
diff --git a/Marr.Data/Converters/EnumStringConverter.cs b/Marr.Data/Converters/EnumStringConverter.cs
index 4e304fc10..eb4f8b01a 100644
--- a/Marr.Data/Converters/EnumStringConverter.cs
+++ b/Marr.Data/Converters/EnumStringConverter.cs
@@ -20,11 +20,16 @@ namespace Marr.Data.Converters
{
public class EnumStringConverter : IConverter
{
- public object FromDB(ColumnMap map, object dbValue)
+ public object FromDB(ConverterContext context)
{
- if (dbValue == null || dbValue == DBNull.Value)
+ if (context.DbValue == null || context.DbValue == DBNull.Value)
return null;
- return Enum.Parse(map.FieldType, (string)dbValue);
+ return Enum.Parse(context.ColumnMap.FieldType, (string)context.DbValue);
+ }
+
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
}
public object ToDB(object clrValue)
diff --git a/Marr.Data/Converters/IConverter.cs b/Marr.Data/Converters/IConverter.cs
index 318f26957..f2e9685a9 100644
--- a/Marr.Data/Converters/IConverter.cs
+++ b/Marr.Data/Converters/IConverter.cs
@@ -20,6 +20,9 @@ namespace Marr.Data.Converters
{
public interface IConverter
{
+ object FromDB(ConverterContext context);
+
+ [Obsolete("use FromDB(ConverterContext context) instead")]
object FromDB(ColumnMap map, object dbValue);
object ToDB(object clrValue);
Type DbType { get; }
diff --git a/Marr.Data/Mapping/MappingHelper.cs b/Marr.Data/Mapping/MappingHelper.cs
index f025528be..0b4c73681 100644
--- a/Marr.Data/Mapping/MappingHelper.cs
+++ b/Marr.Data/Mapping/MappingHelper.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Data.Common;
+using Marr.Data.Converters;
namespace Marr.Data.Mapping
{
@@ -53,7 +54,15 @@ namespace Marr.Data.Mapping
// Handle conversions
if (dataMap.Converter != null)
{
- dbValue = dataMap.Converter.FromDB(dataMap, dbValue);
+ var convertContext = new ConverterContext
+ {
+ DbValue = dbValue,
+ ColumnMap = dataMap,
+ MapCollection = mappings,
+ DataRecord = reader
+ };
+
+ dbValue = dataMap.Converter.FromDB(convertContext);
}
if (dbValue != DBNull.Value && dbValue != null)
diff --git a/Marr.Data/Marr.Data.csproj b/Marr.Data/Marr.Data.csproj
index f7e58cb01..9ae7c2082 100644
--- a/Marr.Data/Marr.Data.csproj
+++ b/Marr.Data/Marr.Data.csproj
@@ -52,6 +52,7 @@
+
diff --git a/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs b/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs
index bf3d72d11..385a9b989 100644
--- a/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs
+++ b/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Test.ClientSchemaTests
[Test]
public void should_return_field_for_every_property()
{
- var schema = SchemaBuilder.GenerateSchema(new TestModel());
+ var schema = SchemaBuilder.ToSchema(new TestModel());
schema.Should().HaveCount(2);
}
@@ -26,7 +26,7 @@ namespace NzbDrone.Api.Test.ClientSchemaTests
LastName = "Poop"
};
- var schema = SchemaBuilder.GenerateSchema(model);
+ var schema = SchemaBuilder.ToSchema(model);
schema.Should().Contain(c => c.Order == 1 && c.Name == "LastName" && c.Label == "Last Name" && c.HelpText == "Your Last Name" && (string) c.Value == "Poop");
schema.Should().Contain(c => c.Order == 0 && c.Name == "FirstName" && c.Label == "First Name" && c.HelpText == "Your First Name" && (string) c.Value == "Bob");
diff --git a/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs b/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs
index 82fb9425a..e03e02c35 100644
--- a/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs
+++ b/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs
@@ -36,7 +36,7 @@ namespace NzbDrone.Api.Test.MappingTests
[TestCase(typeof(Episode), typeof(EpisodeResource))]
[TestCase(typeof(RootFolder), typeof(RootFolderResource))]
[TestCase(typeof(NamingConfig), typeof(NamingConfigResource))]
- [TestCase(typeof(Indexer), typeof(IndexerResource))]
+ [TestCase(typeof(IndexerDefinition), typeof(IndexerResource))]
[TestCase(typeof(ReleaseInfo), typeof(ReleaseResource))]
[TestCase(typeof(ParsedEpisodeInfo), typeof(ReleaseResource))]
[TestCase(typeof(DownloadDecision), typeof(ReleaseResource))]
diff --git a/NzbDrone.Api/ClientSchema/SchemaBuilder.cs b/NzbDrone.Api/ClientSchema/SchemaBuilder.cs
index 99b2c6d15..c5c96c302 100644
--- a/NzbDrone.Api/ClientSchema/SchemaBuilder.cs
+++ b/NzbDrone.Api/ClientSchema/SchemaBuilder.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using NzbDrone.Common;
+using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Reflection;
using NzbDrone.Core.Annotations;
@@ -8,8 +10,10 @@ namespace NzbDrone.Api.ClientSchema
{
public static class SchemaBuilder
{
- public static List GenerateSchema(object model)
+ public static List ToSchema(object model)
{
+ Ensure.That(() => model).IsNotNull();
+
var properties = model.GetType().GetSimpleProperties();
var result = new List(properties.Count);
@@ -50,10 +54,55 @@ namespace NzbDrone.Api.ClientSchema
}
+
+ public static object ReadFormSchema(List fields, Type targetType)
+ {
+ Ensure.That(() => targetType).IsNotNull();
+
+ var properties = targetType.GetSimpleProperties();
+
+ var target = Activator.CreateInstance(targetType);
+
+ foreach (var propertyInfo in properties)
+ {
+ var fieldAttribute = propertyInfo.GetAttribute(false);
+
+ if (fieldAttribute != null)
+ {
+ var field = fields.Find(f => f.Name == propertyInfo.Name);
+
+ if (propertyInfo.PropertyType == typeof(Int32))
+ {
+ var intValue = Convert.ToInt32(field.Value);
+ propertyInfo.SetValue(target, intValue, null);
+ }
+
+ else if (propertyInfo.PropertyType == typeof(Nullable))
+ {
+ var intValue = field.Value.ToString().ParseInt32();
+ propertyInfo.SetValue(target, intValue, null);
+ }
+
+ else
+ {
+ propertyInfo.SetValue(target, field.Value, null);
+ }
+ }
+ }
+
+ return target;
+
+ }
+
+ public static T ReadFormSchema(List fields)
+ {
+ return (T)ReadFormSchema(fields, typeof (T));
+ }
+
private static List GetSelectOptions(Type selectOptions)
{
var options = from Enum e in Enum.GetValues(selectOptions)
- select new SelectOption { Value = Convert.ToInt32(e), Name = e.ToString() };
+ select new SelectOption { Value = Convert.ToInt32(e), Name = e.ToString() };
return options.OrderBy(o => o.Value).ToList();
}
diff --git a/NzbDrone.Api/ClientSchema/SchemaDeserializer.cs b/NzbDrone.Api/ClientSchema/SchemaDeserializer.cs
index 9985ffb49..36d2a68e8 100644
--- a/NzbDrone.Api/ClientSchema/SchemaDeserializer.cs
+++ b/NzbDrone.Api/ClientSchema/SchemaDeserializer.cs
@@ -8,38 +8,6 @@ namespace NzbDrone.Api.ClientSchema
{
public static class SchemaDeserializer
{
- public static T DeserializeSchema(T model, List fields)
- {
- var properties = model.GetType().GetSimpleProperties();
-
- foreach (var propertyInfo in properties)
- {
- var fieldAttribute = propertyInfo.GetAttribute(false);
-
- if (fieldAttribute != null)
- {
- var field = fields.Find(f => f.Name == propertyInfo.Name);
-
- if (propertyInfo.PropertyType == typeof (Int32))
- {
- var intValue = Convert.ToInt32(field.Value);
- propertyInfo.SetValue(model, intValue, null);
- }
-
- else if (propertyInfo.PropertyType == typeof(Nullable))
- {
- var intValue = field.Value.ToString().ParseInt32();
- propertyInfo.SetValue(model, intValue, null);
- }
-
- else
- {
- propertyInfo.SetValue(model, field.Value, null);
- }
- }
- }
-
- return model;
- }
+
}
}
\ No newline at end of file
diff --git a/NzbDrone.Api/IndexerResource.cs b/NzbDrone.Api/IndexerResource.cs
new file mode 100644
index 000000000..65c5bad64
--- /dev/null
+++ b/NzbDrone.Api/IndexerResource.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using NzbDrone.Api.ClientSchema;
+using NzbDrone.Api.REST;
+
+namespace NzbDrone.Api
+{
+ public class ProviderResource : RestResource
+ {
+ public Boolean Enable { get; set; }
+ public String Name { get; set; }
+ public List Fields { get; set; }
+ public String Implementation { get; set; }
+ public String ConfigContract { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Api/Indexers/IndexerModule.cs b/NzbDrone.Api/Indexers/IndexerModule.cs
index 02215d3ed..33c56a108 100644
--- a/NzbDrone.Api/Indexers/IndexerModule.cs
+++ b/NzbDrone.Api/Indexers/IndexerModule.cs
@@ -1,113 +1,12 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using NzbDrone.Api.ClientSchema;
-using NzbDrone.Api.REST;
-using NzbDrone.Core.Indexers;
-using Omu.ValueInjecter;
-using FluentValidation;
-using NzbDrone.Api.Mapping;
+using NzbDrone.Core.Indexers;
namespace NzbDrone.Api.Indexers
{
- public class IndexerModule : NzbDroneRestModule
+ public class IndexerModule : ProviderModuleBase
{
- private readonly IIndexerService _indexerService;
-
- public IndexerModule(IIndexerService indexerService)
- {
- _indexerService = indexerService;
- GetResourceAll = GetAll;
- GetResourceById = GetIndexer;
- CreateResource = CreateIndexer;
- UpdateResource = UpdateIndexer;
- DeleteResource = DeleteIndexer;
-
-
- SharedValidator.RuleFor(c => c.Name).NotEmpty();
- SharedValidator.RuleFor(c => c.Implementation).NotEmpty();
-
- PostValidator.RuleFor(c => c.Fields).NotEmpty();
- }
-
- private IndexerResource GetIndexer(int id)
- {
- return _indexerService.Get(id).InjectTo();
- }
-
- private List GetAll()
- {
- var indexers = _indexerService.All();
-
- var result = new List(indexers.Count);
-
- foreach (var indexer in indexers)
- {
- var indexerResource = new IndexerResource();
- indexerResource.InjectFrom(indexer);
- indexerResource.Fields = SchemaBuilder.GenerateSchema(indexer.Settings);
-
- result.Add(indexerResource);
- }
-
- return result;
- }
-
- private int CreateIndexer(IndexerResource indexerResource)
- {
- var indexer = GetIndexer(indexerResource);
- indexer = _indexerService.Create(indexer);
- return indexer.Id;
- }
-
- private void UpdateIndexer(IndexerResource indexerResource)
- {
- var indexer = _indexerService.Get(indexerResource.Id);
- indexer.InjectFrom(indexerResource);
- indexer.Settings = SchemaDeserializer.DeserializeSchema(indexer.Settings, indexerResource.Fields);
-
- ValidateIndexer(indexer);
-
- _indexerService.Update(indexer);
- }
-
-
- private static void ValidateIndexer(Indexer indexer)
- {
- if (indexer.Enable)
- {
- var validationResult = indexer.Settings.Validate();
-
- if (!validationResult.IsValid)
- {
- throw new ValidationException(validationResult.Errors);
- }
- }
- }
-
- private Indexer GetIndexer(IndexerResource indexerResource)
- {
- var indexer = _indexerService.Schema()
- .SingleOrDefault(i =>
- i.Implementation.Equals(indexerResource.Implementation,
- StringComparison.InvariantCultureIgnoreCase));
-
- if (indexer == null)
- {
- throw new BadRequestException("Invalid Indexer Implementation");
- }
-
- indexer.InjectFrom(indexerResource);
- indexer.Settings = SchemaDeserializer.DeserializeSchema(indexer.Settings, indexerResource.Fields);
-
- ValidateIndexer(indexer);
-
- return indexer;
- }
-
- private void DeleteIndexer(int id)
+ public IndexerModule(IndexerFactory indexerFactory)
+ : base(indexerFactory, "indexer")
{
- _indexerService.Delete(id);
}
}
}
\ No newline at end of file
diff --git a/NzbDrone.Api/Indexers/IndexerResource.cs b/NzbDrone.Api/Indexers/IndexerResource.cs
index 34a31551a..a613526fe 100644
--- a/NzbDrone.Api/Indexers/IndexerResource.cs
+++ b/NzbDrone.Api/Indexers/IndexerResource.cs
@@ -11,5 +11,6 @@ namespace NzbDrone.Api.Indexers
public String Name { get; set; }
public List Fields { get; set; }
public String Implementation { get; set; }
+ public String ConfigContract { get; set; }
}
}
\ No newline at end of file
diff --git a/NzbDrone.Api/Indexers/IndexerSchemaModule.cs b/NzbDrone.Api/Indexers/IndexerSchemaModule.cs
index ad2ca7846..a0312bdc4 100644
--- a/NzbDrone.Api/Indexers/IndexerSchemaModule.cs
+++ b/NzbDrone.Api/Indexers/IndexerSchemaModule.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Linq;
using NzbDrone.Api.ClientSchema;
using NzbDrone.Core.Indexers;
using Omu.ValueInjecter;
@@ -7,26 +8,28 @@ namespace NzbDrone.Api.Indexers
{
public class IndexerSchemaModule : NzbDroneRestModule
{
- private readonly IIndexerService _indexerService;
+ private readonly IIndexerFactory _indexerFactory;
- public IndexerSchemaModule(IIndexerService indexerService)
+ public IndexerSchemaModule(IIndexerFactory indexerFactory)
: base("indexer/schema")
{
- _indexerService = indexerService;
+ _indexerFactory = indexerFactory;
GetResourceAll = GetSchema;
}
private List GetSchema()
{
- var indexers = _indexerService.Schema();
- var result = new List(indexers.Count);
+ var indexers = _indexerFactory.Templates().Where(c => c.Implementation =="Newznab");
+
+
+ var result = new List(indexers.Count());
foreach (var indexer in indexers)
{
var indexerResource = new IndexerResource();
indexerResource.InjectFrom(indexer);
- indexerResource.Fields = SchemaBuilder.GenerateSchema(indexer.Settings);
+ indexerResource.Fields = SchemaBuilder.ToSchema(indexer.Settings);
result.Add(indexerResource);
}
diff --git a/NzbDrone.Api/Notifications/NotificationModule.cs b/NzbDrone.Api/Notifications/NotificationModule.cs
index bc7ca8aac..c8be13f67 100644
--- a/NzbDrone.Api/Notifications/NotificationModule.cs
+++ b/NzbDrone.Api/Notifications/NotificationModule.cs
@@ -4,6 +4,7 @@ using System.Linq;
using NzbDrone.Api.ClientSchema;
using NzbDrone.Api.Mapping;
using NzbDrone.Api.REST;
+using NzbDrone.Common.Reflection;
using NzbDrone.Core.Notifications;
using Omu.ValueInjecter;
@@ -39,7 +40,7 @@ namespace NzbDrone.Api.Notifications
{
var notificationResource = new NotificationResource();
notificationResource.InjectFrom(notification);
- notificationResource.Fields = SchemaBuilder.GenerateSchema(notification.Settings);
+ notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings);
notificationResource.TestCommand = String.Format("test{0}", notification.Implementation.ToLowerInvariant());
result.Add(notificationResource);
@@ -79,7 +80,10 @@ namespace NzbDrone.Api.Notifications
}
notification.InjectFrom(notificationResource);
- notification.Settings = SchemaDeserializer.DeserializeSchema(notification.Settings, notificationResource.Fields);
+
+ //var configType = ReflectionExtensions.CoreAssembly.FindTypeByName(notification)
+
+ //notification.Settings = SchemaBuilder.ReadFormSchema(notification.Settings, notificationResource.Fields);
return notification;
}
diff --git a/NzbDrone.Api/Notifications/NotificationSchemaModule.cs b/NzbDrone.Api/Notifications/NotificationSchemaModule.cs
index d347e343c..68a5bd594 100644
--- a/NzbDrone.Api/Notifications/NotificationSchemaModule.cs
+++ b/NzbDrone.Api/Notifications/NotificationSchemaModule.cs
@@ -28,7 +28,7 @@ namespace NzbDrone.Api.Notifications
{
var notificationResource = new NotificationResource();
notificationResource.InjectFrom(notification);
- notificationResource.Fields = SchemaBuilder.GenerateSchema(notification.Settings);
+ notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings);
notificationResource.TestCommand = String.Format("test{0}", notification.Implementation.ToLowerInvariant());
result.Add(notificationResource);
diff --git a/NzbDrone.Api/NzbDrone.Api.csproj b/NzbDrone.Api/NzbDrone.Api.csproj
index 8de55e952..88f133b26 100644
--- a/NzbDrone.Api/NzbDrone.Api.csproj
+++ b/NzbDrone.Api/NzbDrone.Api.csproj
@@ -109,6 +109,8 @@
+
+
diff --git a/NzbDrone.Api/ProviderModuleBase.cs b/NzbDrone.Api/ProviderModuleBase.cs
new file mode 100644
index 000000000..f379f598a
--- /dev/null
+++ b/NzbDrone.Api/ProviderModuleBase.cs
@@ -0,0 +1,134 @@
+using System.Collections.Generic;
+using System.Linq;
+using FluentValidation;
+using Nancy;
+using NzbDrone.Api.ClientSchema;
+using NzbDrone.Api.Extensions;
+using NzbDrone.Api.Indexers;
+using NzbDrone.Api.Mapping;
+using NzbDrone.Common.Reflection;
+using NzbDrone.Core.ThingiProvider;
+using Omu.ValueInjecter;
+
+namespace NzbDrone.Api
+{
+ public abstract class ProviderModuleBase : NzbDroneRestModule
+ where TProviderDefinition : ProviderDefinition, new()
+ where TProvider : IProvider
+ where TProviderResource : ProviderResource, new()
+ {
+ private readonly IProviderFactory _providerFactory;
+
+ protected ProviderModuleBase(IProviderFactory providerFactory, string resource)
+ : base(resource)
+ {
+ _providerFactory = providerFactory;
+ Get["templates"] = x => GetTemplates();
+ GetResourceAll = GetAll;
+ GetResourceById = GetProviderById;
+ CreateResource = CreateProvider;
+ UpdateResource = UpdateProvider;
+ DeleteResource = DeleteProvider;
+
+
+
+ SharedValidator.RuleFor(c => c.Name).NotEmpty();
+ SharedValidator.RuleFor(c => c.Implementation).NotEmpty();
+ SharedValidator.RuleFor(c => c.ConfigContract).NotEmpty();
+
+ PostValidator.RuleFor(c => c.Fields).NotEmpty();
+ }
+
+ private TProviderResource GetProviderById(int id)
+ {
+ return _providerFactory.Get(id).InjectTo();
+ }
+
+ private List GetAll()
+ {
+ var indexerDefinitions = _providerFactory.All();
+
+ var result = new List(indexerDefinitions.Count);
+
+ foreach (var definition in indexerDefinitions)
+ {
+ var indexerResource = new TProviderResource();
+ indexerResource.InjectFrom(definition);
+ indexerResource.Fields = SchemaBuilder.ToSchema(definition.Settings);
+
+ result.Add(indexerResource);
+ }
+
+ return result;
+ }
+
+ private int CreateProvider(TProviderResource indexerResource)
+ {
+ var indexer = GetDefinition(indexerResource);
+ indexer = _providerFactory.Create(indexer);
+ return indexer.Id;
+ }
+
+ private void UpdateProvider(TProviderResource indexerResource)
+ {
+ var indexer = GetDefinition(indexerResource);
+
+ ValidateIndexer(indexer);
+
+ _providerFactory.Update(indexer);
+ }
+
+
+ private static void ValidateIndexer(ProviderDefinition definition)
+ {
+ if (!definition.Enable) return;
+
+ var validationResult = definition.Settings.Validate();
+
+ if (!validationResult.IsValid)
+ {
+ throw new ValidationException(validationResult.Errors);
+ }
+ }
+
+ private TProviderDefinition GetDefinition(TProviderResource indexerResource)
+ {
+
+ var definition = new TProviderDefinition();
+
+ definition.InjectFrom(indexerResource);
+
+ var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);
+ definition.Settings = (IProviderConfig)SchemaBuilder.ReadFormSchema(indexerResource.Fields, configContract);
+
+ ValidateIndexer(definition);
+
+ return definition;
+ }
+
+ private void DeleteProvider(int id)
+ {
+ _providerFactory.Delete(id);
+ }
+
+ private Response GetTemplates()
+ {
+
+ var indexers = _providerFactory.Templates();
+
+
+ var result = new List(indexers.Count());
+
+ foreach (var indexer in indexers)
+ {
+ var indexerResource = new IndexerResource();
+ indexerResource.InjectFrom(indexer);
+ indexerResource.Fields = SchemaBuilder.ToSchema(indexer.Settings);
+
+ result.Add(indexerResource);
+ }
+
+ return result.AsResponse();
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.App.Test/ContainerFixture.cs b/NzbDrone.App.Test/ContainerFixture.cs
index 14a35688d..a165f9348 100644
--- a/NzbDrone.App.Test/ContainerFixture.cs
+++ b/NzbDrone.App.Test/ContainerFixture.cs
@@ -37,7 +37,7 @@ namespace NzbDrone.App.Test
{
var factory = MainAppContainerBuilder.BuildContainer(args).Resolve();
- factory.Build().Should().NotBeNull();
+ factory.Build().Should().NotBeNull();
}
[Test]
diff --git a/NzbDrone.Common/Reflection/ReflectionExtensions.cs b/NzbDrone.Common/Reflection/ReflectionExtensions.cs
index 98ff9ff12..898d45119 100644
--- a/NzbDrone.Common/Reflection/ReflectionExtensions.cs
+++ b/NzbDrone.Common/Reflection/ReflectionExtensions.cs
@@ -7,6 +7,8 @@ namespace NzbDrone.Common.Reflection
{
public static class ReflectionExtensions
{
+ public static readonly Assembly CoreAssembly = Assembly.Load("NzbDrone.Core");
+
public static List GetSimpleProperties(this Type type)
{
var properties = type.GetProperties();
@@ -58,6 +60,11 @@ namespace NzbDrone.Common.Reflection
return (T)attribute;
}
+ public static Type FindTypeByName(this Assembly assembly, string name)
+ {
+ return assembly.GetTypes().SingleOrDefault(c => c.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
+ }
+
public static bool HasAttribute(this Type type)
{
return type.GetCustomAttributes(typeof(TAttribute), true).Any();
diff --git a/NzbDrone.Core.Test/Datastore/Converters/ProviderSettingConverterFixture.cs b/NzbDrone.Core.Test/Datastore/Converters/ProviderSettingConverterFixture.cs
new file mode 100644
index 000000000..9aafbee73
--- /dev/null
+++ b/NzbDrone.Core.Test/Datastore/Converters/ProviderSettingConverterFixture.cs
@@ -0,0 +1,39 @@
+using System;
+using FluentAssertions;
+using Marr.Data.Converters;
+using NUnit.Framework;
+using NzbDrone.Core.Datastore.Converters;
+using NzbDrone.Core.Test.Framework;
+using NzbDrone.Core.ThingiProvider;
+
+namespace NzbDrone.Core.Test.Datastore.Converters
+{
+ [TestFixture]
+ public class ProviderSettingConverterFixture : CoreTest
+ {
+ [Test]
+ public void should_return_null_config_if_config_is_null()
+ {
+ var result = Subject.FromDB(new ConverterContext()
+ {
+ DbValue = DBNull.Value
+ });
+
+
+ result.Should().Be(NullConfig.Instance);
+ }
+
+ [TestCase(null)]
+ [TestCase("")]
+ public void should_return_null_config_if_config_is_empty(object dbValue)
+ {
+ var result = Subject.FromDB(new ConverterContext()
+ {
+ DbValue = dbValue
+ });
+
+
+ result.Should().Be(NullConfig.Instance);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/IndexerTests/IndexerServiceFixture.cs b/NzbDrone.Core.Test/IndexerTests/IndexerServiceFixture.cs
index 2de52fb5f..bbfb8404a 100644
--- a/NzbDrone.Core.Test/IndexerTests/IndexerServiceFixture.cs
+++ b/NzbDrone.Core.Test/IndexerTests/IndexerServiceFixture.cs
@@ -13,7 +13,7 @@ using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.IndexerTests
{
- public class IndexerServiceFixture : DbTest
+ public class IndexerServiceFixture : DbTest
{
private List _indexers;
@@ -57,10 +57,8 @@ namespace NzbDrone.Core.Test.IndexerTests
var indexers = Subject.All().ToList();
indexers.Should().NotBeEmpty();
indexers.Should().NotContain(c => c.Settings == null);
- indexers.Should().NotContain(c => c.Instance == null);
indexers.Should().NotContain(c => c.Name == null);
indexers.Select(c => c.Name).Should().OnlyHaveUniqueItems();
- indexers.Select(c => c.Instance).Should().OnlyHaveUniqueItems();
}
@@ -73,6 +71,7 @@ namespace NzbDrone.Core.Test.IndexerTests
var existingIndexers = Builder.CreateNew().BuildNew();
+ existingIndexers.ConfigContract = typeof (NewznabSettings).Name;
repo.Insert(existingIndexers);
diff --git a/NzbDrone.Core.Test/IndexerTests/IntegrationTests/IndexerIntegrationTests.cs b/NzbDrone.Core.Test/IndexerTests/IntegrationTests/IndexerIntegrationTests.cs
index 1be142824..28dc053e4 100644
--- a/NzbDrone.Core.Test/IndexerTests/IntegrationTests/IndexerIntegrationTests.cs
+++ b/NzbDrone.Core.Test/IndexerTests/IntegrationTests/IndexerIntegrationTests.cs
@@ -7,6 +7,7 @@ using NzbDrone.Core.Indexers.Wombles;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NUnit.Framework;
+using NzbDrone.Core.ThingiProvider;
using NzbDrone.Test.Common.Categories;
using System.Linq;
@@ -27,6 +28,12 @@ namespace NzbDrone.Core.Test.IndexerTests.IntegrationTests
{
var indexer = new Wombles();
+ indexer.Definition = new IndexerDefinition
+ {
+ Name = "Wombles",
+ Settings = NullConfig.Instance
+ };
+
var result = Subject.FetchRss(indexer);
ValidateResult(result, skipSize: true, skipInfo: true);
@@ -37,6 +44,11 @@ namespace NzbDrone.Core.Test.IndexerTests.IntegrationTests
public void extv_rss()
{
var indexer = new Eztv();
+ indexer.Definition = new IndexerDefinition
+ {
+ Name = "Eztv",
+ Settings = NullConfig.Instance
+ };
var result = Subject.FetchRss(indexer);
@@ -48,14 +60,14 @@ namespace NzbDrone.Core.Test.IndexerTests.IntegrationTests
public void nzbsorg_rss()
{
var indexer = new Newznab();
- indexer.Settings = new NewznabSettings
- {
- ApiKey = "64d61d3cfd4b75e51d01cbc7c6a78275",
- Url = "http://nzbs.org"
- };
-
- indexer.InstanceDefinition = new IndexerDefinition();
- indexer.InstanceDefinition.Name = "nzbs.org";
+
+ indexer.Definition = new IndexerDefinition();
+ indexer.Definition.Name = "nzbs.org";
+ indexer.Definition.Settings = new NewznabSettings
+ {
+ ApiKey = "64d61d3cfd4b75e51d01cbc7c6a78275",
+ Url = "http://nzbs.org"
+ };
var result = Subject.FetchRss(indexer);
diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 58b09e81e..8a79c19af 100644
--- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -102,6 +102,7 @@
+
@@ -181,6 +182,8 @@
+
+
diff --git a/NzbDrone.Core.Test/ThingiProvider/ProviderBaseFixture.cs b/NzbDrone.Core.Test/ThingiProvider/ProviderBaseFixture.cs
new file mode 100644
index 000000000..641e62dca
--- /dev/null
+++ b/NzbDrone.Core.Test/ThingiProvider/ProviderBaseFixture.cs
@@ -0,0 +1,31 @@
+using FizzWare.NBuilder;
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Core.Indexers;
+using NzbDrone.Core.Indexers.Newznab;
+using NzbDrone.Core.Test.Framework;
+using NzbDrone.Core.ThingiProvider;
+
+namespace NzbDrone.Core.Test.ThingiProvider
+{
+
+ public class ProviderRepositoryFixture : DbTest
+ {
+ [Test]
+ public void should_read_write_download_provider()
+ {
+ var model = Builder.CreateNew().BuildNew();
+ var newznabSettings = Builder.CreateNew().Build();
+ model.Settings = newznabSettings;
+ Subject.Insert(model);
+
+ var storedProvider = Subject.Single();
+
+ storedProvider.Settings.Should().BeOfType();
+
+ var storedSetting = (NewznabSettings)storedProvider.Settings;
+
+ storedSetting.ShouldHave().AllProperties().EqualTo(newznabSettings);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/ThingiProviderTests/NullConfigFixture.cs b/NzbDrone.Core.Test/ThingiProviderTests/NullConfigFixture.cs
new file mode 100644
index 000000000..0f47d9a91
--- /dev/null
+++ b/NzbDrone.Core.Test/ThingiProviderTests/NullConfigFixture.cs
@@ -0,0 +1,17 @@
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Core.Test.Framework;
+using NzbDrone.Core.ThingiProvider;
+
+namespace NzbDrone.Core.Test.ThingiProviderTests
+{
+ [TestFixture]
+ public class NullConfigFixture : CoreTest
+ {
+ [Test]
+ public void should_be_valid()
+ {
+ Subject.Validate().IsValid.Should().BeTrue();
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Datastore/Converters/BooleanIntConverter.cs b/NzbDrone.Core/Datastore/Converters/BooleanIntConverter.cs
index 88d06c669..7ec60e201 100644
--- a/NzbDrone.Core/Datastore/Converters/BooleanIntConverter.cs
+++ b/NzbDrone.Core/Datastore/Converters/BooleanIntConverter.cs
@@ -6,14 +6,14 @@ namespace NzbDrone.Core.Datastore.Converters
{
public class BooleanIntConverter : IConverter
{
- public object FromDB(ColumnMap map, object dbValue)
+ public object FromDB(ConverterContext context)
{
- if (dbValue == DBNull.Value)
+ if (context.DbValue == DBNull.Value)
{
return DBNull.Value;
}
- var val = (Int64)dbValue;
+ var val = (Int64)context.DbValue;
switch (val)
{
@@ -22,10 +22,15 @@ namespace NzbDrone.Core.Datastore.Converters
case 0:
return false;
default:
- throw new ConversionException(string.Format("The BooleanCharConverter could not convert the value '{0}' to a Boolean.", dbValue));
+ throw new ConversionException(string.Format("The BooleanCharConverter could not convert the value '{0}' to a Boolean.", context.DbValue));
}
}
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
+ }
+
public object ToDB(object clrValue)
{
var val = (Nullable)clrValue;
diff --git a/NzbDrone.Core/Datastore/Converters/EmbeddedDocumentConverter.cs b/NzbDrone.Core/Datastore/Converters/EmbeddedDocumentConverter.cs
index b222eb320..e144d4cf4 100644
--- a/NzbDrone.Core/Datastore/Converters/EmbeddedDocumentConverter.cs
+++ b/NzbDrone.Core/Datastore/Converters/EmbeddedDocumentConverter.cs
@@ -7,22 +7,26 @@ namespace NzbDrone.Core.Datastore.Converters
{
public class EmbeddedDocumentConverter : IConverter
{
-
- public object FromDB(ColumnMap map, object dbValue)
+ public virtual object FromDB(ConverterContext context)
{
- if (dbValue == DBNull.Value)
+ if (context.DbValue == DBNull.Value)
{
return DBNull.Value;
}
- var stringValue = (string)dbValue;
+ var stringValue = (string)context.DbValue;
if (string.IsNullOrWhiteSpace(stringValue))
{
return null;
}
- return Json.Deserialize(stringValue, map.FieldType);
+ return Json.Deserialize(stringValue, context.ColumnMap.FieldType);
+ }
+
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
}
public object ToDB(object clrValue)
diff --git a/NzbDrone.Core/Datastore/Converters/EnumIntConverter.cs b/NzbDrone.Core/Datastore/Converters/EnumIntConverter.cs
index f79c736c2..40c2727bc 100644
--- a/NzbDrone.Core/Datastore/Converters/EnumIntConverter.cs
+++ b/NzbDrone.Core/Datastore/Converters/EnumIntConverter.cs
@@ -14,16 +14,21 @@ namespace NzbDrone.Core.Datastore.Converters
}
}
- public object FromDB(ColumnMap map, object dbValue)
+ public object FromDB(ConverterContext context)
{
- if (dbValue != null && dbValue != DBNull.Value)
+ if (context.DbValue != null && context.DbValue != DBNull.Value)
{
- return Enum.ToObject(map.FieldType, (Int64)dbValue);
+ return Enum.ToObject(context.ColumnMap.FieldType, (Int64)context.DbValue);
}
return null;
}
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
+ }
+
public object ToDB(object clrValue)
{
if (clrValue != null)
diff --git a/NzbDrone.Core/Datastore/Converters/Int32Converter.cs b/NzbDrone.Core/Datastore/Converters/Int32Converter.cs
index fcf66a045..c69bfb9a5 100644
--- a/NzbDrone.Core/Datastore/Converters/Int32Converter.cs
+++ b/NzbDrone.Core/Datastore/Converters/Int32Converter.cs
@@ -6,6 +6,21 @@ namespace NzbDrone.Core.Datastore.Converters
{
public class Int32Converter : IConverter
{
+ public object FromDB(ConverterContext context)
+ {
+ if (context.DbValue == DBNull.Value)
+ {
+ return DBNull.Value;
+ }
+
+ if (context.DbValue is Int32)
+ {
+ return context.DbValue;
+ }
+
+ return Convert.ToInt32(context.DbValue);
+ }
+
public object FromDB(ColumnMap map, object dbValue)
{
if (dbValue == DBNull.Value)
diff --git a/NzbDrone.Core/Datastore/Converters/ProviderSettingConverter.cs b/NzbDrone.Core/Datastore/Converters/ProviderSettingConverter.cs
new file mode 100644
index 000000000..ace64d6af
--- /dev/null
+++ b/NzbDrone.Core/Datastore/Converters/ProviderSettingConverter.cs
@@ -0,0 +1,40 @@
+using System;
+using Marr.Data.Converters;
+using NzbDrone.Common.Reflection;
+using NzbDrone.Common.Serializer;
+using NzbDrone.Core.ThingiProvider;
+
+namespace NzbDrone.Core.Datastore.Converters
+{
+ public class ProviderSettingConverter : EmbeddedDocumentConverter
+ {
+ public override object FromDB(ConverterContext context)
+ {
+ if (context.DbValue == DBNull.Value)
+ {
+ return NullConfig.Instance;
+ }
+
+ var stringValue = (string)context.DbValue;
+
+ if (string.IsNullOrWhiteSpace(stringValue))
+ {
+ return NullConfig.Instance;
+ }
+
+ var ordinal = context.DataRecord.GetOrdinal("ConfigContract");
+ var contract = context.DataRecord.GetString(ordinal);
+
+
+ var impType = typeof (IProviderConfig).Assembly.FindTypeByName(contract);
+
+ if (impType == null)
+ {
+ throw new ConfigContractNotFoundException(contract);
+ }
+
+ return Json.Deserialize(stringValue, impType);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Datastore/Converters/QualityIntConverter.cs b/NzbDrone.Core/Datastore/Converters/QualityIntConverter.cs
index 839ef85be..6dc9d6c24 100644
--- a/NzbDrone.Core/Datastore/Converters/QualityIntConverter.cs
+++ b/NzbDrone.Core/Datastore/Converters/QualityIntConverter.cs
@@ -7,18 +7,23 @@ namespace NzbDrone.Core.Datastore.Converters
{
public class QualityIntConverter : IConverter
{
- public object FromDB(ColumnMap map, object dbValue)
+ public object FromDB(ConverterContext context)
{
- if (dbValue == DBNull.Value)
+ if (context.DbValue == DBNull.Value)
{
return Quality.Unknown;
}
- var val = Convert.ToInt32(dbValue);
+ var val = Convert.ToInt32(context.DbValue);
return (Quality)val;
}
+ public object FromDB(ColumnMap map, object dbValue)
+ {
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
+ }
+
public object ToDB(object clrValue)
{
if(clrValue == null) return 0;
diff --git a/NzbDrone.Core/Datastore/Converters/UtcConverter.cs b/NzbDrone.Core/Datastore/Converters/UtcConverter.cs
index 0bdc802dc..25d313a6c 100644
--- a/NzbDrone.Core/Datastore/Converters/UtcConverter.cs
+++ b/NzbDrone.Core/Datastore/Converters/UtcConverter.cs
@@ -6,9 +6,14 @@ namespace NzbDrone.Core.Datastore.Converters
{
public class UtcConverter : IConverter
{
+ public object FromDB(ConverterContext context)
+ {
+ return context.DbValue;
+ }
+
public object FromDB(ColumnMap map, object dbValue)
{
- return dbValue;
+ return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
}
public object ToDB(object clrValue)
diff --git a/NzbDrone.Core/Datastore/Migration/022_move_notification_to_generic_provider.cs b/NzbDrone.Core/Datastore/Migration/022_move_notification_to_generic_provider.cs
new file mode 100644
index 000000000..2b5182419
--- /dev/null
+++ b/NzbDrone.Core/Datastore/Migration/022_move_notification_to_generic_provider.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using FluentMigrator;
+using NzbDrone.Common.Serializer;
+using NzbDrone.Core.Datastore.Migration.Framework;
+
+namespace NzbDrone.Core.Datastore.Migration
+{
+ [Migration(22)]
+ public class move_indexer_to_generic_provider : NzbDroneMigrationBase
+ {
+ protected override void MainDbUpgrade()
+ {
+ Alter.Table("Indexers").AddColumn("ConfigContract").AsString().Nullable();
+
+ //Execute.WithConnection(ConvertSeasons);
+ }
+
+ private void ConvertSeasons(IDbConnection conn, IDbTransaction tran)
+ {
+ using (IDbCommand allSeriesCmd = conn.CreateCommand())
+ {
+ allSeriesCmd.Transaction = tran;
+ allSeriesCmd.CommandText = @"SELECT Id FROM Series";
+ using (IDataReader allSeriesReader = allSeriesCmd.ExecuteReader())
+ {
+ while (allSeriesReader.Read())
+ {
+ int seriesId = allSeriesReader.GetInt32(0);
+ var seasons = new List();
+
+ using (IDbCommand seasonsCmd = conn.CreateCommand())
+ {
+ seasonsCmd.Transaction = tran;
+ seasonsCmd.CommandText = String.Format(@"SELECT SeasonNumber, Monitored FROM Seasons WHERE SeriesId = {0}", seriesId);
+
+ using (IDataReader seasonReader = seasonsCmd.ExecuteReader())
+ {
+ while (seasonReader.Read())
+ {
+ int seasonNumber = seasonReader.GetInt32(0);
+ bool monitored = seasonReader.GetBoolean(1);
+
+ if (seasonNumber == 0)
+ {
+ monitored = false;
+ }
+
+ seasons.Add(new { seasonNumber, monitored });
+ }
+ }
+ }
+
+ using (IDbCommand updateCmd = conn.CreateCommand())
+ {
+ var text = String.Format("UPDATE Series SET Seasons = '{0}' WHERE Id = {1}", seasons.ToJson(), seriesId);
+
+ updateCmd.Transaction = tran;
+ updateCmd.CommandText = text;
+ updateCmd.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/NzbDrone.Core/Datastore/Migration/023_add_config_contract_to_indexers.cs b/NzbDrone.Core/Datastore/Migration/023_add_config_contract_to_indexers.cs
new file mode 100644
index 000000000..cf2153605
--- /dev/null
+++ b/NzbDrone.Core/Datastore/Migration/023_add_config_contract_to_indexers.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using FluentMigrator;
+using NzbDrone.Common.Serializer;
+using NzbDrone.Core.Datastore.Migration.Framework;
+
+namespace NzbDrone.Core.Datastore.Migration
+{
+ [Migration(23)]
+ public class add_config_contract_to_indexers : NzbDroneMigrationBase
+ {
+ protected override void MainDbUpgrade()
+ {
+ Update.Table("Indexers").Set(new { ConfigContract = "NewznabSettings" }).Where(new { Implementation = "Newznab" });
+ Update.Table("Indexers").Set(new { ConfigContract = "OmgwtfnzbsSettings" }).Where(new { Implementation = "Omgwtfnzbs" });
+ Update.Table("Indexers").Set(new { ConfigContract = "NullConfig" }).Where(new { Implementation = "Wombles" });
+ Update.Table("Indexers").Set(new { ConfigContract = "NullConfig" }).Where(new { Implementation = "Eztv" });
+
+ Delete.FromTable("Indexers").IsNull("ConfigContract");
+ }
+ }
+}
diff --git a/NzbDrone.Core/Datastore/TableMapping.cs b/NzbDrone.Core/Datastore/TableMapping.cs
index 533b3ab70..bade3c2d6 100644
--- a/NzbDrone.Core/Datastore/TableMapping.cs
+++ b/NzbDrone.Core/Datastore/TableMapping.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Marr.Data;
using Marr.Data.Mapping;
+using NzbDrone.Common.Reflection;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.Datastore.Converters;
@@ -15,6 +16,7 @@ using NzbDrone.Core.Organizer;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.SeriesStats;
+using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Datastore
@@ -69,6 +71,7 @@ namespace NzbDrone.Core.Datastore
private static void RegisterMappers()
{
RegisterEmbeddedConverter();
+ RegisterProviderSettingConverter();
MapRepository.Instance.RegisterTypeConverter(typeof(Int32), new Int32Converter());
MapRepository.Instance.RegisterTypeConverter(typeof(DateTime), new UtcConverter());
@@ -78,10 +81,20 @@ namespace NzbDrone.Core.Datastore
MapRepository.Instance.RegisterTypeConverter(typeof(Dictionary), new EmbeddedDocumentConverter());
}
+ private static void RegisterProviderSettingConverter()
+ {
+ var settingTypes = typeof(IProviderConfig).Assembly.ImplementationsOf();
+
+ var providerSettingConverter = new ProviderSettingConverter();
+ foreach (var embeddedType in settingTypes)
+ {
+ MapRepository.Instance.RegisterTypeConverter(embeddedType, providerSettingConverter);
+ }
+ }
+
private static void RegisterEmbeddedConverter()
{
- var embeddedTypes = typeof(IEmbeddedDocument).Assembly.GetTypes()
- .Where(c => c.GetInterfaces().Any(i => i == typeof(IEmbeddedDocument)));
+ var embeddedTypes = typeof(IEmbeddedDocument).Assembly.ImplementationsOf();
var embeddedConvertor = new EmbeddedDocumentConverter();
diff --git a/NzbDrone.Core/IndexerSearch/NzbSearchService.cs b/NzbDrone.Core/IndexerSearch/NzbSearchService.cs
index 5770687b8..96b52e8cf 100644
--- a/NzbDrone.Core/IndexerSearch/NzbSearchService.cs
+++ b/NzbDrone.Core/IndexerSearch/NzbSearchService.cs
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.IndexerSearch
public class NzbSearchService : ISearchForNzb
{
- private readonly IIndexerService _indexerService;
+ private readonly IIndexerFactory _indexerFactory;
private readonly IFetchFeedFromIndexers _feedFetcher;
private readonly ISceneMappingService _sceneMapping;
private readonly ISeriesService _seriesService;
@@ -32,7 +32,7 @@ namespace NzbDrone.Core.IndexerSearch
private readonly IMakeDownloadDecision _makeDownloadDecision;
private readonly Logger _logger;
- public NzbSearchService(IIndexerService indexerService,
+ public NzbSearchService(IIndexerFactory indexerFactory,
IFetchFeedFromIndexers feedFetcher,
ISceneMappingService sceneMapping,
ISeriesService seriesService,
@@ -40,7 +40,7 @@ namespace NzbDrone.Core.IndexerSearch
IMakeDownloadDecision makeDownloadDecision,
Logger logger)
{
- _indexerService = indexerService;
+ _indexerFactory = indexerFactory;
_feedFetcher = feedFetcher;
_sceneMapping = sceneMapping;
_seriesService = seriesService;
@@ -132,7 +132,7 @@ namespace NzbDrone.Core.IndexerSearch
private List Dispatch(Func> searchAction, SearchCriteriaBase criteriaBase)
{
- var indexers = _indexerService.GetAvailableIndexers().ToList();
+ var indexers = _indexerFactory.GetAvailableProviders().ToList();
var reports = new List();
_logger.ProgressInfo("Searching {0} indexers for {1}", indexers.Count, criteriaBase);
diff --git a/NzbDrone.Core/Indexers/Eztv/Eztv.cs b/NzbDrone.Core/Indexers/Eztv/Eztv.cs
index 541f3a078..52c55df60 100644
--- a/NzbDrone.Core/Indexers/Eztv/Eztv.cs
+++ b/NzbDrone.Core/Indexers/Eztv/Eztv.cs
@@ -1,28 +1,19 @@
using System;
using System.Collections.Generic;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers.Eztv
{
- public class Eztv : IndexerBase
+ public class Eztv : IndexerBase
{
- public override string Name
- {
- get { return "Eztv"; }
- }
-
- public override IndexerKind Kind
+ public override DownloadProtocol Protocol
{
get
{
- return IndexerKind.Torrent;
+ return DownloadProtocol.Torrent;
}
}
- public override bool EnableByDefault
- {
- get { return false; }
- }
-
public override IParseFeed Parser
{
get
@@ -35,10 +26,7 @@ namespace NzbDrone.Core.Indexers.Eztv
{
get
{
- return new[]
- {
- "http://www.ezrss.it/feed/"
- };
+ yield return "http://www.ezrss.it/feed/";
}
}
@@ -55,7 +43,7 @@ namespace NzbDrone.Core.Indexers.Eztv
public override IEnumerable GetDailyEpisodeSearchUrls(string seriesTitle, int tvRageId, DateTime date)
{
- //EZTV doesn't support searching based on actual epidose airdate. they only support release date.
+ //EZTV doesn't support searching based on actual episode airdate. they only support release date.
return new string[0];
}
}
diff --git a/NzbDrone.Core/Indexers/FetchAndParseRssService.cs b/NzbDrone.Core/Indexers/FetchAndParseRssService.cs
index c9633c8d0..534668b6b 100644
--- a/NzbDrone.Core/Indexers/FetchAndParseRssService.cs
+++ b/NzbDrone.Core/Indexers/FetchAndParseRssService.cs
@@ -14,13 +14,13 @@ namespace NzbDrone.Core.Indexers
public class FetchAndParseRssService : IFetchAndParseRss
{
- private readonly IIndexerService _indexerService;
+ private readonly IIndexerFactory _indexerFactory;
private readonly IFetchFeedFromIndexers _feedFetcher;
private readonly Logger _logger;
- public FetchAndParseRssService(IIndexerService indexerService, IFetchFeedFromIndexers feedFetcher, Logger logger)
+ public FetchAndParseRssService(IIndexerFactory indexerFactory, IFetchFeedFromIndexers feedFetcher, Logger logger)
{
- _indexerService = indexerService;
+ _indexerFactory = indexerFactory;
_feedFetcher = feedFetcher;
_logger = logger;
}
@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Indexers
{
var result = new List();
- var indexers = _indexerService.GetAvailableIndexers().ToList();
+ var indexers = _indexerFactory.GetAvailableProviders().ToList();
if (!indexers.Any())
{
diff --git a/NzbDrone.Core/Indexers/IIndexer.cs b/NzbDrone.Core/Indexers/IIndexer.cs
index a681ae3df..34daa6a26 100644
--- a/NzbDrone.Core/Indexers/IIndexer.cs
+++ b/NzbDrone.Core/Indexers/IIndexer.cs
@@ -1,23 +1,15 @@
using System;
using System.Collections.Generic;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers
{
- public interface IIndexer
+ public interface IIndexer : IProvider
{
- string Name { get; }
-
- bool EnableByDefault { get; }
-
- IEnumerable DefaultDefinitions { get; }
-
- IndexerDefinition InstanceDefinition { get; set; }
-
- IEnumerable RecentFeed { get; }
-
IParseFeed Parser { get; }
- IndexerKind Kind { get; }
+ DownloadProtocol Protocol { get; }
+ IEnumerable RecentFeed { get; }
IEnumerable GetEpisodeSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int episodeNumber);
IEnumerable GetDailyEpisodeSearchUrls(string seriesTitle, int tvRageId, DateTime date);
IEnumerable GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset);
diff --git a/NzbDrone.Core/Indexers/IndexerBase.cs b/NzbDrone.Core/Indexers/IndexerBase.cs
index 6f544a2be..41942d35b 100644
--- a/NzbDrone.Core/Indexers/IndexerBase.cs
+++ b/NzbDrone.Core/Indexers/IndexerBase.cs
@@ -1,41 +1,62 @@
using System;
using System.Collections.Generic;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers
{
- public abstract class IndexerBase : IIndexer
+ public abstract class IndexerBase : IIndexer where TSettings : IProviderConfig, new()
{
- public abstract string Name { get; }
-
- public abstract IndexerKind Kind { get; }
-
- public virtual bool EnableByDefault { get { return true; } }
-
- public IndexerDefinition InstanceDefinition { get; set; }
+ public Type ConfigContract
+ {
+ get
+ {
+ return typeof(TSettings);
+ }
+ }
- public virtual IEnumerable DefaultDefinitions
+ public virtual IEnumerable DefaultDefinitions
{
get
{
+ var config = (IProviderConfig)new TSettings();
+
yield return new IndexerDefinition
{
- Name = Name,
- Enable = EnableByDefault,
+ Name = GetType().Name,
+ Enable = config.Validate().IsValid,
Implementation = GetType().Name,
- Settings = String.Empty
+ Settings = config
};
}
}
+ public ProviderDefinition Definition { get; set; }
+
+ public abstract DownloadProtocol Protocol { get; }
+
+ protected TSettings Settings
+ {
+ get
+ {
+ return (TSettings)Definition.Settings;
+ }
+ }
+
public virtual IParseFeed Parser { get; private set; }
public abstract IEnumerable RecentFeed { get; }
public abstract IEnumerable GetEpisodeSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int episodeNumber);
public abstract IEnumerable GetDailyEpisodeSearchUrls(string seriesTitle, int tvRageId, DateTime date);
public abstract IEnumerable GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset);
+
+
+ public override string ToString()
+ {
+ return GetType().Name;
+ }
}
- public enum IndexerKind
+ public enum DownloadProtocol
{
Usenet,
Torrent
diff --git a/NzbDrone.Core/Indexers/IndexerDefinition.cs b/NzbDrone.Core/Indexers/IndexerDefinition.cs
index a061052e7..5909532b4 100644
--- a/NzbDrone.Core/Indexers/IndexerDefinition.cs
+++ b/NzbDrone.Core/Indexers/IndexerDefinition.cs
@@ -1,13 +1,8 @@
-using System;
-using NzbDrone.Core.Datastore;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers
{
- public class IndexerDefinition : ModelBase
+ public class IndexerDefinition : ProviderDefinition
{
- public Boolean Enable { get; set; }
- public String Name { get; set; }
- public String Settings { get; set; }
- public String Implementation { get; set; }
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/Indexers/IndexerFactory.cs b/NzbDrone.Core/Indexers/IndexerFactory.cs
new file mode 100644
index 000000000..b89f0d539
--- /dev/null
+++ b/NzbDrone.Core/Indexers/IndexerFactory.cs
@@ -0,0 +1,41 @@
+using System.Collections.Generic;
+using System.Linq;
+using NLog;
+using NzbDrone.Core.ThingiProvider;
+
+namespace NzbDrone.Core.Indexers
+{
+ public interface IIndexerFactory : IProviderFactory
+ {
+
+ }
+
+ public class IndexerFactory : ProviderFactory, IIndexerFactory
+ {
+ private readonly IIndexerRepository _providerRepository;
+ private readonly IEnumerable _providers;
+
+ public IndexerFactory(IIndexerRepository providerRepository, IEnumerable providers, Logger logger)
+ : base(providerRepository, providers, logger)
+ {
+ _providerRepository = providerRepository;
+ _providers = providers;
+ }
+
+ protected override void InitializeProviders()
+ {
+ var definitions = _providers.Where(c => c.Protocol == DownloadProtocol.Usenet)
+ .SelectMany(indexer => indexer.DefaultDefinitions);
+
+ var currentProviders = All();
+
+ var newProviders = definitions.Where(def => currentProviders.All(c => c.Implementation != def.Implementation)).ToList();
+
+
+ if (newProviders.Any())
+ {
+ _providerRepository.InsertMany(newProviders.Cast().ToList());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Indexers/IndexerFetchService.cs b/NzbDrone.Core/Indexers/IndexerFetchService.cs
index ba284c8b7..b571f6466 100644
--- a/NzbDrone.Core/Indexers/IndexerFetchService.cs
+++ b/NzbDrone.Core/Indexers/IndexerFetchService.cs
@@ -33,11 +33,11 @@ namespace NzbDrone.Core.Indexers
public virtual IList FetchRss(IIndexer indexer)
{
- _logger.Debug("Fetching feeds from " + indexer.Name);
+ _logger.Debug("Fetching feeds from " + indexer);
var result = Fetch(indexer, indexer.RecentFeed);
- _logger.Debug("Finished processing feeds from " + indexer.Name);
+ _logger.Debug("Finished processing feeds from " + indexer);
return result;
}
@@ -48,7 +48,7 @@ namespace NzbDrone.Core.Indexers
var result = Fetch(indexer, searchCriteria, 0).DistinctBy(c => c.DownloadUrl).ToList();
- _logger.Info("Finished searching {0} for {1}. Found {2}", indexer.Name, searchCriteria, result.Count);
+ _logger.Info("Finished searching {0} for {1}. Found {2}", indexer, searchCriteria, result.Count);
return result;
}
@@ -61,7 +61,7 @@ namespace NzbDrone.Core.Indexers
var result = Fetch(indexer, searchUrls);
- _logger.Info("{0} offset {1}. Found {2}", indexer.Name, searchCriteria, result.Count);
+ _logger.Info("{0} offset {1}. Found {2}", indexer, searchCriteria, result.Count);
if (result.Count > 90)
{
@@ -79,7 +79,7 @@ namespace NzbDrone.Core.Indexers
var result = Fetch(indexer, searchUrls);
- _logger.Info("Finished searching {0} for {1}. Found {2}", indexer.Name, searchCriteria, result.Count);
+ _logger.Info("Finished searching {0} for {1}. Found {2}", indexer, searchCriteria, result.Count);
return result;
}
@@ -90,7 +90,7 @@ namespace NzbDrone.Core.Indexers
var searchUrls = indexer.GetDailyEpisodeSearchUrls(searchCriteria.QueryTitle, searchCriteria.Series.TvRageId, searchCriteria.Airtime);
var result = Fetch(indexer, searchUrls);
- _logger.Info("Finished searching {0} for {1}. Found {2}", indexer.Name, searchCriteria, result.Count);
+ _logger.Info("Finished searching {0} for {1}. Found {2}", indexer, searchCriteria, result.Count);
return result;
}
@@ -119,17 +119,16 @@ namespace NzbDrone.Core.Indexers
if (webException.Message.Contains("502") || webException.Message.Contains("503") ||
webException.Message.Contains("timed out"))
{
- _logger.Warn("{0} server is currently unavailable. {1} {2}", indexer.Name, url,
- webException.Message);
+ _logger.Warn("{0} server is currently unavailable. {1} {2}", indexer, url, webException.Message);
}
else
{
- _logger.Warn("{0} {1} {2}", indexer.Name, url, webException.Message);
+ _logger.Warn("{0} {1} {2}", indexer, url, webException.Message);
}
}
catch (ApiKeyException)
{
- _logger.Warn("Invalid API Key for {0} {1}", indexer.Name, url);
+ _logger.Warn("Invalid API Key for {0} {1}", indexer, url);
}
catch (Exception feedEx)
{
@@ -138,7 +137,7 @@ namespace NzbDrone.Core.Indexers
}
}
- result.ForEach(c => c.Indexer = indexer.Name);
+ result.ForEach(c => c.Indexer = indexer.Definition.Name);
return result;
}
diff --git a/NzbDrone.Core/Indexers/IndexerRepository.cs b/NzbDrone.Core/Indexers/IndexerRepository.cs
index b4c6446a1..269bb5507 100644
--- a/NzbDrone.Core/Indexers/IndexerRepository.cs
+++ b/NzbDrone.Core/Indexers/IndexerRepository.cs
@@ -1,33 +1,20 @@
-using System;
-using System.Linq;
-using NzbDrone.Core.Datastore;
+using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers
{
- public interface IIndexerRepository : IBasicRepository
+ public interface IIndexerRepository : IProviderRepository
{
- IndexerDefinition Get(string name);
- IndexerDefinition Find(string name);
+
}
- public class IndexerRepository : BasicRepository, IIndexerRepository
+ public class IndexerRepository : ProviderRepository, IIndexerRepository
{
public IndexerRepository(IDatabase database, IEventAggregator eventAggregator)
: base(database, eventAggregator)
{
}
-
- public IndexerDefinition Get(string name)
- {
- return Query.Single(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
- }
-
- public IndexerDefinition Find(string name)
- {
- return Query.SingleOrDefault(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
- }
-
}
}
diff --git a/NzbDrone.Core/Indexers/IndexerService.cs b/NzbDrone.Core/Indexers/IndexerService.cs
deleted file mode 100644
index e1b49c2dd..000000000
--- a/NzbDrone.Core/Indexers/IndexerService.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using NLog;
-using NzbDrone.Common.Serializer;
-using NzbDrone.Core.Configuration;
-using NzbDrone.Core.Indexers.Newznab;
-using NzbDrone.Core.Lifecycle;
-using NzbDrone.Core.Messaging.Events;
-using Omu.ValueInjecter;
-
-namespace NzbDrone.Core.Indexers
-{
- public class Indexer
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public bool Enable { get; set; }
- public IIndexerSetting Settings { get; set; }
- public IIndexer Instance { get; set; }
- public string Implementation { get; set; }
- }
-
- public interface IIndexerService
- {
- List All();
- List GetAvailableIndexers();
- Indexer Get(int id);
- Indexer Get(string name);
- List Schema();
- Indexer Create(Indexer indexer);
- Indexer Update(Indexer indexer);
- void Delete(int id);
- }
-
- public class IndexerService : IIndexerService, IHandle
- {
- private readonly IIndexerRepository _indexerRepository;
- private readonly IConfigFileProvider _configFileProvider;
- private readonly INewznabTestService _newznabTestService;
- private readonly Logger _logger;
-
- private readonly List _indexers;
-
- public IndexerService(IIndexerRepository indexerRepository,
- IEnumerable indexers,
- IConfigFileProvider configFileProvider,
- INewznabTestService newznabTestService,
- Logger logger)
- {
- _indexerRepository = indexerRepository;
- _configFileProvider = configFileProvider;
- _newznabTestService = newznabTestService;
- _logger = logger;
-
-
- if (!configFileProvider.Torrent)
- {
- _indexers = indexers.Where(c => c.Kind != IndexerKind.Torrent).ToList();
- }
- else
- {
- _indexers = indexers.ToList();
- }
- }
-
- public List All()
- {
- return _indexerRepository.All().Select(ToIndexer).ToList();
- }
-
- public List GetAvailableIndexers()
- {
- return All().Where(c => c.Enable && c.Settings.Validate().IsValid).Select(c => c.Instance).ToList();
- }
-
- public Indexer Get(int id)
- {
- return ToIndexer(_indexerRepository.Get(id));
- }
-
- public Indexer Get(string name)
- {
- return ToIndexer(_indexerRepository.Get(name));
- }
-
- public List Schema()
- {
- var indexers = new List();
-
- var newznab = new Indexer();
- newznab.Instance = new Newznab.Newznab();
- newznab.Id = 1;
- newznab.Name = "Newznab";
- newznab.Settings = new NewznabSettings();
- newznab.Implementation = "Newznab";
-
- indexers.Add(newznab);
-
- return indexers;
- }
-
- public Indexer Create(Indexer indexer)
- {
- var definition = new IndexerDefinition
- {
- Name = indexer.Name,
- Enable = indexer.Enable,
- Implementation = indexer.Implementation,
- Settings = indexer.Settings.ToJson()
- };
-
- var instance = ToIndexer(definition).Instance;
- _newznabTestService.Test(instance);
-
- definition = _indexerRepository.Insert(definition);
- indexer.Id = definition.Id;
-
- return indexer;
- }
-
- public Indexer Update(Indexer indexer)
- {
- var definition = _indexerRepository.Get(indexer.Id);
- definition.InjectFrom(indexer);
- definition.Settings = indexer.Settings.ToJson();
- _indexerRepository.Update(definition);
-
- return indexer;
- }
-
- public void Delete(int id)
- {
- _indexerRepository.Delete(id);
- }
-
- private Indexer ToIndexer(IndexerDefinition definition)
- {
- var indexer = new Indexer();
- indexer.Id = definition.Id;
- indexer.Enable = definition.Enable;
- indexer.Instance = GetInstance(definition);
- indexer.Name = definition.Name;
- indexer.Implementation = definition.Implementation;
-
- if (indexer.Instance.GetType().GetMethod("ImportSettingsFromJson") != null)
- {
- indexer.Settings = ((dynamic)indexer.Instance).ImportSettingsFromJson(definition.Settings);
- }
- else
- {
- indexer.Settings = NullSetting.Instance;
- }
-
- return indexer;
- }
-
- private IIndexer GetInstance(IndexerDefinition indexerDefinition)
- {
- var type = GetImplementation(indexerDefinition);
- var instance = (IIndexer)Activator.CreateInstance(type);
- instance.InstanceDefinition = indexerDefinition;
- return instance;
- }
-
- private Type GetImplementation(IndexerDefinition indexerDefinition)
- {
- return _indexers.Select(c => c.GetType()).SingleOrDefault(c => c.Name.Equals(indexerDefinition.Implementation, StringComparison.InvariantCultureIgnoreCase));
- }
-
- public void Handle(ApplicationStartedEvent message)
- {
- _logger.Debug("Initializing indexers. Count {0}", _indexers.Count);
-
- RemoveMissingImplementations();
-
- var definitions = _indexers.SelectMany(indexer => indexer.DefaultDefinitions);
-
- var currentIndexer = All();
-
- var newIndexers = definitions.Where(def => currentIndexer.All(c => c.Implementation != def.Implementation)).ToList();
-
-
- if (newIndexers.Any())
- {
- _indexerRepository.InsertMany(newIndexers);
- }
- }
-
- private void RemoveMissingImplementations()
- {
- var storedIndexers = _indexerRepository.All();
-
- foreach (var indexerDefinition in storedIndexers.Where(i => GetImplementation(i) == null))
- {
- _logger.Debug("Removing Indexer {0} ", indexerDefinition.Name);
- _indexerRepository.Delete(indexerDefinition);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/NzbDrone.Core/Indexers/IndexerSettingProvider.cs b/NzbDrone.Core/Indexers/IndexerSettingProvider.cs
deleted file mode 100644
index ab7da9e58..000000000
--- a/NzbDrone.Core/Indexers/IndexerSettingProvider.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using NzbDrone.Common.Serializer;
-
-namespace NzbDrone.Core.Indexers
-{
- public interface IProviderIndexerSetting
- {
- TSetting Get(IIndexer indexer) where TSetting : IIndexerSetting, new();
- }
-
- public class IndexerSettingProvider : IProviderIndexerSetting
- {
- private readonly IIndexerRepository _indexerRepository;
-
- public IndexerSettingProvider(IIndexerRepository indexerRepository)
- {
- _indexerRepository = indexerRepository;
- }
-
- public TSetting Get(IIndexer indexer) where TSetting : IIndexerSetting, new()
- {
- var indexerDef = _indexerRepository.Find(indexer.Name);
-
- if (indexerDef == null || string.IsNullOrWhiteSpace(indexerDef.Settings))
- {
- return new TSetting();
- }
-
- return Json.Deserialize(indexerDef.Settings);
- }
- }
-}
\ No newline at end of file
diff --git a/NzbDrone.Core/Indexers/IndexerSettingUpdatedEvent.cs b/NzbDrone.Core/Indexers/IndexerSettingUpdatedEvent.cs
index 8b3edc513..783948b2e 100644
--- a/NzbDrone.Core/Indexers/IndexerSettingUpdatedEvent.cs
+++ b/NzbDrone.Core/Indexers/IndexerSettingUpdatedEvent.cs
@@ -1,13 +1,14 @@
using NzbDrone.Common.Messaging;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers
{
public class IndexerSettingUpdatedEvent : IEvent
{
public string IndexerName { get; private set; }
- public IIndexerSetting IndexerSetting { get; private set; }
+ public IProviderConfig IndexerSetting { get; private set; }
- public IndexerSettingUpdatedEvent(string indexerName, IIndexerSetting indexerSetting)
+ public IndexerSettingUpdatedEvent(string indexerName, IProviderConfig indexerSetting)
{
IndexerName = indexerName;
IndexerSetting = indexerSetting;
diff --git a/NzbDrone.Core/Indexers/IndexerWithSetting.cs b/NzbDrone.Core/Indexers/IndexerWithSetting.cs
deleted file mode 100644
index 78db54932..000000000
--- a/NzbDrone.Core/Indexers/IndexerWithSetting.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using NzbDrone.Common.Serializer;
-
-namespace NzbDrone.Core.Indexers
-{
- public abstract class IndexerWithSetting : IndexerBase where TSetting : class, IIndexerSetting, new()
- {
- public TSetting Settings { get; set; }
-
- public override bool EnableByDefault
- {
- get { return false; }
- }
-
- public TSetting ImportSettingsFromJson(string json)
- {
- Settings = Json.Deserialize(json) ?? new TSetting();
-
- return Settings;
- }
- }
-}
\ No newline at end of file
diff --git a/NzbDrone.Core/Indexers/Newznab/Newznab.cs b/NzbDrone.Core/Indexers/Newznab/Newznab.cs
index 8a13d2282..a4c106846 100644
--- a/NzbDrone.Core/Indexers/Newznab/Newznab.cs
+++ b/NzbDrone.Core/Indexers/Newznab/Newznab.cs
@@ -2,10 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Serializer;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers.Newznab
{
- public class Newznab : IndexerWithSetting
+ public class Newznab : IndexerBase
{
public override IParseFeed Parser
{
@@ -15,7 +16,7 @@ namespace NzbDrone.Core.Indexers.Newznab
}
}
- public override IEnumerable DefaultDefinitions
+ public override IEnumerable DefaultDefinitions
{
get
{
@@ -51,7 +52,7 @@ namespace NzbDrone.Core.Indexers.Newznab
}
}
- private string GetSettings(string url, List categories)
+ private NewznabSettings GetSettings(string url, List categories)
{
var settings = new NewznabSettings { Url = url };
@@ -60,7 +61,7 @@ namespace NzbDrone.Core.Indexers.Newznab
settings.Categories = categories;
}
- return settings.ToJson();
+ return settings;
}
public override IEnumerable RecentFeed
@@ -68,7 +69,7 @@ namespace NzbDrone.Core.Indexers.Newznab
get
{
//Todo: We should be able to update settings on start
- if (Name.Equals("nzbs.org", StringComparison.InvariantCultureIgnoreCase))
+ if (Settings.Url.Contains("nzbs.org"))
{
Settings.Categories = new List { 5000 };
}
@@ -114,19 +115,11 @@ namespace NzbDrone.Core.Indexers.Newznab
return RecentFeed.Select(url => String.Format("{0}&limit=100&q={1}&season={2}&offset={3}", url, NewsnabifyTitle(seriesTitle), seasonNumber, offset));
}
- public override string Name
+ public override DownloadProtocol Protocol
{
get
{
- return InstanceDefinition.Name;
- }
- }
-
- public override IndexerKind Kind
- {
- get
- {
- return IndexerKind.Usenet;
+ return DownloadProtocol.Usenet;
}
}
@@ -135,4 +128,4 @@ namespace NzbDrone.Core.Indexers.Newznab
return title.Replace("+", "%20");
}
}
-}
\ No newline at end of file
+}
diff --git a/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs b/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs
index c83623ace..5f05ba96d 100644
--- a/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs
+++ b/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using FluentValidation;
using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Newznab
@@ -16,7 +17,7 @@ namespace NzbDrone.Core.Indexers.Newznab
}
- public class NewznabSettings : IIndexerSetting
+ public class NewznabSettings : IProviderConfig
{
private static readonly NewznabSettingsValidator Validator = new NewznabSettingsValidator();
diff --git a/NzbDrone.Core/Indexers/Omgwtfnzbs/Omgwtfnzbs.cs b/NzbDrone.Core/Indexers/Omgwtfnzbs/Omgwtfnzbs.cs
index 15f6dbbe5..c4daeab66 100644
--- a/NzbDrone.Core/Indexers/Omgwtfnzbs/Omgwtfnzbs.cs
+++ b/NzbDrone.Core/Indexers/Omgwtfnzbs/Omgwtfnzbs.cs
@@ -3,18 +3,13 @@ using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.Omgwtfnzbs
{
- public class Omgwtfnzbs : IndexerWithSetting
+ public class Omgwtfnzbs : IndexerBase
{
- public override string Name
- {
- get { return "omgwtfnzbs"; }
- }
-
- public override IndexerKind Kind
+ public override DownloadProtocol Protocol
{
get
{
- return IndexerKind.Usenet;
+ return DownloadProtocol.Usenet;
}
}
diff --git a/NzbDrone.Core/Indexers/Omgwtfnzbs/OmgwtfnzbsSettings.cs b/NzbDrone.Core/Indexers/Omgwtfnzbs/OmgwtfnzbsSettings.cs
index 778b3a48e..900055608 100644
--- a/NzbDrone.Core/Indexers/Omgwtfnzbs/OmgwtfnzbsSettings.cs
+++ b/NzbDrone.Core/Indexers/Omgwtfnzbs/OmgwtfnzbsSettings.cs
@@ -2,6 +2,7 @@
using FluentValidation;
using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers.Omgwtfnzbs
{
@@ -14,7 +15,7 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
}
}
- public class OmgwtfnzbsSettings : IIndexerSetting
+ public class OmgwtfnzbsSettings : IProviderConfig
{
private static readonly OmgwtfnzbsSettingsValidator Validator = new OmgwtfnzbsSettingsValidator();
diff --git a/NzbDrone.Core/Indexers/Wombles/Wombles.cs b/NzbDrone.Core/Indexers/Wombles/Wombles.cs
index 95cd559de..5355d853d 100644
--- a/NzbDrone.Core/Indexers/Wombles/Wombles.cs
+++ b/NzbDrone.Core/Indexers/Wombles/Wombles.cs
@@ -1,20 +1,16 @@
using System;
using System.Collections.Generic;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers.Wombles
{
- public class Wombles : IndexerBase
+ public class Wombles : IndexerBase
{
- public override string Name
- {
- get { return "WomblesIndex"; }
- }
-
- public override IndexerKind Kind
+ public override DownloadProtocol Protocol
{
get
{
- return IndexerKind.Usenet;
+ return DownloadProtocol.Usenet;
}
}
diff --git a/NzbDrone.Core/Notifications/Email/EmailSettings.cs b/NzbDrone.Core/Notifications/Email/EmailSettings.cs
index 6ee61b6a2..42aa725cd 100644
--- a/NzbDrone.Core/Notifications/Email/EmailSettings.cs
+++ b/NzbDrone.Core/Notifications/Email/EmailSettings.cs
@@ -1,9 +1,11 @@
using System;
+using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.Email
{
- public class EmailSettings : INotifcationSettings
+ public class EmailSettings : IProviderConfig
{
public EmailSettings()
{
@@ -38,5 +40,10 @@ namespace NzbDrone.Core.Notifications.Email
return !string.IsNullOrWhiteSpace(Server) && Port > 0 && !string.IsNullOrWhiteSpace(From) && !string.IsNullOrWhiteSpace(To);
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs b/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs
index c66060a94..dd049268d 100644
--- a/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs
+++ b/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs
@@ -1,9 +1,11 @@
using System;
+using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.Growl
{
- public class GrowlSettings : INotifcationSettings
+ public class GrowlSettings : IProviderConfig
{
public GrowlSettings()
{
@@ -26,5 +28,10 @@ namespace NzbDrone.Core.Notifications.Growl
return !string.IsNullOrWhiteSpace(Host) && !string.IsNullOrWhiteSpace(Password) && Port > 0;
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/Notifications/INotifcationSettings.cs b/NzbDrone.Core/Notifications/INotifcationSettings.cs
deleted file mode 100644
index 49e113de4..000000000
--- a/NzbDrone.Core/Notifications/INotifcationSettings.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace NzbDrone.Core.Notifications
-{
- public interface INotifcationSettings
- {
- bool IsValid { get; }
- }
-}
diff --git a/NzbDrone.Core/Notifications/Notification.cs b/NzbDrone.Core/Notifications/Notification.cs
index 09919c958..40275ecf9 100644
--- a/NzbDrone.Core/Notifications/Notification.cs
+++ b/NzbDrone.Core/Notifications/Notification.cs
@@ -1,4 +1,6 @@
-namespace NzbDrone.Core.Notifications
+using NzbDrone.Core.ThingiProvider;
+
+namespace NzbDrone.Core.Notifications
{
public class Notification
{
@@ -8,7 +10,7 @@
public string Link { get; set; }
public bool OnGrab { get; set; }
public bool OnDownload { get; set; }
- public INotifcationSettings Settings { get; set; }
+ public IProviderConfig Settings { get; set; }
public INotification Instance { get; set; }
public string Implementation { get; set; }
}
diff --git a/NzbDrone.Core/Notifications/NotificationBase.cs b/NzbDrone.Core/Notifications/NotificationBase.cs
index e8577c978..d121bd44b 100644
--- a/NzbDrone.Core/Notifications/NotificationBase.cs
+++ b/NzbDrone.Core/Notifications/NotificationBase.cs
@@ -1,9 +1,10 @@
using NzbDrone.Common.Serializer;
+using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Notifications
{
- public abstract class NotificationBase : INotification where TSetting : class, INotifcationSettings, new()
+ public abstract class NotificationBase : INotification where TSetting : class, IProviderConfig, new()
{
public abstract string Name { get; }
public abstract string ImplementationName { get; }
diff --git a/NzbDrone.Core/Notifications/NotificationDefinition.cs b/NzbDrone.Core/Notifications/NotificationDefinition.cs
index 7456c7783..41fc64509 100644
--- a/NzbDrone.Core/Notifications/NotificationDefinition.cs
+++ b/NzbDrone.Core/Notifications/NotificationDefinition.cs
@@ -1,5 +1,6 @@
using System;
using NzbDrone.Core.Datastore;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications
{
@@ -11,4 +12,11 @@ namespace NzbDrone.Core.Notifications
public String Settings { get; set; }
public String Implementation { get; set; }
}
+
+
+ public class NotificationProviderModel : ProviderDefinition
+ {
+ public Boolean OnGrab { get; set; }
+ public Boolean OnDownload { get; set; }
+ }
}
\ No newline at end of file
diff --git a/NzbDrone.Core/Notifications/NotificationService.cs b/NzbDrone.Core/Notifications/NotificationService.cs
index 0553f4669..458c80d65 100644
--- a/NzbDrone.Core/Notifications/NotificationService.cs
+++ b/NzbDrone.Core/Notifications/NotificationService.cs
@@ -7,6 +7,7 @@ using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Events;
+using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Tv;
using Omu.ValueInjecter;
@@ -18,7 +19,7 @@ namespace NzbDrone.Core.Notifications
Notification Get(int id);
List Schema();
Notification Create(Notification notification);
- Notification Update(Notification notification);
+ void Update(Notification notification);
void Delete(int id);
}
@@ -71,7 +72,7 @@ namespace NzbDrone.Core.Notifications
var instanceType = newNotification.Instance.GetType();
var baseGenArgs = instanceType.BaseType.GetGenericArguments();
- newNotification.Settings = (INotifcationSettings)Activator.CreateInstance(baseGenArgs[0]);
+ newNotification.Settings = (IProviderConfig)Activator.CreateInstance(baseGenArgs[0]);
newNotification.Implementation = type.Name;
notifications.Add(newNotification);
@@ -93,15 +94,13 @@ namespace NzbDrone.Core.Notifications
return notification;
}
- public Notification Update(Notification notification)
+ public void Update(Notification notification)
{
var definition = _notificationRepository.Get(notification.Id);
definition.InjectFrom(notification);
definition.Settings = notification.Settings.ToJson();
_notificationRepository.Update(definition);
-
- return notification;
}
public void Delete(int id)
diff --git a/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs b/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs
index 53f4d8a58..b26afa1fd 100644
--- a/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs
+++ b/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs
@@ -1,10 +1,11 @@
using NzbDrone.Common.Serializer;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications
{
public interface INotificationSettingsProvider
{
- TSetting Get(INotification indexer) where TSetting : INotifcationSettings, new();
+ TSetting Get(INotification indexer) where TSetting : IProviderConfig, new();
}
public class NotificationSettingsProvider : INotificationSettingsProvider
@@ -16,7 +17,7 @@ namespace NzbDrone.Core.Notifications
_notificationRepository = notificationRepository;
}
- public TSetting Get(INotification indexer) where TSetting : INotifcationSettings, new()
+ public TSetting Get(INotification indexer) where TSetting : IProviderConfig, new()
{
var indexerDef = _notificationRepository.Find(indexer.Name);
diff --git a/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroidSettings.cs b/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroidSettings.cs
index c8c941239..48c8c6fc6 100644
--- a/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroidSettings.cs
+++ b/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroidSettings.cs
@@ -1,9 +1,11 @@
using System;
+using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.NotifyMyAndroid
{
- public class NotifyMyAndroidSettings : INotifcationSettings
+ public class NotifyMyAndroidSettings : IProviderConfig
{
[FieldDefinition(0, Label = "API Key", HelpLink = "http://www.notifymyandroid.com/")]
public String ApiKey { get; set; }
@@ -18,5 +20,10 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid
return !String.IsNullOrWhiteSpace(ApiKey) && Priority != null & Priority >= -1 && Priority <= 2;
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs b/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs
index 130552e52..a0d762406 100644
--- a/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs
+++ b/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs
@@ -1,9 +1,11 @@
using System;
+using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.Plex
{
- public class PlexClientSettings : INotifcationSettings
+ public class PlexClientSettings : IProviderConfig
{
public PlexClientSettings()
{
@@ -29,5 +31,10 @@ namespace NzbDrone.Core.Notifications.Plex
return !string.IsNullOrWhiteSpace(Host);
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs b/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs
index 40b05a2c0..ed410767b 100644
--- a/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs
+++ b/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs
@@ -1,9 +1,11 @@
using System;
+using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.Plex
{
- public class PlexServerSettings : INotifcationSettings
+ public class PlexServerSettings : IProviderConfig
{
public PlexServerSettings()
{
@@ -26,5 +28,10 @@ namespace NzbDrone.Core.Notifications.Plex
return !string.IsNullOrWhiteSpace(Host);
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs b/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs
index f6b9a7603..66b574179 100644
--- a/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs
+++ b/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs
@@ -1,9 +1,11 @@
using System;
+using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.Prowl
{
- public class ProwlSettings : INotifcationSettings
+ public class ProwlSettings : IProviderConfig
{
[FieldDefinition(0, Label = "API Key", HelpLink = "https://www.prowlapp.com/api_settings.php")]
public String ApiKey { get; set; }
@@ -18,5 +20,10 @@ namespace NzbDrone.Core.Notifications.Prowl
return !string.IsNullOrWhiteSpace(ApiKey) && Priority != null & Priority >= -2 && Priority <= 2;
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs b/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs
index f7a492622..1886991d8 100644
--- a/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs
+++ b/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs
@@ -1,9 +1,11 @@
using System;
+using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.PushBullet
{
- public class PushBulletSettings : INotifcationSettings
+ public class PushBulletSettings : IProviderConfig
{
[FieldDefinition(0, Label = "API Key", HelpLink = "https://www.pushbullet.com/")]
public String ApiKey { get; set; }
@@ -18,5 +20,10 @@ namespace NzbDrone.Core.Notifications.PushBullet
return !String.IsNullOrWhiteSpace(ApiKey) && DeviceId > 0;
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs b/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs
index 43c7937b6..ca4c332c7 100644
--- a/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs
+++ b/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs
@@ -1,9 +1,11 @@
using System;
+using FluentValidation.Results;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.Pushover
{
- public class PushoverSettings : INotifcationSettings
+ public class PushoverSettings : IProviderConfig
{
[FieldDefinition(0, Label = "User Key", HelpLink = "https://pushover.net/")]
public String UserKey { get; set; }
@@ -18,5 +20,10 @@ namespace NzbDrone.Core.Notifications.Pushover
return !string.IsNullOrWhiteSpace(UserKey) && Priority != null & Priority >= -1 && Priority <= 2;
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs b/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs
index 0a09d9d57..2c0569c89 100644
--- a/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs
+++ b/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs
@@ -1,11 +1,13 @@
using System;
using System.ComponentModel;
+using FluentValidation.Results;
using Newtonsoft.Json;
using NzbDrone.Core.Annotations;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.Xbmc
{
- public class XbmcSettings : INotifcationSettings
+ public class XbmcSettings : IProviderConfig
{
public XbmcSettings()
{
@@ -51,5 +53,10 @@ namespace NzbDrone.Core.Notifications.Xbmc
return !string.IsNullOrWhiteSpace(Host) && Port > 0;
}
}
+
+ public ValidationResult Validate()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj
index 3c48dd31d..766536d42 100644
--- a/NzbDrone.Core/NzbDrone.Core.csproj
+++ b/NzbDrone.Core/NzbDrone.Core.csproj
@@ -141,6 +141,7 @@
+
@@ -172,6 +173,8 @@
+
+
@@ -241,12 +244,10 @@
-
-
@@ -343,13 +344,11 @@
-
-
@@ -371,7 +370,6 @@
-
@@ -417,6 +415,8 @@
+
+
@@ -427,6 +427,13 @@
+
+
+
+
+
+
+
@@ -505,7 +512,7 @@
Code
-
+
Code
diff --git a/NzbDrone.Core/NzbDrone.Core.ncrunchproject b/NzbDrone.Core/NzbDrone.Core.ncrunchproject
index b2eed192e..b36cf9e27 100644
--- a/NzbDrone.Core/NzbDrone.Core.ncrunchproject
+++ b/NzbDrone.Core/NzbDrone.Core.ncrunchproject
@@ -13,7 +13,7 @@
true
true
5000
- Debug
+ RELEASE
x86
x86
diff --git a/NzbDrone.Core/ThingiProvider/ConfigContractNotFoundException.cs b/NzbDrone.Core/ThingiProvider/ConfigContractNotFoundException.cs
new file mode 100644
index 000000000..47d6ecdf3
--- /dev/null
+++ b/NzbDrone.Core/ThingiProvider/ConfigContractNotFoundException.cs
@@ -0,0 +1,13 @@
+using NzbDrone.Common.Exceptions;
+
+namespace NzbDrone.Core.ThingiProvider
+{
+ public class ConfigContractNotFoundException : NzbDroneException
+ {
+ public ConfigContractNotFoundException(string contract)
+ : base("Couldn't find config contract " + contract)
+ {
+ }
+
+ }
+}
diff --git a/NzbDrone.Core/ThingiProvider/IProvider.cs b/NzbDrone.Core/ThingiProvider/IProvider.cs
new file mode 100644
index 000000000..4947c3d8b
--- /dev/null
+++ b/NzbDrone.Core/ThingiProvider/IProvider.cs
@@ -0,0 +1,14 @@
+
+using System;
+using System.Collections.Generic;
+
+namespace NzbDrone.Core.ThingiProvider
+{
+ public interface IProvider
+ {
+ Type ConfigContract { get; }
+
+ IEnumerable DefaultDefinitions { get; }
+ ProviderDefinition Definition { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Indexers/IIndexerSetting.cs b/NzbDrone.Core/ThingiProvider/IProviderConfig.cs
similarity index 53%
rename from NzbDrone.Core/Indexers/IIndexerSetting.cs
rename to NzbDrone.Core/ThingiProvider/IProviderConfig.cs
index 4f9cf16de..46501fb34 100644
--- a/NzbDrone.Core/Indexers/IIndexerSetting.cs
+++ b/NzbDrone.Core/ThingiProvider/IProviderConfig.cs
@@ -1,9 +1,9 @@
using FluentValidation.Results;
-namespace NzbDrone.Core.Indexers
+namespace NzbDrone.Core.ThingiProvider
{
- public interface IIndexerSetting
+ public interface IProviderConfig
{
ValidationResult Validate();
}
-}
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/ThingiProvider/IProviderFactory.cs b/NzbDrone.Core/ThingiProvider/IProviderFactory.cs
new file mode 100644
index 000000000..54e8315a6
--- /dev/null
+++ b/NzbDrone.Core/ThingiProvider/IProviderFactory.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+
+namespace NzbDrone.Core.ThingiProvider
+{
+ public interface IProviderFactory
+ where TProviderDefinition : ProviderDefinition, new()
+ where TProvider : IProvider
+ {
+ List All();
+ List GetAvailableProviders();
+ TProviderDefinition Get(int id);
+ TProviderDefinition Create(TProviderDefinition indexer);
+ void Update(TProviderDefinition indexer);
+ void Delete(int id);
+ List Templates();
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/ThingiProvider/IProviderRepository.cs b/NzbDrone.Core/ThingiProvider/IProviderRepository.cs
new file mode 100644
index 000000000..13043b64d
--- /dev/null
+++ b/NzbDrone.Core/ThingiProvider/IProviderRepository.cs
@@ -0,0 +1,8 @@
+using NzbDrone.Core.Datastore;
+
+namespace NzbDrone.Core.ThingiProvider
+{
+ public interface IProviderRepository : IBasicRepository where TProvider : ModelBase, new()
+ {
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Indexers/NullSetting.cs b/NzbDrone.Core/ThingiProvider/NullConfig.cs
similarity index 50%
rename from NzbDrone.Core/Indexers/NullSetting.cs
rename to NzbDrone.Core/ThingiProvider/NullConfig.cs
index a7013335a..6eea2e66c 100644
--- a/NzbDrone.Core/Indexers/NullSetting.cs
+++ b/NzbDrone.Core/ThingiProvider/NullConfig.cs
@@ -1,10 +1,10 @@
using FluentValidation.Results;
-namespace NzbDrone.Core.Indexers
+namespace NzbDrone.Core.ThingiProvider
{
- public class NullSetting : IIndexerSetting
+ public class NullConfig : IProviderConfig
{
- public static readonly NullSetting Instance = new NullSetting();
+ public static readonly NullConfig Instance = new NullConfig();
public ValidationResult Validate()
{
diff --git a/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs b/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs
new file mode 100644
index 000000000..ef21d3206
--- /dev/null
+++ b/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs
@@ -0,0 +1,30 @@
+using NzbDrone.Core.Datastore;
+
+namespace NzbDrone.Core.ThingiProvider
+{
+ public abstract class ProviderDefinition : ModelBase
+ {
+ private IProviderConfig _settings;
+ public string Name { get; set; }
+ public string Implementation { get; set; }
+ public bool Enable { get; set; }
+
+ public string ConfigContract { get; set; }
+
+ public IProviderConfig Settings
+ {
+ get
+ {
+ return _settings;
+ }
+ set
+ {
+ _settings = value;
+ if (value != null)
+ {
+ ConfigContract = value.GetType().Name;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/ThingiProvider/ProviderFactory.cs b/NzbDrone.Core/ThingiProvider/ProviderFactory.cs
new file mode 100644
index 000000000..bbd909bb3
--- /dev/null
+++ b/NzbDrone.Core/ThingiProvider/ProviderFactory.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NLog;
+using NzbDrone.Core.Lifecycle;
+using NzbDrone.Core.Messaging.Events;
+
+namespace NzbDrone.Core.ThingiProvider
+{
+ public abstract class ProviderFactory : IProviderFactory, IHandle
+ where TProviderDefinition : ProviderDefinition, new()
+ where TProvider : IProvider
+ {
+ private readonly IProviderRepository _providerRepository;
+ private readonly Logger _logger;
+
+ private readonly List _providers;
+
+ protected ProviderFactory(IProviderRepository providerRepository, IEnumerable providers, Logger logger)
+ {
+ _providerRepository = providerRepository;
+ _providers = providers.ToList();
+ _logger = logger;
+ }
+
+ public List All()
+ {
+ return _providerRepository.All().ToList();
+ }
+
+ public List Templates()
+ {
+ return _providers.Select(p => new TProviderDefinition()
+ {
+ ConfigContract = p.ConfigContract.Name,
+ Implementation = p.GetType().Name,
+ Settings = (IProviderConfig)Activator.CreateInstance(p.ConfigContract)
+ }).ToList();
+ }
+
+ public List GetAvailableProviders()
+ {
+ return All().Where(c => c.Enable && c.Settings.Validate().IsValid)
+ .Select(GetInstance).ToList();
+ }
+
+ public TProviderDefinition Get(int id)
+ {
+ return _providerRepository.Get(id);
+ }
+
+ public TProviderDefinition Create(TProviderDefinition provider)
+ {
+ return _providerRepository.Insert(provider);
+ }
+
+ public void Update(TProviderDefinition definition)
+ {
+ _providerRepository.Update(definition);
+ }
+
+ public void Delete(int id)
+ {
+ _providerRepository.Delete(id);
+ }
+
+ private TProvider GetInstance(TProviderDefinition definition)
+ {
+ var type = GetImplementation(definition);
+ var instance = (TProvider)Activator.CreateInstance(type);
+ instance.Definition = definition;
+ return instance;
+ }
+
+ private Type GetImplementation(TProviderDefinition definition)
+ {
+ return _providers.Select(c => c.GetType()).SingleOrDefault(c => c.Name.Equals(definition.Implementation, StringComparison.InvariantCultureIgnoreCase));
+ }
+
+ public void Handle(ApplicationStartedEvent message)
+ {
+ _logger.Debug("Initializing Providers. Count {0}", _providers.Count);
+
+ RemoveMissingImplementations();
+
+ InitializeProviders();
+ }
+
+ protected virtual void InitializeProviders()
+ {
+ }
+
+ private void RemoveMissingImplementations()
+ {
+ var storedProvider = _providerRepository.All();
+
+ foreach (var invalidDefinition in storedProvider.Where(def => GetImplementation(def) == null))
+ {
+ _logger.Debug("Removing {0} ", invalidDefinition.Name);
+ _providerRepository.Delete(invalidDefinition);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/ThingiProvider/ProviderRepository.cs b/NzbDrone.Core/ThingiProvider/ProviderRepository.cs
new file mode 100644
index 000000000..cceaaefcb
--- /dev/null
+++ b/NzbDrone.Core/ThingiProvider/ProviderRepository.cs
@@ -0,0 +1,16 @@
+using System;
+using NzbDrone.Core.Datastore;
+using NzbDrone.Core.Messaging.Events;
+
+namespace NzbDrone.Core.ThingiProvider
+{
+ public class ProviderRepository : BasicRepository, IProviderRepository
+ where TProviderDefinition : ModelBase,
+ new()
+ {
+ protected ProviderRepository(IDatabase database, IEventAggregator eventAggregator)
+ : base(database, eventAggregator)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Integration.Test/IndexerIntegrationFixture.cs b/NzbDrone.Integration.Test/IndexerIntegrationFixture.cs
index 33fb6e0ab..96003762b 100644
--- a/NzbDrone.Integration.Test/IndexerIntegrationFixture.cs
+++ b/NzbDrone.Integration.Test/IndexerIntegrationFixture.cs
@@ -1,5 +1,7 @@
-using FluentAssertions;
+using System.Linq;
+using FluentAssertions;
using NUnit.Framework;
+using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Integration.Test
{
@@ -13,6 +15,7 @@ namespace NzbDrone.Integration.Test
indexers.Should().NotBeEmpty();
indexers.Should().NotContain(c => string.IsNullOrWhiteSpace(c.Name));
+ indexers.Where(c => c.ConfigContract == typeof(NullConfig).Name).Should().OnlyContain(c => c.Enable);
}
}
}
\ No newline at end of file
diff --git a/NzbDrone.Integration.Test/ReleaseIntegrationTest.cs b/NzbDrone.Integration.Test/ReleaseIntegrationTest.cs
index b9a86674e..eb76f1255 100644
--- a/NzbDrone.Integration.Test/ReleaseIntegrationTest.cs
+++ b/NzbDrone.Integration.Test/ReleaseIntegrationTest.cs
@@ -1,4 +1,5 @@
-using FluentAssertions;
+using System.Threading;
+using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Api.Indexers;
@@ -10,10 +11,13 @@ namespace NzbDrone.Integration.Test
[Test]
public void should_only_have_unknown_series_releases()
{
+
var releases = Releases.All();
+ var indexers = Indexers.All();
+
releases.Should().OnlyContain(c => c.Rejections.Contains("Unknown Series"));
- releases.Should().OnlyContain(c=>BeValidRelease(c));
+ releases.Should().OnlyContain(c => BeValidRelease(c));
}
diff --git a/NzbDrone.ncrunchsolution b/NzbDrone.ncrunchsolution
index 098d74afe..28e2de798 100644
--- a/NzbDrone.ncrunchsolution
+++ b/NzbDrone.ncrunchsolution
@@ -7,7 +7,7 @@
Disabled
Disabled
Disabled
- Run all tests automatically:BFRydWU=;Run all tests manually:BUZhbHNl;Run impacted tests automatically, others manually (experimental!):CklzSW1wYWN0ZWQ=;Run pinned tests automatically, others manually:CElzUGlubmVk;Fast:DlN0cnVjdHVyYWxOb2RlBAAAABNEb2VzTm90SGF2ZUNhdGVnb3J5D0ludGVncmF0aW9uVGVzdBNEb2VzTm90SGF2ZUNhdGVnb3J5BkRiVGVzdApJc0ltcGFjdGVkE0RvZXNOb3RIYXZlQ2F0ZWdvcnkORGlza0FjY2Vzc1Rlc3QAAAAAAAAAAAAAAAA=
+ Run all tests automatically:BFRydWU=;Run all tests manually:BUZhbHNl;Run impacted tests automatically, others manually (experimental!):CklzSW1wYWN0ZWQ=;Run pinned tests automatically, others manually:CElzUGlubmVk;Fast:DlN0cnVjdHVyYWxOb2RlBQAAABNEb2VzTm90SGF2ZUNhdGVnb3J5D0ludGVncmF0aW9uVGVzdBNEb2VzTm90SGF2ZUNhdGVnb3J5BkRiVGVzdApJc0ltcGFjdGVkE0RvZXNOb3RIYXZlQ2F0ZWdvcnkORGlza0FjY2Vzc1Rlc3QISXNQaW5uZWQAAAAAAAAAAAAAAAABAAAA
\ No newline at end of file