Add annotations to swagger + more ASF API breaking changes that @Aareksio is ready for

This commit is contained in:
JustArchi 2018-10-08 00:09:30 +02:00
parent b3c3db30fa
commit cd28845d7b
9 changed files with 77 additions and 18 deletions

View file

@ -56,6 +56,7 @@
<PackageReference Include="NLog.Web.AspNetCore" Version="4.7.0" />
<PackageReference Include="protobuf-net" Version="3.0.0-alpha.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="3.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">

View file

@ -27,16 +27,21 @@ using ArchiSteamFarm.IPC.Requests;
using ArchiSteamFarm.IPC.Responses;
using ArchiSteamFarm.Localization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
namespace ArchiSteamFarm.IPC.Controllers.Api {
[ApiController]
[Produces("application/json")]
[Route("Api/ASF")]
[SwaggerResponse(400, "The request has failed, check " + nameof(GenericResponse.Message) + " from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))]
[SwaggerResponse(401, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set, but you've failed to authenticate. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
[SwaggerResponse(403, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set and you've failed to authenticate too many times, try again in an hour. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
public sealed class ASFController : ControllerBase {
/// <summary>
/// Fetches common info related to ASF as a whole.
/// </summary>
[HttpGet]
[SwaggerResponse(200, type: typeof(GenericResponse<ASFResponse>))]
public ActionResult<GenericResponse<ASFResponse>> ASFGet() {
uint memoryUsage = (uint) GC.GetTotalMemory(false) / 1024;
@ -53,7 +58,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// <summary>
/// Updates ASF's global config.
/// </summary>
[Consumes("application/json")]
[HttpPost]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public async Task<ActionResult<GenericResponse>> ASFPost([FromBody] ASFRequest request) {
if (request == null) {
ASF.ArchiLogger.LogNullError(nameof(request));
@ -81,6 +88,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Makes ASF shutdown itself.
/// </summary>
[HttpPost("Exit")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public ActionResult<GenericResponse> ExitPost() {
(bool success, string output) = Actions.Exit();
return Ok(new GenericResponse(success, output));
@ -90,6 +98,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Makes ASF restart itself.
/// </summary>
[HttpPost("Restart")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public ActionResult<GenericResponse> RestartPost() {
(bool success, string output) = Actions.Restart();
return Ok(new GenericResponse(success, output));
@ -99,6 +108,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Makes ASF update itself.
/// </summary>
[HttpPost("Update")]
[SwaggerResponse(200, type: typeof(GenericResponse<Version>))]
public async Task<ActionResult<GenericResponse<Version>>> UpdatePost() {
(bool success, Version version) = await Actions.Update().ConfigureAwait(false);
return Ok(new GenericResponse<Version>(success, version));

View file

@ -29,16 +29,21 @@ using ArchiSteamFarm.IPC.Requests;
using ArchiSteamFarm.IPC.Responses;
using ArchiSteamFarm.Localization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
namespace ArchiSteamFarm.IPC.Controllers.Api {
[ApiController]
[Produces("application/json")]
[Route("Api/Bot")]
[SwaggerResponse(400, "The request has failed, check " + nameof(GenericResponse.Message) + " from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))]
[SwaggerResponse(401, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set, but you've failed to authenticate. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
[SwaggerResponse(403, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set and you've failed to authenticate too many times, try again in an hour. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
public sealed class BotController : ControllerBase {
/// <summary>
/// Deletes all files related to given bots.
/// </summary>
[HttpDelete("{botNames:required}")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public async Task<ActionResult<GenericResponse>> BotDelete(string botNames) {
if (string.IsNullOrEmpty(botNames)) {
ASF.ArchiLogger.LogNullError(nameof(botNames));
@ -58,24 +63,27 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Fetches common info related to given bots.
/// </summary>
[HttpGet("{botNames:required}")]
public ActionResult<GenericResponse<HashSet<Bot>>> BotGet(string botNames) {
[SwaggerResponse(200, type: typeof(GenericResponse<IDictionary<string, Bot>>))]
public ActionResult<GenericResponse<IDictionary<string, Bot>>> BotGet(string botNames) {
if (string.IsNullOrEmpty(botNames)) {
ASF.ArchiLogger.LogNullError(nameof(botNames));
return BadRequest(new GenericResponse<HashSet<Bot>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
return BadRequest(new GenericResponse<IDictionary<string, Bot>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
}
HashSet<Bot> bots = Bot.GetBots(botNames);
if (bots == null) {
return BadRequest(new GenericResponse<HashSet<Bot>>(false, string.Format(Strings.ErrorIsInvalid, nameof(bots))));
return BadRequest(new GenericResponse<IDictionary<string, Bot>>(false, string.Format(Strings.ErrorIsInvalid, nameof(bots))));
}
return Ok(new GenericResponse<HashSet<Bot>>(bots));
return Ok(new GenericResponse<IDictionary<string, Bot>>(bots.ToDictionary(bot => bot.BotName, bot => bot)));
}
/// <summary>
/// Updates bot config of given bot.
/// </summary>
[Consumes("application/json")]
[HttpPost("{botName:required}")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public async Task<ActionResult<GenericResponse>> BotPost(string botName, [FromBody] BotRequest request) {
if (string.IsNullOrEmpty(botName) || (request == null)) {
ASF.ArchiLogger.LogNullError(nameof(botName) + " || " + nameof(request));
@ -113,6 +121,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Removes BGR output files of given bots.
/// </summary>
[HttpDelete("{botNames:required}/GamesToRedeemInBackground")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public async Task<ActionResult<GenericResponse>> GamesToRedeemInBackgroundDelete(string botNames) {
if (string.IsNullOrEmpty(botNames)) {
ASF.ArchiLogger.LogNullError(nameof(botNames));
@ -132,15 +141,16 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Fetches BGR output files of given bots.
/// </summary>
[HttpGet("{botNames:required}/GamesToRedeemInBackground")]
public async Task<ActionResult<GenericResponse<Dictionary<string, GamesToRedeemInBackgroundResponse>>>> GamesToRedeemInBackgroundGet(string botNames) {
[SwaggerResponse(200, type: typeof(GenericResponse<IReadOnlyDictionary<string, GamesToRedeemInBackgroundResponse>>))]
public async Task<ActionResult<GenericResponse<IReadOnlyDictionary<string, GamesToRedeemInBackgroundResponse>>>> GamesToRedeemInBackgroundGet(string botNames) {
if (string.IsNullOrEmpty(botNames)) {
ASF.ArchiLogger.LogNullError(nameof(botNames));
return BadRequest(new GenericResponse<Dictionary<string, GamesToRedeemInBackgroundResponse>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, GamesToRedeemInBackgroundResponse>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
}
HashSet<Bot> bots = Bot.GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return BadRequest(new GenericResponse<Dictionary<string, GamesToRedeemInBackgroundResponse>>(false, string.Format(Strings.BotNotFound, botNames)));
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, GamesToRedeemInBackgroundResponse>>(false, string.Format(Strings.BotNotFound, botNames)));
}
IList<(Dictionary<string, string> UnusedKeys, Dictionary<string, string> UsedKeys)> results = await Utilities.InParallel(bots.Select(bot => bot.GetUsedAndUnusedKeys())).ConfigureAwait(false);
@ -152,13 +162,15 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
result[bot.BotName] = new GamesToRedeemInBackgroundResponse(unusedKeys, usedKeys);
}
return Ok(new GenericResponse<Dictionary<string, GamesToRedeemInBackgroundResponse>>(result));
return Ok(new GenericResponse<IReadOnlyDictionary<string, GamesToRedeemInBackgroundResponse>>(result));
}
/// <summary>
/// Adds keys to redeem using BGR to given bot.
/// </summary>
[Consumes("application/json")]
[HttpPost("{botName:required}/GamesToRedeemInBackground")]
[SwaggerResponse(200, type: typeof(GenericResponse<OrderedDictionary>))]
public async Task<ActionResult<GenericResponse<OrderedDictionary>>> GamesToRedeemInBackgroundPost(string botName, [FromBody] GamesToRedeemInBackgroundRequest request) {
if (string.IsNullOrEmpty(botName) || (request == null)) {
ASF.ArchiLogger.LogNullError(nameof(botName) + " || " + nameof(request));
@ -180,7 +192,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// <summary>
/// Pauses given bots.
/// </summary>
[Consumes("application/json")]
[HttpPost("{botNames:required}/Pause")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public async Task<ActionResult<GenericResponse>> PausePost(string botNames, [FromBody] BotPauseRequest request) {
if (string.IsNullOrEmpty(botNames) || (request == null)) {
ASF.ArchiLogger.LogNullError(nameof(botNames) + " || " + nameof(request));
@ -200,6 +214,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Resumes given bots.
/// </summary>
[HttpPost("{botNames:required}/Resume")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public async Task<ActionResult<GenericResponse>> ResumePost(string botNames) {
if (string.IsNullOrEmpty(botNames)) {
ASF.ArchiLogger.LogNullError(nameof(botNames));
@ -219,6 +234,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Starts given bots.
/// </summary>
[HttpPost("{botNames:required}/Start")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public async Task<ActionResult<GenericResponse>> StartPost(string botNames) {
if (string.IsNullOrEmpty(botNames)) {
ASF.ArchiLogger.LogNullError(nameof(botNames));
@ -238,6 +254,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Stops given bots.
/// </summary>
[HttpPost("{botNames:required}/Stop")]
[SwaggerResponse(200, type: typeof(GenericResponse))]
public async Task<ActionResult<GenericResponse>> StopPost(string botNames) {
if (string.IsNullOrEmpty(botNames)) {
ASF.ArchiLogger.LogNullError(nameof(botNames));

View file

@ -25,11 +25,15 @@ using System.Threading.Tasks;
using ArchiSteamFarm.IPC.Responses;
using ArchiSteamFarm.Localization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
namespace ArchiSteamFarm.IPC.Controllers.Api {
[ApiController]
[Produces("application/json")]
[Route("Api/Command")]
[SwaggerResponse(400, "The request has failed, check " + nameof(GenericResponse.Message) + " from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))]
[SwaggerResponse(401, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set, but you've failed to authenticate. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
[SwaggerResponse(403, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set and you've failed to authenticate too many times, try again in an hour. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
public sealed class CommandController : ControllerBase {
/// <summary>
/// Executes a command.
@ -39,6 +43,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// You should use "given bot" commands when executing this endpoint, omitting targets of the command will cause the command to be executed on first defined bot
/// </remarks>
[HttpPost("{command:required}")]
[SwaggerResponse(200, type: typeof(GenericResponse<string>))]
public async Task<ActionResult<GenericResponse<string>>> CommandPost(string command) {
if (string.IsNullOrEmpty(command)) {
ASF.ArchiLogger.LogNullError(nameof(command));

View file

@ -20,6 +20,7 @@
// limitations under the License.
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
@ -30,11 +31,15 @@ using ArchiSteamFarm.Localization;
using ArchiSteamFarm.NLog;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Swashbuckle.AspNetCore.Annotations;
namespace ArchiSteamFarm.IPC.Controllers.Api {
[ApiController]
[Produces("application/json")]
[Route("Api/NLog")]
[SwaggerResponse(400, "The request has failed, check " + nameof(GenericResponse.Message) + " from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))]
[SwaggerResponse(401, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set, but you've failed to authenticate. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
[SwaggerResponse(403, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set and you've failed to authenticate too many times, try again in an hour. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
public sealed class NLogController : ControllerBase {
private static readonly ConcurrentDictionary<WebSocket, SemaphoreSlim> ActiveLogWebSockets = new ConcurrentDictionary<WebSocket, SemaphoreSlim>();
@ -45,6 +50,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// This API endpoint requires a websocket connection.
/// </remarks>
[HttpGet]
[SwaggerResponse(200, type: typeof(IEnumerable<GenericResponse<string>>))]
public async Task<ActionResult> NLogGet() {
if (!HttpContext.WebSockets.IsWebSocketRequest) {
return BadRequest(new GenericResponse(false, string.Format(Strings.WarningFailedWithError, nameof(HttpContext.WebSockets.IsWebSocketRequest) + ": " + HttpContext.WebSockets.IsWebSocketRequest)));

View file

@ -23,11 +23,15 @@ using System;
using ArchiSteamFarm.IPC.Responses;
using ArchiSteamFarm.Localization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
namespace ArchiSteamFarm.IPC.Controllers.Api {
[ApiController]
[Produces("application/json")]
[Route("Api/Structure")]
[SwaggerResponse(400, "The request has failed, check " + nameof(GenericResponse.Message) + " from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))]
[SwaggerResponse(401, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set, but you've failed to authenticate. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
[SwaggerResponse(403, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set and you've failed to authenticate too many times, try again in an hour. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
public sealed class StructureController : ControllerBase {
/// <summary>
/// Fetches structure of given type.
@ -36,6 +40,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Structure is defined as a representation of given object in its default state.
/// </remarks>
[HttpGet("{structure:required}")]
[SwaggerResponse(200, type: typeof(GenericResponse<object>))]
public ActionResult<GenericResponse<object>> StructureGet(string structure) {
if (string.IsNullOrEmpty(structure)) {
ASF.ArchiLogger.LogNullError(nameof(structure));

View file

@ -27,11 +27,15 @@ using ArchiSteamFarm.IPC.Responses;
using ArchiSteamFarm.Localization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Swashbuckle.AspNetCore.Annotations;
namespace ArchiSteamFarm.IPC.Controllers.Api {
[ApiController]
[Produces("application/json")]
[Route("Api/Type")]
[SwaggerResponse(400, "The request has failed, check " + nameof(GenericResponse.Message) + " from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))]
[SwaggerResponse(401, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set, but you've failed to authenticate. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
[SwaggerResponse(403, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set and you've failed to authenticate too many times, try again in an hour. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
public sealed class TypeController : ControllerBase {
/// <summary>
/// Fetches type info of given type.
@ -40,6 +44,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// Type info is defined as a representation of given object with its fields and properties being assigned to a string value that defines their type.
/// </remarks>
[HttpGet("{type:required}")]
[SwaggerResponse(200, type: typeof(GenericResponse<TypeResponse>))]
public ActionResult<GenericResponse<TypeResponse>> TypeGet(string type) {
if (string.IsNullOrEmpty(type)) {
ASF.ArchiLogger.LogNullError(nameof(type));

View file

@ -28,11 +28,15 @@ using ArchiSteamFarm.IPC.Requests;
using ArchiSteamFarm.IPC.Responses;
using ArchiSteamFarm.Localization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
namespace ArchiSteamFarm.IPC.Controllers.Api {
[ApiController]
[Produces("application/json")]
[Route("Api/WWW")]
[SwaggerResponse(400, "The request has failed, check " + nameof(GenericResponse.Message) + " from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))]
[SwaggerResponse(401, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set, but you've failed to authenticate. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
[SwaggerResponse(403, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set and you've failed to authenticate too many times, try again in an hour. See " + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/IPC#authentication.")]
public sealed class WWWController : ControllerBase {
/// <summary>
/// Fetches files in given directory relative to WWW root.
@ -41,15 +45,16 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// This is internal API being utilizied by our ASF-ui IPC frontend. You should not depend on existence of any /Api/WWW as they can disappear and change anytime.
/// </remarks>
[HttpGet("Directory/{directory:required}")]
public ActionResult<GenericResponse<HashSet<string>>> DirectoryGet(string directory) {
[SwaggerResponse(200, type: typeof(GenericResponse<IReadOnlyCollection<string>>))]
public ActionResult<GenericResponse<IReadOnlyCollection<string>>> DirectoryGet(string directory) {
if (string.IsNullOrEmpty(directory)) {
ASF.ArchiLogger.LogNullError(nameof(directory));
return BadRequest(new GenericResponse<HashSet<string>>(false, string.Format(Strings.ErrorIsEmpty, nameof(directory))));
return BadRequest(new GenericResponse<IReadOnlyCollection<string>>(false, string.Format(Strings.ErrorIsEmpty, nameof(directory))));
}
string directoryPath = Path.Combine(ArchiKestrel.WebsiteDirectory, directory);
if (!Directory.Exists(directoryPath)) {
return BadRequest(new GenericResponse<HashSet<string>>(false, string.Format(Strings.ErrorIsInvalid, directory)));
return BadRequest(new GenericResponse<IReadOnlyCollection<string>>(false, string.Format(Strings.ErrorIsInvalid, directory)));
}
string[] files;
@ -57,11 +62,11 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
try {
files = Directory.GetFiles(directoryPath);
} catch (Exception e) {
return BadRequest(new GenericResponse<HashSet<string>>(false, string.Format(Strings.ErrorParsingObject, nameof(files)) + Environment.NewLine + e));
return BadRequest(new GenericResponse<IReadOnlyCollection<string>>(false, string.Format(Strings.ErrorParsingObject, nameof(files)) + Environment.NewLine + e));
}
HashSet<string> result = files.Select(Path.GetFileName).ToHashSet();
return Ok(new GenericResponse<HashSet<string>>(result));
return Ok(new GenericResponse<IReadOnlyCollection<string>>(result));
}
/// <summary>
@ -71,18 +76,19 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// This is internal API being utilizied by our ASF-ui IPC frontend. You should not depend on existence of any /Api/WWW as they can disappear and change anytime.
/// </remarks>
[HttpGet("GitHub/Releases")]
public async Task<ActionResult<GenericResponse<IEnumerable<GitHubReleaseResponse>>>> GitHubReleasesGet([FromQuery] byte count = 10) {
[SwaggerResponse(200, type: typeof(GenericResponse<IReadOnlyCollection<GitHubReleaseResponse>>))]
public async Task<ActionResult<GenericResponse<IReadOnlyCollection<GitHubReleaseResponse>>>> GitHubReleasesGet([FromQuery] byte count = 10) {
if (count == 0) {
return BadRequest(new GenericResponse<IEnumerable<GitHubReleaseResponse>>(false, string.Format(Strings.ErrorIsEmpty, nameof(count))));
return BadRequest(new GenericResponse<IReadOnlyCollection<GitHubReleaseResponse>>(false, string.Format(Strings.ErrorIsEmpty, nameof(count))));
}
List<GitHub.ReleaseResponse> response = await GitHub.GetReleases(count).ConfigureAwait(false);
if ((response == null) || (response.Count == 0)) {
return BadRequest(new GenericResponse<IEnumerable<GitHub.ReleaseResponse>>(false, string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)));
return BadRequest(new GenericResponse<IReadOnlyCollection<GitHub.ReleaseResponse>>(false, string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)));
}
IEnumerable<GitHubReleaseResponse> result = response.Select(singleResponse => new GitHubReleaseResponse(singleResponse));
return Ok(new GenericResponse<IEnumerable<GitHubReleaseResponse>>(result));
List<GitHubReleaseResponse> result = response.Select(singleResponse => new GitHubReleaseResponse(singleResponse)).ToList();
return Ok(new GenericResponse<IReadOnlyCollection<GitHubReleaseResponse>>(result));
}
/// <summary>
@ -92,6 +98,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// This is internal API being utilizied by our ASF-ui IPC frontend. You should not depend on existence of any /Api/WWW as they can disappear and change anytime.
/// </remarks>
[HttpGet("GitHub/Releases/{version:required}")]
[SwaggerResponse(200, type: typeof(GenericResponse<GitHubReleaseResponse>))]
public async Task<ActionResult<GenericResponse<GitHubReleaseResponse>>> GitHubReleasesGet(string version) {
if (string.IsNullOrEmpty(version)) {
return BadRequest(new GenericResponse<GitHubReleaseResponse>(false, string.Format(Strings.ErrorIsEmpty, nameof(version))));
@ -111,7 +118,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
/// <remarks>
/// This is internal API being utilizied by our ASF-ui IPC frontend. You should not depend on existence of any /Api/WWW as they can disappear and change anytime.
/// </remarks>
[Consumes("application/json")]
[HttpPost("Send")]
[SwaggerResponse(200, type: typeof(GenericResponse<string>))]
public async Task<ActionResult<GenericResponse<string>>> SendPost([FromBody] WWWSendRequest request) {
if (request == null) {
ASF.ArchiLogger.LogNullError(nameof(request));

View file

@ -95,6 +95,7 @@ namespace ArchiSteamFarm.IPC {
services.AddSwaggerGen(
c => {
c.DescribeAllEnumsAsStrings();
c.EnableAnnotations();
c.SwaggerDoc("ASF", new Info { Title = "ASF API" });
string xmlDocumentationFile = Path.Combine(AppContext.BaseDirectory, SharedInfo.AssemblyDocumentation);