Include annonations for API docs

This commit is contained in:
Bogdan 2024-04-22 08:16:48 +03:00
parent 627b2a4289
commit f9c3586563
13 changed files with 106 additions and 49 deletions

View File

@ -97,6 +97,7 @@ namespace NzbDrone.Host
services.AddSwaggerGen(c =>
{
c.EnableAnnotations();
c.SwaggerDoc("v3", new OpenApiInfo
{
Version = "3.0.0",

View File

@ -7,6 +7,7 @@ using NzbDrone.Core.Indexers;
using Sonarr.Http;
using Sonarr.Http.Extensions;
using Sonarr.Http.REST.Attributes;
using Swashbuckle.AspNetCore.Annotations;
namespace Sonarr.Api.V3.Blocklist
{
@ -25,6 +26,7 @@ namespace Sonarr.Api.V3.Blocklist
[HttpGet]
[Produces("application/json")]
[SwaggerOperation(Summary = "Gets a list of blocklists.")]
public PagingResource<BlocklistResource> GetBlocklist([FromQuery] PagingRequestResource paging, [FromQuery] int[] seriesIds = null, [FromQuery] DownloadProtocol[] protocols = null)
{
var pagingResource = new PagingResource<BlocklistResource>(paging);
@ -44,6 +46,7 @@ namespace Sonarr.Api.V3.Blocklist
}
[RestDeleteById]
[SwaggerOperation(Summary = "Deletes a blocklist by id.")]
public void DeleteBlocklist(int id)
{
_blocklistService.Delete(id);
@ -51,6 +54,7 @@ namespace Sonarr.Api.V3.Blocklist
[HttpDelete("bulk")]
[Produces("application/json")]
[SwaggerOperation(Summary = "Deletes a list of blocklists in bulk.")]
public object Remove([FromBody] BlocklistBulkResource resource)
{
_blocklistService.Delete(resource.Ids);

View File

@ -10,6 +10,7 @@ using NzbDrone.Core.Tv;
using NzbDrone.SignalR;
using Sonarr.Api.V3.Episodes;
using Sonarr.Http;
using Swashbuckle.AspNetCore.Annotations;
namespace Sonarr.Api.V3.Calendar
{
@ -29,8 +30,15 @@ namespace Sonarr.Api.V3.Calendar
_tagService = tagService;
}
[NonAction]
public override ActionResult<EpisodeResource> GetResourceByIdWithErrorHandler(int id)
{
throw new NotImplementedException();
}
[HttpGet]
[Produces("application/json")]
[SwaggerOperation(Summary = "Gets a list of episodes.")]
public List<EpisodeResource> GetCalendar(DateTime? start, DateTime? end, bool unmonitored = false, bool includeSeries = false, bool includeEpisodeFile = false, bool includeEpisodeImages = false, string tags = "")
{
var startUse = start ?? DateTime.Today;

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NLog;
using NzbDrone.Common.Cache;
@ -18,6 +19,7 @@ using NzbDrone.Core.Profiles.Qualities;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Validation;
using Sonarr.Http;
using Swashbuckle.AspNetCore.Annotations;
using HttpStatusCode = System.Net.HttpStatusCode;
namespace Sonarr.Api.V3.Indexers
@ -68,7 +70,8 @@ namespace Sonarr.Api.V3.Indexers
[HttpPost]
[Consumes("application/json")]
public async Task<object> DownloadRelease([FromBody] ReleaseResource release)
[SwaggerOperation(Summary = "Sends release to the download client.")]
public async Task<object> DownloadRelease([FromBody, SwaggerRequestBody(@"Requires ""guid"" and ""indexerId""", Required = true)] ReleaseResource release)
{
var remoteEpisode = _remoteEpisodeCache.Find(GetCacheKey(release));
@ -89,7 +92,7 @@ namespace Sonarr.Api.V3.Indexers
Ensure.That(release.Quality, () => release.Quality).IsNotNull();
Ensure.That(release.Languages, () => release.Languages).IsNotNull();
// Clone the remote episode so we don't overwrite anything on the original
// Clone the remote episode, so we don't overwrite anything on the original
remoteEpisode = new RemoteEpisode
{
Release = remoteEpisode.Release,
@ -170,6 +173,8 @@ namespace Sonarr.Api.V3.Indexers
[HttpGet]
[Produces("application/json")]
[SwaggerOperation(Summary = "Gets a list of releases for an interactive search.")]
[SwaggerResponse(StatusCodes.Status200OK, type: typeof(List<ReleaseResource>))]
public async Task<List<ReleaseResource>> GetReleases(int? seriesId, int? episodeId, int? seasonNumber)
{
if (episodeId.HasValue)

View File

@ -6,6 +6,7 @@ using Sonarr.Http;
using Sonarr.Http.REST;
using Sonarr.Http.REST.Attributes;
using Sonarr.Http.Validation;
using Swashbuckle.AspNetCore.Annotations;
namespace Sonarr.Api.V3.Profiles.Delay
{
@ -35,6 +36,7 @@ namespace Sonarr.Api.V3.Profiles.Delay
[RestPostById]
[Consumes("application/json")]
[SwaggerOperation(Summary = "Creates a delay profile.")]
public ActionResult<DelayProfileResource> Create([FromBody] DelayProfileResource resource)
{
var model = resource.ToModel();
@ -44,6 +46,7 @@ namespace Sonarr.Api.V3.Profiles.Delay
}
[RestDeleteById]
[SwaggerOperation(Summary = "Deletes a delay profile.")]
public void DeleteProfile(int id)
{
if (id == 1)
@ -56,6 +59,7 @@ namespace Sonarr.Api.V3.Profiles.Delay
[RestPutById]
[Consumes("application/json")]
[SwaggerOperation(Summary = "Updates a delay profile.")]
public ActionResult<DelayProfileResource> Update([FromBody] DelayProfileResource resource)
{
var model = resource.ToModel();
@ -70,12 +74,14 @@ namespace Sonarr.Api.V3.Profiles.Delay
[HttpGet]
[Produces("application/json")]
[SwaggerOperation(Summary = "Gets a list of delay profiles.")]
public List<DelayProfileResource> GetAll()
{
return _delayProfileService.All().ToResource();
}
[HttpPut("reorder/{id}")]
[SwaggerOperation(Summary = "Updates order for delay profile.")]
public List<DelayProfileResource> Reorder([FromRoute] int id, [FromQuery] int? after)
{
ValidateId(id);

View File

@ -6,6 +6,7 @@
<PackageReference Include="FluentValidation" Version="9.5.4" />
<PackageReference Include="Ical.Net" Version="4.2.0" />
<PackageReference Include="NLog" Version="4.7.14" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Core\Sonarr.Core.csproj" />

View File

@ -10,6 +10,7 @@ using NzbDrone.Core.Backup;
using Sonarr.Http;
using Sonarr.Http.REST;
using Sonarr.Http.REST.Attributes;
using Swashbuckle.AspNetCore.Annotations;
namespace Sonarr.Api.V3.System.Backup
{
@ -32,6 +33,8 @@ namespace Sonarr.Api.V3.System.Backup
}
[HttpGet]
[Produces("application/json")]
[SwaggerOperation(Summary = "Gets a list of backups.")]
public List<BackupResource> GetBackupFiles()
{
var backups = _backupService.GetBackups();
@ -50,6 +53,7 @@ namespace Sonarr.Api.V3.System.Backup
}
[RestDeleteById]
[SwaggerOperation(Summary = "Deletes a backup.")]
public void DeleteBackup(int id)
{
var backup = GetBackup(id);
@ -70,6 +74,8 @@ namespace Sonarr.Api.V3.System.Backup
}
[HttpPost("restore/{id:int}")]
[Produces("application/json")]
[SwaggerOperation(Summary = "Restores a backup.")]
public object Restore([FromRoute] int id)
{
var backup = GetBackup(id);
@ -91,6 +97,8 @@ namespace Sonarr.Api.V3.System.Backup
[HttpPost("restore/upload")]
[RequestFormLimits(MultipartBodyLengthLimit = 500000000)]
[Produces("application/json")]
[SwaggerOperation(Summary = "Restores a backup by uploading.")]
public object UploadAndRestore()
{
var files = Request.Form.Files;

View File

@ -1,3 +1,4 @@
using System;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Datastore;
@ -26,6 +27,12 @@ namespace Sonarr.Api.V3.Wanted
_episodeCutoffService = episodeCutoffService;
}
[NonAction]
public override ActionResult<EpisodeResource> GetResourceByIdWithErrorHandler(int id)
{
throw new NotImplementedException();
}
[HttpGet]
[Produces("application/json")]
public PagingResource<EpisodeResource> GetCutoffUnmetEpisodes([FromQuery] PagingRequestResource paging, bool includeSeries = false, bool includeEpisodeFile = false, bool includeImages = false, bool monitored = true)

View File

@ -1,3 +1,4 @@
using System;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Datastore;
@ -22,6 +23,12 @@ namespace Sonarr.Api.V3.Wanted
{
}
[NonAction]
public override ActionResult<EpisodeResource> GetResourceByIdWithErrorHandler(int id)
{
throw new NotImplementedException();
}
[HttpGet]
[Produces("application/json")]
public PagingResource<EpisodeResource> GetMissingEpisodes([FromQuery] PagingRequestResource paging, bool includeSeries = false, bool includeImages = false, bool monitored = true)

View File

@ -32,6 +32,7 @@
"tags": [
"ApiInfo"
],
"summary": "Get information about the API.",
"responses": {
"200": {
"description": "Success"
@ -243,6 +244,7 @@
"tags": [
"AutoTagging"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -285,18 +287,11 @@
"tags": [
"Backup"
],
"summary": "Gets a list of backups.",
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/BackupResource"
}
}
},
"application/json": {
"schema": {
"type": "array",
@ -304,14 +299,6 @@
"$ref": "#/components/schemas/BackupResource"
}
}
},
"text/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/BackupResource"
}
}
}
}
}
@ -323,6 +310,7 @@
"tags": [
"Backup"
],
"summary": "Deletes a backup.",
"parameters": [
{
"name": "id",
@ -346,6 +334,7 @@
"tags": [
"Backup"
],
"summary": "Restores a backup.",
"parameters": [
{
"name": "id",
@ -369,6 +358,7 @@
"tags": [
"Backup"
],
"summary": "Restores a backup by uploading.",
"responses": {
"200": {
"description": "Success"
@ -381,6 +371,7 @@
"tags": [
"Blocklist"
],
"summary": "Gets a list of blocklists.",
"parameters": [
{
"name": "page",
@ -455,6 +446,7 @@
"tags": [
"Blocklist"
],
"summary": "Deletes a blocklist by id.",
"parameters": [
{
"name": "id",
@ -478,6 +470,7 @@
"tags": [
"Blocklist"
],
"summary": "Deletes a list of blocklists in bulk.",
"requestBody": {
"content": {
"application/json": {
@ -509,6 +502,7 @@
"tags": [
"Calendar"
],
"summary": "Gets a list of episodes.",
"parameters": [
{
"name": "start",
@ -584,36 +578,6 @@
}
}
},
"/api/v3/calendar/{id}": {
"get": {
"tags": [
"Calendar"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EpisodeResource"
}
}
}
}
}
}
},
"/feed/v3/calendar/sonarr.ics": {
"get": {
"tags": [
@ -752,6 +716,7 @@
"tags": [
"Command"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -907,6 +872,7 @@
"tags": [
"CustomFilter"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -1062,6 +1028,7 @@
"tags": [
"CustomFormat"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -1189,6 +1156,7 @@
"tags": [
"Cutoff"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -1219,6 +1187,7 @@
"tags": [
"DelayProfile"
],
"summary": "Creates a delay profile.",
"requestBody": {
"content": {
"application/json": {
@ -1255,6 +1224,7 @@
"tags": [
"DelayProfile"
],
"summary": "Gets a list of delay profiles.",
"responses": {
"200": {
"description": "Success",
@ -1277,6 +1247,7 @@
"tags": [
"DelayProfile"
],
"summary": "Deletes a delay profile.",
"parameters": [
{
"name": "id",
@ -1298,6 +1269,7 @@
"tags": [
"DelayProfile"
],
"summary": "Updates a delay profile.",
"parameters": [
{
"name": "id",
@ -1344,6 +1316,7 @@
"tags": [
"DelayProfile"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -1374,6 +1347,7 @@
"tags": [
"DelayProfile"
],
"summary": "Updates order for delay profile.",
"parameters": [
{
"name": "id",
@ -1576,6 +1550,7 @@
"tags": [
"DownloadClient"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -1814,6 +1789,7 @@
"tags": [
"DownloadClientConfig"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -1958,6 +1934,7 @@
"tags": [
"Episode"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -2129,6 +2106,7 @@
"tags": [
"EpisodeFile"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -2676,6 +2654,7 @@
"tags": [
"HostConfig"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -2829,6 +2808,7 @@
"tags": [
"ImportList"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -3067,6 +3047,7 @@
"tags": [
"ImportListConfig"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -3276,6 +3257,7 @@
"tags": [
"ImportListExclusion"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -3429,6 +3411,7 @@
"tags": [
"Indexer"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -3667,6 +3650,7 @@
"tags": [
"IndexerConfig"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -3773,6 +3757,7 @@
"tags": [
"Language"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -3912,6 +3897,7 @@
"tags": [
"LanguageProfile"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -4000,6 +3986,7 @@
"tags": [
"Localization"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -4316,6 +4303,7 @@
"tags": [
"MediaManagementConfig"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -4469,6 +4457,7 @@
"tags": [
"Metadata"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -4672,6 +4661,7 @@
"tags": [
"Missing"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -4787,6 +4777,7 @@
"tags": [
"NamingConfig"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -5041,6 +5032,7 @@
"tags": [
"Notification"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -5294,6 +5286,7 @@
"tags": [
"QualityDefinition"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -5527,6 +5520,7 @@
"tags": [
"QualityProfile"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -5942,14 +5936,17 @@
"tags": [
"Release"
],
"summary": "Sends release to the download client.",
"requestBody": {
"description": "Requires \"guid\" and \"indexerId\"",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReleaseResource"
}
}
}
},
"required": true
},
"responses": {
"200": {
@ -5961,6 +5958,7 @@
"tags": [
"Release"
],
"summary": "Gets a list of releases for an interactive search.",
"parameters": [
{
"name": "seriesId",
@ -6170,6 +6168,7 @@
"tags": [
"ReleaseProfile"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -6382,6 +6381,7 @@
"tags": [
"RemotePathMapping"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -6531,6 +6531,7 @@
"tags": [
"RootFolder"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -7168,6 +7169,7 @@
"tags": [
"Tag"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -7220,6 +7222,7 @@
"tags": [
"TagDetails"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -7288,6 +7291,7 @@
"tags": [
"Task"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",
@ -7364,6 +7368,7 @@
"tags": [
"UiConfig"
],
"summary": "Gets a resource by id.",
"parameters": [
{
"name": "id",

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
namespace NzbDrone.Http
{
@ -7,6 +8,7 @@ namespace NzbDrone.Http
{
[HttpGet("/api")]
[Produces("application/json")]
[SwaggerOperation(Summary = "Get information about the API.")]
public object GetApiInfo()
{
return new ApiInfoResource

View File

@ -12,6 +12,7 @@ using NzbDrone.Common.Instrumentation;
using NzbDrone.Core.Datastore;
using Sonarr.Http.REST.Attributes;
using Sonarr.Http.Validation;
using Swashbuckle.AspNetCore.Annotations;
namespace Sonarr.Http.REST
{
@ -48,6 +49,7 @@ namespace Sonarr.Http.REST
[RestGetById]
[Produces("application/json")]
[SwaggerOperation(Summary = "Gets a resource by id.")]
public virtual ActionResult<TResource> GetResourceByIdWithErrorHandler(int id)
{
try

View File

@ -6,6 +6,7 @@
<PackageReference Include="FluentValidation" Version="9.5.4" />
<PackageReference Include="ImpromptuInterface" Version="7.0.1" />
<PackageReference Include="NLog" Version="4.7.14" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Core\Sonarr.Core.csproj" />