Created Settings Page and Home Page. Fixed load plugin error when the bot restarts

This commit is contained in:
2025-04-28 12:07:51 +03:00
parent 4ea7b25e4d
commit 7106a928d6
3 changed files with 235 additions and 5 deletions

View File

@@ -38,9 +38,9 @@ public class PluginLoader : IPluginLoader
public void SetDiscordClient(DiscordSocketClient discordSocketClient)
{
if (_DiscordClient is not null)
if (_DiscordClient is not null && discordSocketClient == _DiscordClient)
{
_Logger.Log("A client is already set. Please set the client only once.", this, LogType.Error);
_Logger.Log("A client is already set. Please set the client only once.", this, LogType.Warning);
return;
}

View File

@@ -1,7 +1,122 @@
@page "/"
@using DiscordBotCore.Bot
@using DiscordBotCore.PluginManagement.Loading
@inject IDiscordBotApplication DiscordBotApplication
@inject IPluginLoader PluginLoader
@inject DiscordBotCore.Logging.ILogger Logger
@inject IJSRuntime JS
@rendermode InteractiveServer
<h3>Console Log Viewer</h3>
<PageTitle>Home</PageTitle>
<div class="container mt-5">
<div class="row">
<div class="col-md-8">
<h4>Console Log</h4>
<div id="consoleLog" class="border p-3 bg-dark text-white" style="height: 400px; overflow-y: auto; font-family: monospace;">
@foreach (var line in Logs)
{
<div style="@GetLogStyle(line)">@line</div>
}
</div>
</div>
<h1>Hello, world!</h1>
<div class="col-md-4">
<h4>Controls</h4>
<button class="btn btn-success mb-2" @onclick="StartApplication" disabled="@IsRunning">Start Application</button>
<button class="btn btn-danger mb-2" @onclick="StopApplication" disabled="@(!IsRunning)">Stop Application</button>
<button class="btn btn-info mb-2" @onclick="LoadPlugins" disabled="@(!IsRunning)">Load Plugins</button>
</div>
</div>
</div>
Welcome to your new app.
<script>
window.scrollToBottom = function (elementId) {
var el = document.getElementById(elementId);
if (el) {
el.scrollTop = el.scrollHeight;
}
}
</script>
@code {
private bool IsRunning { get; set; }
private List<string> Logs { get; set; } = new();
private Timer? _logTimer;
private int _lastLogCount = 0;
private readonly object _logLock = new();
protected override void OnInitialized()
{
IsRunning = DiscordBotApplication.IsReady;
_logTimer = new Timer(async _ => await RefreshLogsAsync(), null, 0, 2000);
}
private async Task StartApplication()
{
if (!DiscordBotApplication.IsReady)
{
await DiscordBotApplication.StartAsync();
Logger.Log("Application started", this);
}
IsRunning = DiscordBotApplication.IsReady;
}
private async Task StopApplication()
{
if (DiscordBotApplication.IsReady)
{
await DiscordBotApplication.StopAsync();
Logger.Log("Application stopped", this);
}
IsRunning = DiscordBotApplication.IsReady;
}
private async Task LoadPlugins()
{
Logger.Log("Loading plugins", this);
await PluginLoader.LoadPlugins();
Logger.Log("Plugins loaded", this);
}
private string GetLogStyle(string line)
{
if (line.Contains("[Error]")) return "color: #ff4d4d;";
if (line.Contains("[Warning]")) return "color: #ffa500;";
if (line.Contains("[Debug]")) return "color: #88f;";
return "";
}
private async Task RefreshLogsAsync()
{
try
{
var logText = Logger.GetLogsHistory();
var newLogs = logText.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
if (newLogs.Length != _lastLogCount)
{
lock (_logLock)
{
Logs = newLogs.ToList();
_lastLogCount = newLogs.Length;
}
await InvokeAsync(async () =>
{
StateHasChanged();
await JS.InvokeVoidAsync("scrollToBottom", "consoleLog");
});
}
}
catch (Exception ex)
{
}
}
public void Dispose()
{
_logTimer?.Dispose();
}
}

View File

@@ -0,0 +1,115 @@
@page "/settings"
@using System.ComponentModel.DataAnnotations
@using DiscordBotCore.Configuration
@using DiscordBotCore.Logging
@inject NavigationManager Navigation
@rendermode InteractiveServer
@if (_settingsViewModel is not null)
{
<EditForm Model="@_settingsViewModel" OnValidSubmit="HandleSubmitTask">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="mb-3">
<label class="form-label" for="tokenInput">Token</label>
<InputText id="tokenInput" class="form-control" @bind-Value="_settingsViewModel.Token" />
</div>
<div class="mb-3">
<label class="form-label" for="prefixInput">Prefix</label>
<InputText id="prefixInput" class="form-control" @bind-Value="_settingsViewModel.Prefix" />
</div>
<div class="mb-3">
<label class="form-label" for="serverIdsInput">Server IDs (comma-separated)</label>
<InputTextArea id="serverIdsInput" class="form-control" @bind-Value="_settingsViewModel.ServerIds" Rows="3" />
</div>
<button type="submit" class="btn btn-primary">Save</button>
</EditForm>
}
@code {
[Inject]
public ILogger Logger { get; set; }
[Inject]
public IConfiguration Configuration { get; set; }
private SettingsViewModel? _settingsViewModel;
protected override void OnInitialized()
{
var token = Configuration.Get<string>("token");
var prefix = Configuration.Get<string>("prefix");
var serverIds = Configuration.GetList<ulong>("ServerIds", new List<ulong>());
if(token == null || prefix == null)
{
Logger.Log("Token or Prefix is not set in the configuration.", this);
_settingsViewModel = new SettingsViewModel
{
Token = "",
Prefix = "",
ServerIds = ""
};
return;
}
_settingsViewModel = new SettingsViewModel
{
Token = token,
Prefix = prefix,
ServerIds = string.Join(",", serverIds)
};
StateHasChanged();
}
private async Task HandleSubmitTask()
{
if (_settingsViewModel is null)
{
return;
}
var token = _settingsViewModel.Token;
var prefix = _settingsViewModel.Prefix;
var serverIds = _settingsViewModel.ServerIds
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(id => ulong.TryParse(id.Trim(), out var result) ? result : 0)
.Where(id => id != 0)
.ToList();
if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(prefix))
{
return;
}
Configuration.Set("token", token);
Configuration.Set("prefix", prefix);
Configuration.Set("ServerIds", serverIds);
await Configuration.SaveToFile();
Logger.Log("Settings saved successfully.", this);
Navigation.NavigateTo($"/");
}
private class SettingsViewModel
{
[Required(ErrorMessage = "Token is required.")]
public string Token { get; set; }
[Required(ErrorMessage = "Prefix is required.")]
public string Prefix { get; set; }
[Required(ErrorMessage = "Server IDs are required.")]
public string ServerIds { get; set; }
}
}