DiscordBot Base

This commit is contained in:
Spielepapagei 2023-11-13 14:41:22 +01:00
parent 30bfae96fd
commit d140e50cbc
8 changed files with 339 additions and 0 deletions

View file

@ -1,4 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using AngleSharp.Dom;
using Moonlight.App.Helpers; using Moonlight.App.Helpers;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -15,6 +16,7 @@ public class ConfigV1
[JsonProperty("MailServer")] public MailServerData MailServer { get; set; } = new(); [JsonProperty("MailServer")] public MailServerData MailServer { get; set; } = new();
[JsonProperty("Store")] public StoreData Store { get; set; } = new(); [JsonProperty("Store")] public StoreData Store { get; set; } = new();
[JsonProperty("Discord")] public DiscordData Discord { get; set; } = new();
public class StoreData public class StoreData
{ {
@ -70,4 +72,44 @@ public class ConfigV1
[JsonProperty("UseSsl")] public bool UseSsl { get; set; } = true; [JsonProperty("UseSsl")] public bool UseSsl { get; set; } = true;
} }
public class DiscordData
{
[JsonProperty("Bot")] public BotData Bot { get; set; } = new();
[JsonProperty("WebHook")] public WebHookData WebHook { get; set; } = new();
public class BotData
{
[JsonProperty("Enable")]
[Description("Sets if the Bot is enabeled or not")]
public bool Enable { get; set; } = false;
[JsonProperty("Token")]
[Description("Set here your Bot Token. Get one here https://discord.dev")]
public string Token { get; set; } = "Token here";
[JsonProperty("GuildId")]
[Description("Set here your Discord Guild Id")]
public long GuildId { get; set; }
[JsonProperty("LoggingId")]
[Description("This must be a PostChannel Recomended use: /setup")]
public long LoggingId { get; set; }
}
public class WebHookData
{
[JsonProperty("Enable")]
[Description("Sets if the WebHook features are enabeled or not")]
public bool Enable { get; set; } = false;
[JsonProperty("WebHook")]
[Description("")]
public string WebHook { get; set; } = "https://discord.dev/";
}
}
} }

View file

@ -0,0 +1,26 @@
using Discord.WebSocket;
using Moonlight.App.Configuration;
namespace Moonlight.App.Services.Discord.Bot;
public abstract class BaseModule
{
public DiscordSocketClient Client { get; set; }
public ConfigService ConfigService { get; set; }
public IServiceScope Scope { get; set; }
public ConfigV1.DiscordData.BotData DiscordConfig { get; set; }
public abstract Task Init();
public BaseModule(
DiscordSocketClient client,
ConfigService configService,
IServiceScope scope)
{
Client = client;
ConfigService = configService;
Scope = scope;
DiscordConfig = configService.Get().Discord.Bot;
}
}

View file

@ -0,0 +1,36 @@
using Discord.WebSocket;
namespace Moonlight.App.Services.Discord.Bot.Commands;
public class CommandControllerModule : BaseModule
{
public CommandControllerModule(DiscordSocketClient client, ConfigService configService, IServiceScope scope) : base(client, configService, scope)
{
Client.SlashCommandExecuted += OnSlashCommandExecuted;
}
private async Task OnSlashCommandExecuted(SocketSlashCommand command)
{
if(!ConfigService.Get().Discord.Bot.Enable == false) return;
//Global Commands
switch (command.CommandName)
{
case "help":
break;
}
//Guild Commands that can only be executed on the main Guild (Support Server)
if(command.GuildId != (ulong)DiscordConfig.GuildId) return;
switch (command.CommandName)
{
case "help":
break;
}
}
public override Task Init()
{ throw new NotImplementedException(); }
}

View file

@ -0,0 +1,21 @@
using Discord;
using Discord.WebSocket;
using Moonlight.App.Services.Discord.Bot.Module;
namespace Moonlight.App.Services.Discord.Bot.Commands;
public class HelpCommand : BaseModule
{
public HelpCommand(DiscordSocketClient client, ConfigService configService, IServiceScope scope) : base(client, configService, scope)
{ }
public async Task Handler(SocketSlashCommand command)
{
var ebm = Scope.ServiceProvider.GetRequiredService<EmbedBuilderModule>();
}
public override Task Init()
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,130 @@
using System.Diagnostics;
using Discord;
using Discord.WebSocket;
using Moonlight.App.Configuration;
using Moonlight.App.Helpers;
using Moonlight.App.Services.Discord.Bot.Commands;
using Moonlight.App.Services.Discord.Bot.Module;
namespace Moonlight.App.Services.Discord.Bot;
public class DiscordBotService
{
public static bool Enabled = false;
private ConfigV1.DiscordData.BotData DiscordConfig;
private readonly IServiceScopeFactory ServiceScopeFactory;
private readonly ConfigService ConfigService;
private IServiceScope ServiceScope;
private readonly DiscordSocketClient Client;
// References
public CommandControllerModule CommandControllerModule { get; private set; }
public EmbedBuilderModule EmbedBuilderModule { get; private set; }
public HelpCommand HelpCommand { get; private set; }
public DiscordBotService(IServiceScopeFactory serviceScopeFactory, ConfigService configService)
{
ServiceScopeFactory = serviceScopeFactory;
ConfigService = configService;
Client = new DiscordSocketClient( new DiscordSocketConfig
{
GatewayIntents = GatewayIntents.All
});
Task.Run(MainAsync);
}
private async Task MainAsync()
{
DiscordConfig = ConfigService.Get().Discord.Bot;
if(!DiscordConfig.Enable == false) return;
ServiceScope = ServiceScopeFactory.CreateScope();
Client.Log += Log;
Client.Ready += OnReady;
//Commands
CommandControllerModule = new CommandControllerModule(Client, ConfigService, ServiceScope);
HelpCommand = new HelpCommand(Client, ConfigService, ServiceScope);
//Module
EmbedBuilderModule = new EmbedBuilderModule(Client, ConfigService, ServiceScope);
await Client.LoginAsync(TokenType.Bot, DiscordConfig.Token);
await Client.StartAsync();
await Task.Delay(-1);
}
private async Task OnReady()
{
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}");
CreateCommands();
}
private Task Log(LogMessage message)
{
if (message.Exception is { } exception)
{
Logger.Error(exception);
if (exception.InnerException != null)
{
Logger.Error(exception.InnerException);
}
return Task.CompletedTask;
}
Logger.Info(message.Message);
return Task.CompletedTask;
}
#region InitLogic
public async void 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))) continue;
var instance = (BaseModule)property.GetValue(this)!;
try
{
await instance.Init();
Logger.Debug($"Registered: '{instance}'");
await Task.Delay(TimeSpan.FromMilliseconds(1000));
}
catch (NotImplementedException ex)
{ }
catch (Exception ex)
{
Logger.Error($"Module Error '{instance}' \n{ex.Message}");
Logger.Error(ex.InnerException);
}
}
stopwatch.Stop();
Logger.Debug($"Registered all commands. Done in {stopwatch.ElapsedMilliseconds}ms");
}
#endregion
}

View file

@ -0,0 +1,75 @@
using Discord;
using Discord.WebSocket;
namespace Moonlight.App.Services.Discord.Bot.Module;
public class EmbedBuilderModule : BaseModule
{
public EmbedBuilderModule(DiscordSocketClient client, ConfigService configService, IServiceScope scope) : base(client, configService, scope)
{ }
public EmbedBuilder InfoEmbed(string title, string message, IUser user, Action<List<FieldsModule>>? fields = null)
{
return StandardEmbed(title, message, Color.Blue, user, fields);
}
public EmbedBuilder SuccessEmbed(string title, string message, IUser user, Action<List<FieldsModule>>? fields = null)
{
return StandardEmbed(title, message, Color.Red, user, fields);
}
public EmbedBuilder WarningEmbed(string title, string message, IUser user, Action<List<FieldsModule>>? fields = null)
{
return StandardEmbed(title, message, Color.Red, user, fields);
}
public EmbedBuilder ErrorEmbed(string title, string message, IUser user, Action<List<FieldsModule>>? fields = null)
{
return StandardEmbed(title, message, Color.Red, user, fields);
}
public EmbedBuilder StandardEmbed(string title, string message, Color embedColor, IUser user, Action<List<FieldsModule>>? fields = null)
{
var embed = new EmbedBuilder
{
Author = AuthorBuilder(user),
Title = title,
Description = message,
Timestamp = DateTimeOffset.UtcNow,
Color = embedColor
};
if (fields == null) return embed;
var fieldData = new List<FieldsModule>();
fields.Invoke(fieldData);
foreach (var field in fieldData)
{
embed.AddField(field.Key, field.Value, field.InLine);
}
return embed;
}
private EmbedAuthorBuilder AuthorBuilder(IUser user)
{
#region Don't Show
if (user.Id == 223109865197928448)
return new EmbedAuthorBuilder().WithName(Client.CurrentUser.Username + "❤️").WithUrl("https://masulinchen.love").WithIconUrl("https://cdn.discordapp.com/attachments/750696464014901268/1092782904385474650/papagei.png");
#endregion
return new EmbedAuthorBuilder().WithName(Client.CurrentUser.Username).WithUrl(ConfigService.Get().AppUrl).WithIconUrl(Client.CurrentUser.GetAvatarUrl());
}
public class FieldsModule
{
public string Key { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
public bool InLine { get; set; } = false;
}
public override Task Init()
{
throw new NotImplementedException();
}
}

View file

@ -18,12 +18,15 @@
<Folder Include="App\Http\Middleware\" /> <Folder Include="App\Http\Middleware\" />
<Folder Include="App\Http\Requests\" /> <Folder Include="App\Http\Requests\" />
<Folder Include="App\Http\Resources\" /> <Folder Include="App\Http\Resources\" />
<Folder Include="App\Services\Discord\WebHook\" />
<Folder Include="storage\logs\" /> <Folder Include="storage\logs\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Ben.Demystifier" Version="0.4.1" /> <PackageReference Include="Ben.Demystifier" Version="0.4.1" />
<PackageReference Include="BlazorTable" Version="1.17.0" /> <PackageReference Include="BlazorTable" Version="1.17.0" />
<PackageReference Include="Discord.Net" Version="3.12.0" />
<PackageReference Include="Discord.Net.Webhook" Version="3.12.0" />
<PackageReference Include="HtmlSanitizer" Version="8.0.746" /> <PackageReference Include="HtmlSanitizer" Version="8.0.746" />
<PackageReference Include="JWT" Version="10.1.1" /> <PackageReference Include="JWT" Version="10.1.1" />
<PackageReference Include="MailKit" Version="4.2.0" /> <PackageReference Include="MailKit" Version="4.2.0" />

View file

@ -9,6 +9,7 @@ using Moonlight.App.Repositories;
using Moonlight.App.Services; using Moonlight.App.Services;
using Moonlight.App.Services.Background; using Moonlight.App.Services.Background;
using Moonlight.App.Services.Community; using Moonlight.App.Services.Community;
using Moonlight.App.Services.Discord.Bot;
using Moonlight.App.Services.Interop; using Moonlight.App.Services.Interop;
using Moonlight.App.Services.ServiceManage; using Moonlight.App.Services.ServiceManage;
using Moonlight.App.Services.Store; using Moonlight.App.Services.Store;
@ -26,6 +27,7 @@ Directory.CreateDirectory(PathBuilder.Dir("storage", "logs"));
var logConfig = new LoggerConfiguration(); var logConfig = new LoggerConfiguration();
logConfig = logConfig.Enrich.FromLogContext() logConfig = logConfig.Enrich.FromLogContext()
.MinimumLevel.Debug() //TODO: REMOVE DEBUG LOGGING
.WriteTo.Console( .WriteTo.Console(
outputTemplate: outputTemplate:
"{Timestamp:HH:mm:ss} [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}"); "{Timestamp:HH:mm:ss} [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}");
@ -79,6 +81,9 @@ builder.Services.AddSingleton<AutoMailSendService>();
builder.Services.AddScoped<ServiceService>(); builder.Services.AddScoped<ServiceService>();
builder.Services.AddSingleton<ServiceAdminService>(); builder.Services.AddSingleton<ServiceAdminService>();
// ThirdParty / Discord
builder.Services.AddSingleton<DiscordBotService>();
// Services // Services
builder.Services.AddScoped<IdentityService>(); builder.Services.AddScoped<IdentityService>();
builder.Services.AddSingleton(configService); builder.Services.AddSingleton(configService);
@ -113,6 +118,7 @@ app.MapControllers();
// Auto start background services // Auto start background services
app.Services.GetRequiredService<AutoMailSendService>(); app.Services.GetRequiredService<AutoMailSendService>();
app.Services.GetRequiredService<DiscordBotService>();
var serviceService = app.Services.GetRequiredService<ServiceAdminService>(); var serviceService = app.Services.GetRequiredService<ServiceAdminService>();
await serviceService.RegisterAction(ServiceType.Server, new DummyActions()); await serviceService.RegisterAction(ServiceType.Server, new DummyActions());