New: API Docs

pull/5116/head
Qstick 2 years ago committed by Mark McDowall
parent 269e72a219
commit 18f77a967b

3
.gitignore vendored

@ -160,3 +160,6 @@ Thumbs.db
src/.idea/ src/.idea/
/distribution/windows/setup/output/* /distribution/windows/setup/output/*
# API doc generation
.config/

@ -6,6 +6,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Owin" Version="6.0.5" /> <PackageReference Include="Microsoft.AspNetCore.Owin" Version="6.0.5" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.4" /> <PackageReference Include="NLog.Extensions.Logging" Version="1.7.4" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.3.2" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
<PackageReference Include="DryIoc.dll" Version="4.8.6" /> <PackageReference Include="DryIoc.dll" Version="4.8.6" />

@ -9,6 +9,7 @@ using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using NLog.Extensions.Logging; using NLog.Extensions.Logging;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Instrumentation;
@ -91,6 +92,73 @@ namespace NzbDrone.Host
}) })
.AddControllersAsServices(); .AddControllersAsServices();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v3", new OpenApiInfo
{
Version = "3.0.0",
Title = "Sonarr",
Description = "Sonarr API docs",
License = new OpenApiLicense
{
Name = "GPL-3.0",
Url = new Uri("https://github.com/Sonarr/Sonarr/blob/develop/LICENSE")
}
});
var apiKeyHeader = new OpenApiSecurityScheme
{
Name = "X-Api-Key",
Type = SecuritySchemeType.ApiKey,
Scheme = "apiKey",
Description = "Apikey passed as header",
In = ParameterLocation.Header,
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "X-Api-Key"
},
};
c.AddSecurityDefinition("X-Api-Key", apiKeyHeader);
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{ apiKeyHeader, new string[] { } }
});
var apikeyQuery = new OpenApiSecurityScheme
{
Name = "apikey",
Type = SecuritySchemeType.ApiKey,
Scheme = "apiKey",
Description = "Apikey passed as header",
In = ParameterLocation.Query,
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "apikey"
},
};
c.AddServer(new OpenApiServer
{
Url = "{protocol}://{hostpath}",
Variables = new Dictionary<string, OpenApiServerVariable>
{
{ "protocol", new OpenApiServerVariable { Default = "http", Enum = new List<string> { "http", "https" } } },
{ "hostpath", new OpenApiServerVariable { Default = "localhost:8989" } }
}
});
c.AddSecurityDefinition("apikey", apikeyQuery);
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{ apikeyQuery, new string[] { } }
});
});
services services
.AddSignalR() .AddSignalR()
.AddJsonProtocol(options => .AddJsonProtocol(options =>
@ -184,6 +252,15 @@ namespace NzbDrone.Host
app.UseWebSockets(); app.UseWebSockets();
// Enable middleware to serve generated Swagger as a JSON endpoint.
if (BuildInfo.IsDebug)
{
app.UseSwagger(c =>
{
c.RouteTemplate = "docs/{documentName}/openapi.json";
});
}
app.UseEndpoints(x => app.UseEndpoints(x =>
{ {
x.MapHub<MessageHub>("/signalr/messages").RequireAuthorization("SignalR"); x.MapHub<MessageHub>("/signalr/messages").RequireAuthorization("SignalR");

@ -22,6 +22,7 @@ namespace Sonarr.Api.V3.Blocklist
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public PagingResource<BlocklistResource> GetBlocklist() public PagingResource<BlocklistResource> GetBlocklist()
{ {
var pagingResource = Request.ReadPagingResourceFromRequest<BlocklistResource>(); var pagingResource = Request.ReadPagingResourceFromRequest<BlocklistResource>();
@ -37,6 +38,7 @@ namespace Sonarr.Api.V3.Blocklist
} }
[HttpDelete("bulk")] [HttpDelete("bulk")]
[Produces("application/json")]
public object Remove([FromBody] BlocklistBulkResource resource) public object Remove([FromBody] BlocklistBulkResource resource)
{ {
_blocklistService.Delete(resource.Ids); _blocklistService.Delete(resource.Ids);

@ -22,6 +22,7 @@ namespace Sonarr.Api.V3.Calendar
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<EpisodeResource> GetCalendar(DateTime? start, DateTime? end, bool unmonitored = false, bool includeSeries = false, bool includeEpisodeFile = false, bool includeEpisodeImages = false) public List<EpisodeResource> GetCalendar(DateTime? start, DateTime? end, bool unmonitored = false, bool includeSeries = false, bool includeEpisodeFile = false, bool includeEpisodeImages = false)
{ {
var startUse = start ?? DateTime.Today; var startUse = start ?? DateTime.Today;

@ -49,6 +49,8 @@ namespace Sonarr.Api.V3.Commands
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<CommandResource> StartCommand(CommandResource commandResource) public ActionResult<CommandResource> StartCommand(CommandResource commandResource)
{ {
var commandType = var commandType =
@ -74,6 +76,7 @@ namespace Sonarr.Api.V3.Commands
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<CommandResource> GetStartedCommands() public List<CommandResource> GetStartedCommands()
{ {
return _commandQueueManager.All() return _commandQueueManager.All()

@ -23,6 +23,7 @@ namespace Sonarr.Api.V3.Config
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public TResource GetConfig() public TResource GetConfig()
{ {
var resource = ToResource(_configService); var resource = ToResource(_configService);
@ -32,6 +33,7 @@ namespace Sonarr.Api.V3.Config
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public virtual ActionResult<TResource> SaveConfig(TResource resource) public virtual ActionResult<TResource> SaveConfig(TResource resource)
{ {
var dictionary = resource.GetType() var dictionary = resource.GetType()

@ -23,12 +23,14 @@ namespace Sonarr.Api.V3.CustomFilters
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<CustomFilterResource> GetCustomFilters() public List<CustomFilterResource> GetCustomFilters()
{ {
return _customFilterService.All().ToResource(); return _customFilterService.All().ToResource();
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<CustomFilterResource> AddCustomFilter(CustomFilterResource resource) public ActionResult<CustomFilterResource> AddCustomFilter(CustomFilterResource resource)
{ {
var customFilter = _customFilterService.Add(resource.ToModel()); var customFilter = _customFilterService.Add(resource.ToModel());
@ -37,6 +39,7 @@ namespace Sonarr.Api.V3.CustomFilters
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<CustomFilterResource> UpdateCustomFilter(CustomFilterResource resource) public ActionResult<CustomFilterResource> UpdateCustomFilter(CustomFilterResource resource)
{ {
_customFilterService.Update(resource.ToModel()); _customFilterService.Update(resource.ToModel());

@ -48,6 +48,7 @@ namespace Sonarr.Api.V3.CustomFormats
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<CustomFormatResource> Create(CustomFormatResource customFormatResource) public ActionResult<CustomFormatResource> Create(CustomFormatResource customFormatResource)
{ {
var model = customFormatResource.ToModel(_specifications); var model = customFormatResource.ToModel(_specifications);
@ -55,6 +56,7 @@ namespace Sonarr.Api.V3.CustomFormats
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<CustomFormatResource> Update(CustomFormatResource resource) public ActionResult<CustomFormatResource> Update(CustomFormatResource resource)
{ {
var model = resource.ToModel(_specifications); var model = resource.ToModel(_specifications);
@ -64,6 +66,7 @@ namespace Sonarr.Api.V3.CustomFormats
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<CustomFormatResource> GetAll() public List<CustomFormatResource> GetAll()
{ {
return _formatService.All().ToResource(); return _formatService.All().ToResource();

@ -16,6 +16,7 @@ namespace Sonarr.Api.V3.DiskSpace
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<DiskSpaceResource> GetFreeSpace() public List<DiskSpaceResource> GetFreeSpace()
{ {
return _diskSpaceService.GetFreeSpace().ConvertAll(DiskSpaceResourceMapper.MapToResource); return _diskSpaceService.GetFreeSpace().ConvertAll(DiskSpaceResourceMapper.MapToResource);

@ -58,6 +58,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<EpisodeFileResource> GetEpisodeFiles(int? seriesId, [FromQuery] List<int> episodeFileIds) public List<EpisodeFileResource> GetEpisodeFiles(int? seriesId, [FromQuery] List<int> episodeFileIds)
{ {
if (!seriesId.HasValue && !episodeFileIds.Any()) if (!seriesId.HasValue && !episodeFileIds.Any())
@ -101,6 +102,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<EpisodeFileResource> SetQuality(EpisodeFileResource episodeFileResource) public ActionResult<EpisodeFileResource> SetQuality(EpisodeFileResource episodeFileResource)
{ {
var episodeFile = _mediaFileService.Get(episodeFileResource.Id); var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
@ -121,6 +123,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
} }
[HttpPut("editor")] [HttpPut("editor")]
[Consumes("application/json")]
public object SetQuality([FromBody] EpisodeFileListResource resource) public object SetQuality([FromBody] EpisodeFileListResource resource)
{ {
var episodeFiles = _mediaFileService.GetFiles(resource.EpisodeFileIds); var episodeFiles = _mediaFileService.GetFiles(resource.EpisodeFileIds);
@ -171,6 +174,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
} }
[HttpDelete("bulk")] [HttpDelete("bulk")]
[Consumes("application/json")]
public object DeleteEpisodeFiles([FromBody] EpisodeFileListResource resource) public object DeleteEpisodeFiles([FromBody] EpisodeFileListResource resource)
{ {
var episodeFiles = _mediaFileService.GetFiles(resource.EpisodeFileIds); var episodeFiles = _mediaFileService.GetFiles(resource.EpisodeFileIds);
@ -185,6 +189,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
} }
[HttpPut("bulk")] [HttpPut("bulk")]
[Consumes("application/json")]
public object SetPropertiesBulk([FromBody] List<EpisodeFileResource> resources) public object SetPropertiesBulk([FromBody] List<EpisodeFileResource> resources)
{ {
var episodeFiles = _mediaFileService.GetFiles(resources.Select(r => r.Id)); var episodeFiles = _mediaFileService.GetFiles(resources.Select(r => r.Id));

@ -23,6 +23,7 @@ namespace Sonarr.Api.V3.Episodes
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<EpisodeResource> GetEpisodes(int? seriesId, int? seasonNumber, [FromQuery]List<int> episodeIds, int? episodeFileId, bool includeImages = false) public List<EpisodeResource> GetEpisodes(int? seriesId, int? seasonNumber, [FromQuery]List<int> episodeIds, int? episodeFileId, bool includeImages = false)
{ {
if (seriesId.HasValue) if (seriesId.HasValue)
@ -47,6 +48,7 @@ namespace Sonarr.Api.V3.Episodes
} }
[HttpPut("{id}")] [HttpPut("{id}")]
[Consumes("application/json")]
public IActionResult SetEpisodeMonitored([FromBody] EpisodeResource resource, [FromRoute] int id) public IActionResult SetEpisodeMonitored([FromBody] EpisodeResource resource, [FromRoute] int id)
{ {
_episodeService.SetEpisodeMonitored(id, resource.Monitored); _episodeService.SetEpisodeMonitored(id, resource.Monitored);
@ -57,6 +59,7 @@ namespace Sonarr.Api.V3.Episodes
} }
[HttpPut("monitor")] [HttpPut("monitor")]
[Consumes("application/json")]
public IActionResult SetEpisodesMonitored([FromBody] EpisodesMonitoredResource resource) public IActionResult SetEpisodesMonitored([FromBody] EpisodesMonitoredResource resource)
{ {
var includeImages = Request.GetBooleanQueryParameter("includeImages", false); var includeImages = Request.GetBooleanQueryParameter("includeImages", false);

@ -16,6 +16,7 @@ namespace Sonarr.Api.V3.Episodes
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<RenameEpisodeResource> GetEpisodes(int seriesId, int? seasonNumber) public List<RenameEpisodeResource> GetEpisodes(int seriesId, int? seasonNumber)
{ {
if (seasonNumber.HasValue) if (seasonNumber.HasValue)

@ -26,12 +26,14 @@ namespace Sonarr.Api.V3.FileSystem
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public IActionResult GetContents(string path, bool includeFiles = false, bool allowFoldersWithoutTrailingSlashes = false) public IActionResult GetContents(string path, bool includeFiles = false, bool allowFoldersWithoutTrailingSlashes = false)
{ {
return Ok(_fileSystemLookupService.LookupContents(path, includeFiles, allowFoldersWithoutTrailingSlashes)); return Ok(_fileSystemLookupService.LookupContents(path, includeFiles, allowFoldersWithoutTrailingSlashes));
} }
[HttpGet("type")] [HttpGet("type")]
[Produces("application/json")]
public object GetEntityType(string path) public object GetEntityType(string path)
{ {
if (_diskProvider.FileExists(path)) if (_diskProvider.FileExists(path))
@ -44,6 +46,7 @@ namespace Sonarr.Api.V3.FileSystem
} }
[HttpGet("mediafiles")] [HttpGet("mediafiles")]
[Produces("application/json")]
public object GetMediaFiles(string path) public object GetMediaFiles(string path)
{ {
if (!_diskProvider.FolderExists(path)) if (!_diskProvider.FolderExists(path))

@ -28,6 +28,7 @@ namespace Sonarr.Api.V3.Health
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<HealthResource> GetHealth() public List<HealthResource> GetHealth()
{ {
return _healthCheckService.Results().ToResource(); return _healthCheckService.Results().ToResource();

@ -57,6 +57,7 @@ namespace Sonarr.Api.V3.History
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public PagingResource<HistoryResource> GetHistory(bool includeSeries, bool includeEpisode) public PagingResource<HistoryResource> GetHistory(bool includeSeries, bool includeEpisode)
{ {
var pagingResource = Request.ReadPagingResourceFromRequest<HistoryResource>(); var pagingResource = Request.ReadPagingResourceFromRequest<HistoryResource>();
@ -88,12 +89,14 @@ namespace Sonarr.Api.V3.History
} }
[HttpGet("since")] [HttpGet("since")]
[Produces("application/json")]
public List<HistoryResource> GetHistorySince(DateTime date, EpisodeHistoryEventType? eventType = null, bool includeSeries = false, bool includeEpisode = false) public List<HistoryResource> GetHistorySince(DateTime date, EpisodeHistoryEventType? eventType = null, bool includeSeries = false, bool includeEpisode = false)
{ {
return _historyService.Since(date, eventType).Select(h => MapToResource(h, includeSeries, includeEpisode)).ToList(); return _historyService.Since(date, eventType).Select(h => MapToResource(h, includeSeries, includeEpisode)).ToList();
} }
[HttpGet("series")] [HttpGet("series")]
[Produces("application/json")]
public List<HistoryResource> GetSeriesHistory(int seriesId, int? seasonNumber, EpisodeHistoryEventType? eventType = null, bool includeSeries = false, bool includeEpisode = false) public List<HistoryResource> GetSeriesHistory(int seriesId, int? seasonNumber, EpisodeHistoryEventType? eventType = null, bool includeSeries = false, bool includeEpisode = false)
{ {
if (seasonNumber.HasValue) if (seasonNumber.HasValue)

@ -29,12 +29,14 @@ namespace Sonarr.Api.V3.ImportLists
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<ImportListExclusionResource> GetImportListExclusions() public List<ImportListExclusionResource> GetImportListExclusions()
{ {
return _importListExclusionService.All().ToResource(); return _importListExclusionService.All().ToResource();
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<ImportListExclusionResource> AddImportListExclusion(ImportListExclusionResource resource) public ActionResult<ImportListExclusionResource> AddImportListExclusion(ImportListExclusionResource resource)
{ {
var importListExclusion = _importListExclusionService.Add(resource.ToModel()); var importListExclusion = _importListExclusionService.Add(resource.ToModel());
@ -43,6 +45,7 @@ namespace Sonarr.Api.V3.ImportLists
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<ImportListExclusionResource> UpdateImportListExclusion(ImportListExclusionResource resource) public ActionResult<ImportListExclusionResource> UpdateImportListExclusion(ImportListExclusionResource resource)
{ {
_importListExclusionService.Update(resource.ToModel()); _importListExclusionService.Update(resource.ToModel());

@ -67,6 +67,7 @@ namespace Sonarr.Api.V3.Indexers
} }
[HttpPost] [HttpPost]
[Consumes("application/json")]
public object DownloadRelease(ReleaseResource release) public object DownloadRelease(ReleaseResource release)
{ {
var remoteEpisode = _remoteEpisodeCache.Find(GetCacheKey(release)); var remoteEpisode = _remoteEpisodeCache.Find(GetCacheKey(release));
@ -138,6 +139,7 @@ namespace Sonarr.Api.V3.Indexers
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<ReleaseResource> GetReleases(int? seriesId, int? episodeId, int? seasonNumber) public List<ReleaseResource> GetReleases(int? seriesId, int? episodeId, int? seasonNumber)
{ {
if (episodeId.HasValue) if (episodeId.HasValue)

@ -44,6 +44,7 @@ namespace Sonarr.Api.V3.Indexers
} }
[HttpPost] [HttpPost]
[Consumes("application/json")]
public ActionResult<List<ReleaseResource>> Create(ReleaseResource release) public ActionResult<List<ReleaseResource>> Create(ReleaseResource release)
{ {
_logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl); _logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl);

@ -17,6 +17,7 @@ namespace Sonarr.Api.V3.Logs
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public PagingResource<LogResource> GetLogs() public PagingResource<LogResource> GetLogs()
{ {
var pagingResource = Request.ReadPagingResourceFromRequest<LogResource>(); var pagingResource = Request.ReadPagingResourceFromRequest<LogResource>();

@ -26,6 +26,7 @@ namespace Sonarr.Api.V3.Logs
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<LogFileResource> GetLogFilesResponse() public List<LogFileResource> GetLogFilesResponse()
{ {
var result = new List<LogFileResource>(); var result = new List<LogFileResource>();
@ -51,6 +52,7 @@ namespace Sonarr.Api.V3.Logs
} }
[HttpGet(@"{filename:regex([[-.a-zA-Z0-9]]+?\.txt)}")] [HttpGet(@"{filename:regex([[-.a-zA-Z0-9]]+?\.txt)}")]
[Produces("text/plain")]
public IActionResult GetLogFileResponse(string filename) public IActionResult GetLogFileResponse(string filename)
{ {
LogManager.Flush(); LogManager.Flush();

@ -21,6 +21,7 @@ namespace Sonarr.Api.V3.ManualImport
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<ManualImportResource> GetMediaFiles(string folder, string downloadId, int? seriesId, int? seasonNumber, bool filterExistingFiles = true) public List<ManualImportResource> GetMediaFiles(string folder, string downloadId, int? seriesId, int? seasonNumber, bool filterExistingFiles = true)
{ {
if (seriesId.HasValue) if (seriesId.HasValue)
@ -32,6 +33,7 @@ namespace Sonarr.Api.V3.ManualImport
} }
[HttpPost] [HttpPost]
[Consumes("application/json")]
public object ReprocessItems([FromBody] List<ManualImportReprocessResource> items) public object ReprocessItems([FromBody] List<ManualImportReprocessResource> items)
{ {
foreach (var item in items) foreach (var item in items)

@ -18,6 +18,7 @@ namespace Sonarr.Api.V3.Parse
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public ParseResource Parse(string title, string path) public ParseResource Parse(string title, string path)
{ {
if (title.IsNullOrWhiteSpace()) if (title.IsNullOrWhiteSpace())

@ -34,6 +34,7 @@ namespace Sonarr.Api.V3.Profiles.Delay
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<DelayProfileResource> Create(DelayProfileResource resource) public ActionResult<DelayProfileResource> Create(DelayProfileResource resource)
{ {
var model = resource.ToModel(); var model = resource.ToModel();
@ -54,6 +55,7 @@ namespace Sonarr.Api.V3.Profiles.Delay
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<DelayProfileResource> Update(DelayProfileResource resource) public ActionResult<DelayProfileResource> Update(DelayProfileResource resource)
{ {
var model = resource.ToModel(); var model = resource.ToModel();
@ -67,6 +69,7 @@ namespace Sonarr.Api.V3.Profiles.Delay
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<DelayProfileResource> GetAll() public List<DelayProfileResource> GetAll()
{ {
return _delayProfileService.All().ToResource(); return _delayProfileService.All().ToResource();

@ -24,6 +24,7 @@ namespace Sonarr.Api.V3.Profiles.Language
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<LanguageProfileResource> Create(LanguageProfileResource resource) public ActionResult<LanguageProfileResource> Create(LanguageProfileResource resource)
{ {
var model = resource.ToModel(); var model = resource.ToModel();
@ -38,6 +39,7 @@ namespace Sonarr.Api.V3.Profiles.Language
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<LanguageProfileResource> Update(LanguageProfileResource resource) public ActionResult<LanguageProfileResource> Update(LanguageProfileResource resource)
{ {
var model = resource.ToModel(); var model = resource.ToModel();
@ -53,6 +55,7 @@ namespace Sonarr.Api.V3.Profiles.Language
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<LanguageProfileResource> GetAll() public List<LanguageProfileResource> GetAll()
{ {
return _profileService.All().ToResource(); return _profileService.All().ToResource();

@ -15,6 +15,7 @@ namespace Sonarr.Api.V3.Profiles.Language
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public LanguageProfileResource GetSchema() public LanguageProfileResource GetSchema()
{ {
var qualityProfile = _profileService.GetDefaultProfile(string.Empty); var qualityProfile = _profileService.GetDefaultProfile(string.Empty);

@ -43,6 +43,7 @@ namespace Sonarr.Api.V3.Profiles.Quality
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<QualityProfileResource> Create(QualityProfileResource resource) public ActionResult<QualityProfileResource> Create(QualityProfileResource resource)
{ {
var model = resource.ToModel(); var model = resource.ToModel();
@ -57,6 +58,7 @@ namespace Sonarr.Api.V3.Profiles.Quality
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<QualityProfileResource> Update(QualityProfileResource resource) public ActionResult<QualityProfileResource> Update(QualityProfileResource resource)
{ {
var model = resource.ToModel(); var model = resource.ToModel();
@ -72,6 +74,7 @@ namespace Sonarr.Api.V3.Profiles.Quality
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<QualityProfileResource> GetAll() public List<QualityProfileResource> GetAll()
{ {
return _profileService.All().ToResource(); return _profileService.All().ToResource();

@ -42,6 +42,7 @@ namespace Sonarr.Api.V3
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<TProviderResource> GetAll() public List<TProviderResource> GetAll()
{ {
var providerDefinitions = _providerFactory.All().OrderBy(p => p.ImplementationName); var providerDefinitions = _providerFactory.All().OrderBy(p => p.ImplementationName);
@ -59,6 +60,7 @@ namespace Sonarr.Api.V3
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<TProviderResource> CreateProvider(TProviderResource providerResource) public ActionResult<TProviderResource> CreateProvider(TProviderResource providerResource)
{ {
var providerDefinition = GetDefinition(providerResource, true, false, false); var providerDefinition = GetDefinition(providerResource, true, false, false);
@ -74,6 +76,7 @@ namespace Sonarr.Api.V3
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<TProviderResource> UpdateProvider(TProviderResource providerResource) public ActionResult<TProviderResource> UpdateProvider(TProviderResource providerResource)
{ {
var providerDefinition = GetDefinition(providerResource, true, false, false); var providerDefinition = GetDefinition(providerResource, true, false, false);
@ -112,6 +115,7 @@ namespace Sonarr.Api.V3
} }
[HttpGet("schema")] [HttpGet("schema")]
[Produces("application/json")]
public List<TProviderResource> GetTemplates() public List<TProviderResource> GetTemplates()
{ {
var defaultDefinitions = _providerFactory.GetDefaultDefinitions().OrderBy(p => p.ImplementationName).ToList(); var defaultDefinitions = _providerFactory.GetDefaultDefinitions().OrderBy(p => p.ImplementationName).ToList();
@ -135,6 +139,7 @@ namespace Sonarr.Api.V3
[SkipValidation(true, false)] [SkipValidation(true, false)]
[HttpPost("test")] [HttpPost("test")]
[Consumes("application/json")]
public object Test([FromBody] TProviderResource providerResource) public object Test([FromBody] TProviderResource providerResource)
{ {
var providerDefinition = GetDefinition(providerResource, true, true, true); var providerDefinition = GetDefinition(providerResource, true, true, true);
@ -171,6 +176,7 @@ namespace Sonarr.Api.V3
[SkipValidation] [SkipValidation]
[HttpPost("action/{name}")] [HttpPost("action/{name}")]
[Consumes("application/json")]
public IActionResult RequestAction(string name, [FromBody] TProviderResource resource) public IActionResult RequestAction(string name, [FromBody] TProviderResource resource)
{ {
var providerDefinition = GetDefinition(resource, false, false, false); var providerDefinition = GetDefinition(resource, false, false, false);

@ -55,6 +55,7 @@ namespace Sonarr.Api.V3.Qualities
.ToResource()); .ToResource());
} }
[NonAction]
public void Handle(CommandExecutedEvent message) public void Handle(CommandExecutedEvent message)
{ {
if (message.Command.Name == "ResetQualityDefinitions") if (message.Command.Name == "ResetQualityDefinitions")

@ -35,6 +35,7 @@ namespace Sonarr.Api.V3.Queue
} }
[HttpPost("grab/bulk")] [HttpPost("grab/bulk")]
[Consumes("application/json")]
public object Grab([FromBody] QueueBulkResource resource) public object Grab([FromBody] QueueBulkResource resource)
{ {
foreach (var id in resource.Ids) foreach (var id in resource.Ids)

@ -99,6 +99,7 @@ namespace Sonarr.Api.V3.Queue
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public PagingResource<QueueResource> GetQueue(bool includeUnknownSeriesItems = false, bool includeSeries = false, bool includeEpisode = false) public PagingResource<QueueResource> GetQueue(bool includeUnknownSeriesItems = false, bool includeSeries = false, bool includeEpisode = false)
{ {
var pagingResource = Request.ReadPagingResourceFromRequest<QueueResource>(); var pagingResource = Request.ReadPagingResourceFromRequest<QueueResource>();

@ -32,6 +32,7 @@ namespace Sonarr.Api.V3.Queue
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<QueueResource> GetQueue(int? seriesId, [FromQuery]List<int> episodeIds, bool includeSeries = false, bool includeEpisode = false) public List<QueueResource> GetQueue(int? seriesId, [FromQuery]List<int> episodeIds, bool includeSeries = false, bool includeEpisode = false)
{ {
var queue = _queueService.GetQueue(); var queue = _queueService.GetQueue();

@ -36,6 +36,7 @@ namespace Sonarr.Api.V3.Queue
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public QueueStatusResource GetQueueStatus() public QueueStatusResource GetQueueStatus()
{ {
_broadcastDebounce.Pause(); _broadcastDebounce.Pause();

@ -40,6 +40,7 @@ namespace Sonarr.Api.V3.RemotePathMappings
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<RemotePathMappingResource> CreateMapping(RemotePathMappingResource resource) public ActionResult<RemotePathMappingResource> CreateMapping(RemotePathMappingResource resource)
{ {
var model = resource.ToModel(); var model = resource.ToModel();
@ -48,6 +49,7 @@ namespace Sonarr.Api.V3.RemotePathMappings
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<RemotePathMappingResource> GetMappings() public List<RemotePathMappingResource> GetMappings()
{ {
return _remotePathMappingService.All().ToResource(); return _remotePathMappingService.All().ToResource();

@ -49,6 +49,7 @@ namespace Sonarr.Api.V3.RootFolders
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<RootFolderResource> CreateRootFolder(RootFolderResource rootFolderResource) public ActionResult<RootFolderResource> CreateRootFolder(RootFolderResource rootFolderResource)
{ {
var model = rootFolderResource.ToModel(); var model = rootFolderResource.ToModel();
@ -57,6 +58,7 @@ namespace Sonarr.Api.V3.RootFolders
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<RootFolderResource> GetRootFolders() public List<RootFolderResource> GetRootFolders()
{ {
return _rootFolderService.AllWithUnmappedFolders().ToResource(); return _rootFolderService.AllWithUnmappedFolders().ToResource();

@ -18,6 +18,7 @@ namespace Sonarr.Api.V3.SeasonPass
} }
[HttpPost] [HttpPost]
[Consumes("application/json")]
public IActionResult UpdateAll(SeasonPassResource resource) public IActionResult UpdateAll(SeasonPassResource resource)
{ {
var seriesToUpdate = _seriesService.GetSeries(resource.Series.Select(s => s.Id)); var seriesToUpdate = _seriesService.GetSeries(resource.Series.Select(s => s.Id));

@ -98,6 +98,7 @@ namespace Sonarr.Api.V3.Series
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<SeriesResource> AllSeries(int? tvdbId, bool includeSeasonImages = false) public List<SeriesResource> AllSeries(int? tvdbId, bool includeSeasonImages = false)
{ {
var seriesStats = _seriesStatisticsService.SeriesStatistics(); var seriesStats = _seriesStatisticsService.SeriesStatistics();
@ -129,6 +130,7 @@ namespace Sonarr.Api.V3.Series
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<SeriesResource> AddSeries(SeriesResource seriesResource) public ActionResult<SeriesResource> AddSeries(SeriesResource seriesResource)
{ {
var series = _addSeriesService.AddSeries(seriesResource.ToModel()); var series = _addSeriesService.AddSeries(seriesResource.ToModel());
@ -137,6 +139,7 @@ namespace Sonarr.Api.V3.Series
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<SeriesResource> UpdateSeries(SeriesResource seriesResource) public ActionResult<SeriesResource> UpdateSeries(SeriesResource seriesResource)
{ {
var moveFiles = Request.GetBooleanQueryParameter("moveFiles"); var moveFiles = Request.GetBooleanQueryParameter("moveFiles");

@ -54,6 +54,7 @@ namespace Sonarr.Api.V3.System
} }
[HttpGet("status")] [HttpGet("status")]
[Produces("application/json")]
public object GetStatus() public object GetStatus()
{ {
return new return new
@ -92,6 +93,7 @@ namespace Sonarr.Api.V3.System
} }
[HttpGet("routes")] [HttpGet("routes")]
[Produces("application/json")]
public IActionResult GetRoutes() public IActionResult GetRoutes()
{ {
using (var sw = new StringWriter()) using (var sw = new StringWriter())
@ -103,6 +105,7 @@ namespace Sonarr.Api.V3.System
} }
[HttpGet("routes/duplicate")] [HttpGet("routes/duplicate")]
[Produces("application/json")]
public object DuplicateRoutes() public object DuplicateRoutes()
{ {
return _detector.GetDuplicateEndpoints(_endpointData); return _detector.GetDuplicateEndpoints(_endpointData);

@ -28,18 +28,21 @@ namespace Sonarr.Api.V3.Tags
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<TagResource> GetAll() public List<TagResource> GetAll()
{ {
return _tagService.All().ToResource(); return _tagService.All().ToResource();
} }
[RestPostById] [RestPostById]
[Consumes("application/json")]
public ActionResult<TagResource> Create(TagResource resource) public ActionResult<TagResource> Create(TagResource resource)
{ {
return Created(_tagService.Add(resource.ToModel()).Id); return Created(_tagService.Add(resource.ToModel()).Id);
} }
[RestPutById] [RestPutById]
[Consumes("application/json")]
public ActionResult<TagResource> Update(TagResource resource) public ActionResult<TagResource> Update(TagResource resource)
{ {
_tagService.Update(resource.ToModel()); _tagService.Update(resource.ToModel());

@ -22,6 +22,7 @@ namespace Sonarr.Api.V3.Tags
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<TagDetailsResource> GetAll() public List<TagDetailsResource> GetAll()
{ {
return _tagService.Details().ToResource(); return _tagService.Details().ToResource();

@ -22,6 +22,7 @@ namespace Sonarr.Api.V3.Update
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public List<UpdateResource> GetRecentUpdates() public List<UpdateResource> GetRecentUpdates()
{ {
var resources = _recentUpdateProvider.GetRecentUpdatePackages() var resources = _recentUpdateProvider.GetRecentUpdatePackages()

@ -26,6 +26,7 @@ namespace Sonarr.Api.V3.Wanted
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public PagingResource<EpisodeResource> GetCutoffUnmetEpisodes(bool includeSeries = false, bool includeEpisodeFile = false, bool includeImages = false) public PagingResource<EpisodeResource> GetCutoffUnmetEpisodes(bool includeSeries = false, bool includeEpisodeFile = false, bool includeImages = false)
{ {
var pagingResource = Request.ReadPagingResourceFromRequest<EpisodeResource>(); var pagingResource = Request.ReadPagingResourceFromRequest<EpisodeResource>();

@ -23,6 +23,7 @@ namespace Sonarr.Api.V3.Wanted
} }
[HttpGet] [HttpGet]
[Produces("application/json")]
public PagingResource<EpisodeResource> GetMissingEpisodes(bool includeSeries = false, bool includeImages = false) public PagingResource<EpisodeResource> GetMissingEpisodes(bool includeSeries = false, bool includeImages = false)
{ {
var pagingResource = Request.ReadPagingResourceFromRequest<EpisodeResource>(); var pagingResource = Request.ReadPagingResourceFromRequest<EpisodeResource>();

File diff suppressed because it is too large Load Diff

@ -39,6 +39,7 @@ namespace Sonarr.Http.REST
} }
[RestGetById] [RestGetById]
[Produces("application/json")]
public ActionResult<TResource> GetResourceByIdWithErrorHandler(int id) public ActionResult<TResource> GetResourceByIdWithErrorHandler(int id)
{ {
try try

Loading…
Cancel
Save