mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-09-20 14:32:05 +00:00
Add ASF API swagger explorer
This commit is contained in:
parent
52a7bb048f
commit
b15edf4559
21 changed files with 295 additions and 40 deletions
|
@ -11,8 +11,9 @@
|
|||
<Description>ASF is an application that allows you to farm steam cards using multiple steam accounts simultaneously.</Description>
|
||||
<ErrorReport>none</ErrorReport>
|
||||
<FileVersion>3.4.0.3</FileVersion>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<NoWarn />
|
||||
<NoWarn>1591</NoWarn>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageIconUrl>https://github.com/JustArchi/ArchiSteamFarm/raw/master/resources/ASF.ico</PackageIconUrl>
|
||||
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
|
||||
|
@ -54,6 +55,7 @@
|
|||
<PackageReference Include="NLog" Version="4.5.10" />
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
|
||||
|
|
|
@ -33,7 +33,7 @@ using SteamKit2;
|
|||
|
||||
namespace ArchiSteamFarm {
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
internal sealed class BotConfig {
|
||||
public sealed class BotConfig {
|
||||
private const bool DefaultAcceptGifts = false;
|
||||
private const bool DefaultAutoSteamSaleEvent = false;
|
||||
private const EBotBehaviour DefaultBotBehaviour = EBotBehaviour.None;
|
||||
|
|
|
@ -30,8 +30,12 @@ using Microsoft.AspNetCore.Mvc;
|
|||
|
||||
namespace ArchiSteamFarm.IPC.Controllers.Api {
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Route("Api/ASF")]
|
||||
public sealed class ASFController : ControllerBase {
|
||||
/// <summary>
|
||||
/// Fetches common info related to ASF as a whole.
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public ActionResult<GenericResponse<ASFResponse>> ASFGet() {
|
||||
uint memoryUsage = (uint) GC.GetTotalMemory(false) / 1024;
|
||||
|
@ -46,6 +50,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse<ASFResponse>(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates ASF's global config.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<GenericResponse>> ASFPost([FromBody] ASFRequest request) {
|
||||
if (request == null) {
|
||||
|
@ -70,18 +77,27 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes ASF shutdown itself.
|
||||
/// </summary>
|
||||
[HttpPost("Exit")]
|
||||
public ActionResult<GenericResponse> ExitPost() {
|
||||
(bool success, string output) = Actions.Exit();
|
||||
return Ok(new GenericResponse(success, output));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes ASF restart itself.
|
||||
/// </summary>
|
||||
[HttpPost("Restart")]
|
||||
public ActionResult<GenericResponse> RestartPost() {
|
||||
(bool success, string output) = Actions.Restart();
|
||||
return Ok(new GenericResponse(success, output));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes ASF update itself.
|
||||
/// </summary>
|
||||
[HttpPost("Update")]
|
||||
public async Task<ActionResult<GenericResponse<Version>>> UpdatePost() {
|
||||
(bool success, Version version) = await Actions.Update().ConfigureAwait(false);
|
||||
|
|
|
@ -32,8 +32,12 @@ using Microsoft.AspNetCore.Mvc;
|
|||
|
||||
namespace ArchiSteamFarm.IPC.Controllers.Api {
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Route("Api/Bot")]
|
||||
public sealed class BotController : ControllerBase {
|
||||
/// <summary>
|
||||
/// Deletes all files related to given bots.
|
||||
/// </summary>
|
||||
[HttpDelete("{botNames:required}")]
|
||||
public async Task<ActionResult<GenericResponse>> BotDelete(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
|
@ -50,6 +54,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse(results.All(result => result)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches common info related to given bots.
|
||||
/// </summary>
|
||||
[HttpGet("{botNames:required}")]
|
||||
public ActionResult<GenericResponse<HashSet<Bot>>> BotGet(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
|
@ -65,6 +72,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse<HashSet<Bot>>(bots));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates bot config of given bot.
|
||||
/// </summary>
|
||||
[HttpPost("{botName:required}")]
|
||||
public async Task<ActionResult<GenericResponse>> BotPost(string botName, [FromBody] BotRequest request) {
|
||||
if (string.IsNullOrEmpty(botName) || (request == null)) {
|
||||
|
@ -99,6 +109,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes BGR output files of given bots.
|
||||
/// </summary>
|
||||
[HttpDelete("{botNames:required}/GamesToRedeemInBackground")]
|
||||
public async Task<ActionResult<GenericResponse>> GamesToRedeemInBackgroundDelete(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
|
@ -115,6 +128,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(results.All(result => result) ? new GenericResponse(true) : new GenericResponse(false, Strings.WarningFailed));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches BGR output files of given bots.
|
||||
/// </summary>
|
||||
[HttpGet("{botNames:required}/GamesToRedeemInBackground")]
|
||||
public async Task<ActionResult<GenericResponse<Dictionary<string, GamesToRedeemInBackgroundResponse>>>> GamesToRedeemInBackgroundGet(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
|
@ -139,6 +155,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse<Dictionary<string, GamesToRedeemInBackgroundResponse>>(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds keys to redeem using BGR to given bot.
|
||||
/// </summary>
|
||||
[HttpPost("{botName:required}/GamesToRedeemInBackground")]
|
||||
public async Task<ActionResult<GenericResponse<OrderedDictionary>>> GamesToRedeemInBackgroundPost(string botName, [FromBody] GamesToRedeemInBackgroundRequest request) {
|
||||
if (string.IsNullOrEmpty(botName) || (request == null)) {
|
||||
|
@ -158,6 +177,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse<OrderedDictionary>(result, request.GamesToRedeemInBackground));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses given bots.
|
||||
/// </summary>
|
||||
[HttpPost("{botNames:required}/Pause")]
|
||||
public async Task<ActionResult<GenericResponse>> PausePost(string botNames, [FromBody] BotPauseRequest request) {
|
||||
if (string.IsNullOrEmpty(botNames) || (request == null)) {
|
||||
|
@ -174,6 +196,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Output))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resumes given bots.
|
||||
/// </summary>
|
||||
[HttpPost("{botNames:required}/Resume")]
|
||||
public async Task<ActionResult<GenericResponse>> ResumePost(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
|
@ -190,6 +215,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Output))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts given bots.
|
||||
/// </summary>
|
||||
[HttpPost("{botNames:required}/Start")]
|
||||
public async Task<ActionResult<GenericResponse>> StartPost(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
|
@ -206,6 +234,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Output))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops given bots.
|
||||
/// </summary>
|
||||
[HttpPost("{botNames:required}/Stop")]
|
||||
public async Task<ActionResult<GenericResponse>> StopPost(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
|
|
|
@ -28,8 +28,16 @@ using Microsoft.AspNetCore.Mvc;
|
|||
|
||||
namespace ArchiSteamFarm.IPC.Controllers.Api {
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Route("Api/Command")]
|
||||
public sealed class CommandController : ControllerBase {
|
||||
/// <summary>
|
||||
/// Executes a command.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This API endpoint is supposed to be entirely replaced by ASF actions available under /Api/ASF/{action} and /Api/Bot/{bot}/{action}.
|
||||
/// 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}")]
|
||||
public async Task<ActionResult<GenericResponse<string>>> CommandPost(string command) {
|
||||
if (string.IsNullOrEmpty(command)) {
|
||||
|
|
|
@ -33,10 +33,17 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace ArchiSteamFarm.IPC.Controllers.Api {
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Route("Api/NLog")]
|
||||
public sealed class NLogController : ControllerBase {
|
||||
private static readonly ConcurrentDictionary<WebSocket, SemaphoreSlim> ActiveLogWebSockets = new ConcurrentDictionary<WebSocket, SemaphoreSlim>();
|
||||
|
||||
/// <summary>
|
||||
/// Fetches ASF log in realtime.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This API endpoint requires a websocket connection.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> NLogGet() {
|
||||
if (!HttpContext.WebSockets.IsWebSocketRequest) {
|
||||
|
|
|
@ -26,8 +26,15 @@ using Microsoft.AspNetCore.Mvc;
|
|||
|
||||
namespace ArchiSteamFarm.IPC.Controllers.Api {
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Route("Api/Structure")]
|
||||
public sealed class StructureController : ControllerBase {
|
||||
/// <summary>
|
||||
/// Fetches structure of given type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Structure is defined as a representation of given object in its default state.
|
||||
/// </remarks>
|
||||
[HttpGet("{structure:required}")]
|
||||
public ActionResult<GenericResponse<object>> StructureGet(string structure) {
|
||||
if (string.IsNullOrEmpty(structure)) {
|
||||
|
|
|
@ -30,8 +30,15 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace ArchiSteamFarm.IPC.Controllers.Api {
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Route("Api/Type")]
|
||||
public sealed class TypeController : ControllerBase {
|
||||
/// <summary>
|
||||
/// Fetches type info of given type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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}")]
|
||||
public ActionResult<GenericResponse<TypeResponse>> TypeGet(string type) {
|
||||
if (string.IsNullOrEmpty(type)) {
|
||||
|
|
|
@ -31,8 +31,15 @@ using Microsoft.AspNetCore.Mvc;
|
|||
|
||||
namespace ArchiSteamFarm.IPC.Controllers.Api {
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Route("Api/WWW")]
|
||||
public sealed class WWWController : ControllerBase {
|
||||
/// <summary>
|
||||
/// Fetches files in given directory relative to WWW root.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
[HttpGet("Directory/{directory:required}")]
|
||||
public ActionResult<GenericResponse<HashSet<string>>> DirectoryGet(string directory) {
|
||||
if (string.IsNullOrEmpty(directory)) {
|
||||
|
@ -57,6 +64,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse<HashSet<string>>(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches newest GitHub releases of ASF project.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
[HttpGet("GitHub/Releases")]
|
||||
public async Task<ActionResult<GenericResponse<IEnumerable<GitHubReleaseResponse>>>> GitHubReleasesGet([FromQuery] byte count = 10) {
|
||||
if (count == 0) {
|
||||
|
@ -72,6 +85,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse<IEnumerable<GitHubReleaseResponse>>(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches specific GitHub release of ASF project.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
[HttpGet("GitHub/Releases/{version:required}")]
|
||||
public async Task<ActionResult<GenericResponse<GitHubReleaseResponse>>> GitHubReleasesGet(string version) {
|
||||
if (string.IsNullOrEmpty(version)) {
|
||||
|
@ -86,6 +105,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse<GitHubReleaseResponse>(new GitHubReleaseResponse(releaseResponse)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a HTTPS request through ASF's built-in HttpClient.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
[HttpPost("Send")]
|
||||
public async Task<ActionResult<GenericResponse<string>>> SendPost([FromBody] WWWSendRequest request) {
|
||||
if (request == null) {
|
||||
|
|
|
@ -19,14 +19,19 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Requests {
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
public sealed class ASFRequest {
|
||||
/// <summary>
|
||||
/// ASF's global config structure.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
internal readonly GlobalConfig GlobalConfig;
|
||||
[Required]
|
||||
public readonly GlobalConfig GlobalConfig;
|
||||
|
||||
// Deserialized from JSON
|
||||
private ASFRequest() { }
|
||||
|
|
|
@ -25,11 +25,17 @@ using Newtonsoft.Json;
|
|||
namespace ArchiSteamFarm.IPC.Requests {
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
public sealed class BotPauseRequest {
|
||||
/// <summary>
|
||||
/// Specifies if pause is permanent or temporary (default).
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal readonly bool Permanent;
|
||||
public readonly bool Permanent;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies automatic resume action in given seconds. Default value of 0 disables automatic resume.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal readonly ushort ResumeInSeconds;
|
||||
public readonly ushort ResumeInSeconds;
|
||||
|
||||
// Deserialized from JSON
|
||||
private BotPauseRequest() { }
|
||||
|
|
|
@ -19,14 +19,19 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Requests {
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
public sealed class BotRequest {
|
||||
/// <summary>
|
||||
/// ASF's bot config structure.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
internal readonly BotConfig BotConfig;
|
||||
[Required]
|
||||
public readonly BotConfig BotConfig;
|
||||
|
||||
// Deserialized from JSON
|
||||
private BotRequest() { }
|
||||
|
|
|
@ -20,14 +20,23 @@
|
|||
// limitations under the License.
|
||||
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Requests {
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
public sealed class GamesToRedeemInBackgroundRequest {
|
||||
/// <summary>
|
||||
/// A string-string map that maps cd-key to redeem (key) to its name (value).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Key in the map must be a valid and unique Steam cd-key.
|
||||
/// Value in the map must be a non-null and non-empty name of the key (e.g. game's name, but can be anything).
|
||||
/// </remarks>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
internal readonly OrderedDictionary GamesToRedeemInBackground;
|
||||
[Required]
|
||||
public readonly OrderedDictionary GamesToRedeemInBackground;
|
||||
|
||||
// Deserialized from JSON
|
||||
private GamesToRedeemInBackgroundRequest() { }
|
||||
|
|
|
@ -19,14 +19,22 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Requests {
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
public sealed class WWWSendRequest {
|
||||
/// <summary>
|
||||
/// Full URL of the request to be made.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// URL must start from https:// scheme.
|
||||
/// </remarks>
|
||||
[Required]
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
internal readonly string URL;
|
||||
public readonly string URL;
|
||||
|
||||
// Deserialized from JSON
|
||||
private WWWSendRequest() { }
|
||||
|
|
|
@ -20,24 +20,45 @@
|
|||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Responses {
|
||||
public sealed class ASFResponse {
|
||||
[JsonProperty]
|
||||
private readonly string BuildVariant;
|
||||
/// <summary>
|
||||
/// ASF's build variant.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly string BuildVariant;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly GlobalConfig GlobalConfig;
|
||||
/// <summary>
|
||||
/// Currently loaded ASF's global config.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly GlobalConfig GlobalConfig;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly uint MemoryUsage;
|
||||
/// <summary>
|
||||
/// Current amount of managed memory being used by the process, in kilobytes.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly uint MemoryUsage;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly DateTime ProcessStartTime;
|
||||
/// <summary>
|
||||
/// Start date of the process.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly DateTime ProcessStartTime;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly Version Version;
|
||||
/// <summary>
|
||||
/// ASF version of currently running binary.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly Version Version;
|
||||
|
||||
internal ASFResponse(string buildVariant, GlobalConfig globalConfig, uint memoryUsage, DateTime processStartTime, Version version) {
|
||||
if (string.IsNullOrEmpty(buildVariant) || (globalConfig == null) || (memoryUsage == 0) || (processStartTime == DateTime.MinValue) || (version == null)) {
|
||||
|
|
|
@ -24,11 +24,17 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace ArchiSteamFarm.IPC.Responses {
|
||||
public sealed class GamesToRedeemInBackgroundResponse {
|
||||
/// <summary>
|
||||
/// Keys that were redeemed and not used during the process, if available.
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
private readonly Dictionary<string, string> UnusedKeys;
|
||||
public readonly Dictionary<string, string> UnusedKeys;
|
||||
|
||||
/// <summary>
|
||||
/// Keys that were redeemed and used during the process, if available.
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
private readonly Dictionary<string, string> UsedKeys;
|
||||
public readonly Dictionary<string, string> UsedKeys;
|
||||
|
||||
internal GamesToRedeemInBackgroundResponse(Dictionary<string, string> unusedKeys = null, Dictionary<string, string> usedKeys = null) {
|
||||
UnusedKeys = unusedKeys;
|
||||
|
|
|
@ -19,13 +19,20 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using ArchiSteamFarm.Localization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Responses {
|
||||
public sealed class GenericResponse<T> : GenericResponse where T : class {
|
||||
/// <summary>
|
||||
/// The actual result of the request, if available.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The type of the result depends on the API endpoint that you've called.
|
||||
/// </remarks>
|
||||
[JsonProperty]
|
||||
private readonly T Result;
|
||||
public readonly T Result;
|
||||
|
||||
internal GenericResponse(T result) : base(result != null) => Result = result;
|
||||
internal GenericResponse(bool success, string message) : base(success, message) { }
|
||||
|
@ -33,11 +40,21 @@ namespace ArchiSteamFarm.IPC.Responses {
|
|||
}
|
||||
|
||||
public class GenericResponse {
|
||||
/// <summary>
|
||||
/// A message that describes what happened with the request, if available.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property will provide exact reason for majority of expected failures.
|
||||
/// </remarks>
|
||||
[JsonProperty]
|
||||
private readonly string Message;
|
||||
public readonly string Message;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly bool Success;
|
||||
/// <summary>
|
||||
/// Boolean type that specifies if the request has succeeded.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly bool Success;
|
||||
|
||||
internal GenericResponse(bool success, string message = null) {
|
||||
Success = success;
|
||||
|
|
|
@ -20,21 +20,38 @@
|
|||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Responses {
|
||||
public sealed class GitHubReleaseResponse {
|
||||
[JsonProperty]
|
||||
private readonly string ChangelogHTML;
|
||||
/// <summary>
|
||||
/// Changelog of the release rendered in HTML.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly string ChangelogHTML;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly DateTime ReleasedAt;
|
||||
/// <summary>
|
||||
/// Date of the release.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly DateTime ReleasedAt;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly bool Stable;
|
||||
/// <summary>
|
||||
/// Boolean value that specifies whether the build is stable or not (pre-release).
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly bool Stable;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly string Version;
|
||||
/// <summary>
|
||||
/// Version of the release.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly string Version;
|
||||
|
||||
internal GitHubReleaseResponse(GitHub.ReleaseResponse releaseResponse) {
|
||||
if (releaseResponse == null) {
|
||||
|
|
|
@ -21,15 +21,29 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Responses {
|
||||
public sealed class TypeResponse {
|
||||
[JsonProperty]
|
||||
private readonly Dictionary<string, string> Body;
|
||||
/// <summary>
|
||||
/// A string-string map representing a decomposition of given type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The actual structure of this field depends on the type that was requested. You can determine that type based on <see cref="Properties"/> metadata.
|
||||
/// For enums, keys are friendly names while values are underlying values of those names.
|
||||
/// For objects, keys are non-private fields and properties, while values are underlying types of those.
|
||||
/// </remarks>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly Dictionary<string, string> Body;
|
||||
|
||||
[JsonProperty]
|
||||
private readonly TypeProperties Properties;
|
||||
/// <summary>
|
||||
/// Metadata of given type.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
[Required]
|
||||
public readonly TypeProperties Properties;
|
||||
|
||||
internal TypeResponse(Dictionary<string, string> body, TypeProperties properties) {
|
||||
if ((body == null) || (properties == null)) {
|
||||
|
@ -40,15 +54,33 @@ namespace ArchiSteamFarm.IPC.Responses {
|
|||
Properties = properties;
|
||||
}
|
||||
|
||||
internal sealed class TypeProperties {
|
||||
public sealed class TypeProperties {
|
||||
/// <summary>
|
||||
/// Base type of given type, if available.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This can be used for determining how <see cref="Body"/> should be interpreted.
|
||||
/// </remarks>
|
||||
[JsonProperty]
|
||||
private readonly string BaseType;
|
||||
public readonly string BaseType;
|
||||
|
||||
/// <summary>
|
||||
/// Custom attributes of given type, if available.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This can be used for determining main enum type if <see cref="BaseType"/> is <see cref="Enum"/>.
|
||||
/// </remarks>
|
||||
[JsonProperty]
|
||||
private readonly HashSet<string> CustomAttributes;
|
||||
public readonly HashSet<string> CustomAttributes;
|
||||
|
||||
/// <summary>
|
||||
/// Underlying type of given type, if available.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This can be used for determining underlying enum type if <see cref="BaseType"/> is <see cref="Enum"/>.
|
||||
/// </remarks>
|
||||
[JsonProperty]
|
||||
private readonly string UnderlyingType;
|
||||
public readonly string UnderlyingType;
|
||||
|
||||
internal TypeProperties(string baseType = null, HashSet<string> customAttributes = null, string underlyingType = null) {
|
||||
BaseType = baseType;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using ArchiSteamFarm.IPC.Middleware;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
@ -29,6 +30,7 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Swashbuckle.AspNetCore.Swagger;
|
||||
|
||||
namespace ArchiSteamFarm.IPC {
|
||||
internal sealed class Startup {
|
||||
|
@ -64,6 +66,12 @@ namespace ArchiSteamFarm.IPC {
|
|||
// We need MVC for /Api
|
||||
app.UseMvcWithDefaultRoute();
|
||||
|
||||
// Use swagger for automatic API documentation generation
|
||||
app.UseSwagger();
|
||||
|
||||
// Use friendly swagger UI
|
||||
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/ASF/swagger.json", "ASF API"));
|
||||
|
||||
// We're using index for URL routing in our static files so re-execute all non-API calls on /
|
||||
app.UseWhen(context => !context.Request.Path.StartsWithSegments("/Api", StringComparison.OrdinalIgnoreCase), appBuilder => appBuilder.UseStatusCodePagesWithReExecute("/"));
|
||||
|
||||
|
@ -83,9 +91,26 @@ namespace ArchiSteamFarm.IPC {
|
|||
// Add support for response compression
|
||||
services.AddResponseCompression();
|
||||
|
||||
// Add swagger documentation generation
|
||||
services.AddSwaggerGen(
|
||||
c => {
|
||||
c.DescribeAllEnumsAsStrings();
|
||||
c.SwaggerDoc("ASF", new Info { Title = "ASF API" });
|
||||
|
||||
string xmlDocumentationFile = Path.Combine(AppContext.BaseDirectory, SharedInfo.AssemblyDocumentation);
|
||||
|
||||
if (File.Exists(xmlDocumentationFile)) {
|
||||
c.IncludeXmlComments(xmlDocumentationFile);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// We need MVC for /Api, but we're going to use only a small subset of all available features
|
||||
IMvcCoreBuilder mvc = services.AddMvcCore();
|
||||
|
||||
// Add API explorer for swagger
|
||||
mvc.AddApiExplorer();
|
||||
|
||||
// Use latest compatibility version for MVC
|
||||
mvc.SetCompatibilityVersion(CompatibilityVersion.Latest);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace ArchiSteamFarm {
|
|||
internal const ulong ArchiSteamID = 76561198006963719;
|
||||
internal const string ASF = nameof(ASF);
|
||||
internal const ulong ASFGroupSteamID = 103582791440160998;
|
||||
internal const string AssemblyDocumentation = AssemblyName + ".xml";
|
||||
internal const string AssemblyName = nameof(ArchiSteamFarm);
|
||||
internal const string ConfigDirectory = "config";
|
||||
internal const string ConfigExtension = ".json";
|
||||
|
|
Loading…
Reference in a new issue