ProjectMakoto/ProjectMakoto/Commands/Configuration/ReactionRolesCommand/ConfigCommand.cs

372 lines
No EOL
21 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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.ReactionRolesCommand;
internal sealed class ConfigCommand : BaseCommand
{
public override Task<bool> BeforeExecution(SharedCommandContext ctx) => this.CheckAdmin();
public override Task ExecuteCommand(SharedCommandContext ctx, Dictionary<string, object> arguments)
{
return Task.Run(async () =>
{
var CommandKey = this.t.Commands.Config.ReactionRoles;
if (await ctx.DbUser.Cooldown.WaitForLight(ctx))
return;
_ = await this.RespondOrEdit(new DiscordEmbedBuilder
{
Description = this.GetString(CommandKey.LoadingReactionRoles, true)
}.AsLoading(ctx, this.GetString(CommandKey.Title)));
_ = await ReactionRolesCommandAbstractions.CheckForInvalid(ctx);
var AddButton = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), this.GetString(CommandKey.AddNewReactionRole), (ctx.DbGuild.ReactionRoles.Length > 100), new DiscordComponentEmoji(DiscordEmoji.FromUnicode("")));
var RemoveButton = new DiscordButtonComponent(ButtonStyle.Danger, Guid.NewGuid().ToString(), this.GetString(CommandKey.RemoveReactionRole), (ctx.DbGuild.ReactionRoles.Length == 0), new DiscordComponentEmoji(DiscordEmoji.FromUnicode("✖")));
var embed = new DiscordEmbedBuilder
{
Description = this.GetString(CommandKey.ReactionRoleCount, true, new TVar("Count", ctx.DbGuild.ReactionRoles.Length))
}.AsAwaitingInput(ctx, this.GetString(CommandKey.Title));
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(embed)
.AddComponents(new List<DiscordComponent>
{
AddButton, RemoveButton
})
.AddComponents(MessageComponents.GetCancelButton(ctx.DbUser, ctx.Bot)));
var e = await ctx.WaitForButtonAsync(TimeSpan.FromMinutes(2));
if (e.TimedOut)
{
this.ModifyToTimedOut(true);
return;
}
_ = e.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
if (e.GetCustomId() == AddButton.CustomId)
{
DiscordMessage selectedMessage = null;
DiscordEmoji selectedEmoji = null;
DiscordRole selectedRole = null;
while (true)
{
var SelectMessage = new DiscordButtonComponent((selectedMessage is null ? ButtonStyle.Primary : ButtonStyle.Secondary), Guid.NewGuid().ToString(), this.GetString(CommandKey.SelectMessage), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("💬")));
var SelectEmoji = new DiscordButtonComponent((selectedEmoji is null ? ButtonStyle.Primary : ButtonStyle.Secondary), Guid.NewGuid().ToString(), this.GetString(CommandKey.SelectEmoji), (selectedMessage is null), new DiscordComponentEmoji(DiscordEmoji.FromUnicode("😀")));
var SelectRole = new DiscordButtonComponent((selectedRole is null ? ButtonStyle.Primary : ButtonStyle.Secondary), Guid.NewGuid().ToString(), this.GetString(CommandKey.SelectRole), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("👤")));
var Finish = new DiscordButtonComponent(ButtonStyle.Success, Guid.NewGuid().ToString(), this.GetString(this.t.Common.Submit), (selectedMessage is null || selectedRole is null || selectedEmoji is null), new DiscordComponentEmoji(DiscordEmoji.FromUnicode("✅")));
var pad = TranslationUtil.CalculatePadding(ctx.DbUser, CommandKey.Message, CommandKey.Emoji, CommandKey.Role);
var action_embed = new DiscordEmbedBuilder
{
Description = $"`{this.GetString(CommandKey.Message).PadRight(pad)}`: {(selectedMessage is null ? this.GetString(this.t.Common.NotSelected, true) : $"[`{this.GetString(this.t.Common.JumpToMessage)}`]({selectedMessage.JumpLink})")}\n" +
$"`{this.GetString(CommandKey.Emoji).PadRight(pad)}`: {(selectedEmoji is null ? this.GetString(this.t.Common.NotSelected, true) : selectedEmoji.ToString())}\n" +
$"`{this.GetString(CommandKey.Role).PadRight(pad)}`: {(selectedRole is null ? this.GetString(this.t.Common.NotSelected, true) : selectedRole.Mention)}"
}.AsAwaitingInput(ctx, this.GetString(CommandKey.Title));
if (ctx.DbGuild.ReactionRoles.Length > 100)
{
action_embed.Description = this.GetString(CommandKey.ReactionRoleLimitReached, true);
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(5000);
await this.ExecuteCommand(ctx, arguments);
return;
}
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed)
.AddComponents(new List<DiscordComponent> { SelectMessage, SelectEmoji, SelectRole, Finish })
.AddComponents(MessageComponents.GetCancelButton(ctx.DbUser, ctx.Bot)));
var Menu = await ctx.WaitForButtonAsync();
if (Menu.TimedOut)
{
this.ModifyToTimedOut();
return;
}
if (Menu.GetCustomId() == SelectMessage.CustomId)
{
var modal = new DiscordInteractionModalBuilder(this.GetString(CommandKey.Title), Guid.NewGuid().ToString())
.AddTextComponent(new DiscordTextComponent(TextComponentStyle.Small, "url", this.GetString(CommandKey.MessageUrl), "https://discord.com/channels/012345678901234567/012345678901234567/012345678912345678", null, null, true));
var ModalResult = await this.PromptModalWithRetry(Menu.Result.Interaction, modal, new DiscordEmbedBuilder
{
Description = this.GetString(CommandKey.MessageUrlInstructions, true),
ImageUrl = "https://cdn.discordapp.com/attachments/906976602557145110/967753175241203712/unknown.png"
}.AsAwaitingInput(ctx, this.GetString(CommandKey.Title)), false);
if (ModalResult.TimedOut)
{
this.ModifyToTimedOut(true);
return;
}
else if (ModalResult.Cancelled)
{
continue;
}
else if (ModalResult.Errored)
{
throw ModalResult.Exception;
}
var url = ModalResult.Result.Interaction.GetModalValueByCustomId("url");
if (!RegexTemplates.DiscordChannelUrl.IsMatch(url) || !url.TryParseMessageLink(out var GuildId, out var ChannelId, out var MessageId))
{
action_embed.Description = $"{this.GetString(CommandKey.InvalidMessageUrl, true)}\n" +
$"`https://discord.com/channels/012345678901234567/012345678901234567/012345678912345678`\n" +
$"`https://ptb.discord.com/channels/012345678901234567/012345678901234567/012345678912345678`\n" +
$"`https://canary.discord.com/channels/012345678901234567/012345678901234567/012345678912345678`";
action_embed.ImageUrl = "";
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(3000);
continue;
}
if (GuildId != ctx.Guild.Id)
{
action_embed.Description = this.GetString(CommandKey.MessageUrlWrongGuild, true);
action_embed.ImageUrl = "";
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(3000);
continue;
}
if (!ctx.Guild.Channels.ContainsKey(ChannelId))
{
action_embed.Description = this.GetString(CommandKey.MessageUrlNoChannel, true);
action_embed.ImageUrl = "";
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(3000);
continue;
}
var channel = ctx.Guild.GetChannel(ChannelId);
if (!channel.TryGetMessage(MessageId, out var reactionMessage))
{
action_embed.Description = this.GetString(CommandKey.MessageUrlNoMessage, true);
action_embed.ImageUrl = "";
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(3000);
continue;
}
selectedMessage = reactionMessage;
continue;
}
else if (Menu.GetCustomId() == SelectEmoji.CustomId)
{
_ = Menu.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
action_embed.Description = this.GetString(CommandKey.ReactWithEmoji, true);
action_embed.ImageUrl = "";
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsAwaitingInput(ctx, this.GetString(CommandKey.Title))));
var emoji_wait = await ctx.Client.GetInteractivity().WaitForReactionAsync(x => x.Channel.Id == ctx.Channel.Id && x.User.Id == ctx.User.Id && x.Message.Id == selectedMessage.Id, TimeSpan.FromMinutes(2));
if (emoji_wait.TimedOut)
{
this.ModifyToTimedOut(true);
return;
}
try
{ _ = emoji_wait.Result.Message.DeleteReactionAsync(emoji_wait.Result.Emoji, ctx.User); }
catch { }
var emoji = emoji_wait.Result.Emoji;
if (emoji.Id != 0 && !ctx.Guild.Emojis.ContainsKey(emoji.Id))
{
action_embed.Description = this.GetString(CommandKey.NoAccessToEmoji, true);
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(3000);
continue;
}
if (ctx.DbGuild.ReactionRoles.Any(x => (x.MessageId == selectedMessage.Id && x.EmojiName == emoji.GetUniqueDiscordName())))
{
action_embed.Description = this.GetString(CommandKey.EmojiAlreadyUsed, true);
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(3000);
continue;
}
selectedEmoji = emoji;
continue;
}
else if (Menu.GetCustomId() == SelectRole.CustomId)
{
_ = Menu.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
_ = await this.RespondOrEdit(action_embed.WithDescription(this.GetString(CommandKey.SelectRolePrompt, true)).AsAwaitingInput(ctx, this.GetString(CommandKey.Title)));
var RoleResult = await this.PromptRoleSelection();
if (RoleResult.TimedOut)
{
this.ModifyToTimedOut(true);
return;
}
else if (RoleResult.Cancelled)
{
continue;
}
else if (RoleResult.Failed)
{
if (RoleResult.Exception.GetType() == typeof(NullReferenceException))
{
_ = await this.RespondOrEdit(new DiscordEmbedBuilder().AsError(ctx).WithDescription(this.GetString(CommandKey.NoRoles, true)));
await Task.Delay(3000);
continue;
}
throw RoleResult.Exception;
}
if (ctx.DbGuild.ReactionRoles.Any(x => x.RoleId == RoleResult.Result.Id))
{
action_embed.Description = this.GetString(CommandKey.RoleAlreadyUsed, true);
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(3000);
continue;
}
selectedRole = RoleResult.Result;
continue;
}
else if (Menu.GetCustomId() == Finish.CustomId)
{
_ = Menu.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
if (ctx.DbGuild.ReactionRoles.Length > 100)
{
action_embed.Description = this.GetString(CommandKey.ReactionRoleLimitReached, true);
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(5000);
await this.ExecuteCommand(ctx, arguments);
return;
}
if (ctx.DbGuild.ReactionRoles.Any(x => x.RoleId == selectedRole.Id))
{
action_embed.Description = this.GetString(CommandKey.RoleAlreadyUsed, true);
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(5000);
await this.ExecuteCommand(ctx, arguments);
return;
}
if (selectedEmoji.Id != 0 && !ctx.Guild.Emojis.ContainsKey(selectedEmoji.Id))
{
action_embed.Description = this.GetString(CommandKey.NoAccessToEmoji, true);
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(5000);
await this.ExecuteCommand(ctx, arguments);
return;
}
if (ctx.DbGuild.ReactionRoles.Any(x => (x.MessageId == selectedMessage.Id && x.EmojiName == selectedEmoji.GetUniqueDiscordName())))
{
action_embed.Description = this.GetString(CommandKey.EmojiAlreadyUsed, true);
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(5000);
await this.ExecuteCommand(ctx, arguments);
return;
}
ctx.DbGuild.ReactionRoles = ctx.DbGuild.ReactionRoles.Add(new()
{
ChannelId = selectedMessage.Channel.Id,
RoleId = selectedRole.Id,
EmojiId = selectedEmoji.Id,
EmojiName = selectedEmoji.GetUniqueDiscordName(),
MessageId = selectedMessage.Id
});
await selectedMessage.CreateReactionAsync(selectedEmoji);
embed.Description = this.GetString(CommandKey.AddedReactionRole, true,
new TVar("Role", selectedRole.Mention),
new TVar("User", selectedMessage.Author.Mention),
new TVar("Channel", selectedMessage.Channel.Mention),
new TVar("Emoji", selectedEmoji));
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsSuccess(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(5000);
await this.ExecuteCommand(ctx, arguments);
return;
}
else if (Menu.GetCustomId() == MessageComponents.CancelButtonId)
{
_ = Menu.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
await this.ExecuteCommand(ctx, arguments);
return;
}
return;
}
}
else if (e.GetCustomId() == RemoveButton.CustomId)
{
var RoleResult = await this.PromptCustomSelection(ctx.DbGuild.ReactionRoles
.Select(x => new DiscordStringSelectComponentOption($"@{ctx.Guild.GetRole(x.RoleId).Name}", x.UUID, $"in Channel #{ctx.Guild.GetChannel(x.ChannelId).Name}", emoji: new DiscordComponentEmoji(x.GetEmoji(ctx.Client)))).ToList());
if (RoleResult.TimedOut)
{
this.ModifyToTimedOut(true);
return;
}
else if (RoleResult.Cancelled)
{
await this.ExecuteCommand(ctx, arguments);
return;
}
else if (RoleResult.Errored)
{
throw RoleResult.Exception;
}
var obj = ctx.DbGuild.ReactionRoles.First(x => x.UUID == RoleResult.Result);
if (ctx.Guild.GetChannel(obj.ChannelId).TryGetMessage(obj.MessageId, out var reactionMessage))
_ = reactionMessage.DeleteReactionsEmojiAsync(obj.GetEmoji(ctx.Client));
var role = ctx.Guild.GetRole(obj.RoleId);
ctx.DbGuild.ReactionRoles = ctx.DbGuild.ReactionRoles.Remove(x => x.MessageId.ToString(), obj);
embed.Description = this.GetString(CommandKey.RemovedReactionRole, true,
new TVar("Role", role.Mention),
new TVar("User", reactionMessage?.Author.Mention ?? "`/`"),
new TVar("Channel", reactionMessage?.Channel.Mention ?? "`/`"),
new TVar("Emoji", obj.GetEmoji(ctx.Client)));
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(embed.AsSuccess(ctx, this.GetString(CommandKey.Title))));
await Task.Delay(5000);
await this.ExecuteCommand(ctx, arguments);
return;
}
else if (e.GetCustomId() == MessageComponents.CancelButtonId)
{
this.DeleteOrInvalidate();
return;
}
});
}
}