diff --git a/DiscordBot/MessageHandler/MessageHandler.cs b/DiscordBot/MessageHandler/MessageHandler.cs index f57a69a..caa3c6b 100644 --- a/DiscordBot/MessageHandler/MessageHandler.cs +++ b/DiscordBot/MessageHandler/MessageHandler.cs @@ -4,10 +4,10 @@ using Microsoft.Extensions.DependencyInjection; using OpenShock.DiscordBot.OpenShockDiscordDb; using OpenShock.DiscordBot.Services; +using OpenShock.DiscordBot.Utils; using OpenShock.SDK.CSharp.Models; -using System.Text.RegularExpressions; -namespace OpenShock.DiscordBot.MessageHandler; +namespace OpenShock.DiscordBot; public sealed partial class MessageHandler { @@ -39,7 +39,8 @@ public async Task HandleMessageAsync(SocketMessage message) bool isInBotChannel = message.Channel.Id == 1114123393567047730; - if (isInBotChannel && message.Content.StartsWith("debug ")) { + if (isInBotChannel && message.Content.StartsWith("debug ")) + { await message.Channel.SendMessageAsync($"Message received: ``{message.Content[6..]}``"); } @@ -67,7 +68,7 @@ public async Task HandleMessageAsync(SocketMessage message) if (isInBotChannel) await message.Channel.SendMessageAsync("Profanity detected, but cant shock you, register and/or enable it"); return; } - + // If the channel is a bot channel, respond with debug message if (isInBotChannel) await message.Channel.SendMessageAsync($"Profanity detected! {count} bad {(count > 1 ? "words" : "word")}, shocking at {intensityPercent:F0}%"); diff --git a/DiscordBot/OpenShockDiscordBot.cs b/DiscordBot/OpenShockDiscordBot.cs deleted file mode 100644 index d4ac4a1..0000000 --- a/DiscordBot/OpenShockDiscordBot.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System.Reflection; -using Discord; -using Discord.Interactions; -using Discord.WebSocket; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using OpenShock.DiscordBot.MessageHandler; -using OpenShock.DiscordBot.OpenShockDiscordDb; -using OpenShock.DiscordBot.Services; -using OpenShock.DiscordBot.Services.UserRepository; -using OpenShock.DiscordBot.Utils; -using Serilog; - -namespace OpenShock.DiscordBot; - -public class OpenShockDiscordBot -{ - public static ILogger Logger = null!; - - public static async Task Main(string[] args) - { - HostBuilder builder = new(); - - builder.UseContentRoot(Directory.GetCurrentDirectory()) - .ConfigureHostConfiguration(config => - { - config.AddEnvironmentVariables(prefix: "DOTNET_"); - if (args is { Length: > 0 }) config.AddCommandLine(args); - }) - .ConfigureAppConfiguration((context, config) => - { - config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false) - .AddJsonFile("appsettings.Custom.json", optional: true, reloadOnChange: false) - .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true, - reloadOnChange: false); - - config.AddEnvironmentVariables(); - if (args is { Length: > 0 }) config.AddCommandLine(args); - }) - .UseDefaultServiceProvider((context, options) => - { - var isDevelopment = context.HostingEnvironment.IsDevelopment(); - options.ValidateScopes = isDevelopment; - options.ValidateOnBuild = isDevelopment; - }) - .UseSerilog((context, _, config) => { config.ReadFrom.Configuration(context.Configuration); }); - - // <---- Services ----> - - builder.ConfigureServices((context, services) => - { - var discordBotConfig = context.Configuration.GetSection("bot").Get() ?? - throw new Exception("Could not load bot config"); - - services.AddSingleton(discordBotConfig); - - services.AddDbContextPool(x => - { - x.UseNpgsql(discordBotConfig.Db.Conn); - - // ReSharper disable once InvertIf - if (discordBotConfig.Db.Debug) - { - x.EnableDetailedErrors(); - x.EnableSensitiveDataLogging(); - } - }); - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton(new DiscordSocketClient(new DiscordSocketConfig - { - GatewayIntents = GatewayIntents.AllUnprivileged | - GatewayIntents.MessageContent - })); - services.AddSingleton(x => - new InteractionService(x.GetRequiredService())); - services.AddSingleton(); - - services.AddHostedService(); - }); - - try - { - var host = builder.Build(); - Logger = host.Services.GetRequiredService>(); - Logger.LogInformation("Starting OpenShock Discord Bot version {Version}", - Assembly.GetEntryAssembly()?.GetName().Version?.ToString()); - - var config = host.Services.GetRequiredService(); - - // <---- DATABASE MIGRATION ----> - - if (!config.Db.SkipMigration) - { - Logger.LogInformation("Running database migrations..."); - using var scope = host.Services.CreateScope(); - var openShockContext = scope.ServiceProvider.GetRequiredService(); - var pendingMigrations = (await openShockContext.Database.GetPendingMigrationsAsync()).ToList(); - - if (pendingMigrations.Count > 0) - { - Logger.LogInformation("Found pending migrations, applying [{@Migrations}]", pendingMigrations); - await openShockContext.Database.MigrateAsync(); - Logger.LogInformation("Applied database migrations... proceeding with startup"); - } - else Logger.LogInformation("No pending migrations found, proceeding with startup"); - } - else Logger.LogWarning("Skipping possible database migrations..."); - - // <---- Initialize Service stuff, this also instantiates the singletons!!! ----> - - var client = host.Services.GetRequiredService(); - var interactionService = host.Services.GetRequiredService(); - var interactionHandler = host.Services.GetRequiredService(); - var messageHandler = host.Services.GetRequiredService(); - - client.Log += LoggingUtils.LogAsync; - client.Ready += () => ReadyAsync(client, interactionService); - - client.MessageReceived += messageHandler.HandleMessageAsync; - - interactionService.Log += LoggingUtils.LogAsync; - - await interactionHandler.InitializeAsync(); - - // <---- Run discord client ----> - - await client.LoginAsync(TokenType.Bot, config.Token); - await client.StartAsync(); - - await host.RunAsync(); - } - catch (Exception e) - { - Console.WriteLine(e); - } - } - - private static async Task ReadyAsync(BaseSocketClient client, InteractionService interactionService) - { - Logger.LogInformation("Connected as [{CurrentUser}]", client.CurrentUser.Username); - await client.SetActivityAsync( - new Game($"electricity flow, v{Assembly.GetEntryAssembly()?.GetName().Version?.ToString()}", - ActivityType.Watching)); - - await interactionService.RegisterCommandsGloballyAsync(); - } -} \ No newline at end of file diff --git a/DiscordBot/Program.cs b/DiscordBot/Program.cs new file mode 100644 index 0000000..6f52a1b --- /dev/null +++ b/DiscordBot/Program.cs @@ -0,0 +1,143 @@ +using Discord; +using Discord.Interactions; +using Discord.WebSocket; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using OpenShock.DiscordBot; +using OpenShock.DiscordBot.OpenShockDiscordDb; +using OpenShock.DiscordBot.Services; +using OpenShock.DiscordBot.Services.UserRepository; +using OpenShock.DiscordBot.Utils; +using Serilog; +using System.Reflection; + +HostBuilder builder = new(); + +builder.UseContentRoot(Directory.GetCurrentDirectory()) + .ConfigureHostConfiguration(config => + { + config.AddEnvironmentVariables(prefix: "DOTNET_"); + if (args is { Length: > 0 }) config.AddCommandLine(args); + }) + .ConfigureAppConfiguration((context, config) => + { + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false) + .AddJsonFile("appsettings.Custom.json", optional: true, reloadOnChange: false) + .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true, + reloadOnChange: false); + + config.AddEnvironmentVariables(); + if (args is { Length: > 0 }) config.AddCommandLine(args); + }) + .UseDefaultServiceProvider((context, options) => + { + var isDevelopment = context.HostingEnvironment.IsDevelopment(); + options.ValidateScopes = isDevelopment; + options.ValidateOnBuild = isDevelopment; + }) + .UseSerilog((context, _, config) => { config.ReadFrom.Configuration(context.Configuration); }); + +// <---- Services ----> + +builder.ConfigureServices((context, services) => +{ + var discordBotConfig = context.Configuration.GetSection("bot").Get() ?? + throw new Exception("Could not load bot config"); + + services.AddSingleton(discordBotConfig); + + services.AddDbContextPool(x => + { + x.UseNpgsql(discordBotConfig.Db.Conn); + + // ReSharper disable once InvertIf + if (discordBotConfig.Db.Debug) + { + x.EnableDetailedErrors(); + x.EnableSensitiveDataLogging(); + } + }); + + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + services.AddSingleton(new DiscordSocketClient(new DiscordSocketConfig + { + GatewayIntents = GatewayIntents.AllUnprivileged | + GatewayIntents.MessageContent + })); + services.AddSingleton(x => + new InteractionService(x.GetRequiredService())); + services.AddSingleton(); + + services.AddHostedService(); +}); + +try +{ + var host = builder.Build(); + var logger = host.Services.GetRequiredService>(); + logger.LogInformation("Starting OpenShock Discord Bot version {Version}", Assembly.GetEntryAssembly()?.GetName().Version?.ToString()); + + var config = host.Services.GetRequiredService(); + + // <---- DATABASE MIGRATION ----> + + if (!config.Db.SkipMigration) + { + logger.LogInformation("Running database migrations..."); + using var scope = host.Services.CreateScope(); + var openShockContext = scope.ServiceProvider.GetRequiredService(); + var pendingMigrations = (await openShockContext.Database.GetPendingMigrationsAsync()).ToList(); + + if (pendingMigrations.Count > 0) + { + logger.LogInformation("Found pending migrations, applying [{@Migrations}]", pendingMigrations); + await openShockContext.Database.MigrateAsync(); + logger.LogInformation("Applied database migrations... proceeding with startup"); + } + else logger.LogInformation("No pending migrations found, proceeding with startup"); + } + else logger.LogWarning("Skipping possible database migrations..."); + + // <---- Initialize Service stuff, this also instantiates the singletons!!! ----> + + var client = host.Services.GetRequiredService(); + var interactionService = host.Services.GetRequiredService(); + var interactionHandler = host.Services.GetRequiredService(); + var messageHandler = host.Services.GetRequiredService(); + + client.Log += LoggingUtils.LogAsync; + client.Ready += () => ReadyAsync(client, interactionService); + + client.MessageReceived += messageHandler.HandleMessageAsync; + + interactionService.Log += LoggingUtils.LogAsync; + + await interactionHandler.InitializeAsync(); + + // <---- Run discord client ----> + + await client.LoginAsync(TokenType.Bot, config.Token); + await client.StartAsync(); + + await host.RunAsync(); +} +catch (Exception e) +{ + Console.WriteLine(e); +} + +static async Task ReadyAsync(BaseSocketClient client, InteractionService interactionService) +{ + Log.Information("Connected as [{CurrentUser}]", client.CurrentUser.Username); + await client.SetActivityAsync( + new Game($"electricity flow, v{Assembly.GetEntryAssembly()?.GetName().Version?.ToString()}", + ActivityType.Watching)); + + await interactionService.RegisterCommandsGloballyAsync(); +} \ No newline at end of file diff --git a/DiscordBot/Utils/ProfanityDetector.cs b/DiscordBot/Utils/ProfanityDetector.cs index a600f7a..e683947 100644 --- a/DiscordBot/Utils/ProfanityDetector.cs +++ b/DiscordBot/Utils/ProfanityDetector.cs @@ -1,6 +1,6 @@ using System.Buffers; -namespace OpenShock.DiscordBot.MessageHandler; +namespace OpenShock.DiscordBot.Utils; public static class ProfanityDetector {