diff --git a/Moonlight/App/Helpers/DiscordMaintenanceToggle.cs b/Moonlight/App/Helpers/DiscordMaintenanceToggle.cs new file mode 100644 index 00000000..fee30658 --- /dev/null +++ b/Moonlight/App/Helpers/DiscordMaintenanceToggle.cs @@ -0,0 +1,13 @@ +using Discord.WebSocket; +using Moonlight.App.Services.DiscordBot; + +namespace Moonlight.App.Helpers; + +public class DiscordMaintenanceToggle +{ + private Task MaintenanceModeToggle(SocketSlashCommand command) + { + DiscordBotService.MaintenanceMode = !DiscordBotService.MaintenanceMode; + return Task.CompletedTask; + } +} diff --git a/Moonlight/App/Repositories/LoadingMessageRepository.cs b/Moonlight/App/Repositories/LoadingMessageRepository.cs new file mode 100644 index 00000000..8575ff74 --- /dev/null +++ b/Moonlight/App/Repositories/LoadingMessageRepository.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Repositories; + +public class LoadingMessageRepository : IDisposable +{ + private readonly DataContext DataContext; + + public LoadingMessageRepository(DataContext dataContext) + { + DataContext = dataContext; + } + + public DbSet Get() + { + return DataContext.LoadingMessages; + } + + public LoadingMessage Add(LoadingMessage loadingMessage) + { + var x = DataContext.LoadingMessages.Add(loadingMessage); + DataContext.SaveChanges(); + return x.Entity; + } + + public void Update(LoadingMessage loadingMessage) + { + DataContext.LoadingMessages.Update(loadingMessage); + DataContext.SaveChanges(); + } + + public void Delete(LoadingMessage loadingMessage) + { + DataContext.LoadingMessages.Remove(loadingMessage); + DataContext.SaveChanges(); + } + + public void Dispose() + { + DataContext.Dispose(); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/DiscordBot/BaseModule.cs b/Moonlight/App/Services/DiscordBot/BaseModule.cs index 616435fd..17e2360e 100644 --- a/Moonlight/App/Services/DiscordBot/BaseModule.cs +++ b/Moonlight/App/Services/DiscordBot/BaseModule.cs @@ -2,12 +2,14 @@ namespace Moonlight.App.Services.DiscordBot; -public class BaseModule +public abstract class BaseModule { public DiscordSocketClient Client { get; set; } public ConfigService ConfigService { get; set; } public IServiceScope Scope { get; set; } - + + public abstract Task RegisterCommands(); + public BaseModule( DiscordSocketClient client, ConfigService configService, diff --git a/Moonlight/App/Services/DiscordBot/DiscordBotService.cs b/Moonlight/App/Services/DiscordBot/DiscordBotService.cs index 1547a42f..dbb99687 100644 --- a/Moonlight/App/Services/DiscordBot/DiscordBotService.cs +++ b/Moonlight/App/Services/DiscordBot/DiscordBotService.cs @@ -1,22 +1,28 @@ -using Discord; +using System.Diagnostics; +using Discord; using Discord.WebSocket; using Logging.Net; +using Moonlight.App.Repositories; +using Moonlight.App.Services.DiscordBot.Commands; +using Moonlight.App.Services.DiscordBot.Modules; namespace Moonlight.App.Services.DiscordBot; public class DiscordBotService { + public static bool MaintenanceMode = false; + private readonly IServiceScopeFactory ServiceScopeFactory; private readonly ConfigService ConfigService; - + private IServiceScope ServiceScope; private readonly DiscordSocketClient Client; - - // Add here references so e.g. - // public ExampleModule ExampleModule { get; private set; } - public DiscordBotService( + // References + public ActivityStatusModule ActivityStatusModule { get; private set; } + +public DiscordBotService( IServiceScopeFactory serviceScopeFactory, ConfigService configService) { @@ -34,24 +40,71 @@ public class DiscordBotService var discordConfig = ConfigService .GetSection("Moonlight") .GetSection("DiscordBot"); - - if(!discordConfig.GetValue("Enable")) + + if (!discordConfig.GetValue("Enable")) return; - + Client.Log += Log; - - // Init here the modules e.g. - // ExampleModule = new(Client, ConfigService, Scope) + Client.Ready += OnReady; + + //Commands + + //Module + ActivityStatusModule = new(Client, ConfigService, ServiceScope); + + await ActivityStatusModule.UpdateActivityStatusList(); await Client.LoginAsync(TokenType.Bot, discordConfig.GetValue("Token")); await Client.StartAsync(); await Task.Delay(-1); } + private async Task OnReady() + { + //await Client.SetGameAsync(name: "https://endelon-hosting.de", type: ActivityType.Watching); + await Client.SetStatusAsync(UserStatus.Idle); + + Logger.Info($"Invite link: https://discord.com/api/oauth2/authorize?client_id={Client.CurrentUser.Id}&permissions=1099511696391&scope=bot%20applications.commands"); + Logger.Info($"Login as {Client.CurrentUser.Username}#{Client.CurrentUser.DiscriminatorValue}"); + + Task.Run(ActivityStatusModule.ActivityStatusScheduler); + } private Task Log(LogMessage message) { Logger.Debug(message.Message); return Task.CompletedTask; } + + public async Task CreateCommands() + { + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + + var type = this.GetType(); + var properties = type.GetProperties(); + Logger.Debug("Start Initializing Commands"); + foreach (var property in properties) + { + if (property.PropertyType.IsSubclassOf(typeof(BaseModule))) + { + try + { + var instance = (BaseModule)property.GetValue(this)!; + await instance.RegisterCommands(); + Logger.Debug("Registered" + instance); + await Task.Delay(TimeSpan.FromMilliseconds(1000)); + } + catch (Exception ex) + { + Logger.Error($"Module Error {ex.Message}"); + Logger.Error(ex.InnerException); + } + } + } + + stopwatch.Stop(); + Logger.Info($"Registered all commands. Done in {stopwatch.ElapsedMilliseconds}ms"); + } + } \ No newline at end of file diff --git a/Moonlight/App/Services/DiscordBot/Modules/ActivityStatusModule.cs b/Moonlight/App/Services/DiscordBot/Modules/ActivityStatusModule.cs new file mode 100644 index 00000000..970fa474 --- /dev/null +++ b/Moonlight/App/Services/DiscordBot/Modules/ActivityStatusModule.cs @@ -0,0 +1,39 @@ +using Discord; +using Discord.WebSocket; +using Moonlight.App.Database.Entities; +using Moonlight.App.Repositories; + +namespace Moonlight.App.Services.DiscordBot.Modules; + +public class ActivityStatusModule : BaseModule +{ + + private List LoadingMessages; + + private readonly PeriodicTimer Timer = new(TimeSpan.FromMinutes(1)); + + public ActivityStatusModule(DiscordSocketClient client, ConfigService configService, IServiceScope scope) : base(client, configService, scope) + { } + public override Task RegisterCommands() + { return Task.CompletedTask; } + + public Task UpdateActivityStatusList() + { + var loadingMessageRepo = Scope.ServiceProvider.GetRequiredService(); + LoadingMessages = loadingMessageRepo.Get().ToList(); + + return Task.CompletedTask; + } + + public async void ActivityStatusScheduler() + { + while (await Timer.WaitForNextTickAsync()) + { + Random rand = new Random(); + LoadingMessage random = LoadingMessages[rand.Next(LoadingMessages.Count)]; + + await Client.SetGameAsync(random.Message, "https://www.endelon.team", ActivityType.Streaming); + } + } + +} \ No newline at end of file diff --git a/Moonlight/App/Services/DiscordBot/Modules/RemoveCommandsModuels.cs b/Moonlight/App/Services/DiscordBot/Modules/RemoveCommandsModuels.cs new file mode 100644 index 00000000..90e05bab --- /dev/null +++ b/Moonlight/App/Services/DiscordBot/Modules/RemoveCommandsModuels.cs @@ -0,0 +1,34 @@ +using System.Diagnostics; +using Discord; +using Discord.WebSocket; +using Logging.Net; + +namespace Moonlight.App.Services.DiscordBot.Commands; + +public class RemoveCommandsModuels : BaseModule +{ + public RemoveCommandsModuels(DiscordSocketClient client, ConfigService configService, IServiceScope scope) : base(client, configService, scope) {} + public override Task RegisterCommands() + { return Task.CompletedTask; } + + private async void VoidCommands() + { + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + + var commands = await Client.GetGlobalApplicationCommandsAsync(); + if (commands == null) return; + + foreach (var slashCommand in commands) + { + if(slashCommand.Name == "commands") continue; + + await slashCommand.DeleteAsync(); + Logger.Debug($"Deleted {slashCommand.Name}, {slashCommand.Id}"); + await Task.Delay(TimeSpan.FromMilliseconds(1000)); + } + + stopwatch.Stop(); + Logger.Info($"Deleted all commands. Done in {stopwatch.ElapsedMilliseconds}ms"); + } +} \ No newline at end of file diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 2c6662f8..816407f9 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -67,7 +67,6 @@ - diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index 5b4efebf..ccd680cd 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -60,7 +60,8 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); - + builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -125,7 +126,6 @@ namespace Moonlight builder.Services.AddSingleton(); // Third party services - builder.Services.AddBlazorTable(); builder.Services.AddSweetAlert2(options => { options.Theme = SweetAlertTheme.Dark; }); builder.Services.AddBlazorContextMenu(); @@ -153,8 +153,9 @@ namespace Moonlight // Support service var supportServerService = app.Services.GetRequiredService(); - // cleanup service + // AutoStart services _ = app.Services.GetRequiredService(); + _ = app.Services.GetRequiredService(); // Discord bot service //var discordBotService = app.Services.GetRequiredService(); diff --git a/Moonlight/Shared/Views/Admin/Sys/DiscordBot.razor b/Moonlight/Shared/Views/Admin/Sys/DiscordBot.razor index 22f7c9ef..282b78d2 100644 --- a/Moonlight/Shared/Views/Admin/Sys/DiscordBot.razor +++ b/Moonlight/Shared/Views/Admin/Sys/DiscordBot.razor @@ -6,20 +6,34 @@ - +
+ + +
-@code +@code { + //ToDo: Ole muss ins Bett gehen + //ToDo: Bot Info Card with Name, Bot Avatar, (RichPresence) Game Status, Activity Status + private async Task RegisterCommands() { - + await DiscordBotService.CreateCommands(); + } + + private Task VoidCommands() + { + return Task.CompletedTask; } } \ No newline at end of file