DiscordBot Base
This commit is contained in:
parent
30bfae96fd
commit
d140e50cbc
|
@ -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/";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
26
Moonlight/App/Services/Discord/Bot/BaseModule.cs
Normal file
26
Moonlight/App/Services/Discord/Bot/BaseModule.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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(); }
|
||||||
|
}
|
21
Moonlight/App/Services/Discord/Bot/Commands/HelpCommand.cs
Normal file
21
Moonlight/App/Services/Discord/Bot/Commands/HelpCommand.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
130
Moonlight/App/Services/Discord/Bot/DiscordBotService.cs
Normal file
130
Moonlight/App/Services/Discord/Bot/DiscordBotService.cs
Normal 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
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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" />
|
||||||
|
|
|
@ -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());
|
||||||
|
|
Loading…
Reference in a new issue