Updated plugin installation and plugin loading
This commit is contained in:
@@ -42,20 +42,20 @@ public class Configuration : ConfigurationBase
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async void LoadFromFile()
|
public override void LoadFromFile()
|
||||||
{
|
{
|
||||||
if (!File.Exists(_DiskLocation))
|
if (!File.Exists(_DiskLocation))
|
||||||
{
|
{
|
||||||
await SaveToFile();
|
SaveToFile().Wait();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string jsonContent = await File.ReadAllTextAsync(_DiskLocation);
|
string jsonContent = File.ReadAllText(_DiskLocation);
|
||||||
var jObject = JsonConvert.DeserializeObject<JObject>(jsonContent);
|
var jObject = JsonConvert.DeserializeObject<JObject>(jsonContent);
|
||||||
|
|
||||||
if (jObject is null)
|
if (jObject is null)
|
||||||
{
|
{
|
||||||
await SaveToFile();
|
SaveToFile().Wait();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public sealed class Logger : ILogger
|
|||||||
{
|
{
|
||||||
string fileName = _logFileStream.Name;
|
string fileName = _logFileStream.Name;
|
||||||
|
|
||||||
_logFileStream.Flush();
|
//_logFileStream.Flush();
|
||||||
_logFileStream.Close();
|
_logFileStream.Close();
|
||||||
|
|
||||||
string[] logs = File.ReadAllLines(fileName);
|
string[] logs = File.ReadAllLines(fileName);
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ public interface IDbEvent
|
|||||||
/// The method that is invoked when the event is loaded into memory
|
/// The method that is invoked when the event is loaded into memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">The arguments for the start method</param>
|
/// <param name="args">The arguments for the start method</param>
|
||||||
Task Start(IDbEventExecutingArgument args);
|
void Start(IDbEventExecutingArgument args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,29 +116,49 @@ public sealed class PluginLoader : IPluginLoader
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryStartEvent(IDbEvent? dbEvent)
|
private bool TryStartEvent(IDbEvent dbEvent)
|
||||||
{
|
{
|
||||||
try
|
string? botPrefix = _Configuration.Get<string>("prefix");
|
||||||
|
if (string.IsNullOrEmpty(botPrefix))
|
||||||
{
|
{
|
||||||
if (dbEvent is null)
|
_Logger.Log("Bot prefix is not set. Please set the bot prefix in the configuration.", this, LogType.Error);
|
||||||
{
|
return false;
|
||||||
throw new ArgumentNullException(nameof(dbEvent));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_discordClient is null)
|
||||||
|
{
|
||||||
|
_Logger.Log("Discord client is not set. Please set the discord client before starting events.", this, LogType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? resourcesFolder = _Configuration.Get<string>("ResourcesFolder");
|
||||||
|
if (string.IsNullOrEmpty(resourcesFolder))
|
||||||
|
{
|
||||||
|
_Logger.Log("Resources folder is not set. Please set the resources folder in the configuration.", this, LogType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(resourcesFolder))
|
||||||
|
{
|
||||||
|
_Logger.Log("Resources folder does not exist. Please create the resources folder.", this, LogType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? eventConfigDirectory = Path.Combine(resourcesFolder, dbEvent.GetType().Assembly.GetName().Name);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(eventConfigDirectory);
|
||||||
|
|
||||||
IDbEventExecutingArgument args = new DbEventExecutingArgument(
|
IDbEventExecutingArgument args = new DbEventExecutingArgument(
|
||||||
_Logger,
|
_Logger,
|
||||||
_discordClient,
|
_discordClient,
|
||||||
_Configuration.Get<string>("prefix"),
|
botPrefix,
|
||||||
new DirectoryInfo(Path.Combine(_Configuration.Get<string>("ResourcesPath"), dbEvent.Name)));
|
new DirectoryInfo(eventConfigDirectory));
|
||||||
|
|
||||||
dbEvent.Start(args);
|
dbEvent.Start(args);
|
||||||
|
|
||||||
|
_Logger.Log("Event started: " + dbEvent.Name, this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_Logger.Log($"Error starting event {dbEvent.Name}: {e.Message}", typeof(PluginLoader), LogType.Error);
|
|
||||||
_Logger.LogException(e, typeof(PluginLoader));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Result> TryStartSlashCommand(IDbSlashCommand? dbSlashCommand)
|
private async Task<Result> TryStartSlashCommand(IDbSlashCommand? dbSlashCommand)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class PluginRepository : IPluginRepository
|
|||||||
public async Task<OnlinePlugin?> GetPluginById(int pluginId)
|
public async Task<OnlinePlugin?> GetPluginById(int pluginId)
|
||||||
{
|
{
|
||||||
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.PluginRepositoryLocation,
|
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.PluginRepositoryLocation,
|
||||||
"get-plugin", new Dictionary<string, string>
|
"get-by-id", new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{ "pluginId", pluginId.ToString() },
|
{ "pluginId", pluginId.ToString() },
|
||||||
{ "includeNotApproved", "false" }
|
{ "includeNotApproved", "false" }
|
||||||
@@ -66,7 +66,7 @@ public class PluginRepository : IPluginRepository
|
|||||||
public async Task<OnlinePlugin?> GetPluginByName(string pluginName, int operatingSystem, bool includeNotApproved)
|
public async Task<OnlinePlugin?> GetPluginByName(string pluginName, int operatingSystem, bool includeNotApproved)
|
||||||
{
|
{
|
||||||
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.PluginRepositoryLocation,
|
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.PluginRepositoryLocation,
|
||||||
"get-plugin-by-name", new Dictionary<string, string>
|
"get-by-name", new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{ "pluginName", pluginName },
|
{ "pluginName", pluginName },
|
||||||
{ "operatingSystem", operatingSystem.ToString() },
|
{ "operatingSystem", operatingSystem.ToString() },
|
||||||
@@ -89,7 +89,7 @@ public class PluginRepository : IPluginRepository
|
|||||||
public async Task<List<OnlineDependencyInfo>> GetDependenciesForPlugin(int pluginId)
|
public async Task<List<OnlineDependencyInfo>> GetDependenciesForPlugin(int pluginId)
|
||||||
{
|
{
|
||||||
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.DependenciesRepositoryLocation,
|
string url = CreateUrlWithQueryParams(_pluginRepositoryConfiguration.DependenciesRepositoryLocation,
|
||||||
"get-dependencies-for-plugin", new Dictionary<string, string>
|
"get-by-plugin-id", new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{ "pluginId", pluginId.ToString() }
|
{ "pluginId", pluginId.ToString() }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ public interface IPluginManager
|
|||||||
{
|
{
|
||||||
Task<List<OnlinePlugin>> GetPluginsList();
|
Task<List<OnlinePlugin>> GetPluginsList();
|
||||||
Task<OnlinePlugin?> GetPluginDataByName(string pluginName);
|
Task<OnlinePlugin?> GetPluginDataByName(string pluginName);
|
||||||
|
Task<OnlinePlugin?> GetPluginDataById(int pluginId);
|
||||||
Task AppendPluginToDatabase(LocalPlugin pluginData);
|
Task AppendPluginToDatabase(LocalPlugin pluginData);
|
||||||
Task<List<LocalPlugin>> GetInstalledPlugins();
|
Task<List<LocalPlugin>> GetInstalledPlugins();
|
||||||
Task<bool> IsPluginInstalled(string pluginName);
|
Task<bool> IsPluginInstalled(string pluginName);
|
||||||
@@ -14,7 +15,7 @@ public interface IPluginManager
|
|||||||
Task<string?> GetDependencyLocation(string dependencyName);
|
Task<string?> GetDependencyLocation(string dependencyName);
|
||||||
Task<string?> GetDependencyLocation(string dependencyName, string pluginName);
|
Task<string?> GetDependencyLocation(string dependencyName, string pluginName);
|
||||||
string GenerateDependencyRelativePath(string pluginName, string dependencyPath);
|
string GenerateDependencyRelativePath(string pluginName, string dependencyPath);
|
||||||
Task InstallPlugin(OnlinePlugin plugin, IProgress<InstallationProgressIndicator> progress);
|
Task InstallPlugin(OnlinePlugin plugin, IProgress<float> progress);
|
||||||
Task<Tuple<Dictionary<string, string>, List<OnlineDependencyInfo>>> GatherInstallDataForPlugin(OnlinePlugin plugin);
|
Task<Tuple<Dictionary<string, string>, List<OnlineDependencyInfo>>> GatherInstallDataForPlugin(OnlinePlugin plugin);
|
||||||
Task SetEnabledStatus(string pluginName, bool status);
|
Task SetEnabledStatus(string pluginName, bool status);
|
||||||
}
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
namespace DiscordBotCore.PluginManagement.Models;
|
|
||||||
|
|
||||||
public class InstallationProgressIndicator
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, float> _DownloadProgress;
|
|
||||||
|
|
||||||
public InstallationProgressIndicator()
|
|
||||||
{
|
|
||||||
_DownloadProgress = new Dictionary<string, float>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetProgress(string fileName, float progress)
|
|
||||||
{
|
|
||||||
_DownloadProgress[fileName] = progress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -50,6 +50,18 @@ public sealed class PluginManager : IPluginManager
|
|||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<OnlinePlugin?> GetPluginDataById(int pluginId)
|
||||||
|
{
|
||||||
|
var plugin = await _PluginRepository.GetPluginById(pluginId);
|
||||||
|
if (plugin is null)
|
||||||
|
{
|
||||||
|
_Logger.Log($"Plugin {pluginId} not found in the repository.", this, LogType.Warning);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task RemovePluginFromDatabase(string pluginName)
|
private async Task RemovePluginFromDatabase(string pluginName)
|
||||||
{
|
{
|
||||||
string? pluginDatabaseFile = _Configuration.Get<string>("PluginDatabase");
|
string? pluginDatabaseFile = _Configuration.Get<string>("PluginDatabase");
|
||||||
@@ -73,7 +85,8 @@ public sealed class PluginManager : IPluginManager
|
|||||||
throw new Exception("Plugin database file not found");
|
throw new Exception("Plugin database file not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<LocalPlugin> installedPlugins = await JsonManager.ConvertFromJson<List<LocalPlugin>>(await File.ReadAllTextAsync(pluginDatabaseFile));
|
List<LocalPlugin> installedPlugins = await GetInstalledPlugins();
|
||||||
|
|
||||||
foreach (var dependency in pluginData.ListOfExecutableDependencies)
|
foreach (var dependency in pluginData.ListOfExecutableDependencies)
|
||||||
{
|
{
|
||||||
pluginData.ListOfExecutableDependencies[dependency.Key] = dependency.Value;
|
pluginData.ListOfExecutableDependencies[dependency.Key] = dependency.Value;
|
||||||
@@ -194,7 +207,7 @@ public sealed class PluginManager : IPluginManager
|
|||||||
return relative;
|
return relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InstallPlugin(OnlinePlugin plugin, IProgress<InstallationProgressIndicator> progress)
|
public async Task InstallPlugin(OnlinePlugin plugin, IProgress<float> progress)
|
||||||
{
|
{
|
||||||
List<OnlineDependencyInfo> dependencies = await _PluginRepository.GetDependenciesForPlugin(plugin.Id);
|
List<OnlineDependencyInfo> dependencies = await _PluginRepository.GetDependenciesForPlugin(plugin.Id);
|
||||||
string? pluginsFolder = _Configuration.Get<string>("PluginFolder");
|
string? pluginsFolder = _Configuration.Get<string>("PluginFolder");
|
||||||
@@ -205,13 +218,7 @@ public sealed class PluginManager : IPluginManager
|
|||||||
|
|
||||||
string downloadLocation = $"{pluginsFolder}/{plugin.Name}.dll";
|
string downloadLocation = $"{pluginsFolder}/{plugin.Name}.dll";
|
||||||
|
|
||||||
InstallationProgressIndicator installationProgressIndicator = new InstallationProgressIndicator();
|
IProgress<float> downloadProgress = new Progress<float>(progress.Report);
|
||||||
|
|
||||||
IProgress<float> downloadProgress = new Progress<float>(fileProgress =>
|
|
||||||
{
|
|
||||||
installationProgressIndicator.SetProgress(plugin.Name, fileProgress);
|
|
||||||
progress.Report(installationProgressIndicator);
|
|
||||||
});
|
|
||||||
|
|
||||||
FileDownloader fileDownloader = new FileDownloader(plugin.DownloadLink, downloadLocation);
|
FileDownloader fileDownloader = new FileDownloader(plugin.DownloadLink, downloadLocation);
|
||||||
await fileDownloader.DownloadFile(downloadProgress.Report);
|
await fileDownloader.DownloadFile(downloadProgress.Report);
|
||||||
@@ -221,16 +228,14 @@ public sealed class PluginManager : IPluginManager
|
|||||||
foreach (var dependency in dependencies)
|
foreach (var dependency in dependencies)
|
||||||
{
|
{
|
||||||
string dependencyLocation = GenerateDependencyRelativePath(plugin.Name, dependency.DownloadLocation);
|
string dependencyLocation = GenerateDependencyRelativePath(plugin.Name, dependency.DownloadLocation);
|
||||||
Action<float> dependencyProgress = new Action<float>(fileProgress =>
|
|
||||||
{
|
|
||||||
installationProgressIndicator.SetProgress(dependency.DependencyName, fileProgress);
|
|
||||||
progress.Report(installationProgressIndicator);
|
|
||||||
});
|
|
||||||
|
|
||||||
executor.AddTask(dependency.DownloadLink, dependencyLocation, dependencyProgress);
|
executor.AddTask(dependency.DownloadLink, dependencyLocation, progress.Report);
|
||||||
}
|
}
|
||||||
|
|
||||||
await executor.ExecuteAllTasks();
|
await executor.ExecuteAllTasks();
|
||||||
|
|
||||||
|
LocalPlugin localPlugin = LocalPlugin.FromOnlineInfo(plugin, dependencies, downloadLocation);
|
||||||
|
await AppendPluginToDatabase(localPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Tuple<Dictionary<string, string>, List<OnlineDependencyInfo>>> GatherInstallDataForPlugin(OnlinePlugin plugin)
|
public async Task<Tuple<Dictionary<string, string>, List<OnlineDependencyInfo>>> GatherInstallDataForPlugin(OnlinePlugin plugin)
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ internal class LevelEvent : IDbEvent
|
|||||||
public string Name => "Leveling System Event Handler";
|
public string Name => "Leveling System Event Handler";
|
||||||
public string Description => "The Leveling System Event Handler";
|
public string Description => "The Leveling System Event Handler";
|
||||||
|
|
||||||
public async Task Start(IDbEventExecutingArgument args)
|
public async void Start(IDbEventExecutingArgument args)
|
||||||
{
|
{
|
||||||
|
args.Logger.Log("Starting Leveling System Event Handler", this);
|
||||||
Directory.CreateDirectory(DataFolder);
|
Directory.CreateDirectory(DataFolder);
|
||||||
await Task.Delay(200);
|
await Task.Delay(200);
|
||||||
Database = new SqlDatabase(DataFolder + "Users.db");
|
Database = new SqlDatabase(DataFolder + "Users.db");
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class HomeController : Controller
|
|||||||
{
|
{
|
||||||
_logger.Log("Loading plugins", this);
|
_logger.Log("Loading plugins", this);
|
||||||
await _pluginLoader.LoadPlugins();
|
await _pluginLoader.LoadPlugins();
|
||||||
_logger.Log("Plugins loaded", this);
|
//_logger.Log("Plugins loaded", this);
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using DiscordBotCore.PluginManagement;
|
using DiscordBotCore.PluginManagement;
|
||||||
|
using DiscordBotCore.PluginManagement.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using WebUI.Models;
|
using WebUI.Models;
|
||||||
using ILogger = DiscordBotCore.Logging.ILogger;
|
using ILogger = DiscordBotCore.Logging.ILogger;
|
||||||
@@ -32,6 +33,7 @@ public class PluginsController : Controller
|
|||||||
pluginViewModel.Author = plugin.Author;
|
pluginViewModel.Author = plugin.Author;
|
||||||
pluginViewModel.Version = plugin.Version;
|
pluginViewModel.Version = plugin.Version;
|
||||||
pluginViewModel.DownloadUrl = plugin.DownloadLink;
|
pluginViewModel.DownloadUrl = plugin.DownloadLink;
|
||||||
|
pluginViewModel.Id = plugin.Id;
|
||||||
|
|
||||||
pluginViewModels.Add(pluginViewModel);
|
pluginViewModels.Add(pluginViewModel);
|
||||||
}
|
}
|
||||||
@@ -66,4 +68,22 @@ public class PluginsController : Controller
|
|||||||
//TODO: Implement delete plugin
|
//TODO: Implement delete plugin
|
||||||
return RedirectToAction("InstalledPlugins");
|
return RedirectToAction("InstalledPlugins");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> InstallPlugin(int pluginId)
|
||||||
|
{
|
||||||
|
var pluginData = await _pluginManager.GetPluginDataById(pluginId);
|
||||||
|
if (pluginData is null)
|
||||||
|
{
|
||||||
|
_logger.Log($"Plugin with ID {pluginId} not found", this);
|
||||||
|
return RedirectToAction("OnlinePlugins");
|
||||||
|
}
|
||||||
|
|
||||||
|
IProgress<float> progress = new Progress<float>(f => _logger.Log($"Installing: {f}"));
|
||||||
|
|
||||||
|
await _pluginManager.InstallPlugin(pluginData, progress);
|
||||||
|
|
||||||
|
_logger.Log($"Plugin {pluginData.Name} installed", this);
|
||||||
|
return RedirectToAction("OnlinePlugins");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,10 +2,10 @@ namespace WebUI.Models;
|
|||||||
|
|
||||||
public class OnlinePluginViewModel
|
public class OnlinePluginViewModel
|
||||||
{
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Author { get; set; }
|
public string Author { get; set; }
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
|
|
||||||
public string DownloadUrl { get; set; }
|
public string DownloadUrl { get; set; }
|
||||||
}
|
}
|
||||||
@@ -73,6 +73,7 @@ var builder = WebApplication.CreateBuilder(args);
|
|||||||
|
|
||||||
string defaultLogFormat = "{ThrowTime} {SenderName} {Message}";
|
string defaultLogFormat = "{ThrowTime} {SenderName} {Message}";
|
||||||
string defaultLogFolder = "./Data/Logs";
|
string defaultLogFolder = "./Data/Logs";
|
||||||
|
string defaultResourcesFolder = "./Data/Resources";
|
||||||
string defaultConfigFile = "./Data/Resources/config.json";
|
string defaultConfigFile = "./Data/Resources/config.json";
|
||||||
string defaultPluginFolder = "./Data/Plugins";
|
string defaultPluginFolder = "./Data/Plugins";
|
||||||
string defaultPluginDatabaseFile = "./Data/Resources/plugins.json";
|
string defaultPluginDatabaseFile = "./Data/Resources/plugins.json";
|
||||||
@@ -135,7 +136,12 @@ builder.Services.AddSingleton<IPluginManager>(sp =>
|
|||||||
ILogger logger = sp.GetRequiredService<ILogger>();
|
ILogger logger = sp.GetRequiredService<ILogger>();
|
||||||
IConfiguration configuration = sp.GetRequiredService<IConfiguration>();
|
IConfiguration configuration = sp.GetRequiredService<IConfiguration>();
|
||||||
|
|
||||||
Directory.CreateDirectory(configuration.Get<string>("PluginFolder", defaultPluginFolder));
|
string pluginFolder = configuration.Get<string>("PluginFolder", defaultPluginFolder);
|
||||||
|
Directory.CreateDirectory(pluginFolder);
|
||||||
|
|
||||||
|
string resourcesFolder = configuration.Get<string>("ResourcesFolder", defaultResourcesFolder);
|
||||||
|
Directory.CreateDirectory(resourcesFolder);
|
||||||
|
|
||||||
string pluginDatabaseFile = configuration.Get<string>("PluginDatabase", defaultPluginDatabaseFile);
|
string pluginDatabaseFile = configuration.Get<string>("PluginDatabase", defaultPluginDatabaseFile);
|
||||||
Directory.CreateDirectory(new FileInfo(pluginDatabaseFile).DirectoryName);
|
Directory.CreateDirectory(new FileInfo(pluginDatabaseFile).DirectoryName);
|
||||||
|
|
||||||
@@ -159,8 +165,6 @@ builder.Services.AddSingleton<IDiscordBotApplication>(sp =>
|
|||||||
return new DiscordBotApplication(logger, configuration, pluginLoader);
|
return new DiscordBotApplication(logger, configuration, pluginLoader);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
@@ -182,4 +186,23 @@ app.MapControllerRoute(
|
|||||||
name: "default",
|
name: "default",
|
||||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
|
||||||
|
// Force eager creation of all required services
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var provider = scope.ServiceProvider;
|
||||||
|
|
||||||
|
// Manually resolve all your singletons here
|
||||||
|
provider.GetRequiredService<ILogger>();
|
||||||
|
IConfiguration config = provider.GetRequiredService<IConfiguration>();
|
||||||
|
provider.GetRequiredService<IPluginRepositoryConfiguration>();
|
||||||
|
provider.GetRequiredService<IPluginRepository>();
|
||||||
|
provider.GetRequiredService<IPluginManager>();
|
||||||
|
provider.GetRequiredService<IPluginLoader>();
|
||||||
|
provider.GetRequiredService<IDiscordBotApplication>();
|
||||||
|
|
||||||
|
// Optional: Log that all services were initialized
|
||||||
|
provider.GetRequiredService<ILogger>().Log("All core services have been initialized at startup.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
@@ -25,7 +25,9 @@
|
|||||||
<td>@plugin.Author</td>
|
<td>@plugin.Author</td>
|
||||||
<td>@plugin.Version</td>
|
<td>@plugin.Version</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="@plugin.DownloadUrl" class="btn btn-primary" target="_blank">Download</a>
|
<form method="post" asp-action="InstallPlugin" asp-route-pluginId="@plugin.Id">
|
||||||
|
<button type="submit" class="btn btn-primary">Download</button>
|
||||||
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user