460 lines
No EOL
24 KiB
C#
460 lines
No EOL
24 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.Configuration;
|
||
|
||
internal sealed class LevelRewardsCommand : 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.LevelRewards;
|
||
|
||
#pragma warning disable CS8321 // Local function is declared but never used
|
||
string GetCurrentConfiguration(SharedCommandContext ctx)
|
||
{
|
||
var CommandKey = ctx.Bot.LoadedTranslations.Commands.Config.LevelRewards;
|
||
|
||
var str = "";
|
||
if (ctx.DbGuild.LevelRewards.Length != 0)
|
||
{
|
||
foreach (var b in ctx.DbGuild.LevelRewards.OrderBy(x => x.Level))
|
||
{
|
||
if (!ctx.Guild.Roles.ContainsKey(b.RoleId))
|
||
{
|
||
ctx.DbGuild.LevelRewards = ctx.DbGuild.LevelRewards.Remove(x => x.RoleId.ToString(), b);
|
||
continue;
|
||
}
|
||
|
||
str += $"**{ctx.BaseCommand.GetString(CommandKey.Level)}**: `{b.Level}`\n" +
|
||
$"**{ctx.BaseCommand.GetString(CommandKey.Role)}**: <@&{b.RoleId}> (`{b.RoleId}`)\n" +
|
||
$"**{ctx.BaseCommand.GetString(CommandKey.Message)}**: `{b.Message}`\n";
|
||
|
||
str += "\n\n";
|
||
}
|
||
}
|
||
else
|
||
{
|
||
str = ctx.BaseCommand.GetString(CommandKey.NoRewardsSetup, true);
|
||
}
|
||
|
||
return str;
|
||
}
|
||
#pragma warning restore CS8321 // Local function is declared but never used
|
||
|
||
if (await ctx.DbUser.Cooldown.WaitForLight(ctx))
|
||
return;
|
||
|
||
var CurrentPage = 0;
|
||
|
||
var embed = new DiscordEmbedBuilder()
|
||
{
|
||
Description = this.GetString(CommandKey.Loading, true)
|
||
}.AsLoading(ctx, this.GetString(CommandKey.Title));
|
||
|
||
_ = await this.RespondOrEdit(embed);
|
||
|
||
embed = embed.AsAwaitingInput(ctx, this.GetString(CommandKey.Title));
|
||
|
||
var selected = "";
|
||
|
||
async Task RefreshMessage()
|
||
{
|
||
List<DiscordStringSelectComponentOption> DefinedRewards = new();
|
||
|
||
embed.Description = "";
|
||
|
||
foreach (var reward in ctx.DbGuild.LevelRewards.ToList().OrderBy(x => x.Level))
|
||
{
|
||
if (!ctx.Guild.Roles.ContainsKey(reward.RoleId))
|
||
{
|
||
ctx.DbGuild.LevelRewards = ctx.DbGuild.LevelRewards.Remove(x => x.RoleId.ToString(), reward);
|
||
continue;
|
||
}
|
||
|
||
var role = ctx.Guild.GetRole(reward.RoleId);
|
||
|
||
DefinedRewards.Add(new DiscordStringSelectComponentOption($"{this.GetString(CommandKey.Level)} {reward.Level}: @{role.Name}", role.Id.ToString(), $"{reward.Message.TruncateWithIndication(100)}", (selected == role.Id.ToString()), new DiscordComponentEmoji(role.Color.GetClosestColorEmoji(ctx.Client))));
|
||
|
||
if (selected == role.Id.ToString())
|
||
{
|
||
embed.Description = $"**{this.GetString(CommandKey.Level)}**: `{reward.Level}`\n" +
|
||
$"**{this.GetString(CommandKey.Role)}**: <@&{reward.RoleId}> (`{reward.RoleId}`)\n" +
|
||
$"**{this.GetString(CommandKey.Message)}**: `{reward.Message}`\n";
|
||
}
|
||
}
|
||
|
||
if (DefinedRewards.Count > 0)
|
||
{
|
||
if (embed.Description == "")
|
||
embed.Description = this.GetString(CommandKey.SelectPrompt, true);
|
||
}
|
||
else
|
||
{
|
||
embed.Description = this.GetString(CommandKey.NoRewardsSetup, true);
|
||
}
|
||
|
||
var PreviousPage = new DiscordButtonComponent(ButtonStyle.Primary, "PreviousPage", this.GetString(this.t.Common.PreviousPage), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("◀")));
|
||
var NextPage = new DiscordButtonComponent(ButtonStyle.Primary, "NextPage", this.GetString(this.t.Common.NextPage), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("▶")));
|
||
|
||
var Add = new DiscordButtonComponent(ButtonStyle.Success, "Add", this.GetString(CommandKey.AddNewButton), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("➕")));
|
||
var Modify = new DiscordButtonComponent(ButtonStyle.Primary, "Modify", this.GetString(CommandKey.ModifyButton), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("🔄")));
|
||
var Delete = new DiscordButtonComponent(ButtonStyle.Danger, "Delete", this.GetString(CommandKey.RemoveButton), false, new DiscordComponentEmoji(DiscordEmoji.FromGuildEmote(ctx.Client, 1005430134070841395)));
|
||
|
||
var Dropdown = new DiscordStringSelectComponent(this.GetString(CommandKey.SelectDropdown), DefinedRewards.Skip(CurrentPage * 20).Take(20).ToList(), "RewardSelection");
|
||
embed = embed.AsAwaitingInput(ctx, this.GetString(CommandKey.Title));
|
||
var builder = new DiscordMessageBuilder().AddEmbed(embed);
|
||
|
||
if (DefinedRewards.Count > 0)
|
||
_ = builder.AddComponents(Dropdown);
|
||
|
||
List<DiscordComponent> Row1 = new();
|
||
List<DiscordComponent> Row2 = new();
|
||
|
||
if (DefinedRewards.Skip(CurrentPage * 20).Count() > 20)
|
||
Row1.Add(NextPage);
|
||
|
||
if (CurrentPage != 0)
|
||
Row1.Add(PreviousPage);
|
||
|
||
Row2.Add(Add);
|
||
|
||
if (selected != "")
|
||
{
|
||
Row2.Add(Modify);
|
||
Row2.Add(Delete);
|
||
}
|
||
|
||
if (Row1.Count > 0)
|
||
_ = builder.AddComponents(Row1);
|
||
|
||
_ = builder.AddComponents(Row2);
|
||
|
||
_ = builder.AddComponents(MessageComponents.GetCancelButton(ctx.DbUser, ctx.Bot));
|
||
|
||
_ = await this.RespondOrEdit(builder);
|
||
}
|
||
|
||
CancellationTokenSource cancellationTokenSource = new();
|
||
|
||
async Task SelectInteraction(DiscordClient s, ComponentInteractionCreateEventArgs e)
|
||
{
|
||
_ = Task.Run(async () =>
|
||
{
|
||
if (e.Message?.Id == ctx.ResponseMessage.Id && e.User.Id == ctx.User.Id)
|
||
{
|
||
cancellationTokenSource.Cancel();
|
||
cancellationTokenSource = new();
|
||
|
||
_ = Task.Delay(120000, cancellationTokenSource.Token).ContinueWith(x =>
|
||
{
|
||
if (x.IsCompletedSuccessfully)
|
||
{
|
||
ctx.Client.ComponentInteractionCreated -= SelectInteraction;
|
||
this.ModifyToTimedOut(true);
|
||
}
|
||
});
|
||
|
||
if (e.GetCustomId() == "RewardSelection")
|
||
{
|
||
_ = e.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
|
||
|
||
selected = e.Values.First();
|
||
await RefreshMessage();
|
||
}
|
||
else if (e.GetCustomId() == "Add")
|
||
{
|
||
ctx.Client.ComponentInteractionCreated -= SelectInteraction;
|
||
_ = e.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
|
||
|
||
DiscordRole selectedRole = null;
|
||
var selectedLevel = -1;
|
||
var selectedCustomText = this.GetGuildString(CommandKey.DefaultCustomText);
|
||
|
||
while (true)
|
||
{
|
||
var SelectRole = new DiscordButtonComponent((selectedRole is null ? ButtonStyle.Primary : ButtonStyle.Secondary), Guid.NewGuid().ToString(), this.GetString(CommandKey.SelectRoleButton), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("👤")));
|
||
var SelectLevel = new DiscordButtonComponent((selectedLevel is -1 ? ButtonStyle.Primary : ButtonStyle.Secondary), Guid.NewGuid().ToString(), this.GetString(CommandKey.SelectLevelButton), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("✨")));
|
||
var SelectCustomText = new DiscordButtonComponent((selectedCustomText.IsNullOrWhiteSpace() ? ButtonStyle.Primary : ButtonStyle.Secondary), Guid.NewGuid().ToString(), this.GetString(CommandKey.ChangeMessageButton), false, new DiscordComponentEmoji(DiscordEmoji.FromUnicode("🗯")));
|
||
var Finish = new DiscordButtonComponent(ButtonStyle.Success, Guid.NewGuid().ToString(), this.GetString(this.t.Common.Submit), (selectedRole is null || selectedLevel is -1 || selectedCustomText.IsNullOrWhiteSpace()), new DiscordComponentEmoji(DiscordEmoji.FromUnicode("✅")));
|
||
|
||
var pad = TranslationUtil.CalculatePadding(ctx.DbUser, CommandKey.Role, CommandKey.Level, CommandKey.Message);
|
||
|
||
var action_embed = new DiscordEmbedBuilder
|
||
{
|
||
Description = $"`{this.GetString(CommandKey.Role).PadRight(pad)}`: {(selectedRole is null ? this.GetString(this.t.Common.NotSelected, true) : selectedRole.Mention)}\n" +
|
||
$"`{this.GetString(CommandKey.Level).PadRight(pad)}`: {(selectedLevel is -1 ? this.GetString(this.t.Common.NotSelected, true) : selectedLevel.ToEmotes())}\n" +
|
||
$"`{this.GetString(CommandKey.Message).PadRight(pad)}`: `{selectedCustomText}`"
|
||
}.AsAwaitingInput(ctx, this.GetString(CommandKey.Title));
|
||
|
||
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed)
|
||
.AddComponents(new List<DiscordComponent> { SelectRole, SelectLevel, SelectCustomText, Finish })
|
||
.AddComponents(MessageComponents.GetCancelButton(ctx.DbUser, ctx.Bot)));
|
||
|
||
var Menu = await ctx.WaitForButtonAsync();
|
||
|
||
if (Menu.TimedOut)
|
||
{
|
||
this.ModifyToTimedOut();
|
||
return;
|
||
}
|
||
|
||
if (Menu.GetCustomId() == SelectRole.CustomId)
|
||
{
|
||
_ = Menu.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
|
||
|
||
var RoleResult = await this.PromptRoleSelection();
|
||
|
||
if (RoleResult.TimedOut)
|
||
{
|
||
this.ModifyToTimedOut();
|
||
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(this.t.Commands.Common.Errors.NoRoles, true)));
|
||
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);
|
||
continue;
|
||
}
|
||
|
||
selectedRole = RoleResult.Result;
|
||
continue;
|
||
}
|
||
else if (Menu.GetCustomId() == SelectLevel.CustomId)
|
||
{
|
||
var modal = new DiscordInteractionModalBuilder(this.GetString(CommandKey.Title), Guid.NewGuid().ToString())
|
||
.AddTextComponent(new DiscordTextComponent(TextComponentStyle.Small, "level", this.GetString(CommandKey.Level), "2", 1, 3, true, (selectedLevel is -1 ? 2 : selectedLevel).ToString()));
|
||
|
||
|
||
var ModalResult = await this.PromptModalWithRetry(Menu.Result.Interaction, modal, false);
|
||
|
||
if (ModalResult.TimedOut)
|
||
{
|
||
this.ModifyToTimedOut(true);
|
||
return;
|
||
}
|
||
else if (ModalResult.Cancelled)
|
||
{
|
||
continue;
|
||
}
|
||
else if (ModalResult.Errored)
|
||
{
|
||
throw ModalResult.Exception;
|
||
}
|
||
|
||
InteractionCreateEventArgs Response = ModalResult.Result;
|
||
var rawInt = Response.Interaction.GetModalValueByCustomId("level");
|
||
|
||
uint level;
|
||
|
||
try
|
||
{
|
||
level = Convert.ToUInt32(rawInt);
|
||
|
||
if (level < 2)
|
||
throw new Exception("");
|
||
}
|
||
catch (Exception)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
selectedLevel = (int)level;
|
||
continue;
|
||
}
|
||
else if (Menu.GetCustomId() == SelectCustomText.CustomId)
|
||
{
|
||
var modal = new DiscordInteractionModalBuilder(this.GetString(CommandKey.Title), Guid.NewGuid().ToString())
|
||
.AddTextComponent(new DiscordTextComponent(TextComponentStyle.Small, "message", this.GetString(CommandKey.Message), this.GetGuildString(CommandKey.DefaultCustomText), 1, 256, true, selectedCustomText));
|
||
|
||
|
||
var ModalResult = await this.PromptModalWithRetry(Menu.Result.Interaction, modal, false);
|
||
|
||
if (ModalResult.TimedOut)
|
||
{
|
||
this.ModifyToTimedOut(true);
|
||
return;
|
||
}
|
||
else if (ModalResult.Cancelled)
|
||
{
|
||
continue;
|
||
}
|
||
else if (ModalResult.Errored)
|
||
{
|
||
throw ModalResult.Exception;
|
||
}
|
||
|
||
InteractionCreateEventArgs Response = ModalResult.Result;
|
||
|
||
var newMessage = Response.Interaction.GetModalValueByCustomId("message");
|
||
|
||
if (newMessage.Length > 256)
|
||
{
|
||
action_embed.Description = this.GetString(CommandKey.MessageTooLong, true);
|
||
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsError(ctx, this.GetString(CommandKey.Title))));
|
||
await Task.Delay(3000);
|
||
continue;
|
||
}
|
||
|
||
selectedCustomText = newMessage;
|
||
continue;
|
||
}
|
||
else if (Menu.GetCustomId() == Finish.CustomId)
|
||
{
|
||
if (selectedRole.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.LevelRewards = ctx.DbGuild.LevelRewards.Add(new()
|
||
{
|
||
Level = selectedLevel,
|
||
RoleId = selectedRole.Id,
|
||
Message = selectedCustomText
|
||
});
|
||
|
||
action_embed.Description = this.GetString(CommandKey.AddedNewReward, true, new TVar("Role", $"<@&{selectedRole.Id}>"), new TVar("Level", selectedLevel));
|
||
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(action_embed.AsSuccess(ctx, this.GetString(CommandKey.Title))));
|
||
|
||
await Task.Delay(5000);
|
||
await RefreshMessage();
|
||
ctx.Client.ComponentInteractionCreated += SelectInteraction;
|
||
return;
|
||
}
|
||
else if (Menu.GetCustomId() == MessageComponents.CancelButtonId)
|
||
{
|
||
_ = Menu.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
|
||
|
||
await RefreshMessage();
|
||
ctx.Client.ComponentInteractionCreated += SelectInteraction;
|
||
return;
|
||
}
|
||
|
||
return;
|
||
}
|
||
}
|
||
else if (e.GetCustomId() == "Modify")
|
||
{
|
||
var modal = new DiscordInteractionModalBuilder()
|
||
.WithTitle(this.GetString(CommandKey.Title))
|
||
.WithCustomId(Guid.NewGuid().ToString())
|
||
.AddTextComponents(new DiscordTextComponent(TextComponentStyle.Small, "new_text", this.GetString(CommandKey.Message), null, 0, 256, false, ctx.DbGuild.LevelRewards.First(x => x.RoleId == Convert.ToUInt64(selected)).Message));
|
||
;
|
||
|
||
var ModalResult = await this.PromptModalWithRetry(e.Interaction, modal, false);
|
||
|
||
if (ModalResult.TimedOut)
|
||
{
|
||
this.ModifyToTimedOut(true);
|
||
return;
|
||
}
|
||
else if (ModalResult.Cancelled)
|
||
{
|
||
await RefreshMessage();
|
||
return;
|
||
}
|
||
else if (ModalResult.Errored)
|
||
{
|
||
throw ModalResult.Exception;
|
||
}
|
||
|
||
InteractionCreateEventArgs Response = ModalResult.Result;
|
||
var result = Response.Interaction.GetModalValueByCustomId("new_text");
|
||
|
||
if (result.Length > 256)
|
||
{
|
||
_ = await this.RespondOrEdit(new DiscordMessageBuilder().AddEmbed(embed.WithDescription(this.GetString(CommandKey.MessageTooLong, true)).AsError(ctx, this.GetString(CommandKey.Title))));
|
||
await Task.Delay(5000);
|
||
await this.ExecuteCommand(ctx, arguments);
|
||
return;
|
||
}
|
||
|
||
ctx.DbGuild.LevelRewards.First(x => x.RoleId == Convert.ToUInt64(selected)).Message = result;
|
||
|
||
await RefreshMessage();
|
||
}
|
||
else if (e.GetCustomId() == "Delete")
|
||
{
|
||
_ = e.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
|
||
|
||
ctx.DbGuild.LevelRewards = ctx.DbGuild.LevelRewards.Remove(x => x.RoleId.ToString(), ctx.DbGuild.LevelRewards.First(x => x.RoleId == Convert.ToUInt64(selected)));
|
||
|
||
if (ctx.DbGuild.LevelRewards.Length == 0)
|
||
{
|
||
await this.ExecuteCommand(ctx, arguments);
|
||
return;
|
||
}
|
||
|
||
embed.Description = this.GetString(CommandKey.SelectPrompt, true);
|
||
selected = "";
|
||
|
||
await RefreshMessage();
|
||
}
|
||
else if (e.GetCustomId() == "PreviousPage")
|
||
{
|
||
_ = e.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
|
||
|
||
CurrentPage--;
|
||
await RefreshMessage();
|
||
}
|
||
else if (e.GetCustomId() == "NextPage")
|
||
{
|
||
_ = e.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
|
||
|
||
CurrentPage++;
|
||
await RefreshMessage();
|
||
}
|
||
else if (e.GetCustomId() == MessageComponents.CancelButtonId)
|
||
{
|
||
_ = e.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
|
||
|
||
this.DeleteOrInvalidate();
|
||
return;
|
||
}
|
||
}
|
||
}).Add(ctx.Bot, ctx);
|
||
}
|
||
|
||
await RefreshMessage();
|
||
|
||
_ = Task.Delay(120000, cancellationTokenSource.Token).ContinueWith(x =>
|
||
{
|
||
if (x.IsCompletedSuccessfully)
|
||
{
|
||
ctx.Client.ComponentInteractionCreated -= SelectInteraction;
|
||
this.ModifyToTimedOut(true);
|
||
}
|
||
});
|
||
|
||
ctx.Client.ComponentInteractionCreated += SelectInteraction;
|
||
});
|
||
}
|
||
} |