diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/LoginController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/LoginController.cs index 66a0fdba..e5d0fba3 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/LoginController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/LoginController.cs @@ -138,7 +138,20 @@ public class LoginController : ControllerBase user.LinkedRpcnId = npTicket.Platform == Platform.RPCS3 ? npTicket.UserId : 0; user.LinkedPsnId = npTicket.Platform != Platform.RPCS3 ? npTicket.UserId : 0; await this.database.SaveChangesAsync(); - + + if (DiscordConfiguration.Instance.DiscordIntegrationEnabled) + { + string registrationAnnouncementMsg = DiscordConfiguration.Instance.RegistrationAnnouncement + .Replace("%user", username) + .Replace("%id", user.UserId.ToString()) + .Replace("%instance", ServerConfiguration.Instance.Customization.ServerName) + .Replace("%platform", npTicket.Platform.ToString()) + .Replace(@"\n", "\n"); + await WebhookHelper.SendWebhook(title: "A new user has registered!", + description: registrationAnnouncementMsg, + dest: WebhookHelper.WebhookDestination.Registration); + } + Logger.Success($"Created new user for {username}, platform={npTicket.Platform}", LogArea.Login); } // automatically change username if it doesn't match diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs index 0ffebd33..738d9794 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs @@ -139,7 +139,7 @@ public class PhotosController : ControllerBase Title = "New photo uploaded!", Description = $"{user.Username} uploaded a new photo.", ImageUrl = $"{ServerConfiguration.Instance.ExternalUrl}/gameAssets/{photo.LargeHash}", - Color = WebhookHelper.UnionColor, + Color = WebhookHelper.GetEmbedColor(), } ); diff --git a/ProjectLighthouse/Configuration/ConfigurationBase.cs b/ProjectLighthouse/Configuration/ConfigurationBase.cs index 009f247c..e1fdb8ff 100644 --- a/ProjectLighthouse/Configuration/ConfigurationBase.cs +++ b/ProjectLighthouse/Configuration/ConfigurationBase.cs @@ -117,7 +117,7 @@ public abstract class ConfigurationBase where T : class, new() { int newVersion = GetVersion(); Logger.Info($"Upgrading config file from version {storedConfig.ConfigVersion} to version {newVersion}", LogArea.Config); - File.Copy(this.ConfigName, this.ConfigName + "." + GetVersion()); + File.Copy(this.ConfigName, this.ConfigName + ".v" + storedConfig.ConfigVersion); this.loadConfig(storedConfig); this.ConfigVersion = newVersion; this.writeConfig(this.ConfigName); diff --git a/ProjectLighthouse/Configuration/ConfigurationCategories/DiscordIntegrationConfiguration.cs b/ProjectLighthouse/Configuration/ConfigurationCategories/DiscordIntegrationConfiguration.cs deleted file mode 100644 index 1454338d..00000000 --- a/ProjectLighthouse/Configuration/ConfigurationCategories/DiscordIntegrationConfiguration.cs +++ /dev/null @@ -1,13 +0,0 @@ -#nullable enable -namespace LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories; - -public class DiscordIntegrationConfiguration -{ - //TODO: integrations should be modular/abstracted away - - public bool DiscordIntegrationEnabled { get; set; } - - public string Url { get; set; } = ""; - - public string ModerationUrl { get; set; } = ""; -} \ No newline at end of file diff --git a/ProjectLighthouse/Configuration/DiscordConfiguration.cs b/ProjectLighthouse/Configuration/DiscordConfiguration.cs new file mode 100644 index 00000000..d6e07d62 --- /dev/null +++ b/ProjectLighthouse/Configuration/DiscordConfiguration.cs @@ -0,0 +1,34 @@ +using YamlDotNet.Serialization; + +namespace LBPUnion.ProjectLighthouse.Configuration; + +public class DiscordConfiguration : ConfigurationBase +{ + // HEY, YOU! + // THIS VALUE MUST BE INCREMENTED FOR EVERY CONFIG CHANGE! + // + // This is so Lighthouse can properly identify outdated configurations and update them with newer settings accordingly. + // If you are modifying anything here, this value MUST be incremented. + // Thanks for listening~ + public override int ConfigVersion { get; set; } = 1; + + public override string ConfigName { get; set; } = "discord.yml"; + + public override bool NeedsConfiguration { get; set; } = false; + + // TODO integrations should be more modular + + public bool DiscordIntegrationEnabled { get; set; } = false; + + public string EmbedColor { get; set; } = "#008CFF"; + + public string PublicUrl { get; set; } = ""; + + public string ModerationUrl { get; set; } = ""; + + public string RegistrationUrl { get; set; } = ""; + + public string RegistrationAnnouncement { get; set; } = "%user just connected to %instance for the first time using %platform!"; + + public override ConfigurationBase Deserialize(IDeserializer deserializer, string text) => deserializer.Deserialize(text); +} \ No newline at end of file diff --git a/ProjectLighthouse/Configuration/ServerConfiguration.cs b/ProjectLighthouse/Configuration/ServerConfiguration.cs index 8e174108..c0bf07e9 100644 --- a/ProjectLighthouse/Configuration/ServerConfiguration.cs +++ b/ProjectLighthouse/Configuration/ServerConfiguration.cs @@ -11,7 +11,7 @@ public class ServerConfiguration : ConfigurationBase // This is so Lighthouse can properly identify outdated configurations and update them with newer settings accordingly. // If you are modifying anything here, this value MUST be incremented. // Thanks for listening~ - public override int ConfigVersion { get; set; } = 18; + public override int ConfigVersion { get; set; } = 19; public override string ConfigName { get; set; } = "lighthouse.yml"; public string WebsiteListenUrl { get; set; } = "http://localhost:10060"; @@ -34,7 +34,6 @@ public class ServerConfiguration : ConfigurationBase public AuthenticationConfiguration Authentication { get; set; } = new(); public CaptchaConfiguration Captcha { get; set; } = new(); public DigestKeyConfiguration DigestKey { get; set; } = new(); - public DiscordIntegrationConfiguration DiscordIntegration { get; set; } = new(); public GoogleAnalyticsConfiguration GoogleAnalytics { get; set; } = new(); public MailConfiguration Mail { get; set; } = new(); public UserGeneratedContentLimitConfiguration UserGeneratedContentLimits { get; set; } = new(); diff --git a/ProjectLighthouse/Helpers/WebhookHelper.cs b/ProjectLighthouse/Helpers/WebhookHelper.cs index afa52f9c..38365e3a 100644 --- a/ProjectLighthouse/Helpers/WebhookHelper.cs +++ b/ProjectLighthouse/Helpers/WebhookHelper.cs @@ -3,6 +3,9 @@ using System.Threading.Tasks; using Discord; using Discord.Webhook; using LBPUnion.ProjectLighthouse.Configuration; +using SixLabors.ImageSharp.PixelFormats; +using Color = SixLabors.ImageSharp.Color; +using DiscordColor = Discord.Color; namespace LBPUnion.ProjectLighthouse.Helpers; @@ -21,31 +24,52 @@ public static class WebhookHelper /// A channel intended for moderators; where grief reports are sent. /// Moderation, + /// + /// A channel intended for public viewing; specifically for announcing user registrations + /// + Registration, } - - private static readonly DiscordWebhookClient publicClient = ServerConfiguration.Instance.DiscordIntegration.DiscordIntegrationEnabled - ? new DiscordWebhookClient(ServerConfiguration.Instance.DiscordIntegration.Url) + + private static bool isDestinationValid(WebhookDestination dest) + { + if (!DiscordConfiguration.Instance.DiscordIntegrationEnabled) return false; + string url = dest switch + { + WebhookDestination.Public => DiscordConfiguration.Instance.PublicUrl, + WebhookDestination.Moderation => DiscordConfiguration.Instance.ModerationUrl, + WebhookDestination.Registration => DiscordConfiguration.Instance.RegistrationUrl, + _ => throw new ArgumentOutOfRangeException(nameof(dest), dest, null), + }; + return !string.IsNullOrWhiteSpace(url); + } + + private static readonly DiscordWebhookClient publicClient = isDestinationValid(WebhookDestination.Public) + ? new DiscordWebhookClient(DiscordConfiguration.Instance.PublicUrl) : null; - private static readonly DiscordWebhookClient moderationClient = ServerConfiguration.Instance.DiscordIntegration.DiscordIntegrationEnabled - ? new DiscordWebhookClient(ServerConfiguration.Instance.DiscordIntegration.ModerationUrl) + private static readonly DiscordWebhookClient moderationClient = isDestinationValid(WebhookDestination.Moderation) + ? new DiscordWebhookClient(DiscordConfiguration.Instance.ModerationUrl) : null; - public static readonly Color UnionColor = new(0, 140, 255); + private static readonly DiscordWebhookClient registrationClient = isDestinationValid(WebhookDestination.Registration) + ? new DiscordWebhookClient(DiscordConfiguration.Instance.RegistrationUrl) + : null; public static Task SendWebhook(EmbedBuilder builder, WebhookDestination dest = WebhookDestination.Public) => SendWebhook(builder.Build(), dest); public static async Task SendWebhook(Embed embed, WebhookDestination dest = WebhookDestination.Public) { - if (!ServerConfiguration.Instance.DiscordIntegration.DiscordIntegrationEnabled) return; + if (!DiscordConfiguration.Instance.DiscordIntegrationEnabled) return; DiscordWebhookClient client = dest switch { WebhookDestination.Public => publicClient, WebhookDestination.Moderation => moderationClient, + WebhookDestination.Registration => registrationClient, _ => throw new ArgumentOutOfRangeException(nameof(dest), dest, null), }; + if (client == null) return; await client.SendMessageAsync ( @@ -56,6 +80,13 @@ public static class WebhookHelper ); } + public static DiscordColor GetEmbedColor() + { + Color embedColor = Color.ParseHex(DiscordConfiguration.Instance.EmbedColor); + Rgb24 pixel = embedColor.ToPixel(); + return new DiscordColor(pixel.R, pixel.G, pixel.B); + } + public static Task SendWebhook(string title, string description, WebhookDestination dest = WebhookDestination.Public) => SendWebhook ( @@ -63,7 +94,7 @@ public static class WebhookHelper { Title = title, Description = description, - Color = UnionColor, + Color = GetEmbedColor(), }, dest );