Added API to DiscordBotCore

This commit is contained in:
2024-11-02 15:43:35 +02:00
parent bd3f79430b
commit f2a9982d41
13 changed files with 343 additions and 17 deletions

View File

@@ -0,0 +1,67 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using DiscordBotCore.API.Endpoints;
using DiscordBotCore.API.Endpoints.PluginManagement;
using DiscordBotCore.Interfaces.API;
using DiscordBotCore.Others;
using Microsoft.AspNetCore.Builder;
namespace DiscordBotCore.API;
public class ApiManager
{
private bool IsRunning { get; set; }
private List<IEndpoint> ApiEndpoints { get; }
public ApiManager()
{
ApiEndpoints = new List<IEndpoint>();
}
public Result AddEndpoint(IEndpoint endpoint)
{
if (ApiEndpoints.Contains(endpoint) || ApiEndpoints.Exists(x => x.Path == endpoint.Path))
{
return Result.Failure("Endpoint already exists");
}
ApiEndpoints.Add(endpoint);
return Result.Success();
}
public void RemoveEndpoint(string endpointPath)
{
this.ApiEndpoints.RemoveAll(endpoint => endpoint.Path == endpointPath);
}
public bool EndpointExists(string endpointPath)
{
return this.ApiEndpoints.Exists(endpoint => endpoint.Path == endpointPath);
}
internal void AddBaseEndpoints()
{
AddEndpoint(new HomeEndpoint());
AddEndpoint(new PluginListEndpoint());
}
public async Task InitializeApi()
{
if (IsRunning)
return;
IsRunning = true;
var builder = WebApplication.CreateBuilder();
var app = builder.Build();
app.UseRouting();
EndpointManager manager = new EndpointManager(app);
foreach(IEndpoint endpoint in this.ApiEndpoints)
{
manager.MapEndpoint(endpoint);
}
await app.RunAsync();
}
}

View File

@@ -0,0 +1,34 @@
using System.Threading.Tasks;
using DiscordBotCore.Others;
namespace DiscordBotCore.API;
public class ApiResponse
{
public string Message { get; set; }
public bool Success { get; set; }
private ApiResponse(string message, bool success)
{
Message = message;
Success = success;
}
public static ApiResponse From(string message, bool success)
{
return new ApiResponse(message, success);
}
public static ApiResponse Fail(string message)
{
return new ApiResponse(message, false);
}
public static ApiResponse Ok()
{
return new ApiResponse(string.Empty, true);
}
public async Task<string> ToJson() => await JsonManager.ConvertToJsonString(this);
}

View File

@@ -0,0 +1,80 @@
using System.IO;
using System.Text;
using DiscordBotCore.Interfaces.API;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
namespace DiscordBotCore.API;
internal sealed class EndpointManager
{
private WebApplication _appBuilder;
internal EndpointManager(WebApplication appBuilder)
{
_appBuilder = appBuilder;
}
internal void MapEndpoint(IEndpoint endpoint)
{
switch (endpoint.HttpMethod)
{
case EndpointType.Get:
_appBuilder.MapGet(endpoint.Path, async context =>
{
//convert the context to a string
string jsonRequest = string.Empty;
if (context.Request.Body.CanRead)
{
using var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
jsonRequest = await reader.ReadToEndAsync();
}
var response = await endpoint.HandleRequest(jsonRequest);
await context.Response.WriteAsync(await response.ToJson());
});
break;
case EndpointType.Put:
_appBuilder.MapPut(endpoint.Path, async context =>
{
string jsonRequest = string.Empty;
if (context.Request.Body.CanRead)
{
using var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
jsonRequest = await reader.ReadToEndAsync();
}
var response = await endpoint.HandleRequest(jsonRequest);
await context.Response.WriteAsync(await response.ToJson());
});
break;
case EndpointType.Post:
_appBuilder.MapPost(endpoint.Path, async context =>
{
string jsonRequest = string.Empty;
if (context.Request.Body.CanRead)
{
using var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
jsonRequest = await reader.ReadToEndAsync();
}
var response = await endpoint.HandleRequest(jsonRequest);
await context.Response.WriteAsync(await response.ToJson());
});
break;
case EndpointType.Delete:
_appBuilder.MapDelete(endpoint.Path, async context =>
{
string jsonRequest = string.Empty;
if (context.Request.Body.CanRead)
{
using var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
jsonRequest = await reader.ReadToEndAsync();
}
var response = await endpoint.HandleRequest(jsonRequest);
await context.Response.WriteAsync(await response.ToJson());
});
break;
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DiscordBotCore.Interfaces.API;
using DiscordBotCore.Others;
using Microsoft.AspNetCore.Http;
namespace DiscordBotCore.API.Endpoints;
internal class HomeEndpoint : IEndpoint
{
private static readonly string _HomeMessage = "Welcome to the DiscordBot API.";
public string Path => "/";
EndpointType IEndpoint.HttpMethod => EndpointType.Get;
public async Task<ApiResponse> HandleRequest(string? jsonText)
{
string response = _HomeMessage;
if (jsonText != string.Empty)
{
var json = await JsonManager.ConvertFromJson<Dictionary<string,string>>(jsonText!);
response += $"\n\nYou sent the following JSON:\n{string.Join("\n", json.Select(x => $"{x.Key}: {x.Value}"))}";
}
return ApiResponse.From(response, true);
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DiscordBotCore.Interfaces.API;
using DiscordBotCore.Others;
using DiscordBotCore.Plugin;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
namespace DiscordBotCore.API.Endpoints.PluginManagement;
public class InstallPluginEndpoint : IEndpoint
{
public string Path => "/api/plugin/install";
public EndpointType HttpMethod => EndpointType.Put;
public async Task<ApiResponse> HandleRequest(string? jsonRequest)
{
Dictionary<string, string> jsonDict = await JsonManager.ConvertFromJson<Dictionary<string, string>>(jsonRequest);
string pluginName = jsonDict["pluginName"];
PluginOnlineInfo? pluginInfo = await Application.CurrentApplication.PluginManager.GetPluginDataByName(pluginName);
if (pluginInfo == null)
{
return ApiResponse.Fail("Plugin not found.");
}
await Application.CurrentApplication.PluginManager.InstallPlugin(pluginInfo, null);
return ApiResponse.Ok();
}
}

View File

@@ -0,0 +1,18 @@
using System.Threading.Tasks;
using DiscordBotCore.Interfaces.API;
using DiscordBotCore.Others;
using Microsoft.AspNetCore.Http;
namespace DiscordBotCore.API.Endpoints.PluginManagement;
public class PluginListEndpoint : IEndpoint
{
public string Path => "/api/plugin/list/online";
public EndpointType HttpMethod => EndpointType.Get;
public async Task<ApiResponse> HandleRequest(string? jsonRequest)
{
var onlineInfos = await Application.CurrentApplication.PluginManager.GetPluginsList();
var response = await JsonManager.ConvertToJsonString(onlineInfos);
return ApiResponse.From(response, true);
}
}

View File

@@ -0,0 +1,17 @@
using System.Threading.Tasks;
using DiscordBotCore.Interfaces.API;
using DiscordBotCore.Others;
namespace DiscordBotCore.API.Endpoints.PluginManagement;
public class PluginListInstalledEndpoint : IEndpoint
{
public string Path => "/api/plugin/list/local";
public EndpointType HttpMethod => EndpointType.Get;
public async Task<ApiResponse> HandleRequest(string? jsonRequest)
{
var listInstalled = await Application.CurrentApplication.PluginManager.GetInstalledPlugins();
var response = await JsonManager.ConvertToJsonString(listInstalled);
return ApiResponse.From(response, true);
}
}