Merge branch 'main' into PleskIntegration

This commit is contained in:
Marcel Baumgartner 2023-04-06 18:54:38 +02:00 committed by GitHub
commit 74fa8af744
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 275 additions and 27 deletions

View file

@ -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;
}
}

View file

@ -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<LoadingMessage> 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();
}
}

View file

@ -2,12 +2,14 @@
namespace Moonlight.App.Services.DiscordBot; namespace Moonlight.App.Services.DiscordBot;
public class BaseModule public abstract class BaseModule
{ {
public DiscordSocketClient Client { get; set; } public DiscordSocketClient Client { get; set; }
public ConfigService ConfigService { get; set; } public ConfigService ConfigService { get; set; }
public IServiceScope Scope { get; set; } public IServiceScope Scope { get; set; }
public abstract Task RegisterCommands();
public BaseModule( public BaseModule(
DiscordSocketClient client, DiscordSocketClient client,
ConfigService configService, ConfigService configService,

View file

@ -1,22 +1,28 @@
using Discord; using System.Diagnostics;
using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using Logging.Net; using Logging.Net;
using Moonlight.App.Repositories;
using Moonlight.App.Services.DiscordBot.Commands;
using Moonlight.App.Services.DiscordBot.Modules;
namespace Moonlight.App.Services.DiscordBot; namespace Moonlight.App.Services.DiscordBot;
public class DiscordBotService public class DiscordBotService
{ {
public static bool MaintenanceMode = false;
private readonly IServiceScopeFactory ServiceScopeFactory; private readonly IServiceScopeFactory ServiceScopeFactory;
private readonly ConfigService ConfigService; private readonly ConfigService ConfigService;
private IServiceScope ServiceScope; private IServiceScope ServiceScope;
private readonly DiscordSocketClient Client; 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, IServiceScopeFactory serviceScopeFactory,
ConfigService configService) ConfigService configService)
{ {
@ -34,24 +40,71 @@ public class DiscordBotService
var discordConfig = ConfigService var discordConfig = ConfigService
.GetSection("Moonlight") .GetSection("Moonlight")
.GetSection("DiscordBot"); .GetSection("DiscordBot");
if(!discordConfig.GetValue<bool>("Enable")) if (!discordConfig.GetValue<bool>("Enable"))
return; return;
Client.Log += Log; Client.Log += Log;
Client.Ready += OnReady;
// Init here the modules e.g.
// ExampleModule = new(Client, ConfigService, Scope) //Commands
//Module
ActivityStatusModule = new(Client, ConfigService, ServiceScope);
await ActivityStatusModule.UpdateActivityStatusList();
await Client.LoginAsync(TokenType.Bot, discordConfig.GetValue<string>("Token")); await Client.LoginAsync(TokenType.Bot, discordConfig.GetValue<string>("Token"));
await Client.StartAsync(); await Client.StartAsync();
await Task.Delay(-1); 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) private Task Log(LogMessage message)
{ {
Logger.Debug(message.Message); Logger.Debug(message.Message);
return Task.CompletedTask; 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");
}
} }

View file

@ -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<LoadingMessage> 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<LoadingMessageRepository>();
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);
}
}
}

View file

@ -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");
}
}

View file

@ -67,7 +67,6 @@
<Folder Include="App\Http\Middleware" /> <Folder Include="App\Http\Middleware" />
<Folder Include="App\Models\Daemon\Requests" /> <Folder Include="App\Models\Daemon\Requests" />
<Folder Include="App\Models\Google\Resources" /> <Folder Include="App\Models\Google\Resources" />
<Folder Include="App\Services\DiscordBot\Modules" />
<Folder Include="resources\lang" /> <Folder Include="resources\lang" />
</ItemGroup> </ItemGroup>

View file

@ -62,6 +62,7 @@ namespace Moonlight
builder.Services.AddScoped<SubscriptionRepository>(); builder.Services.AddScoped<SubscriptionRepository>();
builder.Services.AddScoped<PleskServerRepository>(); builder.Services.AddScoped<PleskServerRepository>();
builder.Services.AddScoped<WebsiteRepository>(); builder.Services.AddScoped<WebsiteRepository>();
builder.Services.AddScoped<LoadingMessageRepository>();
builder.Services.AddScoped<AuditLogEntryRepository>(); builder.Services.AddScoped<AuditLogEntryRepository>();
builder.Services.AddScoped<ErrorLogEntryRepository>(); builder.Services.AddScoped<ErrorLogEntryRepository>();
@ -129,7 +130,6 @@ namespace Moonlight
builder.Services.AddSingleton<DiscordBotService>(); builder.Services.AddSingleton<DiscordBotService>();
// Third party services // Third party services
builder.Services.AddBlazorTable(); builder.Services.AddBlazorTable();
builder.Services.AddSweetAlert2(options => { options.Theme = SweetAlertTheme.Dark; }); builder.Services.AddSweetAlert2(options => { options.Theme = SweetAlertTheme.Dark; });
builder.Services.AddBlazorContextMenu(); builder.Services.AddBlazorContextMenu();
@ -157,8 +157,9 @@ namespace Moonlight
// Support service // Support service
var supportServerService = app.Services.GetRequiredService<SupportServerService>(); var supportServerService = app.Services.GetRequiredService<SupportServerService>();
// cleanup service // AutoStart services
_ = app.Services.GetRequiredService<CleanupService>(); _ = app.Services.GetRequiredService<CleanupService>();
_ = app.Services.GetRequiredService<DiscordBotService>();
// Discord bot service // Discord bot service
//var discordBotService = app.Services.GetRequiredService<DiscordBotService>(); //var discordBotService = app.Services.GetRequiredService<DiscordBotService>();

View file

@ -6,20 +6,34 @@
<OnlyAdmin> <OnlyAdmin>
<AdminSystemNavigation Index="6"/> <AdminSystemNavigation Index="6"/>
<div class="mt-3 card card-body"> <div class="mt-3 card card-body">
<WButton Text="Register commands" <WButton Text="Register commands"
WorkingText="Working" WorkingText="Working"
CssClasses="btn-primary" CssClasses="btn-primary"
OnClick="RegisterCommands"> OnClick="RegisterCommands">
</WButton> </WButton>
<WButton Text="Void commands"
WorkingText="Working"
CssClasses="mt-3 btn-danger"
OnClick="VoidCommands">
</WButton>
</div> </div>
</OnlyAdmin> </OnlyAdmin>
@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() private async Task RegisterCommands()
{ {
await DiscordBotService.CreateCommands();
}
private Task VoidCommands()
{
return Task.CompletedTask;
} }
} }

View file

@ -60,7 +60,7 @@
<input class="form-control" type="number" placeholder="@(SmartTranslateService.Translate("Priority"))" @bind="NewRecord.Priority"/> <input class="form-control" type="number" placeholder="@(SmartTranslateService.Translate("Priority"))" @bind="NewRecord.Priority"/>
</div> </div>
</div> </div>
<div class="d-flex"> <div class="d-flex me-2">
<div class="mt-3 ms-auto"> <div class="mt-3 ms-auto">
<WButton Text="@(SmartTranslateService.Translate("Add"))" <WButton Text="@(SmartTranslateService.Translate("Add"))"
WorkingText="@(SmartTranslateService.Translate("Adding"))" WorkingText="@(SmartTranslateService.Translate("Adding"))"
@ -79,7 +79,7 @@
<div class="separator"></div> <div class="separator"></div>
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header" id="heading@(record.Id)"> <h2 class="accordion-header" id="heading@(record.Id)">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse@(record.Id)" aria-expanded="false" aria-controls="collapse@(record.Id)"> <button class="accordion-button ps-6 collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse@(record.Id)" aria-expanded="false" aria-controls="collapse@(record.Id)">
<div class="row w-100"> <div class="row w-100">
<div class="ms-5 col"> <div class="ms-5 col">
@(record.Type.ToString().ToUpper()) @(record.Type.ToString().ToUpper())
@ -103,7 +103,7 @@
</button> </button>
</h2> </h2>
<div id="collapse@(record.Id)" class="accordion-collapse collapse" aria-labelledby="heading@(record.Id)" data-bs-parent="#accordionDomain"> <div id="collapse@(record.Id)" class="accordion-collapse collapse" aria-labelledby="heading@(record.Id)" data-bs-parent="#accordionDomain">
<div class="accordion-body"> <div class="accordion-body ms-3 me-3">
<div class="w-100 d-flex flex-row justify-content-between align-items-center"> <div class="w-100 d-flex flex-row justify-content-between align-items-center">
<div class="p-2"> <div class="p-2">
<input class="form-control" type="text" value="@(record.Type.ToString().ToUpper())" disabled=""/> <input class="form-control" type="text" value="@(record.Type.ToString().ToUpper())" disabled=""/>
@ -129,8 +129,8 @@
</div> </div>
</div> </div>
<div class="separator mx-5"></div> <div class="separator mx-5"></div>
<div class="accordion-body"> <div class="accordion-body me-0 ms-5">
<div class="d-flex"> <div class="d-flex me-2">
<div class="me-auto"> <div class="me-auto">
<WButton Text="@(SmartTranslateService.Translate("Delete"))" <WButton Text="@(SmartTranslateService.Translate("Delete"))"
WorkingText="@(SmartTranslateService.Translate("Deleting"))" WorkingText="@(SmartTranslateService.Translate("Deleting"))"
@ -138,9 +138,9 @@
OnClick="() => Delete(record)"> OnClick="() => Delete(record)">
</WButton> </WButton>
</div> </div>
<div> <div class="me-3 ms-3">
<button class="btn btn-light" data-bs-toggle="collapse" data-bs-target="#collapse@(record.Id)"> <button class="btn btn-light" data-bs-toggle="collapse" data-bs-target="#collapse@(record.Id)">
<TL>Cancle</TL> <TL>Cancel</TL>
</button> </button>
<WButton Text="@(SmartTranslateService.Translate("Save"))" <WButton Text="@(SmartTranslateService.Translate("Save"))"
WorkingText="@(SmartTranslateService.Translate("Saving"))" WorkingText="@(SmartTranslateService.Translate("Saving"))"

View file

@ -1,2 +1,51 @@
@page "/domains" @page "/domains"
@using Moonlight.App.Repositories.Domains
@using Moonlight.App.Database.Entities
@using Microsoft.EntityFrameworkCore
@using BlazorTable
@using Moonlight.App.Services
@using domain = Moonlight.App.Database.Entities.Domain
@inject DomainRepository DomainRepository
@inject DomainService DomainService
@inject SmartTranslateService SmartTranslateService
<LazyLoader Load="Load">
@foreach (var domain in domains)
{
<div class="row px-5 mb-5">
<div class="card card-body">
<div class="row">
<div class="col">
<div class="d-flex align-items-center">
<div class="symbol symbol-50px me-3">
<i class="bx bx-md bx-purchase-tag"></i>
</div>
<div class="d-flex justify-content-start flex-column">
<a href="/domain/@domain.Id" class="text-gray-800 text-hover-primary mb-1 fs-5">@domain.Name.@domain.SharedDomain.Name</a>
</div>
</div>
</div>
</div>
</div>
</div>
}
</LazyLoader>
@code {
[CascadingParameter]
public User? User { get; set; }
private domain[] domains { get; set; }
public async Task Load(LazyLoader loader)
{
domains = DomainRepository
.Get()
.Include(x => x.SharedDomain)
.Include(x => x.Owner)
.Where(x => x.Owner == User)
.ToArray();
}
}