mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2026-04-17 21:44:48 -04:00
New: Bulk Manage Applications, Download Clients
Co-authored-by: Qstick <qstick@gmail.com>
This commit is contained in:
@@ -48,6 +48,8 @@
|
||||
"ApplyTagsHelpTexts3": "Remove: Remove the entered tags",
|
||||
"ApplyTagsHelpTexts4": "Replace: Replace the tags with the entered tags (enter no tags to clear all tags)",
|
||||
"Apps": "Apps",
|
||||
"AppsMinimumSeeders": "Apps Minimum Seeders",
|
||||
"AppsMinimumSeedersHelpText": "Minimum seeders required by the Applications for the indexer to grab, empty is Sync profile's default",
|
||||
"AreYouSureYouWantToDeleteCategory": "Are you sure you want to delete mapped category?",
|
||||
"AreYouSureYouWantToResetYourAPIKey": "Are you sure you want to reset your API Key?",
|
||||
"Artist": "Artist",
|
||||
@@ -102,7 +104,9 @@
|
||||
"ConnectionLostMessage": "Prowlarr has lost its connection to the backend and will need to be reloaded to restore functionality.",
|
||||
"Connections": "Connections",
|
||||
"CouldNotConnectSignalR": "Could not connect to SignalR, UI won't update",
|
||||
"CountIndexersSelected": "{0} indexers selected",
|
||||
"CountApplicationsSelected": "{0} application(s) selected",
|
||||
"CountDownloadClientsSelected": "{0} download client(s) selected",
|
||||
"CountIndexersSelected": "{0} indexer(s) selected",
|
||||
"Custom": "Custom",
|
||||
"CustomFilters": "Custom Filters",
|
||||
"DBMigration": "DB Migration",
|
||||
@@ -122,6 +126,10 @@
|
||||
"DeleteIndexerProxyMessageText": "Are you sure you want to delete the proxy '{0}'?",
|
||||
"DeleteNotification": "Delete Notification",
|
||||
"DeleteNotificationMessageText": "Are you sure you want to delete the notification '{0}'?",
|
||||
"DeleteSelectedApplications": "Delete Selected Applications",
|
||||
"DeleteSelectedApplicationsMessageText": "Are you sure you want to delete {0} selected application(s)?",
|
||||
"DeleteSelectedDownloadClients": "Delete Download Client(s)",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Are you sure you want to delete {0} selected download client(s)?",
|
||||
"DeleteSelectedIndexer": "Delete Selected Indexer",
|
||||
"DeleteSelectedIndexers": "Delete Selected Indexers",
|
||||
"DeleteSelectedIndexersMessageText": "Are you sure you want to delete {0} selected indexer(s)?",
|
||||
@@ -137,6 +145,7 @@
|
||||
"Donations": "Donations",
|
||||
"DownloadClient": "Download Client",
|
||||
"DownloadClientCategory": "Download Client Category",
|
||||
"DownloadClientPriorityHelpText": "Prioritize multiple Download Clients. Round-Robin is used for clients with the same priority.",
|
||||
"DownloadClientSettings": "Download Client Settings",
|
||||
"DownloadClientStatusCheckAllClientMessage": "All download clients are unavailable due to failures",
|
||||
"DownloadClientStatusCheckSingleClientMessage": "Download clients unavailable due to failures: {0}",
|
||||
@@ -145,6 +154,7 @@
|
||||
"Duration": "Duration",
|
||||
"Edit": "Edit",
|
||||
"EditIndexer": "Edit Indexer",
|
||||
"EditSelectedDownloadClients": "Edit Selected Download Clients",
|
||||
"EditSelectedIndexers": "Edit Selected Indexers",
|
||||
"EditSyncProfile": "Edit Sync Profile",
|
||||
"ElapsedTime": "Elapsed Time",
|
||||
@@ -204,6 +214,7 @@
|
||||
"Id": "Id",
|
||||
"IgnoredAddresses": "Ignored Addresses",
|
||||
"IllRestartLater": "I'll restart later",
|
||||
"Implementation": "Implementation",
|
||||
"IncludeHealthWarningsHelpText": "Include Health Warnings",
|
||||
"IncludeManualGrabsHelpText": "Include Manual Grabs made within Prowlarr",
|
||||
"Indexer": "Indexer",
|
||||
@@ -263,6 +274,8 @@
|
||||
"Logs": "Logs",
|
||||
"MIA": "MIA",
|
||||
"MaintenanceRelease": "Maintenance Release: bug fixes and other improvements. See Github Commit History for more details",
|
||||
"ManageApplications": "Manage Applications",
|
||||
"ManageDownloadClients": "Manage Download Clients",
|
||||
"Manual": "Manual",
|
||||
"MappedCategories": "Mapped Categories",
|
||||
"MappedDrivesRunningAsService": "Mapped network drives are not available when running as a Windows Service. Please see the FAQ for more information",
|
||||
@@ -287,6 +300,7 @@
|
||||
"NoBackupsAreAvailable": "No backups are available",
|
||||
"NoChange": "No Change",
|
||||
"NoChanges": "No Changes",
|
||||
"NoDownloadClientsFound": "No download clients found",
|
||||
"NoHistoryFound": "No history found",
|
||||
"NoIndexersFound": "No indexers found",
|
||||
"NoLeaveIt": "No, Leave It",
|
||||
@@ -313,6 +327,8 @@
|
||||
"OpenBrowserOnStart": "Open browser on start",
|
||||
"OpenThisModal": "Open This Modal",
|
||||
"Options": "Options",
|
||||
"PackSeedTime": "Pack Seed Time",
|
||||
"PackSeedTimeHelpText": "The time a pack (season or discography) torrent should be seeded before stopping, empty is app's default",
|
||||
"PackageVersion": "Package Version",
|
||||
"PageSize": "Page Size",
|
||||
"PageSizeHelpText": "Number of items to show on each page",
|
||||
@@ -326,8 +342,6 @@
|
||||
"PortNumber": "Port Number",
|
||||
"Presets": "Presets",
|
||||
"Priority": "Priority",
|
||||
"PriorityHelpText": "Prioritize multiple Download Clients. Round-Robin is used for clients with the same priority.",
|
||||
"PrioritySettings": "Priority",
|
||||
"Privacy": "Privacy",
|
||||
"Private": "Private",
|
||||
"Protocol": "Protocol",
|
||||
@@ -398,6 +412,10 @@
|
||||
"SearchTypes": "Search Types",
|
||||
"Season": "Season",
|
||||
"Security": "Security",
|
||||
"SeedRatio": "Seed Ratio",
|
||||
"SeedRatioHelpText": "The ratio a torrent should reach before stopping, empty is app's default",
|
||||
"SeedTime": "Seed Time",
|
||||
"SeedTimeHelpText": "The time a torrent should be seeded before stopping, empty is app's default",
|
||||
"Seeders": "Seeders",
|
||||
"SelectAll": "Select All",
|
||||
"SelectIndexers": "Select Indexers",
|
||||
|
||||
@@ -12,9 +12,10 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
bool Exists(int id);
|
||||
TProviderDefinition Find(int id);
|
||||
TProviderDefinition Get(int id);
|
||||
IEnumerable<TProviderDefinition> Get(IEnumerable<int> ids);
|
||||
TProviderDefinition Create(TProviderDefinition definition);
|
||||
void Update(TProviderDefinition definition);
|
||||
void Update(IEnumerable<TProviderDefinition> definitions);
|
||||
IEnumerable<TProviderDefinition> Update(IEnumerable<TProviderDefinition> definitions);
|
||||
void Delete(int id);
|
||||
void Delete(IEnumerable<int> ids);
|
||||
IEnumerable<TProviderDefinition> GetDefaultDefinitions();
|
||||
|
||||
@@ -101,6 +101,11 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
return _providerRepository.Get(id);
|
||||
}
|
||||
|
||||
public IEnumerable<TProviderDefinition> Get(IEnumerable<int> ids)
|
||||
{
|
||||
return _providerRepository.Get(ids);
|
||||
}
|
||||
|
||||
public TProviderDefinition Find(int id)
|
||||
{
|
||||
return _providerRepository.Find(id);
|
||||
@@ -120,10 +125,12 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
_eventAggregator.PublishEvent(new ProviderUpdatedEvent<TProvider>(updatedDef));
|
||||
}
|
||||
|
||||
public virtual void Update(IEnumerable<TProviderDefinition> definitions)
|
||||
public virtual IEnumerable<TProviderDefinition> Update(IEnumerable<TProviderDefinition> definitions)
|
||||
{
|
||||
_providerRepository.UpdateMany(definitions.ToList());
|
||||
_eventAggregator.PublishEvent(new ProviderBulkUpdatedEvent<TProvider>(definitions));
|
||||
|
||||
return definitions;
|
||||
}
|
||||
|
||||
public void Delete(int id)
|
||||
|
||||
28
src/Prowlarr.Api.V1/Applications/ApplicationBulkResource.cs
Normal file
28
src/Prowlarr.Api.V1/Applications/ApplicationBulkResource.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Applications;
|
||||
|
||||
namespace Prowlarr.Api.V1.Applications
|
||||
{
|
||||
public class ApplicationBulkResource : ProviderBulkResource<ApplicationBulkResource>
|
||||
{
|
||||
public ApplicationSyncLevel? SyncLevel { get; set; }
|
||||
}
|
||||
|
||||
public class ApplicationBulkResourceMapper : ProviderBulkResourceMapper<ApplicationBulkResource, ApplicationDefinition>
|
||||
{
|
||||
public override List<ApplicationDefinition> UpdateModel(ApplicationBulkResource resource, List<ApplicationDefinition> existingDefinitions)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
return new List<ApplicationDefinition>();
|
||||
}
|
||||
|
||||
existingDefinitions.ForEach(existing =>
|
||||
{
|
||||
existing.SyncLevel = resource.SyncLevel ?? existing.SyncLevel;
|
||||
});
|
||||
|
||||
return existingDefinitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
using NzbDrone.Core.Applications;
|
||||
using Prowlarr.Http;
|
||||
|
||||
namespace Prowlarr.Api.V1.Application
|
||||
namespace Prowlarr.Api.V1.Applications
|
||||
{
|
||||
[V1ApiController("applications")]
|
||||
public class ApplicationController : ProviderControllerBase<ApplicationResource, IApplication, ApplicationDefinition>
|
||||
public class ApplicationController : ProviderControllerBase<ApplicationResource, ApplicationBulkResource, IApplication, ApplicationDefinition>
|
||||
{
|
||||
public static readonly ApplicationResourceMapper ResourceMapper = new ApplicationResourceMapper();
|
||||
public static readonly ApplicationResourceMapper ResourceMapper = new ();
|
||||
public static readonly ApplicationBulkResourceMapper BulkResourceMapper = new ();
|
||||
|
||||
public ApplicationController(ApplicationFactory applicationsFactory)
|
||||
: base(applicationsFactory, "applications", ResourceMapper)
|
||||
: base(applicationsFactory, "applications", ResourceMapper, BulkResourceMapper)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using NzbDrone.Core.Applications;
|
||||
|
||||
namespace Prowlarr.Api.V1.Application
|
||||
namespace Prowlarr.Api.V1.Applications
|
||||
{
|
||||
public class ApplicationResource : ProviderResource<ApplicationResource>
|
||||
{
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Download;
|
||||
|
||||
namespace Prowlarr.Api.V1.DownloadClient
|
||||
{
|
||||
public class DownloadClientBulkResource : ProviderBulkResource<DownloadClientBulkResource>
|
||||
{
|
||||
public bool? Enable { get; set; }
|
||||
public int? Priority { get; set; }
|
||||
}
|
||||
|
||||
public class DownloadClientBulkResourceMapper : ProviderBulkResourceMapper<DownloadClientBulkResource, DownloadClientDefinition>
|
||||
{
|
||||
public override List<DownloadClientDefinition> UpdateModel(DownloadClientBulkResource resource, List<DownloadClientDefinition> existingDefinitions)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
return new List<DownloadClientDefinition>();
|
||||
}
|
||||
|
||||
existingDefinitions.ForEach(existing =>
|
||||
{
|
||||
existing.Enable = resource.Enable ?? existing.Enable;
|
||||
existing.Priority = resource.Priority ?? existing.Priority;
|
||||
});
|
||||
|
||||
return existingDefinitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,13 @@ using Prowlarr.Http;
|
||||
namespace Prowlarr.Api.V1.DownloadClient
|
||||
{
|
||||
[V1ApiController]
|
||||
public class DownloadClientController : ProviderControllerBase<DownloadClientResource, IDownloadClient, DownloadClientDefinition>
|
||||
public class DownloadClientController : ProviderControllerBase<DownloadClientResource, DownloadClientBulkResource, IDownloadClient, DownloadClientDefinition>
|
||||
{
|
||||
public static readonly DownloadClientResourceMapper ResourceMapper = new DownloadClientResourceMapper();
|
||||
public static readonly DownloadClientResourceMapper ResourceMapper = new ();
|
||||
public static readonly DownloadClientBulkResourceMapper BulkResourceMapper = new ();
|
||||
|
||||
public DownloadClientController(IDownloadClientFactory downloadClientFactory)
|
||||
: base(downloadClientFactory, "downloadclient", ResourceMapper)
|
||||
: base(downloadClientFactory, "downloadclient", ResourceMapper, BulkResourceMapper)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using NzbDrone.Core.IndexerProxies;
|
||||
|
||||
namespace Prowlarr.Api.V1.IndexerProxies
|
||||
{
|
||||
public class IndexerProxyBulkResource : ProviderBulkResource<IndexerProxyBulkResource>
|
||||
{
|
||||
}
|
||||
|
||||
public class IndexerProxyBulkResourceMapper : ProviderBulkResourceMapper<IndexerProxyBulkResource, IndexerProxyDefinition>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,31 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Core.IndexerProxies;
|
||||
using Prowlarr.Http;
|
||||
|
||||
namespace Prowlarr.Api.V1.IndexerProxies
|
||||
{
|
||||
[V1ApiController]
|
||||
public class IndexerProxyController : ProviderControllerBase<IndexerProxyResource, IIndexerProxy, IndexerProxyDefinition>
|
||||
public class IndexerProxyController : ProviderControllerBase<IndexerProxyResource, IndexerProxyBulkResource, IIndexerProxy, IndexerProxyDefinition>
|
||||
{
|
||||
public static readonly IndexerProxyResourceMapper ResourceMapper = new IndexerProxyResourceMapper();
|
||||
public static readonly IndexerProxyResourceMapper ResourceMapper = new ();
|
||||
public static readonly IndexerProxyBulkResourceMapper BulkResourceMapper = new ();
|
||||
|
||||
public IndexerProxyController(IndexerProxyFactory notificationFactory)
|
||||
: base(notificationFactory, "indexerProxy", ResourceMapper)
|
||||
: base(notificationFactory, "indexerProxy", ResourceMapper, BulkResourceMapper)
|
||||
{
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public override ActionResult<IndexerProxyResource> UpdateProvider([FromBody] IndexerProxyBulkResource providerResource)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public override object DeleteProviders([FromBody] IndexerProxyBulkResource resource)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
44
src/Prowlarr.Api.V1/Indexers/IndexerBulkResource.cs
Normal file
44
src/Prowlarr.Api.V1/Indexers/IndexerBulkResource.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Indexers;
|
||||
|
||||
namespace Prowlarr.Api.V1.Indexers
|
||||
{
|
||||
public class IndexerBulkResource : ProviderBulkResource<IndexerBulkResource>
|
||||
{
|
||||
public bool? Enable { get; set; }
|
||||
public int? AppProfileId { get; set; }
|
||||
public int? Priority { get; set; }
|
||||
public int? MinimumSeeders { get; set; }
|
||||
public double? SeedRatio { get; set; }
|
||||
public int? SeedTime { get; set; }
|
||||
public int? PackSeedTime { get; set; }
|
||||
}
|
||||
|
||||
public class IndexerBulkResourceMapper : ProviderBulkResourceMapper<IndexerBulkResource, IndexerDefinition>
|
||||
{
|
||||
public override List<IndexerDefinition> UpdateModel(IndexerBulkResource resource, List<IndexerDefinition> existingDefinitions)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
return new List<IndexerDefinition>();
|
||||
}
|
||||
|
||||
existingDefinitions.ForEach(existing =>
|
||||
{
|
||||
existing.Enable = resource.Enable ?? existing.Enable;
|
||||
existing.AppProfileId = resource.AppProfileId ?? existing.AppProfileId;
|
||||
existing.Priority = resource.Priority ?? existing.Priority;
|
||||
|
||||
if (existing.Protocol == DownloadProtocol.Torrent)
|
||||
{
|
||||
((ITorrentIndexerSettings)existing.Settings).TorrentBaseSettings.AppMinimumSeeders = resource.MinimumSeeders ?? ((ITorrentIndexerSettings)existing.Settings).TorrentBaseSettings.AppMinimumSeeders;
|
||||
((ITorrentIndexerSettings)existing.Settings).TorrentBaseSettings.SeedRatio = resource.SeedRatio ?? ((ITorrentIndexerSettings)existing.Settings).TorrentBaseSettings.SeedRatio;
|
||||
((ITorrentIndexerSettings)existing.Settings).TorrentBaseSettings.SeedTime = resource.SeedTime ?? ((ITorrentIndexerSettings)existing.Settings).TorrentBaseSettings.SeedTime;
|
||||
((ITorrentIndexerSettings)existing.Settings).TorrentBaseSettings.PackSeedTime = resource.PackSeedTime ?? ((ITorrentIndexerSettings)existing.Settings).TorrentBaseSettings.PackSeedTime;
|
||||
}
|
||||
});
|
||||
|
||||
return existingDefinitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ using Prowlarr.Http;
|
||||
namespace Prowlarr.Api.V1.Indexers
|
||||
{
|
||||
[V1ApiController]
|
||||
public class IndexerController : ProviderControllerBase<IndexerResource, IIndexer, IndexerDefinition>
|
||||
public class IndexerController : ProviderControllerBase<IndexerResource, IndexerBulkResource, IIndexer, IndexerDefinition>
|
||||
{
|
||||
public IndexerController(IndexerFactory indexerFactory, IndexerResourceMapper resourceMapper)
|
||||
: base(indexerFactory, "indexer", resourceMapper)
|
||||
public IndexerController(IndexerFactory indexerFactory, IndexerResourceMapper resourceMapper, IndexerBulkResourceMapper bulkResourceMapper)
|
||||
: base(indexerFactory, "indexer", resourceMapper, bulkResourceMapper)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using Prowlarr.Http;
|
||||
|
||||
namespace Prowlarr.Api.V1.Indexers
|
||||
{
|
||||
[V1ApiController("indexer/editor")]
|
||||
public class IndexerEditorController : Controller
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
private readonly IManageCommandQueue _commandQueueManager;
|
||||
private readonly IndexerResourceMapper _resourceMapper;
|
||||
|
||||
public IndexerEditorController(IIndexerFactory indexerFactory, IManageCommandQueue commandQueueManager, IndexerResourceMapper resourceMapper)
|
||||
{
|
||||
_indexerFactory = indexerFactory;
|
||||
_commandQueueManager = commandQueueManager;
|
||||
_resourceMapper = resourceMapper;
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Consumes("application/json")]
|
||||
public IActionResult SaveAll(IndexerEditorResource resource)
|
||||
{
|
||||
var indexersToUpdate = _indexerFactory.AllProviders(false).Select(x => (IndexerDefinition)x.Definition).Where(d => resource.IndexerIds.Contains(d.Id));
|
||||
|
||||
foreach (var indexer in indexersToUpdate)
|
||||
{
|
||||
if (resource.Enable.HasValue)
|
||||
{
|
||||
indexer.Enable = resource.Enable.Value;
|
||||
}
|
||||
|
||||
if (resource.AppProfileId.HasValue)
|
||||
{
|
||||
indexer.AppProfileId = resource.AppProfileId.Value;
|
||||
}
|
||||
|
||||
if (resource.Priority.HasValue)
|
||||
{
|
||||
indexer.Priority = resource.Priority.Value;
|
||||
}
|
||||
|
||||
if (resource.Tags != null)
|
||||
{
|
||||
var newTags = resource.Tags;
|
||||
var applyTags = resource.ApplyTags;
|
||||
|
||||
switch (applyTags)
|
||||
{
|
||||
case ApplyTags.Add:
|
||||
newTags.ForEach(t => indexer.Tags.Add(t));
|
||||
break;
|
||||
case ApplyTags.Remove:
|
||||
newTags.ForEach(t => indexer.Tags.Remove(t));
|
||||
break;
|
||||
case ApplyTags.Replace:
|
||||
indexer.Tags = new HashSet<int>(newTags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_indexerFactory.Update(indexersToUpdate);
|
||||
|
||||
var indexers = _indexerFactory.All();
|
||||
|
||||
foreach (var definition in indexers)
|
||||
{
|
||||
_indexerFactory.SetProviderCharacteristics(definition);
|
||||
}
|
||||
|
||||
return Accepted(_resourceMapper.ToResource(indexers));
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Consumes("application/json")]
|
||||
public object DeleteIndexers([FromBody] IndexerEditorResource resource)
|
||||
{
|
||||
_indexerFactory.Delete(resource.IndexerIds);
|
||||
|
||||
return new { };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Prowlarr.Api.V1.Indexers
|
||||
{
|
||||
public class IndexerEditorResource
|
||||
{
|
||||
public List<int> IndexerIds { get; set; }
|
||||
public bool? Enable { get; set; }
|
||||
public int? AppProfileId { get; set; }
|
||||
public int? Priority { get; set; }
|
||||
public List<int> Tags { get; set; }
|
||||
public ApplyTags ApplyTags { get; set; }
|
||||
}
|
||||
|
||||
public enum ApplyTags
|
||||
{
|
||||
Add,
|
||||
Remove,
|
||||
Replace
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using NzbDrone.Core.Notifications;
|
||||
|
||||
namespace Prowlarr.Api.V1.Notifications
|
||||
{
|
||||
public class NotificationBulkResource : ProviderBulkResource<NotificationBulkResource>
|
||||
{
|
||||
}
|
||||
|
||||
public class NotificationBulkResourceMapper : ProviderBulkResourceMapper<NotificationBulkResource, NotificationDefinition>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,31 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Core.Notifications;
|
||||
using Prowlarr.Http;
|
||||
|
||||
namespace Prowlarr.Api.V1.Notifications
|
||||
{
|
||||
[V1ApiController]
|
||||
public class NotificationController : ProviderControllerBase<NotificationResource, INotification, NotificationDefinition>
|
||||
public class NotificationController : ProviderControllerBase<NotificationResource, NotificationBulkResource, INotification, NotificationDefinition>
|
||||
{
|
||||
public static readonly NotificationResourceMapper ResourceMapper = new NotificationResourceMapper();
|
||||
public static readonly NotificationResourceMapper ResourceMapper = new ();
|
||||
public static readonly NotificationBulkResourceMapper BulkResourceMapper = new ();
|
||||
|
||||
public NotificationController(NotificationFactory notificationFactory)
|
||||
: base(notificationFactory, "notification", ResourceMapper)
|
||||
: base(notificationFactory, "notification", ResourceMapper, BulkResourceMapper)
|
||||
{
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public override ActionResult<NotificationResource> UpdateProvider([FromBody] NotificationBulkResource providerResource)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public override object DeleteProviders([FromBody] NotificationBulkResource resource)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
39
src/Prowlarr.Api.V1/ProviderBulkResource.cs
Normal file
39
src/Prowlarr.Api.V1/ProviderBulkResource.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace Prowlarr.Api.V1
|
||||
{
|
||||
public class ProviderBulkResource<T>
|
||||
{
|
||||
public List<int> Ids { get; set; }
|
||||
public List<int> Tags { get; set; }
|
||||
public ApplyTags ApplyTags { get; set; }
|
||||
|
||||
public ProviderBulkResource()
|
||||
{
|
||||
Ids = new List<int>();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ApplyTags
|
||||
{
|
||||
Add,
|
||||
Remove,
|
||||
Replace
|
||||
}
|
||||
|
||||
public class ProviderBulkResourceMapper<TProviderBulkResource, TProviderDefinition>
|
||||
where TProviderBulkResource : ProviderBulkResource<TProviderBulkResource>, new()
|
||||
where TProviderDefinition : ProviderDefinition, new()
|
||||
{
|
||||
public virtual List<TProviderDefinition> UpdateModel(TProviderBulkResource resource, List<TProviderDefinition> existingDefinitions)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
return new List<TProviderDefinition>();
|
||||
}
|
||||
|
||||
return existingDefinitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,18 +10,25 @@ using Prowlarr.Http.REST;
|
||||
|
||||
namespace Prowlarr.Api.V1
|
||||
{
|
||||
public abstract class ProviderControllerBase<TProviderResource, TProvider, TProviderDefinition> : RestController<TProviderResource>
|
||||
public abstract class ProviderControllerBase<TProviderResource, TBulkProviderResource, TProvider, TProviderDefinition> : RestController<TProviderResource>
|
||||
where TProviderDefinition : ProviderDefinition, new()
|
||||
where TBulkProviderResource : ProviderBulkResource<TBulkProviderResource>, new()
|
||||
where TProvider : IProvider
|
||||
where TProviderResource : ProviderResource<TProviderResource>, new()
|
||||
{
|
||||
protected readonly IProviderFactory<TProvider, TProviderDefinition> _providerFactory;
|
||||
protected readonly ProviderResourceMapper<TProviderResource, TProviderDefinition> _resourceMapper;
|
||||
private readonly ProviderBulkResourceMapper<TBulkProviderResource, TProviderDefinition> _bulkResourceMapper;
|
||||
|
||||
protected ProviderControllerBase(IProviderFactory<TProvider, TProviderDefinition> providerFactory, string resource, ProviderResourceMapper<TProviderResource, TProviderDefinition> resourceMapper)
|
||||
protected ProviderControllerBase(IProviderFactory<TProvider,
|
||||
TProviderDefinition> providerFactory,
|
||||
string resource,
|
||||
ProviderResourceMapper<TProviderResource, TProviderDefinition> resourceMapper,
|
||||
ProviderBulkResourceMapper<TBulkProviderResource, TProviderDefinition> bulkResourceMapper)
|
||||
{
|
||||
_providerFactory = providerFactory;
|
||||
_resourceMapper = resourceMapper;
|
||||
_bulkResourceMapper = bulkResourceMapper;
|
||||
|
||||
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
||||
SharedValidator.RuleFor(c => c.Name).Must((v, c) => !_providerFactory.All().Any(p => p.Name == c && p.Id != v.Id)).WithMessage("Should be unique");
|
||||
@@ -92,6 +99,47 @@ namespace Prowlarr.Api.V1
|
||||
return Accepted(providerResource.Id);
|
||||
}
|
||||
|
||||
[HttpPut("bulk")]
|
||||
[Consumes("application/json")]
|
||||
[Produces("application/json")]
|
||||
public virtual ActionResult<TProviderResource> UpdateProvider([FromBody] TBulkProviderResource providerResource)
|
||||
{
|
||||
if (!providerResource.Ids.Any())
|
||||
{
|
||||
throw new BadRequestException("ids must be provided");
|
||||
}
|
||||
|
||||
var definitionsToUpdate = _providerFactory.Get(providerResource.Ids).ToList();
|
||||
|
||||
foreach (var definition in definitionsToUpdate)
|
||||
{
|
||||
_providerFactory.SetProviderCharacteristics(definition);
|
||||
|
||||
if (providerResource.Tags != null)
|
||||
{
|
||||
var newTags = providerResource.Tags;
|
||||
var applyTags = providerResource.ApplyTags;
|
||||
|
||||
switch (applyTags)
|
||||
{
|
||||
case ApplyTags.Add:
|
||||
newTags.ForEach(t => definition.Tags.Add(t));
|
||||
break;
|
||||
case ApplyTags.Remove:
|
||||
newTags.ForEach(t => definition.Tags.Remove(t));
|
||||
break;
|
||||
case ApplyTags.Replace:
|
||||
definition.Tags = new HashSet<int>(newTags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bulkResourceMapper.UpdateModel(providerResource, definitionsToUpdate);
|
||||
|
||||
return Accepted(_providerFactory.Update(definitionsToUpdate).Select(x => _resourceMapper.ToResource(x)));
|
||||
}
|
||||
|
||||
private TProviderDefinition GetDefinition(TProviderResource providerResource, bool validate, bool includeWarnings, bool forceValidate)
|
||||
{
|
||||
var definition = _resourceMapper.ToModel(providerResource);
|
||||
@@ -112,6 +160,16 @@ namespace Prowlarr.Api.V1
|
||||
return new { };
|
||||
}
|
||||
|
||||
[HttpDelete("bulk")]
|
||||
[Consumes("application/json")]
|
||||
[Produces("application/json")]
|
||||
public virtual object DeleteProviders([FromBody] TBulkProviderResource resource)
|
||||
{
|
||||
_providerFactory.Delete(resource.Ids);
|
||||
|
||||
return new { };
|
||||
}
|
||||
|
||||
[HttpGet("schema")]
|
||||
[Produces("application/json")]
|
||||
public virtual List<TProviderResource> GetTemplates()
|
||||
|
||||
Reference in New Issue
Block a user