Finished implementing xp shop. It allows users to buy frames and backgrounds if the user enables the feature in data/xp.yml. It can also be available only to patrons

This commit is contained in:
Kwoth
2022-07-25 18:10:00 +02:00
parent 967784c860
commit 6a042c3faa
21 changed files with 10983 additions and 74 deletions

View File

@@ -1,4 +1,5 @@
using Nadeko.Common;
using NadekoBot.Modules.Xp;
namespace NadekoBot.Extensions;
@@ -193,14 +194,29 @@ public static class MessageChannelExtensions
private static readonly IEmote _arrowLeft = Emote.Parse("<:x:969658061805465651>");
private static readonly IEmote _arrowRight = Emote.Parse("<:x:969658062220701746>");
public static async Task SendPaginatedConfirmAsync(
public static Task SendPaginatedConfirmAsync(
this ICommandContext ctx,
int currentPage,
Func<int, Task<IEmbedBuilder>> pageFunc,
int totalElements,
int itemsPerPage,
bool addPaginatedFooter = true)
=> ctx.SendPaginatedConfirmAsync(currentPage,
pageFunc,
default(Func<int, ValueTask<SimpleInteraction<object>?>>),
totalElements,
itemsPerPage,
addPaginatedFooter);
public static async Task SendPaginatedConfirmAsync<T>(
this ICommandContext ctx,
int currentPage,
Func<int, Task<IEmbedBuilder>> pageFunc,
Func<int, ValueTask<SimpleInteraction<T>?>>? interFactory,
int totalElements,
int itemsPerPage,
bool addPaginatedFooter = true)
{
var lastPage = (totalElements - 1) / itemsPerPage;
@@ -209,70 +225,93 @@ public static class MessageChannelExtensions
if (addPaginatedFooter)
embed.AddPaginatedFooter(currentPage, lastPage);
var component = new ComponentBuilder()
.WithButton(new ButtonBuilder()
.WithStyle(ButtonStyle.Primary)
.WithCustomId(BUTTON_LEFT)
.WithDisabled(lastPage == 0)
.WithEmote(_arrowLeft))
.WithButton(new ButtonBuilder()
.WithStyle(ButtonStyle.Primary)
.WithCustomId(BUTTON_RIGHT)
.WithDisabled(lastPage == 0)
.WithEmote(_arrowRight))
.Build();
var msg = await ctx.Channel.SendAsync(null, embed: embed.Build(), components: component);
Task OnInteractionAsync(SocketInteraction si)
SimpleInteraction<T>? maybeInter = null;
async Task<ComponentBuilder> GetComponentBuilder()
{
_ = Task.Run(async () =>
var cb = new ComponentBuilder();
cb.WithButton(new ButtonBuilder()
.WithStyle(ButtonStyle.Primary)
.WithCustomId(BUTTON_LEFT)
.WithDisabled(lastPage == 0)
.WithEmote(_arrowLeft)
.WithDisabled(currentPage <= 0));
if (interFactory is not null)
{
try
{
if (si is not SocketMessageComponent smc)
return;
maybeInter = await interFactory(currentPage);
if (smc.Message.Id != msg.Id)
return;
if (maybeInter is not null)
cb.WithButton(maybeInter.Button);
}
if (smc.Data.CustomId != BUTTON_LEFT && smc.Data.CustomId != BUTTON_RIGHT)
return;
cb.WithButton(new ButtonBuilder()
.WithStyle(ButtonStyle.Primary)
.WithCustomId(BUTTON_RIGHT)
.WithDisabled(lastPage == 0 || currentPage >= lastPage)
.WithEmote(_arrowRight));
await si.DeferAsync();
if (smc.User.Id != ctx.User.Id)
return;
return cb;
}
if (smc.Data.CustomId == BUTTON_LEFT)
{
if (currentPage == 0)
return;
async Task UpdatePageAsync(SocketMessageComponent smc)
{
var toSend = await pageFunc(currentPage);
if (addPaginatedFooter)
toSend.AddPaginatedFooter(currentPage, lastPage);
var component = (await GetComponentBuilder()).Build();
var toSend = await pageFunc(--currentPage);
if (addPaginatedFooter)
toSend.AddPaginatedFooter(currentPage, lastPage);
await smc.ModifyOriginalResponseAsync(x => x.Embed = toSend.Build());
}
else if (smc.Data.CustomId == BUTTON_RIGHT)
{
if (lastPage > currentPage)
{
var toSend = await pageFunc(++currentPage);
if (addPaginatedFooter)
toSend.AddPaginatedFooter(currentPage, lastPage);
await smc.ModifyOriginalResponseAsync(x => x.Embed = toSend.Build());
}
}
}
catch (Exception ex)
{
Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message);
}
await smc.ModifyOriginalResponseAsync(x =>
{
x.Embed = toSend.Build();
x.Components = component;
});
}
var component = (await GetComponentBuilder()).Build();
var msg = await ctx.Channel.SendAsync(null, embed: embed.Build(), components: component);
return Task.CompletedTask;
async Task OnInteractionAsync(SocketInteraction si)
{
try
{
if (si is not SocketMessageComponent smc)
return;
if (smc.Message.Id != msg.Id)
return;
await si.DeferAsync();
if (smc.User.Id != ctx.User.Id)
return;
if (smc.Data.CustomId == BUTTON_LEFT)
{
if (currentPage == 0)
return;
--currentPage;
_ = UpdatePageAsync(smc);
}
else if (smc.Data.CustomId == BUTTON_RIGHT)
{
if (currentPage >= lastPage)
return;
++currentPage;
_ = UpdatePageAsync(smc);
}
else if (maybeInter is { } inter && inter.Button.CustomId == smc.Data.CustomId)
{
await inter.TriggerAsync(smc);
_ = UpdatePageAsync(smc);
}
}
catch (Exception ex)
{
Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message);
}
}
if (lastPage == 0)