Updated repository manager for the new backend

This commit is contained in:
2025-04-01 18:47:13 +03:00
parent a6ed4078ca
commit 62ba5ec63d
8 changed files with 62 additions and 170 deletions

View File

@@ -1,29 +1,39 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using DiscordBotCore.Interfaces.PluginManagement;
using DiscordBotCore.Others;
using DiscordBotCore.Plugin;
using Microsoft.AspNetCore.Http.Extensions;
namespace DiscordBotCore.Online.Helpers;
public class PluginRepository : IPluginRepository
{
private readonly IPluginRepositoryConfiguration _pluginRepositoryConfiguration;
public HttpClient _httpClient;
private readonly HttpClient _httpClient;
public PluginRepository(IPluginRepositoryConfiguration pluginRepositoryConfiguration)
{
_pluginRepositoryConfiguration = pluginRepositoryConfiguration;
_httpClient = new HttpClient();
_httpClient.BaseAddress = new System.Uri(_pluginRepositoryConfiguration.BaseUrl);
_httpClient.BaseAddress = new Uri(_pluginRepositoryConfiguration.BaseUrl);
}
public async Task<List<OnlinePlugin>> GetAllPlugins()
{
HttpResponseMessage response =
await _httpClient.GetAsync(_pluginRepositoryConfiguration.PluginRepositoryLocation + "get-all-plugins");
int operatingSystem = OS.GetOperatingSystemInt();
bool includeNotApproved = false;
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.PluginRepositoryLocation,
"get-all-plugins", new Dictionary<string, string>
{
{ "operatingSystem", operatingSystem.ToString() },
{ "includeNotApproved", includeNotApproved.ToString() }
});
HttpResponseMessage response = await _httpClient.GetAsync(url);
if (!response.IsSuccessStatusCode)
{
@@ -39,9 +49,13 @@ public class PluginRepository : IPluginRepository
public async Task<OnlinePlugin?> GetPluginById(int pluginId)
{
HttpResponseMessage response =
await _httpClient.GetAsync(_pluginRepositoryConfiguration.PluginRepositoryLocation +
$"get-plugin/{pluginId}");
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.PluginRepositoryLocation,
"get-plugin", new Dictionary<string, string>
{
{ "pluginId", pluginId.ToString() },
{ "includeNotApproved", "false" }
});
HttpResponseMessage response = await _httpClient.GetAsync(url);
if (!response.IsSuccessStatusCode)
{
@@ -57,9 +71,14 @@ public class PluginRepository : IPluginRepository
public async Task<OnlinePlugin?> GetPluginByName(string pluginName)
{
HttpResponseMessage response =
await _httpClient.GetAsync(_pluginRepositoryConfiguration.PluginRepositoryLocation +
$"get-plugin-by-name/{pluginName}");
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.PluginRepositoryLocation,
"get-plugin-by-name", new Dictionary<string, string>
{
{ "pluginName", pluginName },
{ "operatingSystem", OS.GetOperatingSystemInt().ToString() },
{ "includeNotApproved", "false" }
});
HttpResponseMessage response = await _httpClient.GetAsync(url);
if (!response.IsSuccessStatusCode)
{
@@ -75,7 +94,13 @@ public class PluginRepository : IPluginRepository
public async Task<List<OnlineDependencyInfo>> GetDependenciesForPlugin(int pluginId)
{
HttpResponseMessage response = await _httpClient.GetAsync(_pluginRepositoryConfiguration.DependenciesRepositoryLocation + $"get-dependencies-for-plugin/{pluginId}");
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.DependenciesRepositoryLocation,
"get-dependencies-for-plugin", new Dictionary<string, string>
{
{ "pluginId", pluginId.ToString() }
});
HttpResponseMessage response = await _httpClient.GetAsync(url);
if(!response.IsSuccessStatusCode)
{
Application.Log("Failed to get dependencies for plugin from the repository", LogType.Warning);
@@ -87,4 +112,18 @@ public class PluginRepository : IPluginRepository
return dependencies;
}
private string CreateUrlWithQueryParams(string baseUrl, string endpoint, Dictionary<string, string> queryParams)
{
QueryBuilder queryBuilder = new QueryBuilder();
foreach (var(key,value) in queryParams)
{
queryBuilder.Add(key, value);
}
string queryString = queryBuilder.ToQueryString().ToString();
string url = baseUrl + endpoint + queryString;
return url;
}
}

View File

@@ -5,7 +5,9 @@ namespace DiscordBotCore.Online.Helpers;
public class PluginRepositoryConfiguration : IPluginRepositoryConfiguration
{
public static PluginRepositoryConfiguration Default => new ("http://localhost:5097/api/v1/", "plugins-repository/", "dependencies-repository/");
public static PluginRepositoryConfiguration Default => new ("http://localhost:8080/api/v1/",
"plugin/",
"dependency/");
public string BaseUrl { get; }
public string PluginRepositoryLocation { get; }

View File

@@ -43,7 +43,7 @@ public sealed class PluginManager : IPluginManager
if (!onlinePlugins.Any())
{
Application.Log("Failed to get all plugins from the repository", LogType.Warning);
Application.Log("Could not get any plugins from the repository", LogType.Warning);
return [];
}

View File

@@ -1,45 +0,0 @@
using DiscordBotCore;
using DiscordBotCore.API.Endpoints.PluginManagement;
using DiscordBotCore.Online;
using DiscordBotCore.Plugin;
using Moq;
namespace SethCoreTests;
public class PluginInstallEndpointTests
{
private readonly Mock<IPluginManager> _mockPluginManager;
private readonly PluginInstallEndpoint _endpoint;
public PluginInstallEndpointTests()
{
_mockPluginManager = new Mock<IPluginManager>();
_endpoint = new PluginInstallEndpoint(_mockPluginManager.Object);
}
[Fact]
public async Task HandleRequest_SuccessfulPluginInstallation_ReturnsOk()
{
var pluginName = "TestPlugin";
var pluginInfo = new OnlinePlugin(1, pluginName, "Description", "1.0", "Author", "http://link", 1);
_mockPluginManager.Setup(pm => pm.GetPluginDataByName(pluginName)).ReturnsAsync(pluginInfo);
_mockPluginManager.Setup(pm => pm.InstallPluginNoProgress(pluginInfo)).Returns(Task.CompletedTask);
var jsonRequest = $"{{\"pluginName\":\"{pluginName}\"}}";
var response = await _endpoint.HandleRequest(jsonRequest);
Assert.True(response.Success);
}
[Fact]
public async Task HandleRequest_PluginNotFound_ReturnsFail()
{
var pluginName = "NonExistentPlugin";
_mockPluginManager.Setup(pm => pm.GetPluginDataByName(pluginName)).ReturnsAsync((OnlinePlugin?)null);
var jsonRequest = $"{{\"pluginName\":\"{pluginName}\"}}";
var response = await _endpoint.HandleRequest(jsonRequest);
Assert.False(response.Success);
}
}

View File

@@ -1,69 +0,0 @@
using System.Net;
using DiscordBotCore.Interfaces.PluginManagement;
using DiscordBotCore.Online.Helpers;
using Moq;
using Moq.Protected;
namespace SethCoreTests;
public class PluginRepositoryTests
{
private readonly Mock<IPluginRepositoryConfiguration> _mockConfig;
private readonly Mock<HttpMessageHandler> _mockHttpMessageHandler;
private readonly PluginRepository _pluginRepository;
public PluginRepositoryTests()
{
_mockConfig = new Mock<IPluginRepositoryConfiguration>();
_mockConfig.SetupGet(c => c.BaseUrl).Returns("http://localhost/");
_mockConfig.SetupGet(c => c.PluginRepositoryLocation).Returns("api/plugins/");
_mockConfig.SetupGet(c => c.DependenciesRepositoryLocation).Returns("api/dependencies/");
_mockHttpMessageHandler = new Mock<HttpMessageHandler>();
var httpClient = new HttpClient(_mockHttpMessageHandler.Object)
{
BaseAddress = new System.Uri(_mockConfig.Object.BaseUrl)
};
_pluginRepository = new PluginRepository(_mockConfig.Object)
{
_httpClient = httpClient
};
}
[Fact]
public async Task GetAllPlugins_ReturnsListOfPlugins()
{
var pluginsJson = "[{\"PluginId\":1,\"PluginName\":\"TestPlugin\",\"PluginDescription\":\"Description\",\"LatestVersion\":\"1.0\",\"PluginAuthor\":\"Author\",\"PluginLink\":\"http://link\",\"OperatingSystem\":1}]";
_mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(pluginsJson)
});
var result = await _pluginRepository.GetAllPlugins();
Assert.Single(result);
Assert.Equal("TestPlugin", result[0].PluginName);
}
[Fact]
public async Task GetPluginById_ReturnsPlugin()
{
var pluginJson = "{\"PluginId\":1,\"PluginName\":\"TestPlugin\",\"PluginDescription\":\"Description\",\"LatestVersion\":\"1.0\",\"PluginAuthor\":\"Author\",\"PluginLink\":\"http://link\",\"OperatingSystem\":1}";
_mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(pluginJson)
});
var result = await _pluginRepository.GetPluginById(1);
Assert.NotNull(result);
Assert.Equal("TestPlugin", result.PluginName);
}
}

View File

@@ -1,28 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.5.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
</ItemGroup>
<ItemGroup>
<Using Include="Xunit"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DiscordBotCore\DiscordBotCore.csproj" />
</ItemGroup>
</Project>

View File

@@ -25,10 +25,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CppCompatibilityModule", "M
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscordBotWebUI", "DiscordBotWebUI\DiscordBotWebUI.csproj", "{8683B195-B729-48BB-805A-D44CA98A0BF6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SethTests", "SethTests", "{9D2F471B-89EE-4F17-B1EA-869069A9A3B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SethCoreTests", "SethCoreTests\SethCoreTests.csproj", "{AB4BD8D1-7384-4669-9D75-3BBECFA0A96E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -67,10 +63,6 @@ Global
{8683B195-B729-48BB-805A-D44CA98A0BF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8683B195-B729-48BB-805A-D44CA98A0BF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8683B195-B729-48BB-805A-D44CA98A0BF6}.Release|Any CPU.Build.0 = Release|Any CPU
{AB4BD8D1-7384-4669-9D75-3BBECFA0A96E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB4BD8D1-7384-4669-9D75-3BBECFA0A96E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB4BD8D1-7384-4669-9D75-3BBECFA0A96E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB4BD8D1-7384-4669-9D75-3BBECFA0A96E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -81,7 +73,6 @@ Global
{FCE9743F-7EB4-4639-A080-FCDDFCC7D689} = {5CF9AD7B-6BF0-4035-835F-722F989C01E1}
{F3C61A47-F758-4145-B496-E3ECCF979D89} = {5CF9AD7B-6BF0-4035-835F-722F989C01E1}
{C67908F9-4A55-4DD8-B993-C26C648226F1} = {EA4FA308-7B2C-458E-8485-8747D745DD59}
{AB4BD8D1-7384-4669-9D75-3BBECFA0A96E} = {9D2F471B-89EE-4F17-B1EA-869069A9A3B8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}

View File

@@ -1,15 +1,17 @@
services:
discord-bot-client:
build:
context: .
dockerfile: DiscordBot/Dockerfile
context: ./DiscordBot
dockerfile: Dockerfile
tty: true
stdin_open: true
discord-bot-webui:
build:
context: .
dockerfile: DiscordBotWebUI/Dockerfile
context: ./DiscordBotWebUI
dockerfile: Dockerfile
ports:
- '4444:8080'
networks: