diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs b/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs index 1399a6b..40efde4 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs @@ -280,7 +280,7 @@ internal class DiscordBot : IHostedService + "You can handle all of your Mare account needs in this server through the easy to use interactive bot prompt. Just follow the instructions!"); eb.WithThumbnailUrl("https://raw.githubusercontent.com/Penumbra-Sync/repo/main/MareSynchronos/images/icon.png"); var cb = new ComponentBuilder(); - cb.WithButton("Start", style: ButtonStyle.Primary, customId: "wizard-home:true", emote: Emoji.Parse("➡️")); + cb.WithButton("Start", style: ButtonStyle.Primary, customId: "wizard-captcha:true", emote: Emoji.Parse("➡️")); if (prevMessage == null) { var msg = await channel.SendMessageAsync(embed: eb.Build(), components: cb.Build()).ConfigureAwait(false); diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBotServices.cs b/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBotServices.cs index 5a73b34..6caa263 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBotServices.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBotServices.cs @@ -16,6 +16,7 @@ public class DiscordBotServices public ConcurrentDictionary LastVanityGidChange = new(); public ConcurrentDictionary ValidInteractions { get; } = new(); public Dictionary VanityRoles { get; set; } = new(); + public ConcurrentBag VerifiedCaptchaUsers { get; } = new(); private readonly IServiceProvider _serviceProvider; private readonly IConfigurationService _configuration; private CancellationTokenSource verificationTaskCts; diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Register.cs b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Register.cs index 4f27f6f..4d297a6 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Register.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Register.cs @@ -145,7 +145,7 @@ public partial class MareWizardModule eb.WithTitle("Failed to verify registration"); eb.WithDescription("The bot was not able to find the required verification code on your Lodestone profile." + Environment.NewLine + Environment.NewLine + "Please restart your verification process, make sure to save your profile _twice_ for it to be properly saved." + Environment.NewLine + Environment.NewLine - + "**Make sure your profile is set to public (All Users) for your character. The bot cannot read logged in or private profiles.**" + Environment.NewLine + Environment.NewLine + + "**Make sure your profile is set to public (All Users) for your character. The bot cannot read profiles with privacy settings set to \"logged in\" or \"private\".**" + Environment.NewLine + Environment.NewLine + "The code the bot is looking for is" + Environment.NewLine + Environment.NewLine + "**" + verificationCode + "**"); cb.WithButton("Cancel", "wizard-register", emote: new Emoji("❌")); diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Relink.cs b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Relink.cs index 4ead563..16bdae8 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Relink.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Relink.cs @@ -137,6 +137,7 @@ public partial class MareWizardModule eb.WithTitle("Failed to verify relink"); eb.WithDescription("The bot was not able to find the required verification code on your Lodestone profile." + Environment.NewLine + Environment.NewLine + "Please restart your relink process, make sure to save your profile _twice_ for it to be properly saved." + Environment.NewLine + Environment.NewLine + + "**Make sure your profile is set to public (All Users) for your character. The bot cannot read profiles with privacy settings set to \"logged in\" or \"private\".**" + Environment.NewLine + Environment.NewLine + "The code the bot is looking for is**" + Environment.NewLine + Environment.NewLine + "**" + verificationCode + "**"); cb.WithButton("Cancel", "wizard-relink", emote: new Emoji("❌")); diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.cs b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.cs index 4865d48..d572c96 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.cs @@ -35,12 +35,84 @@ public partial class MareWizardModule : InteractionModuleBase _connectionMultiplexer = connectionMultiplexer; } + [ComponentInteraction("wizard-captcha:*")] + public async Task WizardCaptcha(bool init = false) + { + if (!init && !(await ValidateInteraction().ConfigureAwait(false))) return; + + if (_botServices.VerifiedCaptchaUsers.Contains(Context.Interaction.User.Id)) + { + await StartWizard(true).ConfigureAwait(false); + return; + } + + EmbedBuilder eb = new(); + + Random rnd = new Random(); + var correctButton = rnd.Next(4) + 1; + string nthButtonText = correctButton switch + { + 1 => "first", + 2 => "second", + 3 => "third", + 4 => "fourth", + _ => "unknown", + }; + + eb.WithTitle("Mare Bot Services Captcha"); + eb.WithDescription("You are seeing this embed because you interact with this bot for the first time since the bot has been restarted." + Environment.NewLine + Environment.NewLine + + "This bot __requires__ embeds for its function. To proceed, please verify you have embeds enabled." + Environment.NewLine + Environment.NewLine + + $"To verify you have embeds enabled __press on the **{nthButtonText}** ({correctButton}) button.__"); + eb.WithColor(Color.LightOrange); + + ComponentBuilder cb = new(); + cb.WithButton("This", correctButton == 1 ? "wizard-home:false" : "wizard-captcha-fail:1", emote: new Emoji("⬅️")); + cb.WithButton("Bot", correctButton == 2 ? "wizard-home:false" : "wizard-captcha-fail:2", emote: new Emoji("🤖")); + cb.WithButton("Requires", correctButton == 3 ? "wizard-home:false" : "wizard-captcha-fail:3", emote: new Emoji("‼️")); + cb.WithButton("Embeds", correctButton == 4 ? "wizard-home:false" : "wizard-captcha-fail:4", emote: new Emoji("✉️")); + + await InitOrUpdateInteraction(init, eb, cb).ConfigureAwait(false); + } + + private async Task InitOrUpdateInteraction(bool init, EmbedBuilder eb, ComponentBuilder cb) + { + if (init) + { + await RespondAsync(embed: eb.Build(), components: cb.Build(), ephemeral: true).ConfigureAwait(false); + var resp = await GetOriginalResponseAsync().ConfigureAwait(false); + _botServices.ValidInteractions[Context.User.Id] = resp.Id; + _logger.LogInformation("Init Msg: {id}", resp.Id); + } + else + { + await ModifyInteraction(eb, cb).ConfigureAwait(false); + } + } + + [ComponentInteraction("wizard-captcha-fail:*")] + public async Task WizardCaptchaFail(int button) + { + ComponentBuilder cb = new(); + cb.WithButton("Restart (with Embeds enabled)", "wizard-captcha:false", emote: new Emoji("↩️")); + await ((Context.Interaction) as IComponentInteraction).UpdateAsync(m => + { + m.Embed = null; + m.Content = "You pressed the wrong button. You likely have embeds disabled. Enable embeds in your Discord client (Settings -> Chat -> \"Show embeds and preview website links pasted into chat\") and try again."; + m.Components = cb.Build(); + }).ConfigureAwait(false); + + await _botServices.LogToChannel($"{Context.User.Mention} FAILED CAPTCHA").ConfigureAwait(false); + } + [ComponentInteraction("wizard-home:*")] public async Task StartWizard(bool init = false) { if (!init && !(await ValidateInteraction().ConfigureAwait(false))) return; + if (!_botServices.VerifiedCaptchaUsers.Contains(Context.Interaction.User.Id)) + _botServices.VerifiedCaptchaUsers.Add(Context.Interaction.User.Id); + _logger.LogInformation("{method}:{userId}", nameof(StartWizard), Context.Interaction.User.Id); using var mareDb = GetDbContext(); @@ -97,17 +169,8 @@ public partial class MareWizardModule : InteractionModuleBase } cb.WithButton("Delete", "wizard-delete", ButtonStyle.Danger, new Emoji("⚠️")); } - if (init) - { - await RespondAsync(embed: eb.Build(), components: cb.Build(), ephemeral: true).ConfigureAwait(false); - var resp = await GetOriginalResponseAsync().ConfigureAwait(false); - _botServices.ValidInteractions[Context.User.Id] = resp.Id; - _logger.LogInformation("Init Msg: {id}", resp.Id); - } - else - { - await ModifyInteraction(eb, cb).ConfigureAwait(false); - } + + await InitOrUpdateInteraction(init, eb, cb).ConfigureAwait(false); } public class VanityUidModal : IModal @@ -180,6 +243,7 @@ public partial class MareWizardModule : InteractionModuleBase { await ((Context.Interaction) as IComponentInteraction).UpdateAsync(m => { + m.Content = null; m.Embed = eb.Build(); m.Components = cb.Build(); }).ConfigureAwait(false);