Created Settings Page and Home Page. Fixed load plugin error when the bot restarts
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
115
WebUI/Components/Pages/Settings.razor
Normal file
115
WebUI/Components/Pages/Settings.razor
Normal 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; }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user