Converted notifications to thingi provider
Fixed: Issues creating and saving Connects
This commit is contained in:
parent
ff7ce397ab
commit
27da44ba45
|
@ -2,11 +2,17 @@
|
||||||
|
|
||||||
namespace NzbDrone.Api.Indexers
|
namespace NzbDrone.Api.Indexers
|
||||||
{
|
{
|
||||||
public class IndexerModule : ProviderModuleBase<ProviderResource, IIndexer, IndexerDefinition>
|
public class IndexerModule : ProviderModuleBase<IndexerResource, IIndexer, IndexerDefinition>
|
||||||
{
|
{
|
||||||
public IndexerModule(IndexerFactory indexerFactory)
|
public IndexerModule(IndexerFactory indexerFactory)
|
||||||
: base(indexerFactory, "indexer")
|
: base(indexerFactory, "indexer")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Validate(IndexerDefinition definition)
|
||||||
|
{
|
||||||
|
if (!definition.Enable) return;
|
||||||
|
base.Validate(definition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,16 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using NzbDrone.Api.ClientSchema;
|
|
||||||
using NzbDrone.Api.REST;
|
|
||||||
|
|
||||||
namespace NzbDrone.Api.Indexers
|
namespace NzbDrone.Api.Indexers
|
||||||
{
|
{
|
||||||
public class IndexerResource : RestResource
|
public class IndexerResource : ProviderResource
|
||||||
{
|
{
|
||||||
public Boolean Enable { get; set; }
|
public Boolean Enable { get; set; }
|
||||||
public String Name { get; set; }
|
|
||||||
public List<Field> Fields { get; set; }
|
|
||||||
public String Implementation { get; set; }
|
|
||||||
public String ConfigContract { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,10 +19,8 @@ namespace NzbDrone.Api.Indexers
|
||||||
|
|
||||||
private List<IndexerResource> GetSchema()
|
private List<IndexerResource> GetSchema()
|
||||||
{
|
{
|
||||||
|
|
||||||
var indexers = _indexerFactory.Templates().Where(c => c.Implementation =="Newznab");
|
var indexers = _indexerFactory.Templates().Where(c => c.Implementation =="Newznab");
|
||||||
|
|
||||||
|
|
||||||
var result = new List<IndexerResource>(indexers.Count());
|
var result = new List<IndexerResource>(indexers.Count());
|
||||||
|
|
||||||
foreach (var indexer in indexers)
|
foreach (var indexer in indexers)
|
||||||
|
|
|
@ -10,82 +10,17 @@ using Omu.ValueInjecter;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Notifications
|
namespace NzbDrone.Api.Notifications
|
||||||
{
|
{
|
||||||
public class NotificationModule : NzbDroneRestModule<NotificationResource>
|
public class IndexerModule : ProviderModuleBase<NotificationResource, INotification, NotificationDefinition>
|
||||||
{
|
{
|
||||||
private readonly INotificationService _notificationService;
|
public IndexerModule(NotificationFactory notificationrFactory)
|
||||||
|
: base(notificationrFactory, "notification")
|
||||||
public NotificationModule(INotificationService notificationService)
|
|
||||||
{
|
{
|
||||||
_notificationService = notificationService;
|
|
||||||
|
|
||||||
GetResourceAll = GetAll;
|
|
||||||
GetResourceById = GetNotification;
|
|
||||||
CreateResource = Create;
|
|
||||||
UpdateResource = Update;
|
|
||||||
DeleteResource = DeleteNotification;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private NotificationResource GetNotification(int id)
|
protected override void Validate(NotificationDefinition definition)
|
||||||
{
|
{
|
||||||
return _notificationService.Get(id).InjectTo<NotificationResource>();
|
if (!definition.OnGrab && !definition.OnDownload) return;
|
||||||
}
|
base.Validate(definition);
|
||||||
|
|
||||||
private List<NotificationResource> GetAll()
|
|
||||||
{
|
|
||||||
var notifications = _notificationService.All();
|
|
||||||
|
|
||||||
var result = new List<NotificationResource>(notifications.Count);
|
|
||||||
|
|
||||||
foreach (var notification in notifications)
|
|
||||||
{
|
|
||||||
var notificationResource = new NotificationResource();
|
|
||||||
notificationResource.InjectFrom(notification);
|
|
||||||
notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings);
|
|
||||||
notificationResource.TestCommand = String.Format("test{0}", notification.Implementation.ToLowerInvariant());
|
|
||||||
|
|
||||||
result.Add(notificationResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int Create(NotificationResource notificationResource)
|
|
||||||
{
|
|
||||||
var notification = ConvertToNotification(notificationResource);
|
|
||||||
return _notificationService.Create(notification).Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update(NotificationResource notificationResource)
|
|
||||||
{
|
|
||||||
var notification = ConvertToNotification(notificationResource);
|
|
||||||
notification.Id = notificationResource.Id;
|
|
||||||
_notificationService.Update(notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeleteNotification(int id)
|
|
||||||
{
|
|
||||||
_notificationService.Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Notification ConvertToNotification(NotificationResource notificationResource)
|
|
||||||
{
|
|
||||||
var notification = _notificationService.Schema()
|
|
||||||
.SingleOrDefault(i =>
|
|
||||||
i.Implementation.Equals(notificationResource.Implementation,
|
|
||||||
StringComparison.InvariantCultureIgnoreCase));
|
|
||||||
|
|
||||||
if (notification == null)
|
|
||||||
{
|
|
||||||
throw new BadRequestException("Invalid Notification Implementation");
|
|
||||||
}
|
|
||||||
|
|
||||||
notification.InjectFrom(notificationResource);
|
|
||||||
|
|
||||||
//var configType = ReflectionExtensions.CoreAssembly.FindTypeByName(notification)
|
|
||||||
|
|
||||||
//notification.Settings = SchemaBuilder.ReadFormSchema(notification.Settings, notificationResource.Fields);
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using NzbDrone.Api.ClientSchema;
|
|
||||||
using NzbDrone.Api.REST;
|
|
||||||
|
|
||||||
namespace NzbDrone.Api.Notifications
|
namespace NzbDrone.Api.Notifications
|
||||||
{
|
{
|
||||||
public class NotificationResource : RestResource
|
public class NotificationResource : ProviderResource
|
||||||
{
|
{
|
||||||
public String Name { get; set; }
|
|
||||||
public String ImplementationName { get; set; }
|
|
||||||
public String Link { get; set; }
|
public String Link { get; set; }
|
||||||
public Boolean OnGrab { get; set; }
|
public Boolean OnGrab { get; set; }
|
||||||
public Boolean OnDownload { get; set; }
|
public Boolean OnDownload { get; set; }
|
||||||
public List<Field> Fields { get; set; }
|
|
||||||
public String Implementation { get; set; }
|
|
||||||
public String TestCommand { get; set; }
|
public String TestCommand { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,20 +7,19 @@ using Omu.ValueInjecter;
|
||||||
namespace NzbDrone.Api.Notifications
|
namespace NzbDrone.Api.Notifications
|
||||||
{
|
{
|
||||||
public class NotificationSchemaModule : NzbDroneRestModule<NotificationResource>
|
public class NotificationSchemaModule : NzbDroneRestModule<NotificationResource>
|
||||||
{
|
{
|
||||||
private readonly INotificationService _notificationService;
|
private readonly INotificationFactory _notificationFactory;
|
||||||
|
|
||||||
public NotificationSchemaModule(INotificationService notificationService)
|
public NotificationSchemaModule(INotificationFactory notificationFactory)
|
||||||
: base("notification/schema")
|
: base("notification/schema")
|
||||||
{
|
{
|
||||||
_notificationService = notificationService;
|
_notificationFactory = notificationFactory;
|
||||||
|
|
||||||
GetResourceAll = GetSchema;
|
GetResourceAll = GetSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<NotificationResource> GetSchema()
|
private List<NotificationResource> GetSchema()
|
||||||
{
|
{
|
||||||
var notifications = _notificationService.Schema();
|
var notifications = _notificationFactory.Templates();
|
||||||
|
|
||||||
var result = new List<NotificationResource>(notifications.Count);
|
var result = new List<NotificationResource>(notifications.Count);
|
||||||
|
|
||||||
|
@ -29,7 +28,6 @@ namespace NzbDrone.Api.Notifications
|
||||||
var notificationResource = new NotificationResource();
|
var notificationResource = new NotificationResource();
|
||||||
notificationResource.InjectFrom(notification);
|
notificationResource.InjectFrom(notification);
|
||||||
notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings);
|
notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings);
|
||||||
notificationResource.TestCommand = String.Format("test{0}", notification.Implementation.ToLowerInvariant());
|
|
||||||
|
|
||||||
result.Add(notificationResource);
|
result.Add(notificationResource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
<Compile Include="Frontend\StaticResourceModule.cs" />
|
<Compile Include="Frontend\StaticResourceModule.cs" />
|
||||||
<Compile Include="History\HistoryResource.cs" />
|
<Compile Include="History\HistoryResource.cs" />
|
||||||
<Compile Include="History\HistoryModule.cs" />
|
<Compile Include="History\HistoryModule.cs" />
|
||||||
<Compile Include="IndexerResource.cs" />
|
<Compile Include="ProviderResource.cs" />
|
||||||
<Compile Include="ProviderModuleBase.cs" />
|
<Compile Include="ProviderModuleBase.cs" />
|
||||||
<Compile Include="Indexers\IndexerSchemaModule.cs" />
|
<Compile Include="Indexers\IndexerSchemaModule.cs" />
|
||||||
<Compile Include="Indexers\IndexerModule.cs" />
|
<Compile Include="Indexers\IndexerModule.cs" />
|
||||||
|
|
|
@ -4,7 +4,6 @@ using FluentValidation;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using NzbDrone.Api.ClientSchema;
|
using NzbDrone.Api.ClientSchema;
|
||||||
using NzbDrone.Api.Extensions;
|
using NzbDrone.Api.Extensions;
|
||||||
using NzbDrone.Api.Indexers;
|
|
||||||
using NzbDrone.Api.Mapping;
|
using NzbDrone.Api.Mapping;
|
||||||
using NzbDrone.Common.Reflection;
|
using NzbDrone.Common.Reflection;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
@ -30,8 +29,6 @@ namespace NzbDrone.Api
|
||||||
UpdateResource = UpdateProvider;
|
UpdateResource = UpdateProvider;
|
||||||
DeleteResource = DeleteProvider;
|
DeleteResource = DeleteProvider;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
||||||
SharedValidator.RuleFor(c => c.Implementation).NotEmpty();
|
SharedValidator.RuleFor(c => c.Implementation).NotEmpty();
|
||||||
SharedValidator.RuleFor(c => c.ConfigContract).NotEmpty();
|
SharedValidator.RuleFor(c => c.ConfigContract).NotEmpty();
|
||||||
|
@ -69,39 +66,25 @@ namespace NzbDrone.Api
|
||||||
return indexer.Id;
|
return indexer.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateProvider(TProviderResource indexerResource)
|
private void UpdateProvider(TProviderResource providerResource)
|
||||||
{
|
{
|
||||||
var indexer = GetDefinition(indexerResource);
|
var providerDefinition = GetDefinition(providerResource);
|
||||||
|
|
||||||
ValidateIndexer(indexer);
|
Validate(providerDefinition);
|
||||||
|
|
||||||
_providerFactory.Update(indexer);
|
_providerFactory.Update(providerDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TProviderDefinition GetDefinition(TProviderResource providerResource)
|
||||||
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();
|
var definition = new TProviderDefinition();
|
||||||
|
|
||||||
definition.InjectFrom(indexerResource);
|
definition.InjectFrom(providerResource);
|
||||||
|
|
||||||
var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);
|
var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);
|
||||||
definition.Settings = (IProviderConfig)SchemaBuilder.ReadFormSchema(indexerResource.Fields, configContract);
|
definition.Settings = (IProviderConfig)SchemaBuilder.ReadFormSchema(providerResource.Fields, configContract);
|
||||||
|
|
||||||
ValidateIndexer(definition);
|
Validate(definition);
|
||||||
|
|
||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
|
@ -113,22 +96,30 @@ namespace NzbDrone.Api
|
||||||
|
|
||||||
private Response GetTemplates()
|
private Response GetTemplates()
|
||||||
{
|
{
|
||||||
|
var templates = _providerFactory.Templates();
|
||||||
|
|
||||||
var indexers = _providerFactory.Templates();
|
var result = new List<TProviderResource>(templates.Count());
|
||||||
|
|
||||||
|
foreach (var providerDefinition in templates)
|
||||||
var result = new List<IndexerResource>(indexers.Count());
|
|
||||||
|
|
||||||
foreach (var indexer in indexers)
|
|
||||||
{
|
{
|
||||||
var indexerResource = new IndexerResource();
|
var providerResource = new TProviderResource();
|
||||||
indexerResource.InjectFrom(indexer);
|
providerResource.InjectFrom(providerDefinition);
|
||||||
indexerResource.Fields = SchemaBuilder.ToSchema(indexer.Settings);
|
providerResource.Fields = SchemaBuilder.ToSchema(providerDefinition.Settings);
|
||||||
|
|
||||||
result.Add(indexerResource);
|
result.Add(providerResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.AsResponse();
|
return result.AsResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void Validate(TProviderDefinition definition)
|
||||||
|
{
|
||||||
|
var validationResult = definition.Settings.Validate();
|
||||||
|
|
||||||
|
if (!validationResult.IsValid)
|
||||||
|
{
|
||||||
|
throw new ValidationException(validationResult.Errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,7 +7,6 @@ namespace NzbDrone.Api
|
||||||
{
|
{
|
||||||
public class ProviderResource : RestResource
|
public class ProviderResource : RestResource
|
||||||
{
|
{
|
||||||
public Boolean Enable { get; set; }
|
|
||||||
public String Name { get; set; }
|
public String Name { get; set; }
|
||||||
public List<Field> Fields { get; set; }
|
public List<Field> Fields { get; set; }
|
||||||
public String Implementation { get; set; }
|
public String Implementation { get; set; }
|
|
@ -1,130 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using FizzWare.NBuilder;
|
|
||||||
using FluentAssertions;
|
|
||||||
using Moq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Common.Composition;
|
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
|
||||||
using NzbDrone.Core.Notifications;
|
|
||||||
using NzbDrone.Core.Notifications.Email;
|
|
||||||
using NzbDrone.Core.Notifications.Growl;
|
|
||||||
using NzbDrone.Core.Notifications.Plex;
|
|
||||||
using NzbDrone.Core.Notifications.Prowl;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
using NzbDrone.Core.Tv;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.NotificationTests
|
|
||||||
{
|
|
||||||
public class NotificationServiceFixture : DbTest<NotificationService, NotificationDefinition>
|
|
||||||
{
|
|
||||||
private List<INotification> _notifications;
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
{
|
|
||||||
_notifications = new List<INotification>();
|
|
||||||
|
|
||||||
_notifications.Add(new Notifications.Xbmc.Xbmc(null));
|
|
||||||
_notifications.Add(new PlexClient(null));
|
|
||||||
_notifications.Add(new PlexServer(null));
|
|
||||||
_notifications.Add(new Email(null));
|
|
||||||
_notifications.Add(new Growl(null));
|
|
||||||
_notifications.Add(new Prowl(null));
|
|
||||||
|
|
||||||
Mocker.SetConstant<IEnumerable<INotification>>(_notifications);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void getting_list_of_indexers_should_be_empty_by_default()
|
|
||||||
{
|
|
||||||
Mocker.SetConstant<INotificationRepository>(Mocker.Resolve<NotificationRepository>());
|
|
||||||
|
|
||||||
var notifications = Subject.All().ToList();
|
|
||||||
notifications.Should().BeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_be_able_to_get_schema_for_all_notifications()
|
|
||||||
{
|
|
||||||
Mocker.SetConstant<INotificationRepository>(Mocker.Resolve<NotificationRepository>());
|
|
||||||
|
|
||||||
Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(Notifications.Xbmc.Xbmc)))
|
|
||||||
.Returns(new Notifications.Xbmc.Xbmc(null));
|
|
||||||
|
|
||||||
Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(PlexClient)))
|
|
||||||
.Returns(new PlexClient(null));
|
|
||||||
|
|
||||||
Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(PlexServer)))
|
|
||||||
.Returns(new PlexServer(null));
|
|
||||||
|
|
||||||
Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(Email)))
|
|
||||||
.Returns(new Email(null));
|
|
||||||
|
|
||||||
Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(Growl)))
|
|
||||||
.Returns(new Growl(null));
|
|
||||||
|
|
||||||
Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(Prowl)))
|
|
||||||
.Returns(new Prowl(null));
|
|
||||||
|
|
||||||
var notifications = Subject.Schema().ToList();
|
|
||||||
notifications.Should().NotBeEmpty();
|
|
||||||
notifications.Should().NotContain(c => c.Settings == null);
|
|
||||||
notifications.Should().NotContain(c => c.Instance == null);
|
|
||||||
notifications.Should().NotContain(c => c.ImplementationName == null);
|
|
||||||
notifications.Select(c => c.ImplementationName).Should().OnlyHaveUniqueItems();
|
|
||||||
notifications.Select(c => c.Instance).Should().OnlyHaveUniqueItems();
|
|
||||||
notifications.Select(c => c.Id).Should().OnlyHaveUniqueItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
[Explicit]
|
|
||||||
public void should_try_other_notifiers_when_one_fails()
|
|
||||||
{
|
|
||||||
var notifications = Builder<NotificationDefinition>.CreateListOfSize(2)
|
|
||||||
.All()
|
|
||||||
.With(n => n.OnGrab = true)
|
|
||||||
.With(n => n.OnDownload = true)
|
|
||||||
.TheFirst(1)
|
|
||||||
.With(n => n.Implementation = "Xbmc")
|
|
||||||
.TheLast(1)
|
|
||||||
.With(n => n.Implementation = "Email")
|
|
||||||
.Build()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var series = Builder<Series>.CreateNew()
|
|
||||||
.With(s => s.SeriesType = SeriesTypes.Standard)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
var parsedEpisodeInfo = Builder<ParsedEpisodeInfo>.CreateNew()
|
|
||||||
.With(p => p.EpisodeNumbers = new int[] {1})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
var localEpisode = Builder<LocalEpisode>.CreateNew()
|
|
||||||
.With(e => e.Series = series)
|
|
||||||
.With(e => e.ParsedEpisodeInfo = parsedEpisodeInfo)
|
|
||||||
.With(e => e.Episodes = Builder<Episode>.CreateListOfSize(1)
|
|
||||||
.Build().ToList())
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
Mocker.GetMock<INotificationRepository>()
|
|
||||||
.Setup(s => s.All())
|
|
||||||
.Returns(notifications);
|
|
||||||
|
|
||||||
//Todo: How can we test this, right now without an empty constructor it won't work
|
|
||||||
Mocker.GetMock<Notifications.Xbmc.Xbmc>()
|
|
||||||
.Setup(s => s.OnDownload(It.IsAny<string>(), series))
|
|
||||||
.Throws(new SocketException());
|
|
||||||
|
|
||||||
Subject.Handle(new EpisodeDownloadedEvent(localEpisode));
|
|
||||||
|
|
||||||
Mocker.GetMock<Notifications.Xbmc.Xbmc>()
|
|
||||||
.Verify(v => v.OnDownload(It.IsAny<string>(), series), Times.Once());
|
|
||||||
|
|
||||||
Mocker.GetMock<Email>()
|
|
||||||
.Verify(v => v.OnDownload(It.IsAny<string>(), series), Times.Once());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -156,7 +156,6 @@
|
||||||
<Compile Include="Messaging\Commands\CommandFixture.cs" />
|
<Compile Include="Messaging\Commands\CommandFixture.cs" />
|
||||||
<Compile Include="Messaging\Events\EventAggregatorFixture.cs" />
|
<Compile Include="Messaging\Events\EventAggregatorFixture.cs" />
|
||||||
<Compile Include="MetadataSourceTests\TraktProxyFixture.cs" />
|
<Compile Include="MetadataSourceTests\TraktProxyFixture.cs" />
|
||||||
<Compile Include="NotificationTests\NotificationServiceFixture.cs" />
|
|
||||||
<Compile Include="NotificationTests\Xbmc\GetJsonVersionFixture.cs" />
|
<Compile Include="NotificationTests\Xbmc\GetJsonVersionFixture.cs" />
|
||||||
<Compile Include="NotificationTests\Xbmc\Http\ActivePlayersFixture.cs" />
|
<Compile Include="NotificationTests\Xbmc\Http\ActivePlayersFixture.cs" />
|
||||||
<Compile Include="NotificationTests\Xbmc\Http\CheckForErrorFixture.cs" />
|
<Compile Include="NotificationTests\Xbmc\Http\CheckForErrorFixture.cs" />
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,68 +0,0 @@
|
||||||
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<dynamic>();
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(25)]
|
||||||
|
public class move_notification_to_generic_provider : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("Notifications").AddColumn("ConfigContract").AsString().Nullable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(26)]
|
||||||
|
public class add_config_contract_to_notifications : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "EmailSettings" }).Where(new { Implementation = "Email" });
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "GrowlSettings" }).Where(new { Implementation = "Growl" });
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "NotifyMyAndroidSettings" }).Where(new { Implementation = "NotifyMyAndroid" });
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "PlexClientSettings" }).Where(new { Implementation = "PlexClient" });
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "PlexServerSettings" }).Where(new { Implementation = "PlexServer" });
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "ProwlSettings" }).Where(new { Implementation = "Prowl" });
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "PushBulletSettings" }).Where(new { Implementation = "PushBullet" });
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "PushoverSettings" }).Where(new { Implementation = "Pushover" });
|
||||||
|
Update.Table("Notifications").Set(new { ConfigContract = "XbmcSettings" }).Where(new { Implementation = "Xbmc" });
|
||||||
|
|
||||||
|
Delete.FromTable("Notifications").IsNull("ConfigContract");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,12 +35,13 @@ namespace NzbDrone.Core.Datastore
|
||||||
|
|
||||||
Mapper.Entity<IndexerDefinition>().RegisterModel("Indexers");
|
Mapper.Entity<IndexerDefinition>().RegisterModel("Indexers");
|
||||||
Mapper.Entity<ScheduledTask>().RegisterModel("ScheduledTasks");
|
Mapper.Entity<ScheduledTask>().RegisterModel("ScheduledTasks");
|
||||||
Mapper.Entity<NotificationDefinition>().RegisterModel("Notifications");
|
Mapper.Entity<NotificationDefinition>()
|
||||||
|
.RegisterModel("Notifications");
|
||||||
|
|
||||||
Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings");
|
Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings");
|
||||||
|
|
||||||
Mapper.Entity<History.History>().RegisterModel("History")
|
Mapper.Entity<History.History>().RegisterModel("History")
|
||||||
.AutoMapChildModels();
|
.AutoMapChildModels();
|
||||||
|
|
||||||
Mapper.Entity<Series>().RegisterModel("Series")
|
Mapper.Entity<Series>().RegisterModel("Series")
|
||||||
.Ignore(s => s.RootFolderPath)
|
.Ignore(s => s.RootFolderPath)
|
||||||
|
@ -96,7 +97,6 @@ namespace NzbDrone.Core.Datastore
|
||||||
{
|
{
|
||||||
var embeddedTypes = typeof(IEmbeddedDocument).Assembly.ImplementationsOf<IEmbeddedDocument>();
|
var embeddedTypes = typeof(IEmbeddedDocument).Assembly.ImplementationsOf<IEmbeddedDocument>();
|
||||||
|
|
||||||
|
|
||||||
var embeddedConvertor = new EmbeddedDocumentConverter();
|
var embeddedConvertor = new EmbeddedDocumentConverter();
|
||||||
var genericListDefinition = typeof(List<>).GetGenericTypeDefinition();
|
var genericListDefinition = typeof(List<>).GetGenericTypeDefinition();
|
||||||
foreach (var embeddedType in embeddedTypes)
|
foreach (var embeddedType in embeddedTypes)
|
||||||
|
|
|
@ -4,5 +4,6 @@ namespace NzbDrone.Core.Indexers
|
||||||
{
|
{
|
||||||
public class IndexerDefinition : ProviderDefinition
|
public class IndexerDefinition : ProviderDefinition
|
||||||
{
|
{
|
||||||
|
public bool Enable { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,7 +31,6 @@ namespace NzbDrone.Core.Indexers
|
||||||
|
|
||||||
var newProviders = definitions.Where(def => currentProviders.All(c => c.Implementation != def.Implementation)).ToList();
|
var newProviders = definitions.Where(def => currentProviders.All(c => c.Implementation != def.Implementation)).ToList();
|
||||||
|
|
||||||
|
|
||||||
if (newProviders.Any())
|
if (newProviders.Any())
|
||||||
{
|
{
|
||||||
_providerRepository.InsertMany(newProviders.Cast<IndexerDefinition>().ToList());
|
_providerRepository.InsertMany(newProviders.Cast<IndexerDefinition>().ToList());
|
||||||
|
|
|
@ -16,7 +16,6 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class NewznabSettings : IProviderConfig
|
public class NewznabSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
private static readonly NewznabSettingsValidator Validator = new NewznabSettingsValidator();
|
private static readonly NewznabSettingsValidator Validator = new NewznabSettingsValidator();
|
||||||
|
|
|
@ -12,16 +12,6 @@ namespace NzbDrone.Core.Notifications.Email
|
||||||
_smtpProvider = smtpProvider;
|
_smtpProvider = smtpProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "Email"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "Email"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return null; }
|
get { return null; }
|
||||||
|
|
|
@ -1,12 +1,26 @@
|
||||||
using System;
|
using System;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Email
|
namespace NzbDrone.Core.Notifications.Email
|
||||||
{
|
{
|
||||||
|
public class EmailSettingsValidator : AbstractValidator<EmailSettings>
|
||||||
|
{
|
||||||
|
public EmailSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.Server).NotEmpty();
|
||||||
|
RuleFor(c => c.Port).GreaterThan(0);
|
||||||
|
RuleFor(c => c.From).NotEmpty();
|
||||||
|
RuleFor(c => c.To).NotEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class EmailSettings : IProviderConfig
|
public class EmailSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly EmailSettingsValidator Validator = new EmailSettingsValidator();
|
||||||
|
|
||||||
public EmailSettings()
|
public EmailSettings()
|
||||||
{
|
{
|
||||||
Port = 25;
|
Port = 25;
|
||||||
|
@ -43,7 +57,7 @@ namespace NzbDrone.Core.Notifications.Email
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Growl
|
||||||
_growlProvider = growlProvider;
|
_growlProvider = growlProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "Growl"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "Growl"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return "http://growl.info/"; }
|
get { return "http://growl.info/"; }
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
using System;
|
using System;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Growl
|
namespace NzbDrone.Core.Notifications.Growl
|
||||||
{
|
{
|
||||||
|
public class GrowlSettingsValidator : AbstractValidator<GrowlSettings>
|
||||||
|
{
|
||||||
|
public GrowlSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.Host).NotEmpty();
|
||||||
|
RuleFor(c => c.Port).GreaterThan(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class GrowlSettings : IProviderConfig
|
public class GrowlSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly GrowlSettingsValidator Validator = new GrowlSettingsValidator();
|
||||||
|
|
||||||
public GrowlSettings()
|
public GrowlSettings()
|
||||||
{
|
{
|
||||||
Port = 23053;
|
Port = 23053;
|
||||||
|
@ -31,7 +43,7 @@ namespace NzbDrone.Core.Notifications.Growl
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications
|
namespace NzbDrone.Core.Notifications
|
||||||
{
|
{
|
||||||
public interface INotification
|
public interface INotification : IProvider
|
||||||
{
|
{
|
||||||
string Name { get; }
|
|
||||||
string ImplementationName { get; }
|
|
||||||
string Link { get; }
|
string Link { get; }
|
||||||
|
|
||||||
NotificationDefinition InstanceDefinition { get; set; }
|
|
||||||
|
|
||||||
void OnGrab(string message);
|
void OnGrab(string message);
|
||||||
void OnDownload(string message, Series series);
|
void OnDownload(string message, Series series);
|
||||||
void AfterRename(Series series);
|
void AfterRename(Series series);
|
||||||
|
|
|
@ -1,28 +1,47 @@
|
||||||
using NzbDrone.Common.Serializer;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications
|
namespace NzbDrone.Core.Notifications
|
||||||
{
|
{
|
||||||
public abstract class NotificationBase<TSetting> : INotification where TSetting : class, IProviderConfig, new()
|
public abstract class NotificationBase<TSettings> : INotification where TSettings : IProviderConfig, new()
|
||||||
{
|
{
|
||||||
public abstract string Name { get; }
|
public Type ConfigContract
|
||||||
public abstract string ImplementationName { get; }
|
{
|
||||||
public abstract string Link { get; }
|
get
|
||||||
|
{
|
||||||
|
return typeof(TSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public NotificationDefinition InstanceDefinition { get; set; }
|
public IEnumerable<ProviderDefinition> DefaultDefinitions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new List<ProviderDefinition>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProviderDefinition Definition { get; set; }
|
||||||
|
|
||||||
|
public abstract string Link { get; }
|
||||||
|
|
||||||
public abstract void OnGrab(string message);
|
public abstract void OnGrab(string message);
|
||||||
public abstract void OnDownload(string message, Series series);
|
public abstract void OnDownload(string message, Series series);
|
||||||
public abstract void AfterRename(Series series);
|
public abstract void AfterRename(Series series);
|
||||||
|
|
||||||
public TSetting Settings { get; private set; }
|
protected TSettings Settings
|
||||||
|
|
||||||
public TSetting ImportSettingsFromJson(string json)
|
|
||||||
{
|
{
|
||||||
Settings = Json.Deserialize<TSetting>(json) ?? new TSetting();
|
get
|
||||||
|
{
|
||||||
|
return (TSettings)Definition.Settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Settings;
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return GetType().Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using NzbDrone.Core.Datastore;
|
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications
|
namespace NzbDrone.Core.Notifications
|
||||||
{
|
{
|
||||||
public class NotificationDefinition : ModelBase
|
public class NotificationDefinition : ProviderDefinition
|
||||||
{
|
|
||||||
public String Name { get; set; }
|
|
||||||
public Boolean OnGrab { get; set; }
|
|
||||||
public Boolean OnDownload { get; set; }
|
|
||||||
public String Settings { get; set; }
|
|
||||||
public String Implementation { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class NotificationProviderModel : ProviderDefinition
|
|
||||||
{
|
{
|
||||||
public Boolean OnGrab { get; set; }
|
public Boolean OnGrab { get; set; }
|
||||||
public Boolean OnDownload { get; set; }
|
public Boolean OnDownload { get; set; }
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Notifications
|
||||||
|
{
|
||||||
|
public interface INotificationFactory : IProviderFactory<INotification, NotificationDefinition>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NotificationFactory : ProviderFactory<INotification, NotificationDefinition>, INotificationFactory
|
||||||
|
{
|
||||||
|
public NotificationFactory(INotificationRepository providerRepository, IEnumerable<INotification> providers, Logger logger)
|
||||||
|
: base(providerRepository, providers, logger)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +1,20 @@
|
||||||
using System;
|
using NzbDrone.Core.Datastore;
|
||||||
using System.Linq;
|
|
||||||
using NzbDrone.Core.Datastore;
|
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications
|
namespace NzbDrone.Core.Notifications
|
||||||
{
|
{
|
||||||
public interface INotificationRepository : IBasicRepository<NotificationDefinition>
|
public interface INotificationRepository : IProviderRepository<NotificationDefinition>
|
||||||
{
|
{
|
||||||
NotificationDefinition Get(string name);
|
|
||||||
NotificationDefinition Find(string name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NotificationRepository : BasicRepository<NotificationDefinition>, INotificationRepository
|
public class NotificationRepository : ProviderRepository<NotificationDefinition>, INotificationRepository
|
||||||
{
|
{
|
||||||
public NotificationRepository(IDatabase database, IEventAggregator eventAggregator)
|
public NotificationRepository(IDatabase database, IEventAggregator eventAggregator)
|
||||||
: base(database, eventAggregator)
|
: base(database, eventAggregator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotificationDefinition Get(string name)
|
|
||||||
{
|
|
||||||
return Query.Single(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
|
|
||||||
}
|
|
||||||
|
|
||||||
public NotificationDefinition Find(string name)
|
|
||||||
{
|
|
||||||
return Query.SingleOrDefault(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,214 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Common.Composition;
|
|
||||||
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;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications
|
|
||||||
{
|
|
||||||
public interface INotificationService
|
|
||||||
{
|
|
||||||
List<Notification> All();
|
|
||||||
Notification Get(int id);
|
|
||||||
List<Notification> Schema();
|
|
||||||
Notification Create(Notification notification);
|
|
||||||
void Update(Notification notification);
|
|
||||||
void Delete(int id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NotificationService
|
|
||||||
: INotificationService,
|
|
||||||
IHandle<EpisodeGrabbedEvent>,
|
|
||||||
IHandle<EpisodeDownloadedEvent>,
|
|
||||||
IHandle<SeriesRenamedEvent>
|
|
||||||
{
|
|
||||||
private readonly INotificationRepository _notificationRepository;
|
|
||||||
private readonly IContainer _container;
|
|
||||||
private readonly List<INotification> _notifications;
|
|
||||||
private readonly Logger _logger;
|
|
||||||
|
|
||||||
public NotificationService(INotificationRepository notificationRepository,
|
|
||||||
IEnumerable<INotification> notifications,
|
|
||||||
IContainer container,
|
|
||||||
Logger logger)
|
|
||||||
{
|
|
||||||
_notificationRepository = notificationRepository;
|
|
||||||
_container = container;
|
|
||||||
_notifications = notifications.ToList();
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Notification> All()
|
|
||||||
{
|
|
||||||
return _notificationRepository.All().Select(ToNotification).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification Get(int id)
|
|
||||||
{
|
|
||||||
return ToNotification(_notificationRepository.Get(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Notification> Schema()
|
|
||||||
{
|
|
||||||
var notifications = new List<Notification>();
|
|
||||||
|
|
||||||
int i = 1;
|
|
||||||
foreach (var notification in _notifications)
|
|
||||||
{
|
|
||||||
var type = notification.GetType();
|
|
||||||
|
|
||||||
var newNotification = new Notification();
|
|
||||||
newNotification.Instance = (INotification)_container.Resolve(type);
|
|
||||||
newNotification.Id = i;
|
|
||||||
newNotification.ImplementationName = notification.ImplementationName;
|
|
||||||
newNotification.Link = notification.Link;
|
|
||||||
|
|
||||||
var instanceType = newNotification.Instance.GetType();
|
|
||||||
var baseGenArgs = instanceType.BaseType.GetGenericArguments();
|
|
||||||
newNotification.Settings = (IProviderConfig)Activator.CreateInstance(baseGenArgs[0]);
|
|
||||||
newNotification.Implementation = type.Name;
|
|
||||||
|
|
||||||
notifications.Add(newNotification);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return notifications.OrderBy(n => n.Name).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification Create(Notification notification)
|
|
||||||
{
|
|
||||||
var definition = new NotificationDefinition();
|
|
||||||
definition.InjectFrom(notification);
|
|
||||||
definition.Settings = notification.Settings.ToJson();
|
|
||||||
|
|
||||||
definition = _notificationRepository.Insert(definition);
|
|
||||||
notification.Id = definition.Id;
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(Notification notification)
|
|
||||||
{
|
|
||||||
var definition = _notificationRepository.Get(notification.Id);
|
|
||||||
definition.InjectFrom(notification);
|
|
||||||
definition.Settings = notification.Settings.ToJson();
|
|
||||||
|
|
||||||
_notificationRepository.Update(definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Delete(int id)
|
|
||||||
{
|
|
||||||
_notificationRepository.Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Notification ToNotification(NotificationDefinition definition)
|
|
||||||
{
|
|
||||||
var notification = new Notification();
|
|
||||||
notification.Id = definition.Id;
|
|
||||||
notification.OnGrab = definition.OnGrab;
|
|
||||||
notification.OnDownload = definition.OnDownload;
|
|
||||||
notification.Instance = GetInstance(definition);
|
|
||||||
notification.Name = definition.Name;
|
|
||||||
notification.Implementation = definition.Implementation;
|
|
||||||
notification.ImplementationName = notification.Instance.ImplementationName;
|
|
||||||
notification.Settings = ((dynamic)notification.Instance).ImportSettingsFromJson(definition.Settings);
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
}
|
|
||||||
|
|
||||||
private INotification GetInstance(NotificationDefinition indexerDefinition)
|
|
||||||
{
|
|
||||||
var type = _notifications.Single(c => c.GetType().Name.Equals(indexerDefinition.Implementation, StringComparison.InvariantCultureIgnoreCase)).GetType();
|
|
||||||
|
|
||||||
var instance = (INotification)_container.Resolve(type);
|
|
||||||
|
|
||||||
instance.InstanceDefinition = indexerDefinition;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetMessage(Series series, List<Episode> episodes, QualityModel quality)
|
|
||||||
{
|
|
||||||
if (series.SeriesType == SeriesTypes.Daily)
|
|
||||||
{
|
|
||||||
var episode = episodes.First();
|
|
||||||
|
|
||||||
return String.Format("{0} - {1} - {2} [{3}]",
|
|
||||||
series.Title,
|
|
||||||
episode.AirDate,
|
|
||||||
episode.Title,
|
|
||||||
quality);
|
|
||||||
}
|
|
||||||
|
|
||||||
var episodeNumbers = String.Concat(episodes.Select(e => e.EpisodeNumber)
|
|
||||||
.Select(i => String.Format("x{0:00}", i)));
|
|
||||||
|
|
||||||
var episodeTitles = String.Join(" + ", episodes.Select(e => e.Title));
|
|
||||||
|
|
||||||
return String.Format("{0} - {1}{2} - {3} {4}",
|
|
||||||
series.Title,
|
|
||||||
episodes.First().SeasonNumber,
|
|
||||||
episodeNumbers,
|
|
||||||
episodeTitles,
|
|
||||||
quality);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Handle(EpisodeGrabbedEvent message)
|
|
||||||
{
|
|
||||||
var messageBody = GetMessage(message.Episode.Series, message.Episode.Episodes, message.Episode.ParsedEpisodeInfo.Quality);
|
|
||||||
|
|
||||||
foreach (var notification in All().Where(n => n.OnGrab))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
notification.Instance.OnGrab(messageBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Unable to send OnGrab notification to: " + notification.Name, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Handle(EpisodeDownloadedEvent message)
|
|
||||||
{
|
|
||||||
var messageBody = GetMessage(message.Episode.Series, message.Episode.Episodes, message.Episode.ParsedEpisodeInfo.Quality);
|
|
||||||
|
|
||||||
foreach (var notification in All().Where(n => n.OnDownload))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
notification.Instance.OnDownload(messageBody, message.Episode.Series);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.WarnException("Unable to send OnDownload notification to: " + notification.Name, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Handle(SeriesRenamedEvent message)
|
|
||||||
{
|
|
||||||
foreach (var notification in All().Where(n => n.OnDownload))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
notification.Instance.AfterRename(message.Series);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.WarnException("Unable to send AfterRename notification to: " + notification.Name, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
using NzbDrone.Common.Serializer;
|
|
||||||
using NzbDrone.Core.ThingiProvider;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications
|
|
||||||
{
|
|
||||||
public interface INotificationSettingsProvider
|
|
||||||
{
|
|
||||||
TSetting Get<TSetting>(INotification indexer) where TSetting : IProviderConfig, new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NotificationSettingsProvider : INotificationSettingsProvider
|
|
||||||
{
|
|
||||||
private readonly INotificationRepository _notificationRepository;
|
|
||||||
|
|
||||||
public NotificationSettingsProvider(INotificationRepository notificationRepository)
|
|
||||||
{
|
|
||||||
_notificationRepository = notificationRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TSetting Get<TSetting>(INotification indexer) where TSetting : IProviderConfig, new()
|
|
||||||
{
|
|
||||||
var indexerDef = _notificationRepository.Find(indexer.Name);
|
|
||||||
|
|
||||||
if (indexerDef == null || string.IsNullOrWhiteSpace(indexerDef.Settings))
|
|
||||||
{
|
|
||||||
return new TSetting();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Json.Deserialize<TSetting>(indexerDef.Settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
||||||
_notifyMyAndroidProxy = notifyMyAndroidProxy;
|
_notifyMyAndroidProxy = notifyMyAndroidProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "NotifyMyAndroid"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "NotifyMyAndroid"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return "http://www.notifymyandroid.com/"; }
|
get { return "http://www.notifymyandroid.com/"; }
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
using System;
|
using System;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
||||||
{
|
{
|
||||||
|
public class NotifyMyAndroidSettingsValidator : AbstractValidator<NotifyMyAndroidSettings>
|
||||||
|
{
|
||||||
|
public NotifyMyAndroidSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.ApiKey).NotEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class NotifyMyAndroidSettings : IProviderConfig
|
public class NotifyMyAndroidSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly NotifyMyAndroidSettingsValidator Validator = new NotifyMyAndroidSettingsValidator();
|
||||||
|
|
||||||
[FieldDefinition(0, Label = "API Key", HelpLink = "http://www.notifymyandroid.com/")]
|
[FieldDefinition(0, Label = "API Key", HelpLink = "http://www.notifymyandroid.com/")]
|
||||||
public String ApiKey { get; set; }
|
public String ApiKey { get; set; }
|
||||||
|
|
||||||
|
@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||||
_plexProvider = plexProvider;
|
_plexProvider = plexProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "Plex Client"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "Plex Client"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return "http://www.plexapp.com/"; }
|
get { return "http://www.plexapp.com/"; }
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
using System;
|
using System;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Plex
|
namespace NzbDrone.Core.Notifications.Plex
|
||||||
{
|
{
|
||||||
|
public class PlexClientSettingsValidator : AbstractValidator<PlexClientSettings>
|
||||||
|
{
|
||||||
|
public PlexClientSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.Host).NotEmpty();
|
||||||
|
RuleFor(c => c.Port).GreaterThan(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class PlexClientSettings : IProviderConfig
|
public class PlexClientSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly PlexClientSettingsValidator Validator = new PlexClientSettingsValidator();
|
||||||
|
|
||||||
public PlexClientSettings()
|
public PlexClientSettings()
|
||||||
{
|
{
|
||||||
Port = 3000;
|
Port = 3000;
|
||||||
|
@ -34,7 +46,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||||
_plexProvider = plexProvider;
|
_plexProvider = plexProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "Plex Server"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "Plex Server"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return "http://www.plexapp.com/"; }
|
get { return "http://www.plexapp.com/"; }
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
using System;
|
using System;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Plex
|
namespace NzbDrone.Core.Notifications.Plex
|
||||||
{
|
{
|
||||||
|
public class PlexServerSettingsValidator : AbstractValidator<PlexServerSettings>
|
||||||
|
{
|
||||||
|
public PlexServerSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.Host).NotEmpty();
|
||||||
|
RuleFor(c => c.Port).GreaterThan(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class PlexServerSettings : IProviderConfig
|
public class PlexServerSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly PlexServerSettingsValidator Validator = new PlexServerSettingsValidator();
|
||||||
|
|
||||||
public PlexServerSettings()
|
public PlexServerSettings()
|
||||||
{
|
{
|
||||||
Port = 32400;
|
Port = 32400;
|
||||||
|
@ -31,7 +43,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,6 @@ namespace NzbDrone.Core.Notifications.Prowl
|
||||||
_prowlProvider = prowlProvider;
|
_prowlProvider = prowlProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "Prowl"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "Prowl"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return "http://www.prowlapp.com/"; }
|
get { return "http://www.prowlapp.com/"; }
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
using System;
|
using System;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Prowl
|
namespace NzbDrone.Core.Notifications.Prowl
|
||||||
{
|
{
|
||||||
|
public class ProwlSettingsValidator : AbstractValidator<ProwlSettings>
|
||||||
|
{
|
||||||
|
public ProwlSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.ApiKey).NotEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class ProwlSettings : IProviderConfig
|
public class ProwlSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly ProwlSettingsValidator Validator = new ProwlSettingsValidator();
|
||||||
|
|
||||||
[FieldDefinition(0, Label = "API Key", HelpLink = "https://www.prowlapp.com/api_settings.php")]
|
[FieldDefinition(0, Label = "API Key", HelpLink = "https://www.prowlapp.com/api_settings.php")]
|
||||||
public String ApiKey { get; set; }
|
public String ApiKey { get; set; }
|
||||||
|
|
||||||
|
@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Prowl
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
||||||
_pushBulletProxy = pushBulletProxy;
|
_pushBulletProxy = pushBulletProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "PushBullet"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "PushBullet"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return "https://www.pushbullet.com/"; }
|
get { return "https://www.pushbullet.com/"; }
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
using System;
|
using System;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.PushBullet
|
namespace NzbDrone.Core.Notifications.PushBullet
|
||||||
{
|
{
|
||||||
|
public class PushBulletSettingsValidator : AbstractValidator<PushBulletSettings>
|
||||||
|
{
|
||||||
|
public PushBulletSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.ApiKey).NotEmpty();
|
||||||
|
RuleFor(c => c.DeviceId).GreaterThan(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class PushBulletSettings : IProviderConfig
|
public class PushBulletSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly PushBulletSettingsValidator Validator = new PushBulletSettingsValidator();
|
||||||
|
|
||||||
[FieldDefinition(0, Label = "API Key", HelpLink = "https://www.pushbullet.com/")]
|
[FieldDefinition(0, Label = "API Key", HelpLink = "https://www.pushbullet.com/")]
|
||||||
public String ApiKey { get; set; }
|
public String ApiKey { get; set; }
|
||||||
|
|
||||||
|
@ -23,7 +35,7 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Pushover
|
||||||
_pushoverProxy = pushoverProxy;
|
_pushoverProxy = pushoverProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "Pushover"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "Pushover"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return "https://pushover.net/"; }
|
get { return "https://pushover.net/"; }
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
using System;
|
using System;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Pushover
|
namespace NzbDrone.Core.Notifications.Pushover
|
||||||
{
|
{
|
||||||
|
public class PushoverSettingsValidator : AbstractValidator<PushoverSettings>
|
||||||
|
{
|
||||||
|
public PushoverSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.UserKey).NotEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class PushoverSettings : IProviderConfig
|
public class PushoverSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly PushoverSettingsValidator Validator = new PushoverSettingsValidator();
|
||||||
|
|
||||||
[FieldDefinition(0, Label = "User Key", HelpLink = "https://pushover.net/")]
|
[FieldDefinition(0, Label = "User Key", HelpLink = "https://pushover.net/")]
|
||||||
public String UserKey { get; set; }
|
public String UserKey { get; set; }
|
||||||
|
|
||||||
|
@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Pushover
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
||||||
_xbmcProvider = xbmcProvider;
|
_xbmcProvider = xbmcProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get { return "XBMC"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ImplementationName
|
|
||||||
{
|
|
||||||
get { return "XBMC"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Link
|
public override string Link
|
||||||
{
|
{
|
||||||
get { return "http://xbmc.org/"; }
|
get { return "http://xbmc.org/"; }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
|
@ -7,8 +8,19 @@ using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Xbmc
|
namespace NzbDrone.Core.Notifications.Xbmc
|
||||||
{
|
{
|
||||||
|
public class XbmcSettingsValidator : AbstractValidator<XbmcSettings>
|
||||||
|
{
|
||||||
|
public XbmcSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.Host).NotEmpty();
|
||||||
|
RuleFor(c => c.DisplayTime).GreaterThan(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class XbmcSettings : IProviderConfig
|
public class XbmcSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
|
private static readonly XbmcSettingsValidator Validator = new XbmcSettingsValidator();
|
||||||
|
|
||||||
public XbmcSettings()
|
public XbmcSettings()
|
||||||
{
|
{
|
||||||
DisplayTime = 5;
|
DisplayTime = 5;
|
||||||
|
@ -56,7 +68,7 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
||||||
|
|
||||||
public ValidationResult Validate()
|
public ValidationResult Validate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Validator.Validate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,9 +173,11 @@
|
||||||
<Compile Include="Datastore\Migration\019_restore_unique_constraints.cs" />
|
<Compile Include="Datastore\Migration\019_restore_unique_constraints.cs" />
|
||||||
<Compile Include="Datastore\Migration\020_add_year_and_seasons_to_series.cs" />
|
<Compile Include="Datastore\Migration\020_add_year_and_seasons_to_series.cs" />
|
||||||
<Compile Include="Datastore\Migration\021_drop_seasons_table.cs" />
|
<Compile Include="Datastore\Migration\021_drop_seasons_table.cs" />
|
||||||
<Compile Include="Datastore\Migration\022_move_notification_to_generic_provider.cs" />
|
<Compile Include="Datastore\Migration\022_move_indexer_to_generic_provider.cs" />
|
||||||
<Compile Include="Datastore\Migration\023_add_config_contract_to_indexers.cs" />
|
<Compile Include="Datastore\Migration\023_add_config_contract_to_indexers.cs" />
|
||||||
<Compile Include="Datastore\Migration\024_drop_tvdb_episodeid.cs" />
|
<Compile Include="Datastore\Migration\024_drop_tvdb_episodeid.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\026_add_config_contract_to_notifications.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\025_move_notification_to_generic_provider.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
||||||
|
@ -269,6 +271,7 @@
|
||||||
<Compile Include="Messaging\Events\IEventAggregator.cs" />
|
<Compile Include="Messaging\Events\IEventAggregator.cs" />
|
||||||
<Compile Include="Messaging\Events\IHandle.cs" />
|
<Compile Include="Messaging\Events\IHandle.cs" />
|
||||||
<Compile Include="MetadataSource\Trakt\TraktException.cs" />
|
<Compile Include="MetadataSource\Trakt\TraktException.cs" />
|
||||||
|
<Compile Include="Notifications\NotificationFactory.cs" />
|
||||||
<Compile Include="Notifications\PushBullet\PushBullet.cs" />
|
<Compile Include="Notifications\PushBullet\PushBullet.cs" />
|
||||||
<Compile Include="Notifications\PushBullet\PushBulletProxy.cs" />
|
<Compile Include="Notifications\PushBullet\PushBulletProxy.cs" />
|
||||||
<Compile Include="Notifications\PushBullet\PushBulletSettings.cs" />
|
<Compile Include="Notifications\PushBullet\PushBulletSettings.cs" />
|
||||||
|
@ -328,10 +331,8 @@
|
||||||
<Compile Include="Notifications\Email\TestEmailCommand.cs" />
|
<Compile Include="Notifications\Email\TestEmailCommand.cs" />
|
||||||
<Compile Include="Notifications\Growl\GrowlSettings.cs" />
|
<Compile Include="Notifications\Growl\GrowlSettings.cs" />
|
||||||
<Compile Include="Notifications\Growl\TestGrowlCommand.cs" />
|
<Compile Include="Notifications\Growl\TestGrowlCommand.cs" />
|
||||||
<Compile Include="Notifications\NotificationSettingsProvider.cs" />
|
|
||||||
<Compile Include="Notifications\INotification.cs" />
|
<Compile Include="Notifications\INotification.cs" />
|
||||||
<Compile Include="Notifications\Notification.cs" />
|
<Compile Include="Notifications\Notification.cs" />
|
||||||
<Compile Include="Notifications\NotificationService.cs" />
|
|
||||||
<Compile Include="Notifications\NotificationRepository.cs" />
|
<Compile Include="Notifications\NotificationRepository.cs" />
|
||||||
<Compile Include="Fluent.cs" />
|
<Compile Include="Fluent.cs" />
|
||||||
<Compile Include="History\HistoryRepository.cs" />
|
<Compile Include="History\HistoryRepository.cs" />
|
||||||
|
|
|
@ -7,7 +7,6 @@ namespace NzbDrone.Core.ThingiProvider
|
||||||
private IProviderConfig _settings;
|
private IProviderConfig _settings;
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Implementation { get; set; }
|
public string Implementation { get; set; }
|
||||||
public bool Enable { get; set; }
|
|
||||||
|
|
||||||
public string ConfigContract { get; set; }
|
public string ConfigContract { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace NzbDrone.Core.ThingiProvider
|
||||||
|
|
||||||
public List<TProvider> GetAvailableProviders()
|
public List<TProvider> GetAvailableProviders()
|
||||||
{
|
{
|
||||||
return All().Where(c => c.Enable && c.Settings.Validate().IsValid)
|
return All().Where(c => c.Settings.Validate().IsValid)
|
||||||
.Select(GetInstance).ToList();
|
.Select(GetInstance).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="add-notification-item span3">
|
<div class="add-notification-item span3">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span3">
|
<div class="span3">
|
||||||
{{implementationName}}
|
{{implementation}}
|
||||||
{{#if link}}
|
{{#if link}}
|
||||||
<a href="{{link}}"><i class="icon-info-sign"/></a>
|
<a href="{{link}}"><i class="icon-info-sign"/></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
define([
|
define([
|
||||||
'AppLayout',
|
'AppLayout',
|
||||||
'marionette',
|
'marionette',
|
||||||
'Settings/Notifications/EditView'
|
'Settings/Notifications/NotificationEditView'
|
||||||
], function (AppLayout, Marionette, EditView) {
|
], function (AppLayout, Marionette, EditView) {
|
||||||
|
|
||||||
return Marionette.ItemView.extend({
|
return Marionette.ItemView.extend({
|
||||||
|
|
|
@ -8,13 +8,13 @@ define(
|
||||||
'Settings/Notifications/DeleteView',
|
'Settings/Notifications/DeleteView',
|
||||||
'Commands/CommandController',
|
'Commands/CommandController',
|
||||||
'Mixins/AsModelBoundView',
|
'Mixins/AsModelBoundView',
|
||||||
'Form/FormBuilder',
|
'underscore',
|
||||||
'underscore'
|
'Form/FormBuilder'
|
||||||
|
|
||||||
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, _) {
|
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, _) {
|
||||||
|
|
||||||
var model = Marionette.ItemView.extend({
|
var model = Marionette.ItemView.extend({
|
||||||
template: 'Settings/Notifications/EditTemplate',
|
template: 'Settings/Notifications/NotificationEditViewTemplate',
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click .x-save' : '_saveNotification',
|
'click .x-save' : '_saveNotification',
|
||||||
|
@ -24,11 +24,6 @@ define(
|
||||||
'click .x-test' : '_test'
|
'click .x-test' : '_test'
|
||||||
},
|
},
|
||||||
|
|
||||||
ui: {
|
|
||||||
testButton: '.x-test',
|
|
||||||
testIcon : '.x-test-icon'
|
|
||||||
},
|
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
this.notificationCollection = options.notificationCollection;
|
this.notificationCollection = options.notificationCollection;
|
||||||
},
|
},
|
||||||
|
@ -68,24 +63,14 @@ define(
|
||||||
},
|
},
|
||||||
|
|
||||||
_test: function () {
|
_test: function () {
|
||||||
var testCommand = this.model.get('testCommand');
|
var testCommand = 'test{0}'.format(this.model.get('implementation'));
|
||||||
if (testCommand) {
|
var properties = {};
|
||||||
this.idle = false;
|
|
||||||
var properties = {};
|
|
||||||
|
|
||||||
_.each(this.model.get('fields'), function (field) {
|
_.each(this.model.get('fields'), function (field) {
|
||||||
properties[field.name] = field.value;
|
properties[field.name] = field.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
CommandController.Execute(testCommand, properties);
|
||||||
CommandController.Execute(testCommand, properties);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_testOnAlways: function () {
|
|
||||||
if (!this.isClosed) {
|
|
||||||
this.idle = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
{{#if id}}
|
{{#if id}}
|
||||||
<h3>Edit - {{implementationName}}</h3>
|
<h3>Edit - {{implementation}}</h3>
|
||||||
{{else}}
|
{{else}}
|
||||||
<h3>Add - {{implementationName}}</h3>
|
<h3>Add - {{implementation}}</h3>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
Loading…
Reference in New Issue