372 lines
No EOL
21 KiB
C#
372 lines
No EOL
21 KiB
C#
// 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;
|
||
}
|
||
});
|
||
}
|
||
} |