// Project Makoto // Copyright (C) 2024 Fortunevale // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY namespace ProjectMakoto.Commands.Configuration; internal sealed class JoinCommand : BaseCommand { public override Task BeforeExecution(SharedCommandContext ctx) => this.CheckAdmin(); public override Task ExecuteCommand(SharedCommandContext ctx, Dictionary arguments) { return Task.Run(async () => { var CommandKey = this.t.Commands.Config.Join; string GetCurrentConfiguration(SharedCommandContext ctx) { var CommandKey = ctx.Bot.LoadedTranslations.Commands.Config.Join; var pad = TranslationUtil.CalculatePadding(ctx.DbUser, CommandKey.Autoban, CommandKey.JoinLogChannel, CommandKey.UserCountChannel, CommandKey.UserCountChannelFormat, CommandKey.Role, CommandKey.ReApplyRoles, CommandKey.ReApplyNickname, CommandKey.AutoKickSpammer, CommandKey.AutoKickNewAccounts, CommandKey.AutoKickNoRoles); return $"{"🌐".UnicodeToEmoji()} `{CommandKey.Autoban.Get(ctx.DbUser).PadRight(pad)}`: {ctx.DbGuild.Join.AutoBanGlobalBans.ToEmote(ctx.Bot)}\n" + $"{"👋".UnicodeToEmoji()} `{CommandKey.JoinLogChannel.Get(ctx.DbUser).PadRight(pad)}`: {(ctx.DbGuild.Join.JoinlogChannelId != 0 ? $"<#{ctx.DbGuild.Join.JoinlogChannelId}>" : false.ToEmote(ctx.Bot))}\n" + $"{"🔢".UnicodeToEmoji()} `{CommandKey.UserCountChannel.Get(ctx.DbUser).PadRight(pad)}`: {(ctx.DbGuild.Join.UserCountChannelId != 0 ? $"<#{ctx.DbGuild.Join.UserCountChannelId}> (`{(ctx.DbGuild.Join.UserCountChannelFormat is not null ? ctx.DbGuild.Join.UserCountChannelFormat : "Users: %s")}`)" : false.ToEmote(ctx.Bot))}\n" + $"{"👤".UnicodeToEmoji()} `{CommandKey.Role.Get(ctx.DbUser).PadRight(pad)}`: {(ctx.DbGuild.Join.AutoAssignRoleId != 0 ? $"<@&{ctx.DbGuild.Join.AutoAssignRoleId}>" : false.ToEmote(ctx.Bot))}\n" + $"{"👥".UnicodeToEmoji()} `{CommandKey.ReApplyRoles.Get(ctx.DbUser).PadRight(pad)}`: {ctx.DbGuild.Join.ReApplyRoles.ToEmote(ctx.Bot)}\n" + $"{"💬".UnicodeToEmoji()} `{CommandKey.ReApplyNickname.Get(ctx.DbUser).PadRight(pad)}`: {ctx.DbGuild.Join.ReApplyNickname.ToEmote(ctx.Bot)}\n\n" + $"{"⚠️".UnicodeToEmoji()} `{CommandKey.AutoKickSpammer.Get(ctx.DbUser).PadRight(pad)}`: {ctx.DbGuild.Join.AutoKickSpammer.ToEmote(ctx.Bot)}\n" + $"{"🕒".UnicodeToEmoji()} `{CommandKey.AutoKickNewAccounts.Get(ctx.DbUser).PadRight(pad)}`: {(ctx.DbGuild.Join.AutoKickAccountAge == TimeSpan.Zero ? false.ToEmote(ctx.Bot) : $"`{ctx.DbGuild.Join.AutoKickAccountAge.GetHumanReadable(TimeFormat.Days, TranslationUtil.GetTranslatedHumanReadableConfig(ctx.DbUser, ctx.Bot))}`")}\n" + $"{"📝".UnicodeToEmoji()} `{CommandKey.AutoKickNoRoles.Get(ctx.DbUser).PadRight(pad)}`: {(ctx.DbGuild.Join.AutoKickNoRoleTime == TimeSpan.Zero ? false.ToEmote(ctx.Bot) : $"`{ctx.DbGuild.Join.AutoKickNoRoleTime.GetHumanReadable(TimeFormat.Minutes, TranslationUtil.GetTranslatedHumanReadableConfig(ctx.DbUser, ctx.Bot))}`")}\n\n" + $"{CommandKey.SecurityNotice.Get(ctx.DbUser).Build(true, new TVar("Permissions", string.Join(", ", Resources.ProtectedPermissions.Select(x => $"{x.ToTranslatedPermissionString(ctx.DbUser, ctx.Bot)}"))))}\n\n" + $"{CommandKey.TimeNotice.Get(ctx.DbUser).Build()}"; } if (await ctx.DbUser.Cooldown.WaitForLight(ctx)) return; var embed = new DiscordEmbedBuilder() { Description = GetCurrentConfiguration(ctx) }.AsAwaitingInput(ctx, this.GetString(CommandKey.Title)); var builder = new DiscordMessageBuilder().AddEmbed(embed); var ToggleGlobalban = new DiscordButtonComponent((ctx.DbGuild.Join.AutoBanGlobalBans ? ButtonStyle.Danger : ButtonStyle.Success), Guid.NewGuid().ToString(), this.GetString(CommandKey.ToggleGlobalBansButton), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("🌐"))); var ChangeJoinlogChannel = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), this.GetString(CommandKey.ChangeJoinlogChannelButton), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("👋"))); var ChangeUserCountChannel = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), this.GetString(CommandKey.ChangeUserCountChannel), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("🔢"))); var ChangeUserCountFormat = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), this.GetString(CommandKey.ChangeUserCountChannelFormat), ctx.DbGuild.Join.UserCountChannelId == 0, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("🔢"))); var ChangeRoleOnJoin = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), this.GetString(CommandKey.ChangeRoleButton), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("👤"))); var ToggleReApplyRoles = new DiscordButtonComponent((ctx.DbGuild.Join.ReApplyRoles ? ButtonStyle.Danger : ButtonStyle.Success), Guid.NewGuid().ToString(), this.GetString(CommandKey.ToggleReApplyRole), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("👥"))); var ToggleReApplyName = new DiscordButtonComponent((ctx.DbGuild.Join.ReApplyNickname ? ButtonStyle.Danger : ButtonStyle.Success), Guid.NewGuid().ToString(), this.GetString(CommandKey.ToggleReApplyNickname), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("💬"))); var ToggleAutoKickSpammer = new DiscordButtonComponent((ctx.DbGuild.Join.AutoKickSpammer ? ButtonStyle.Danger : ButtonStyle.Success), Guid.NewGuid().ToString(), this.GetString(CommandKey.ToggleAutoKickSpammer), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("⚠️"))); var ChangeAutoKickNewAccounts = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), this.GetString(CommandKey.ChangeAutoKickNewAccounts), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("🕒"))); var ChangeAutoKickNoRoles = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), this.GetString(CommandKey.ChangeAutoKickNoRoles), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("📝"))); _ = await this.RespondOrEdit(builder .AddComponents(new List { ToggleGlobalban, ToggleReApplyRoles, ToggleReApplyName, }) .AddComponents(new List { ChangeJoinlogChannel, ChangeRoleOnJoin, ChangeUserCountChannel, ChangeUserCountFormat, }) .AddComponents(new List { ToggleAutoKickSpammer, ChangeAutoKickNewAccounts, ChangeAutoKickNoRoles, }) .AddComponents(MessageComponents.GetCancelButton(ctx.DbUser, ctx.Bot))); var e = await ctx.WaitForButtonAsync(TimeSpan.FromMinutes(2)); if (e.TimedOut) { this.ModifyToTimedOut(true); return; } if (e.GetCustomId() != ChangeUserCountFormat.CustomId) _ = e.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate); if (e.GetCustomId() == ToggleGlobalban.CustomId) { ctx.DbGuild.Join.AutoBanGlobalBans = !ctx.DbGuild.Join.AutoBanGlobalBans; await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ToggleReApplyRoles.CustomId) { ctx.DbGuild.Join.ReApplyRoles = !ctx.DbGuild.Join.ReApplyRoles; await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ToggleReApplyName.CustomId) { ctx.DbGuild.Join.ReApplyNickname = !ctx.DbGuild.Join.ReApplyNickname; await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ChangeJoinlogChannel.CustomId) { var ChannelResult = await this.PromptChannelSelection(ChannelType.Text, new ChannelPromptConfiguration { CreateChannelOption = new() { Name = this.GetString(CommandKey.JoinLogChannelName), ChannelType = ChannelType.Text }, DisableOption = this.GetString(CommandKey.DisableJoinlog) }); if (ChannelResult.TimedOut) { this.ModifyToTimedOut(true); return; } else if (ChannelResult.Cancelled) { await this.ExecuteCommand(ctx, arguments); return; } else if (ChannelResult.Failed) { if (ChannelResult.Exception.GetType() == typeof(NullReferenceException)) { _ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsError(ctx).WithDescription(this.GetString(this.t.Commands.Common.Errors.NoChannels))); await Task.Delay(3000); await this.ExecuteCommand(ctx, arguments); return; } throw ChannelResult.Exception; } ctx.DbGuild.Join.JoinlogChannelId = ChannelResult.Result is null ? 0 : ChannelResult.Result.Id; await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ChangeUserCountChannel.CustomId) { var ChannelResult = await this.PromptChannelSelection(ChannelType.Text, new ChannelPromptConfiguration { CreateChannelOption = new() { Name = "tmp-usercount", ChannelType = ChannelType.Text }, DisableOption = this.GetString(CommandKey.DisableUserCountChannel) }); if (ChannelResult.TimedOut) { this.ModifyToTimedOut(true); return; } else if (ChannelResult.Cancelled) { await this.ExecuteCommand(ctx, arguments); return; } else if (ChannelResult.Failed) { if (ChannelResult.Exception.GetType() == typeof(NullReferenceException)) { _ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsError(ctx).WithDescription(this.GetString(this.t.Commands.Common.Errors.NoChannels))); await Task.Delay(3000); await this.ExecuteCommand(ctx, arguments); return; } throw ChannelResult.Exception; } ctx.DbGuild.Join.UserCountChannelId = ChannelResult.Result is null ? 0 : ChannelResult.Result.Id; if (ChannelResult.Result is not null) await JoinEvents.RunUserCountUpdater(ctx.Bot, ctx.Guild); await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ChangeUserCountFormat.CustomId) { var modelResult = await this.PromptModalWithRetry(e.Result.Interaction, new DiscordInteractionModalBuilder(this.GetString(CommandKey.ChangeUserCountChannelFormat)) .AddTextComponent(new DiscordTextComponent(TextComponentStyle.Small, "new_format", this.GetString(CommandKey.ChangeUserCountChannelFormatModal), null, 2, 16)), false); if (modelResult.TimedOut) { this.ModifyToTimedOut(true); return; } else if (modelResult.Cancelled) { await this.ExecuteCommand(ctx, arguments); return; } else if (modelResult.Failed) { if (modelResult.Exception.GetType() == typeof(NullReferenceException)) { _ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsError(ctx).WithDescription(this.GetString(this.t.Commands.Common.Errors.NoChannels))); await Task.Delay(3000); await this.ExecuteCommand(ctx, arguments); return; } throw modelResult.Exception; } ctx.DbGuild.Join.UserCountChannelFormat = modelResult.Result.Interaction.GetModalValueByCustomId("new_format"); if (ctx.DbGuild.Join.UserCountChannelId != 0) await JoinEvents.RunUserCountUpdater(ctx.Bot, ctx.Guild); await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ChangeRoleOnJoin.CustomId) { var RoleResult = await this.PromptRoleSelection(new RolePromptConfiguration { CreateRoleOption = this.GetString(CommandKey.AutoAssignRoleName), DisableOption = this.GetString(CommandKey.DisableRoleOnJoin) }); if (RoleResult.TimedOut) { this.ModifyToTimedOut(); return; } else if (RoleResult.Cancelled) { await this.ExecuteCommand(ctx, arguments); return; } else if (RoleResult.Failed) { if (RoleResult.Exception.GetType() == typeof(NullReferenceException)) { _ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsError(ctx).WithDescription(this.GetString(this.t.Commands.Common.Errors.NoRoles))); await Task.Delay(3000); return; } throw RoleResult.Exception; } if (RoleResult.Result?.Id == ctx.DbGuild.BumpReminder.RoleId) { _ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsError(ctx).WithDescription(this.GetString(CommandKey.CantUseRole, true))); await Task.Delay(3000); await this.ExecuteCommand(ctx, arguments); return; } ctx.DbGuild.Join.AutoAssignRoleId = RoleResult.Result is null ? 0 : RoleResult.Result.Id; await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ToggleAutoKickSpammer.CustomId) { ctx.DbGuild.Join.AutoKickSpammer = !ctx.DbGuild.Join.AutoKickSpammer; await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ChangeAutoKickNewAccounts.CustomId) { var TimeResult = await this.PromptForTimeSpan(TimeSpan.FromDays(30), TimeSpan.Zero, ctx.DbGuild.Join.AutoKickAccountAge); if (TimeResult.TimedOut) { this.ModifyToTimedOut(); return; } else if (TimeResult.Cancelled) { await this.ExecuteCommand(ctx, arguments); return; } else if (TimeResult.Failed) { if (TimeResult.Exception.GetType() == typeof(InvalidOperationException)) { _ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsError(ctx).WithDescription(this.GetString(CommandKey.AutoKickNewAccountsDurationLimit))); await Task.Delay(3000); return; } throw TimeResult.Exception; } ctx.DbGuild.Join.AutoKickAccountAge = TimeResult.Result; await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == ChangeAutoKickNoRoles.CustomId) { var TimeResult = await this.PromptForTimeSpan(TimeSpan.FromMinutes(30), TimeSpan.Zero, ctx.DbGuild.Join.AutoKickNoRoleTime); if (TimeResult.TimedOut) { this.ModifyToTimedOut(); return; } else if (TimeResult.Cancelled) { await this.ExecuteCommand(ctx, arguments); return; } else if (TimeResult.Failed) { if (TimeResult.Exception.GetType() == typeof(NullReferenceException)) { _ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsError(ctx).WithDescription(this.GetString(CommandKey.AutoKickNoRolesDurationLimit))); await Task.Delay(3000); return; } throw TimeResult.Exception; } if (TimeResult.Result < TimeSpan.FromMinutes(1) && TimeResult.Result != TimeSpan.Zero) { _ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsWarning(ctx).WithDescription($"{this.GetString(CommandKey.LowTimeWarning, true, new TVar("Time", TimeResult.Result.GetHumanReadable(TimeFormat.Minutes, TranslationUtil.GetTranslatedHumanReadableConfig(ctx.DbUser, ctx.Bot))))}\n\n" + $"{this.GetString(this.t.Commands.Moderation.CustomEmbed.ContinueTimer, true, new TVar("Timestamp", DateTime.UtcNow.AddSeconds(6).ToTimestamp()))}")); await Task.Delay(5000); } ctx.DbGuild.Join.AutoKickNoRoleTime = TimeResult.Result; await this.ExecuteCommand(ctx, arguments); return; } else if (e.GetCustomId() == MessageComponents.CancelButtonId) { this.DeleteOrInvalidate(); } }); } }