mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-10-03 09:09:42 +02:00
Add support for Applications
This commit is contained in:
48
src/NzbDrone.Core/Applications/ApplicationBase.cs
Normal file
48
src/NzbDrone.Core/Applications/ApplicationBase.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Applications
|
||||
{
|
||||
public abstract class ApplicationBase<TSettings> : IApplications
|
||||
where TSettings : IProviderConfig, new()
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
|
||||
public Type ConfigContract => typeof(TSettings);
|
||||
|
||||
public virtual ProviderMessage Message => null;
|
||||
|
||||
public ProviderDefinition Definition { get; set; }
|
||||
public abstract ValidationResult Test();
|
||||
|
||||
protected TSettings Settings => (TSettings)Definition.Settings;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return GetType().Name;
|
||||
}
|
||||
|
||||
public virtual IEnumerable<ProviderDefinition> DefaultDefinitions
|
||||
{
|
||||
get
|
||||
{
|
||||
var config = (IProviderConfig)new TSettings();
|
||||
|
||||
yield return new ApplicationDefinition
|
||||
{
|
||||
Name = GetType().Name,
|
||||
SyncLevel = ApplicationSyncLevel.AddOnly,
|
||||
Implementation = GetType().Name,
|
||||
Settings = config
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public virtual object RequestAction(string action, IDictionary<string, string> query)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
11
src/NzbDrone.Core/Applications/ApplicationDefinition.cs
Normal file
11
src/NzbDrone.Core/Applications/ApplicationDefinition.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Applications
|
||||
{
|
||||
public class ApplicationDefinition : ProviderDefinition
|
||||
{
|
||||
public ApplicationSyncLevel SyncLevel { get; set; }
|
||||
|
||||
public override bool Enable => SyncLevel == ApplicationSyncLevel.AddOnly || SyncLevel == ApplicationSyncLevel.FullSync;
|
||||
}
|
||||
}
|
21
src/NzbDrone.Core/Applications/ApplicationFactory.cs
Normal file
21
src/NzbDrone.Core/Applications/ApplicationFactory.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Composition;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Applications
|
||||
{
|
||||
public interface IApplicationsFactory : IProviderFactory<IApplications, ApplicationDefinition>
|
||||
{
|
||||
}
|
||||
|
||||
public class ApplicationFactory : ProviderFactory<IApplications, ApplicationDefinition>, IApplicationsFactory
|
||||
{
|
||||
public ApplicationFactory(IApplicationsRepository providerRepository, IEnumerable<IApplications> providers, IContainer container, IEventAggregator eventAggregator, Logger logger)
|
||||
: base(providerRepository, providers, container, eventAggregator, logger)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
24
src/NzbDrone.Core/Applications/ApplicationRepository.cs
Normal file
24
src/NzbDrone.Core/Applications/ApplicationRepository.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Applications
|
||||
{
|
||||
public interface IApplicationsRepository : IProviderRepository<ApplicationDefinition>
|
||||
{
|
||||
void UpdateSettings(ApplicationDefinition model);
|
||||
}
|
||||
|
||||
public class ApplicationRepository : ProviderRepository<ApplicationDefinition>, IApplicationsRepository
|
||||
{
|
||||
public ApplicationRepository(IMainDatabase database, IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
public void UpdateSettings(ApplicationDefinition model)
|
||||
{
|
||||
SetFields(model, m => m.Settings);
|
||||
}
|
||||
}
|
||||
}
|
16
src/NzbDrone.Core/Applications/ApplicationService.cs
Normal file
16
src/NzbDrone.Core/Applications/ApplicationService.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using NLog;
|
||||
|
||||
namespace NzbDrone.Core.Applications
|
||||
{
|
||||
public class ApplicationService
|
||||
{
|
||||
private readonly IApplicationsFactory _applicationsFactory;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ApplicationService(IApplicationsFactory applicationsFactory, Logger logger)
|
||||
{
|
||||
_applicationsFactory = applicationsFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
}
|
||||
}
|
9
src/NzbDrone.Core/Applications/ApplicationSyncLevel.cs
Normal file
9
src/NzbDrone.Core/Applications/ApplicationSyncLevel.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace NzbDrone.Core.Applications
|
||||
{
|
||||
public enum ApplicationSyncLevel
|
||||
{
|
||||
Disabled,
|
||||
AddOnly,
|
||||
FullSync
|
||||
}
|
||||
}
|
8
src/NzbDrone.Core/Applications/IApplications.cs
Normal file
8
src/NzbDrone.Core/Applications/IApplications.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Applications
|
||||
{
|
||||
public interface IApplications : IProvider
|
||||
{
|
||||
}
|
||||
}
|
27
src/NzbDrone.Core/Applications/Radarr/Radarr.cs
Normal file
27
src/NzbDrone.Core/Applications/Radarr/Radarr.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.Applications.Radarr
|
||||
{
|
||||
public class Radarr : ApplicationBase<RadarrSettings>
|
||||
{
|
||||
public override string Name => "Radarr";
|
||||
|
||||
private readonly IRadarrV3Proxy _radarrV3Proxy;
|
||||
|
||||
public Radarr(IRadarrV3Proxy radarrV3Proxy)
|
||||
{
|
||||
_radarrV3Proxy = radarrV3Proxy;
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
||||
failures.AddIfNotNull(_radarrV3Proxy.Test(Settings));
|
||||
|
||||
return new ValidationResult(failures);
|
||||
}
|
||||
}
|
||||
}
|
36
src/NzbDrone.Core/Applications/Radarr/RadarrSettings.cs
Normal file
36
src/NzbDrone.Core/Applications/Radarr/RadarrSettings.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Applications.Radarr
|
||||
{
|
||||
public class RadarrSettingsValidator : AbstractValidator<RadarrSettings>
|
||||
{
|
||||
public RadarrSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.BaseUrl).IsValidUrl();
|
||||
RuleFor(c => c.ApiKey).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class RadarrSettings : IProviderConfig
|
||||
{
|
||||
private static readonly RadarrSettingsValidator Validator = new RadarrSettingsValidator();
|
||||
|
||||
public RadarrSettings()
|
||||
{
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "Radarr Server", HelpText = "Radarr server URL, including http(s):// and port if needed")]
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey, HelpText = "The ApiKey generated by Radarr in Settings/General")]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
7
src/NzbDrone.Core/Applications/Radarr/RadarrStatus.cs
Normal file
7
src/NzbDrone.Core/Applications/Radarr/RadarrStatus.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace NzbDrone.Core.Applications.Radarr
|
||||
{
|
||||
public class RadarrStatus
|
||||
{
|
||||
public string Version { get; set; }
|
||||
}
|
||||
}
|
78
src/NzbDrone.Core/Applications/Radarr/RadarrV3Proxy.cs
Normal file
78
src/NzbDrone.Core/Applications/Radarr/RadarrV3Proxy.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using FluentValidation.Results;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.Applications.Radarr
|
||||
{
|
||||
public interface IRadarrV3Proxy
|
||||
{
|
||||
ValidationFailure Test(RadarrSettings settings);
|
||||
}
|
||||
|
||||
public class RadarrV3Proxy : IRadarrV3Proxy
|
||||
{
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public RadarrV3Proxy(IHttpClient httpClient, Logger logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public RadarrStatus GetStatus(RadarrSettings settings)
|
||||
{
|
||||
return Execute<RadarrStatus>("/api/v3/system/status", settings);
|
||||
}
|
||||
|
||||
public ValidationFailure Test(RadarrSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
GetStatus(settings);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Error(ex, "API Key is invalid");
|
||||
return new ValidationFailure("ApiKey", "API Key is invalid");
|
||||
}
|
||||
|
||||
_logger.Error(ex, "Unable to send test message");
|
||||
return new ValidationFailure("ApiKey", "Unable to send test message");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message");
|
||||
return new ValidationFailure("", "Unable to send test message");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private TResource Execute<TResource>(string resource, RadarrSettings settings)
|
||||
where TResource : new()
|
||||
{
|
||||
if (settings.BaseUrl.IsNullOrWhiteSpace() || settings.ApiKey.IsNullOrWhiteSpace())
|
||||
{
|
||||
return new TResource();
|
||||
}
|
||||
|
||||
var baseUrl = settings.BaseUrl.TrimEnd('/');
|
||||
|
||||
var request = new HttpRequestBuilder(baseUrl).Resource(resource).Accept(HttpAccept.Json)
|
||||
.SetHeader("X-Api-Key", settings.ApiKey).Build();
|
||||
|
||||
var response = _httpClient.Get(request);
|
||||
|
||||
var results = JsonConvert.DeserializeObject<TResource>(response.Content);
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
@@ -52,7 +52,9 @@ namespace NzbDrone.Core.Datastore.Migration
|
||||
.WithColumn("Name").AsString().Unique()
|
||||
.WithColumn("Implementation").AsString()
|
||||
.WithColumn("Settings").AsString().Nullable()
|
||||
.WithColumn("ConfigContract").AsString().Nullable();
|
||||
.WithColumn("ConfigContract").AsString().Nullable()
|
||||
.WithColumn("SyncLevel").AsInt32()
|
||||
.WithColumn("Tags").AsString().Nullable();
|
||||
|
||||
Create.TableForModel("Tags")
|
||||
.WithColumn("Label").AsString().Unique();
|
||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dapper;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Core.Applications;
|
||||
using NzbDrone.Core.Authentication;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.CustomFilters;
|
||||
@@ -51,6 +52,9 @@ namespace NzbDrone.Core.Datastore
|
||||
.Ignore(x => x.ImplementationName)
|
||||
.Ignore(i => i.SupportsOnHealthIssue);
|
||||
|
||||
Mapper.Entity<ApplicationDefinition>("Applications").RegisterModel()
|
||||
.Ignore(x => x.ImplementationName);
|
||||
|
||||
Mapper.Entity<History.History>("History").RegisterModel();
|
||||
|
||||
Mapper.Entity<Log>("Logs").RegisterModel();
|
||||
|
14
src/Prowlarr.Api.V1/Applications/ApplicationModule.cs
Normal file
14
src/Prowlarr.Api.V1/Applications/ApplicationModule.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using NzbDrone.Core.Applications;
|
||||
|
||||
namespace Prowlarr.Api.V1.Application
|
||||
{
|
||||
public class ApplicationModule : ProviderModuleBase<ApplicationResource, IApplications, ApplicationDefinition>
|
||||
{
|
||||
public static readonly ApplicationResourceMapper ResourceMapper = new ApplicationResourceMapper();
|
||||
|
||||
public ApplicationModule(ApplicationFactory applicationsFactory)
|
||||
: base(applicationsFactory, "applications", ResourceMapper)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
41
src/Prowlarr.Api.V1/Applications/ApplicationResource.cs
Normal file
41
src/Prowlarr.Api.V1/Applications/ApplicationResource.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using NzbDrone.Core.Applications;
|
||||
|
||||
namespace Prowlarr.Api.V1.Application
|
||||
{
|
||||
public class ApplicationResource : ProviderResource
|
||||
{
|
||||
public ApplicationSyncLevel SyncLevel { get; set; }
|
||||
public string TestCommand { get; set; }
|
||||
}
|
||||
|
||||
public class ApplicationResourceMapper : ProviderResourceMapper<ApplicationResource, ApplicationDefinition>
|
||||
{
|
||||
public override ApplicationResource ToResource(ApplicationDefinition definition)
|
||||
{
|
||||
if (definition == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var resource = base.ToResource(definition);
|
||||
|
||||
resource.SyncLevel = definition.SyncLevel;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
public override ApplicationDefinition ToModel(ApplicationResource resource)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var definition = base.ToModel(resource);
|
||||
|
||||
definition.SyncLevel = resource.SyncLevel;
|
||||
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user