mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
fix: Fixed .h not working on some commands
add: Added select menu for the .mdls command dev: Reworked the way interactions are created and sent. It is much better but far from perfect
This commit is contained in:
@@ -12,7 +12,7 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
|||||||
private TypedKey<KeepReport> _keepReportKey = new("cleanup:report");
|
private TypedKey<KeepReport> _keepReportKey = new("cleanup:report");
|
||||||
private TypedKey<bool> _keepTriggerKey = new("cleanup:trigger");
|
private TypedKey<bool> _keepTriggerKey = new("cleanup:trigger");
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private ConcurrentDictionary<int, ulong[]> guildIds;
|
private ConcurrentDictionary<int, ulong[]> guildIds = new();
|
||||||
private readonly IBotCredsProvider _creds;
|
private readonly IBotCredsProvider _creds;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
|
@@ -68,9 +68,9 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
public async Task ExprAdd(string key, [Leftover] string message)
|
public async Task ExprAdd(string trigger, [Leftover] string response)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key))
|
if (string.IsNullOrWhiteSpace(response) || string.IsNullOrWhiteSpace(trigger))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ExprAddInternalAsync(key, message);
|
await ExprAddInternalAsync(trigger, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
|
@@ -74,7 +74,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
var stats = await _gamblingTxTracker.GetAllAsync();
|
var stats = await _gamblingTxTracker.GetAllAsync();
|
||||||
|
|
||||||
var eb = _sender.CreateEmbed()
|
var eb = _sender.CreateEmbed()
|
||||||
.WithOkColor();
|
.WithOkColor();
|
||||||
|
|
||||||
var str = "` Feature `|` Bet `|`Paid Out`|` RoI `\n";
|
var str = "` Feature `|` Bet `|`Paid Out`|` RoI `\n";
|
||||||
str += "――――――――――――――――――――\n";
|
str += "――――――――――――――――――――\n";
|
||||||
@@ -119,15 +119,15 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
|
|
||||||
// [21:03] Bob Page: Kinda remids me of US economy
|
// [21:03] Bob Page: Kinda remids me of US economy
|
||||||
var embed = _sender.CreateEmbed()
|
var embed = _sender.CreateEmbed()
|
||||||
.WithTitle(GetText(strs.economy_state))
|
.WithTitle(GetText(strs.economy_state))
|
||||||
.AddField(GetText(strs.currency_owned), N(ec.Cash - ec.Bot))
|
.AddField(GetText(strs.currency_owned), N(ec.Cash - ec.Bot))
|
||||||
.AddField(GetText(strs.currency_one_percent), (onePercent * 100).ToString("F2") + "%")
|
.AddField(GetText(strs.currency_one_percent), (onePercent * 100).ToString("F2") + "%")
|
||||||
.AddField(GetText(strs.currency_planted), N(ec.Planted))
|
.AddField(GetText(strs.currency_planted), N(ec.Planted))
|
||||||
.AddField(GetText(strs.owned_waifus_total), N(ec.Waifus))
|
.AddField(GetText(strs.owned_waifus_total), N(ec.Waifus))
|
||||||
.AddField(GetText(strs.bot_currency), N(ec.Bot))
|
.AddField(GetText(strs.bot_currency), N(ec.Bot))
|
||||||
.AddField(GetText(strs.bank_accounts), N(ec.Bank))
|
.AddField(GetText(strs.bank_accounts), N(ec.Bank))
|
||||||
.AddField(GetText(strs.total), N(ec.Cash + ec.Planted + ec.Waifus + ec.Bank))
|
.AddField(GetText(strs.total), N(ec.Cash + ec.Planted + ec.Waifus + ec.Bank))
|
||||||
.WithOkColor();
|
.WithOkColor();
|
||||||
|
|
||||||
// ec.Cash already contains ec.Bot as it's the total of all values in the CurrencyAmount column of the DiscordUser table
|
// ec.Cash already contains ec.Bot as it's the total of all values in the CurrencyAmount column of the DiscordUser table
|
||||||
await Response().Embed(embed).SendAsync();
|
await Response().Embed(embed).SendAsync();
|
||||||
@@ -155,17 +155,14 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NadekoInteraction CreateRemindMeInteraction(int period)
|
private NadekoInteraction CreateRemindMeInteraction(int period)
|
||||||
{
|
=> _inter
|
||||||
return _inter
|
|
||||||
.Create(ctx.User.Id,
|
.Create(ctx.User.Id,
|
||||||
new SimpleInteraction<DateTime>(
|
new ButtonBuilder(
|
||||||
new ButtonBuilder(
|
label: "Remind me",
|
||||||
label: "Remind me",
|
emote: Emoji.Parse("⏰"),
|
||||||
emote: Emoji.Parse("⏰"),
|
customId: "timely:remind_me"),
|
||||||
customId: "timely:remind_me"),
|
(smc) => RemindTimelyAction(smc, DateTime.UtcNow.Add(TimeSpan.FromHours(period)))
|
||||||
RemindTimelyAction,
|
);
|
||||||
DateTime.UtcNow.Add(TimeSpan.FromHours(period))));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
public async Task Timely()
|
public async Task Timely()
|
||||||
@@ -311,9 +308,9 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
}
|
}
|
||||||
|
|
||||||
var embed = _sender.CreateEmbed()
|
var embed = _sender.CreateEmbed()
|
||||||
.WithTitle(GetText(strs.transactions(((SocketGuild)ctx.Guild)?.GetUser(userId)?.ToString()
|
.WithTitle(GetText(strs.transactions(((SocketGuild)ctx.Guild)?.GetUser(userId)?.ToString()
|
||||||
?? $"{userId}")))
|
?? $"{userId}")))
|
||||||
.WithOkColor();
|
.WithOkColor();
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
foreach (var tr in trs)
|
foreach (var tr in trs)
|
||||||
@@ -408,7 +405,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
await Response().Confirm(strs.has(Format.Code(userId.ToString()), cur)).SendAsync();
|
await Response().Confirm(strs.has(Format.Code(userId.ToString()), cur)).SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task BankAction(SocketMessageComponent smc, object _)
|
private async Task BankAction(SocketMessageComponent smc)
|
||||||
{
|
{
|
||||||
var balance = await _bank.GetBalanceAsync(ctx.User.Id);
|
var balance = await _bank.GetBalanceAsync(ctx.User.Id);
|
||||||
|
|
||||||
@@ -419,11 +416,11 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NadekoInteraction CreateCashInteraction()
|
private NadekoInteraction CreateCashInteraction()
|
||||||
=> _inter.Create<object>(ctx.User.Id,
|
=> _inter.Create(ctx.User.Id,
|
||||||
new(new(
|
new ButtonBuilder(
|
||||||
customId: "cash:bank_show_balance",
|
customId: "cash:bank_show_balance",
|
||||||
emote: new Emoji("🏦")),
|
emote: new Emoji("🏦")),
|
||||||
BankAction));
|
BankAction);
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[Priority(1)]
|
[Priority(1)]
|
||||||
@@ -732,10 +729,10 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
}
|
}
|
||||||
|
|
||||||
var eb = _sender.CreateEmbed()
|
var eb = _sender.CreateEmbed()
|
||||||
.WithAuthor(ctx.User)
|
.WithAuthor(ctx.User)
|
||||||
.WithDescription(Format.Bold(str))
|
.WithDescription(Format.Bold(str))
|
||||||
.AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture))
|
.AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture))
|
||||||
.WithOkColor();
|
.WithOkColor();
|
||||||
|
|
||||||
await Response().Embed(eb).SendAsync();
|
await Response().Embed(eb).SendAsync();
|
||||||
}
|
}
|
||||||
@@ -787,7 +784,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
return await uow.Set<DiscordUser>().GetTopRichest(_client.CurrentUser.Id, curPage);
|
return await uow.Set<DiscordUser>().GetTopRichest(_client.CurrentUser.Id, curPage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = Response()
|
var res = Response()
|
||||||
.Paginated();
|
.Paginated();
|
||||||
|
|
||||||
@@ -799,8 +796,9 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
.CurrentPage(page)
|
.CurrentPage(page)
|
||||||
.Page((toSend, curPage) =>
|
.Page((toSend, curPage) =>
|
||||||
{
|
{
|
||||||
var embed = _sender.CreateEmbed().WithOkColor()
|
var embed = _sender.CreateEmbed()
|
||||||
.WithTitle(CurrencySign + " " + GetText(strs.leaderboard));
|
.WithOkColor()
|
||||||
|
.WithTitle(CurrencySign + " " + GetText(strs.leaderboard));
|
||||||
|
|
||||||
if (!toSend.Any())
|
if (!toSend.Any())
|
||||||
{
|
{
|
||||||
@@ -923,11 +921,11 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
}
|
}
|
||||||
|
|
||||||
var eb = _sender.CreateEmbed()
|
var eb = _sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithDescription(sb.ToString())
|
.WithDescription(sb.ToString())
|
||||||
.AddField(GetText(strs.multiplier), $"{result.Multiplier:0.##}x", true)
|
.AddField(GetText(strs.multiplier), $"{result.Multiplier:0.##}x", true)
|
||||||
.AddField(GetText(strs.won), $"{(long)result.Won}", true)
|
.AddField(GetText(strs.won), $"{(long)result.Won}", true)
|
||||||
.WithAuthor(ctx.User);
|
.WithAuthor(ctx.User);
|
||||||
|
|
||||||
|
|
||||||
await Response().Embed(eb).SendAsync();
|
await Response().Embed(eb).SendAsync();
|
||||||
|
@@ -76,9 +76,12 @@ public partial class Gambling
|
|||||||
.WithOkColor();
|
.WithOkColor();
|
||||||
|
|
||||||
var bb = new ButtonBuilder(emote: Emoji.Parse("🔁"), customId: "slot:again", label: "Pull Again");
|
var bb = new ButtonBuilder(emote: Emoji.Parse("🔁"), customId: "slot:again", label: "Pull Again");
|
||||||
var si = new SimpleInteraction<long>(bb, (_, amount) => Slot(amount), amount);
|
var inter = _inter.Create(ctx.User.Id, bb, smc =>
|
||||||
|
{
|
||||||
|
smc.DeferAsync();
|
||||||
|
return Slot(amount);
|
||||||
|
});
|
||||||
|
|
||||||
var inter = _inter.Create(ctx.User.Id, si);
|
|
||||||
var msg = await ctx.Channel.SendFileAsync(imgStream,
|
var msg = await ctx.Channel.SendFileAsync(imgStream,
|
||||||
"result.png",
|
"result.png",
|
||||||
embed: eb.Build(),
|
embed: eb.Build(),
|
||||||
|
@@ -4,6 +4,7 @@ using NadekoBot.Modules.Help.Services;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Nadeko.Common.Medusa;
|
using Nadeko.Common.Medusa;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.Mapping;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Help;
|
namespace NadekoBot.Modules.Help;
|
||||||
|
|
||||||
@@ -86,11 +87,31 @@ public sealed partial class Help : NadekoModule<HelpService>
|
|||||||
topLevelModules.Add(m);
|
topLevelModules.Add(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var menu = new SelectMenuBuilder()
|
||||||
|
.WithPlaceholder("Select a module to see its commands")
|
||||||
|
.WithCustomId("modules");
|
||||||
|
|
||||||
|
foreach (var m in topLevelModules)
|
||||||
|
menu.AddOption(m.Name, m.Name, GetModuleEmoji(m.Name));
|
||||||
|
|
||||||
|
var inter = _inter.Create(ctx.User.Id,
|
||||||
|
menu,
|
||||||
|
async (smc) =>
|
||||||
|
{
|
||||||
|
await smc.DeferAsync();
|
||||||
|
var val = smc.Data.Values.FirstOrDefault();
|
||||||
|
if (val is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await Commands(val);
|
||||||
|
});
|
||||||
|
|
||||||
await Response()
|
await Response()
|
||||||
.Paginated()
|
.Paginated()
|
||||||
.Items(topLevelModules)
|
.Items(topLevelModules)
|
||||||
.PageSize(12)
|
.PageSize(12)
|
||||||
.CurrentPage(page)
|
.CurrentPage(page)
|
||||||
|
.Interaction(inter)
|
||||||
.AddFooter(false)
|
.AddFooter(false)
|
||||||
.Page((items, _) =>
|
.Page((items, _) =>
|
||||||
{
|
{
|
||||||
@@ -442,7 +463,7 @@ public sealed partial class Help : NadekoModule<HelpService>
|
|||||||
.SendAsync();
|
.SendAsync();
|
||||||
|
|
||||||
|
|
||||||
private Task SelfhostAction(SocketMessageComponent smc, object _)
|
private Task SelfhostAction(SocketMessageComponent smc)
|
||||||
=> smc.RespondConfirmAsync(_sender,
|
=> smc.RespondConfirmAsync(_sender,
|
||||||
"""
|
"""
|
||||||
- In case you don't want or cannot Donate to NadekoBot project, but you
|
- In case you don't want or cannot Donate to NadekoBot project, but you
|
||||||
@@ -460,11 +481,11 @@ public sealed partial class Help : NadekoModule<HelpService>
|
|||||||
public async Task Donate()
|
public async Task Donate()
|
||||||
{
|
{
|
||||||
var selfhostInter = _inter.Create(ctx.User.Id,
|
var selfhostInter = _inter.Create(ctx.User.Id,
|
||||||
new SimpleInteraction<object>(new ButtonBuilder(
|
new ButtonBuilder(
|
||||||
emote: new Emoji("🖥️"),
|
emote: new Emoji("🖥️"),
|
||||||
customId: "donate:selfhosting",
|
customId: "donate:selfhosting",
|
||||||
label: "Selfhosting"),
|
label: "Selfhosting"),
|
||||||
SelfhostAction));
|
SelfhostAction);
|
||||||
|
|
||||||
var eb = _sender.CreateEmbed()
|
var eb = _sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
|
@@ -117,35 +117,35 @@ public partial class Utility
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageMessages)]
|
[UserPerm(GuildPerm.ManageMessages)]
|
||||||
[Priority(0)]
|
[Priority(0)]
|
||||||
public Task Repeat(ITextChannel ch, StoopidTime interval, [Leftover] string message)
|
public Task Repeat(ITextChannel channel, StoopidTime interval, [Leftover] string message)
|
||||||
=> Repeat(ch, null, interval, message);
|
=> Repeat(channel, null, interval, message);
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageMessages)]
|
[UserPerm(GuildPerm.ManageMessages)]
|
||||||
[Priority(1)]
|
[Priority(1)]
|
||||||
public Task Repeat(GuildDateTime dt, [Leftover] string message)
|
public Task Repeat(GuildDateTime timeOfDay, [Leftover] string message)
|
||||||
=> Repeat(dt, null, message);
|
=> Repeat(timeOfDay, null, message);
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageMessages)]
|
[UserPerm(GuildPerm.ManageMessages)]
|
||||||
[Priority(1)]
|
[Priority(1)]
|
||||||
public Task Repeat(ITextChannel channel, GuildDateTime dt, [Leftover] string message)
|
public Task Repeat(ITextChannel channel, GuildDateTime timeOfDay, [Leftover] string message)
|
||||||
=> Repeat(channel, dt, null, message);
|
=> Repeat(channel, timeOfDay, null, message);
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageMessages)]
|
[UserPerm(GuildPerm.ManageMessages)]
|
||||||
[Priority(2)]
|
[Priority(2)]
|
||||||
public Task Repeat(GuildDateTime? dt, StoopidTime? interval, [Leftover] string message)
|
public Task Repeat(GuildDateTime? timeOfDay, StoopidTime? interval, [Leftover] string message)
|
||||||
=> Repeat(ctx.Channel, dt, interval, message);
|
=> Repeat(ctx.Channel, timeOfDay, interval, message);
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageMessages)]
|
[UserPerm(GuildPerm.ManageMessages)]
|
||||||
[Priority(3)]
|
[Priority(3)]
|
||||||
public async Task Repeat(IMessageChannel channel, GuildDateTime? dt, StoopidTime? interval,
|
public async Task Repeat(IMessageChannel channel, GuildDateTime? timeOfDay, StoopidTime? interval,
|
||||||
[Leftover] string message)
|
[Leftover] string message)
|
||||||
{
|
{
|
||||||
if (channel is not ITextChannel txtCh || txtCh.GuildId != ctx.Guild.Id)
|
if (channel is not ITextChannel txtCh || txtCh.GuildId != ctx.Guild.Id)
|
||||||
@@ -155,7 +155,7 @@ public partial class Utility
|
|||||||
if (!perms.SendMessages)
|
if (!perms.SendMessages)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var startTimeOfDay = dt?.InputTimeUtc.TimeOfDay;
|
var startTimeOfDay = timeOfDay?.InputTimeUtc.TimeOfDay;
|
||||||
// if interval not null, that means user specified it (don't change it)
|
// if interval not null, that means user specified it (don't change it)
|
||||||
|
|
||||||
// if interval is null set the default to:
|
// if interval is null set the default to:
|
||||||
|
@@ -475,7 +475,8 @@ public partial class Xp : NadekoModule<XpService>
|
|||||||
emote: Emoji.Parse("👐"),
|
emote: Emoji.Parse("👐"),
|
||||||
isDisabled: ownedItem.IsUsing);
|
isDisabled: ownedItem.IsUsing);
|
||||||
|
|
||||||
var inter = new SimpleInteraction<(string key, XpShopItemType type)?>(
|
var inter = _inter.Create(
|
||||||
|
ctx.User.Id,
|
||||||
button,
|
button,
|
||||||
OnShopUse,
|
OnShopUse,
|
||||||
(key, itemType));
|
(key, itemType));
|
||||||
@@ -488,7 +489,8 @@ public partial class Xp : NadekoModule<XpService>
|
|||||||
"xpshop:buy",
|
"xpshop:buy",
|
||||||
emote: Emoji.Parse("💰"));
|
emote: Emoji.Parse("💰"));
|
||||||
|
|
||||||
var inter = new SimpleInteraction<(string key, XpShopItemType type)?>(
|
var inter = _inter.Create(
|
||||||
|
ctx.User.Id,
|
||||||
button,
|
button,
|
||||||
OnShopBuy,
|
OnShopBuy,
|
||||||
(key, itemType));
|
(key, itemType));
|
||||||
@@ -507,10 +509,10 @@ public partial class Xp : NadekoModule<XpService>
|
|||||||
NadekoInteraction GetUseInteraction()
|
NadekoInteraction GetUseInteraction()
|
||||||
{
|
{
|
||||||
return _inter.Create(ctx.User.Id,
|
return _inter.Create(ctx.User.Id,
|
||||||
new SimpleInteraction<object>(
|
new(label: "Use", customId: "xpshop:use_item", emote: Emoji.Parse("👐")),
|
||||||
new ButtonBuilder(label: "Use", customId: "xpshop:use_item", emote: Emoji.Parse("👐")),
|
async (_, state) => await XpShopUse(state.type, state.key),
|
||||||
async (smc, _) => await XpShopUse(type, key)
|
(type, key)
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != BuyResult.Success)
|
if (result != BuyResult.Success)
|
||||||
@@ -551,11 +553,8 @@ public partial class Xp : NadekoModule<XpService>
|
|||||||
await ctx.OkAsync();
|
await ctx.OkAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnShopUse(SocketMessageComponent smc, (string? key, XpShopItemType type)? maybeState)
|
private async Task OnShopUse(SocketMessageComponent smc, (string key, XpShopItemType type) state)
|
||||||
{
|
{
|
||||||
if (maybeState is not { } state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var (key, type) = state;
|
var (key, type) = state;
|
||||||
|
|
||||||
var result = await _service.UseShopItemAsync(ctx.User.Id, type, key);
|
var result = await _service.UseShopItemAsync(ctx.User.Id, type, key);
|
||||||
@@ -567,11 +566,8 @@ public partial class Xp : NadekoModule<XpService>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnShopBuy(SocketMessageComponent smc, (string? key, XpShopItemType type)? maybeState)
|
private async Task OnShopBuy(SocketMessageComponent smc, (string key, XpShopItemType type) state)
|
||||||
{
|
{
|
||||||
if (maybeState is not { } state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var (key, type) = state;
|
var (key, type) = state;
|
||||||
|
|
||||||
var result = await _service.BuyShopItemAsync(ctx.User.Id, type, key);
|
var result = await _service.BuyShopItemAsync(ctx.User.Id, type, key);
|
||||||
|
@@ -2,7 +2,22 @@
|
|||||||
|
|
||||||
public interface INadekoInteractionService
|
public interface INadekoInteractionService
|
||||||
{
|
{
|
||||||
|
public NadekoInteraction Create(
|
||||||
|
ulong userId,
|
||||||
|
ButtonBuilder button,
|
||||||
|
Func<SocketMessageComponent, Task> onTrigger,
|
||||||
|
bool singleUse = true);
|
||||||
|
|
||||||
public NadekoInteraction Create<T>(
|
public NadekoInteraction Create<T>(
|
||||||
ulong userId,
|
ulong userId,
|
||||||
SimpleInteraction<T> inter);
|
ButtonBuilder button,
|
||||||
|
Func<SocketMessageComponent, T, Task> onTrigger,
|
||||||
|
in T state,
|
||||||
|
bool singleUse = true);
|
||||||
|
|
||||||
|
NadekoInteraction Create(
|
||||||
|
ulong userId,
|
||||||
|
SelectMenuBuilder menu,
|
||||||
|
Func<SocketMessageComponent, Task> onTrigger,
|
||||||
|
bool singleUse = true);
|
||||||
}
|
}
|
7
src/NadekoBot/_common/Interaction/InteractionHelpers.cs
Normal file
7
src/NadekoBot/_common/Interaction/InteractionHelpers.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace NadekoBot;
|
||||||
|
|
||||||
|
public static class InteractionHelpers
|
||||||
|
{
|
||||||
|
public static readonly IEmote ArrowLeft = Emote.Parse("<:x:1232256519844790302>");
|
||||||
|
public static readonly IEmote ArrowRight = Emote.Parse("<:x:1232256515298295838>");
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
namespace NadekoBot;
|
||||||
|
|
||||||
|
public sealed class NadekoButtonInteraction : NadekoInteraction
|
||||||
|
{
|
||||||
|
public NadekoButtonInteraction(
|
||||||
|
DiscordSocketClient client,
|
||||||
|
ulong authorId,
|
||||||
|
ButtonBuilder button,
|
||||||
|
Func<SocketMessageComponent, Task> onClick,
|
||||||
|
bool onlyAuthor,
|
||||||
|
bool singleUse = true)
|
||||||
|
: base(client, authorId, button.CustomId, onClick, onlyAuthor, singleUse)
|
||||||
|
{
|
||||||
|
Button = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ButtonBuilder Button { get; }
|
||||||
|
|
||||||
|
public override void AddTo(ComponentBuilder cb)
|
||||||
|
=> cb.WithButton(Button);
|
||||||
|
}
|
@@ -0,0 +1,15 @@
|
|||||||
|
namespace NadekoBot;
|
||||||
|
|
||||||
|
public static class NadekoInteractionExtensions
|
||||||
|
{
|
||||||
|
public static MessageComponent CreateComponent(
|
||||||
|
this NadekoInteraction nadekoInteraction
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var cb = new ComponentBuilder();
|
||||||
|
|
||||||
|
nadekoInteraction.AddTo(cb);
|
||||||
|
|
||||||
|
return cb.Build();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
namespace NadekoBot;
|
||||||
|
|
||||||
|
public sealed class NadekoSelectInteraction : NadekoInteraction
|
||||||
|
{
|
||||||
|
public NadekoSelectInteraction(
|
||||||
|
DiscordSocketClient client,
|
||||||
|
ulong authorId,
|
||||||
|
SelectMenuBuilder menu,
|
||||||
|
Func<SocketMessageComponent, Task> onClick,
|
||||||
|
bool onlyAuthor,
|
||||||
|
bool singleUse = true)
|
||||||
|
: base(client, authorId, menu.CustomId, onClick, onlyAuthor, singleUse)
|
||||||
|
{
|
||||||
|
Menu = menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectMenuBuilder Menu { get; }
|
||||||
|
|
||||||
|
public override void AddTo(ComponentBuilder cb)
|
||||||
|
=> cb.WithSelectMenu(Menu);
|
||||||
|
}
|
@@ -1,9 +1,8 @@
|
|||||||
namespace NadekoBot;
|
namespace NadekoBot;
|
||||||
|
|
||||||
public sealed class NadekoInteraction
|
public abstract class NadekoInteraction
|
||||||
{
|
{
|
||||||
private readonly ulong _authorId;
|
private readonly ulong _authorId;
|
||||||
private readonly ButtonBuilder _button;
|
|
||||||
private readonly Func<SocketMessageComponent, Task> _onClick;
|
private readonly Func<SocketMessageComponent, Task> _onClick;
|
||||||
private readonly bool _onlyAuthor;
|
private readonly bool _onlyAuthor;
|
||||||
public DiscordSocketClient Client { get; }
|
public DiscordSocketClient Client { get; }
|
||||||
@@ -11,19 +10,24 @@ public sealed class NadekoInteraction
|
|||||||
private readonly TaskCompletionSource<bool> _interactionCompletedSource;
|
private readonly TaskCompletionSource<bool> _interactionCompletedSource;
|
||||||
|
|
||||||
private IUserMessage message = null!;
|
private IUserMessage message = null!;
|
||||||
|
private readonly string _customId;
|
||||||
|
private readonly bool _singleUse;
|
||||||
|
|
||||||
public NadekoInteraction(DiscordSocketClient client,
|
public NadekoInteraction(
|
||||||
|
DiscordSocketClient client,
|
||||||
ulong authorId,
|
ulong authorId,
|
||||||
ButtonBuilder button,
|
string customId,
|
||||||
Func<SocketMessageComponent, Task> onClick,
|
Func<SocketMessageComponent, Task> onClick,
|
||||||
bool onlyAuthor)
|
bool onlyAuthor,
|
||||||
|
bool singleUse = true)
|
||||||
{
|
{
|
||||||
_authorId = authorId;
|
_authorId = authorId;
|
||||||
_button = button;
|
_customId = customId;
|
||||||
_onClick = onClick;
|
_onClick = onClick;
|
||||||
_onlyAuthor = onlyAuthor;
|
_onlyAuthor = onlyAuthor;
|
||||||
|
_singleUse = singleUse;
|
||||||
_interactionCompletedSource = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
_interactionCompletedSource = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
|
||||||
Client = client;
|
Client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,12 +36,15 @@ public sealed class NadekoInteraction
|
|||||||
message = msg;
|
message = msg;
|
||||||
|
|
||||||
Client.InteractionCreated += OnInteraction;
|
Client.InteractionCreated += OnInteraction;
|
||||||
await Task.WhenAny(Task.Delay(15_000), _interactionCompletedSource.Task);
|
if (_singleUse)
|
||||||
|
await Task.WhenAny(Task.Delay(30_000), _interactionCompletedSource.Task);
|
||||||
|
else
|
||||||
|
await Task.Delay(30_000);
|
||||||
Client.InteractionCreated -= OnInteraction;
|
Client.InteractionCreated -= OnInteraction;
|
||||||
|
|
||||||
await msg.ModifyAsync(m => m.Components = new ComponentBuilder().Build());
|
await msg.ModifyAsync(m => m.Components = new ComponentBuilder().Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task OnInteraction(SocketInteraction arg)
|
private Task OnInteraction(SocketInteraction arg)
|
||||||
{
|
{
|
||||||
if (arg is not SocketMessageComponent smc)
|
if (arg is not SocketMessageComponent smc)
|
||||||
@@ -49,33 +56,25 @@ public sealed class NadekoInteraction
|
|||||||
if (_onlyAuthor && smc.User.Id != _authorId)
|
if (_onlyAuthor && smc.User.Id != _authorId)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
if (smc.Data.CustomId != _button.CustomId)
|
if (smc.Data.CustomId != _customId)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await ExecuteOnActionAsync(smc);
|
|
||||||
|
|
||||||
// this should only be a thing on single-response buttons
|
|
||||||
_interactionCompletedSource.TrySetResult(true);
|
_interactionCompletedSource.TrySetResult(true);
|
||||||
|
await ExecuteOnActionAsync(smc);
|
||||||
|
|
||||||
if (!smc.HasResponded)
|
if (!smc.HasResponded)
|
||||||
{
|
{
|
||||||
await smc.DeferAsync();
|
await smc.DeferAsync();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public MessageComponent CreateComponent()
|
public abstract void AddTo(ComponentBuilder cb);
|
||||||
{
|
|
||||||
var comp = new ComponentBuilder()
|
|
||||||
.WithButton(_button);
|
|
||||||
|
|
||||||
return comp.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ExecuteOnActionAsync(SocketMessageComponent smc)
|
public Task ExecuteOnActionAsync(SocketMessageComponent smc)
|
||||||
=> _onClick(smc);
|
=> _onClick(smc);
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
namespace NadekoBot;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents essential interacation data
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Emote">Emote which will show on a button</param>
|
|
||||||
/// <param name="CustomId">Custom interaction id</param>
|
|
||||||
public record NadekoInteractionData(IEmote Emote, string CustomId, string? Text = null);
|
|
@@ -9,12 +9,39 @@ public class NadekoInteractionService : INadekoInteractionService, INService
|
|||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NadekoInteraction Create(
|
||||||
|
ulong userId,
|
||||||
|
ButtonBuilder button,
|
||||||
|
Func<SocketMessageComponent, Task> onTrigger,
|
||||||
|
bool singleUse = true)
|
||||||
|
=> new NadekoButtonInteraction(_client,
|
||||||
|
userId,
|
||||||
|
button,
|
||||||
|
onTrigger,
|
||||||
|
onlyAuthor: true,
|
||||||
|
singleUse: singleUse);
|
||||||
|
|
||||||
public NadekoInteraction Create<T>(
|
public NadekoInteraction Create<T>(
|
||||||
ulong userId,
|
ulong userId,
|
||||||
SimpleInteraction<T> inter)
|
ButtonBuilder button,
|
||||||
=> new NadekoInteraction(_client,
|
Func<SocketMessageComponent, T, Task> onTrigger,
|
||||||
|
in T state,
|
||||||
|
bool singleUse = true)
|
||||||
|
=> Create(userId,
|
||||||
|
button,
|
||||||
|
((Func<T, Func<SocketMessageComponent, Task>>)((data)
|
||||||
|
=> smc => onTrigger(smc, data)))(state),
|
||||||
|
singleUse);
|
||||||
|
|
||||||
|
public NadekoInteraction Create(
|
||||||
|
ulong userId,
|
||||||
|
SelectMenuBuilder menu,
|
||||||
|
Func<SocketMessageComponent, Task> onTrigger,
|
||||||
|
bool singleUse = true)
|
||||||
|
=> new NadekoSelectInteraction(_client,
|
||||||
userId,
|
userId,
|
||||||
inter.Button,
|
menu,
|
||||||
inter.TriggerAsync,
|
onTrigger,
|
||||||
onlyAuthor: true);
|
onlyAuthor: true,
|
||||||
|
singleUse: singleUse);
|
||||||
}
|
}
|
@@ -1,32 +0,0 @@
|
|||||||
namespace NadekoBot;
|
|
||||||
|
|
||||||
public static class InteractionHelpers
|
|
||||||
{
|
|
||||||
public static readonly IEmote ArrowLeft = Emote.Parse("<:x:1232256519844790302>");
|
|
||||||
public static readonly IEmote ArrowRight = Emote.Parse("<:x:1232256515298295838>");
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class SimpleInteractionBase
|
|
||||||
{
|
|
||||||
public abstract Task TriggerAsync(SocketMessageComponent smc);
|
|
||||||
public abstract ButtonBuilder Button { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SimpleInteraction<T> : SimpleInteractionBase
|
|
||||||
{
|
|
||||||
public override ButtonBuilder Button { get; }
|
|
||||||
private readonly Func<SocketMessageComponent, T, Task> _onClick;
|
|
||||||
private readonly T? _state;
|
|
||||||
|
|
||||||
public SimpleInteraction(ButtonBuilder button, Func<SocketMessageComponent, T?, Task> onClick, T? state = default)
|
|
||||||
{
|
|
||||||
Button = button;
|
|
||||||
_onClick = onClick;
|
|
||||||
_state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task TriggerAsync(SocketMessageComponent smc)
|
|
||||||
{
|
|
||||||
await _onClick(smc, _state!);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -34,34 +34,79 @@ public partial class ResponseBuilder
|
|||||||
if (_paginationBuilder.AddPaginatedFooter)
|
if (_paginationBuilder.AddPaginatedFooter)
|
||||||
embed.AddPaginatedFooter(currentPage, lastPage);
|
embed.AddPaginatedFooter(currentPage, lastPage);
|
||||||
|
|
||||||
SimpleInteractionBase? maybeInter = null;
|
NadekoInteraction? maybeInter = null;
|
||||||
|
|
||||||
async Task<ComponentBuilder> GetComponentBuilder()
|
var model = await _builder.BuildAsync(ephemeral);
|
||||||
|
|
||||||
|
async Task<(NadekoButtonInteraction left, NadekoInteraction? extra, NadekoButtonInteraction right)>
|
||||||
|
GetInteractions()
|
||||||
{
|
{
|
||||||
var cb = new ComponentBuilder();
|
var leftButton = new ButtonBuilder()
|
||||||
|
.WithStyle(ButtonStyle.Primary)
|
||||||
|
.WithCustomId(BUTTON_LEFT)
|
||||||
|
.WithDisabled(lastPage == 0)
|
||||||
|
.WithEmote(InteractionHelpers.ArrowLeft)
|
||||||
|
.WithDisabled(currentPage <= 0);
|
||||||
|
|
||||||
cb.WithButton(new ButtonBuilder()
|
var leftBtnInter = new NadekoButtonInteraction(_client,
|
||||||
.WithStyle(ButtonStyle.Primary)
|
model.User?.Id ?? 0,
|
||||||
.WithCustomId(BUTTON_LEFT)
|
leftButton,
|
||||||
.WithDisabled(lastPage == 0)
|
(smc) =>
|
||||||
.WithEmote(InteractionHelpers.ArrowLeft)
|
{
|
||||||
.WithDisabled(currentPage <= 0));
|
try
|
||||||
|
{
|
||||||
|
if (currentPage > 0)
|
||||||
|
currentPage--;
|
||||||
|
|
||||||
|
_ = UpdatePageAsync(smc);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
singleUse: false);
|
||||||
|
|
||||||
if (_paginationBuilder.InteractionFunc is not null)
|
if (_paginationBuilder.InteractionFunc is not null)
|
||||||
{
|
{
|
||||||
maybeInter = await _paginationBuilder.InteractionFunc(currentPage);
|
maybeInter = await _paginationBuilder.InteractionFunc(currentPage);
|
||||||
|
|
||||||
if (maybeInter is not null)
|
|
||||||
cb.WithButton(maybeInter.Button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cb.WithButton(new ButtonBuilder()
|
var rightButton = new ButtonBuilder()
|
||||||
.WithStyle(ButtonStyle.Primary)
|
.WithStyle(ButtonStyle.Primary)
|
||||||
.WithCustomId(BUTTON_RIGHT)
|
.WithCustomId(BUTTON_RIGHT)
|
||||||
.WithDisabled(lastPage is not null && (lastPage == 0 || currentPage >= lastPage))
|
.WithDisabled(lastPage == 0)
|
||||||
.WithEmote(InteractionHelpers.ArrowRight));
|
.WithEmote(InteractionHelpers.ArrowRight)
|
||||||
|
.WithDisabled(lastPage == 0 || currentPage > lastPage);
|
||||||
|
|
||||||
return cb;
|
var rightBtnInter = new NadekoButtonInteraction(_client,
|
||||||
|
model.User?.Id ?? 0,
|
||||||
|
rightButton,
|
||||||
|
(smc) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (currentPage >= lastPage)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
currentPage++;
|
||||||
|
|
||||||
|
_ = UpdatePageAsync(smc);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
singleUse: false);
|
||||||
|
|
||||||
|
return (leftBtnInter, maybeInter, rightBtnInter);
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task UpdatePageAsync(SocketMessageComponent smc)
|
async Task UpdatePageAsync(SocketMessageComponent smc)
|
||||||
@@ -71,75 +116,37 @@ public partial class ResponseBuilder
|
|||||||
if (_paginationBuilder.AddPaginatedFooter)
|
if (_paginationBuilder.AddPaginatedFooter)
|
||||||
toSend.AddPaginatedFooter(currentPage, lastPage);
|
toSend.AddPaginatedFooter(currentPage, lastPage);
|
||||||
|
|
||||||
var component = (await GetComponentBuilder()).Build();
|
var (left, extra, right) = (await GetInteractions());
|
||||||
|
|
||||||
|
var cb = new ComponentBuilder();
|
||||||
|
left.AddTo(cb);
|
||||||
|
right.AddTo(cb);
|
||||||
|
extra?.AddTo(cb);
|
||||||
|
|
||||||
await smc.ModifyOriginalResponseAsync(x =>
|
await smc.ModifyOriginalResponseAsync(x =>
|
||||||
{
|
{
|
||||||
x.Embed = toSend.Build();
|
x.Embed = toSend.Build();
|
||||||
x.Components = component;
|
x.Components = cb.Build();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var model = await _builder.BuildAsync(ephemeral);
|
var (left, extra, right) = await GetInteractions();
|
||||||
|
|
||||||
|
var cb = new ComponentBuilder();
|
||||||
|
left.AddTo(cb);
|
||||||
|
right.AddTo(cb);
|
||||||
|
extra?.AddTo(cb);
|
||||||
|
|
||||||
var component = (await GetComponentBuilder()).Build();
|
|
||||||
var msg = await model.TargetChannel
|
var msg = await model.TargetChannel
|
||||||
.SendMessageAsync(model.Text,
|
.SendMessageAsync(model.Text,
|
||||||
embed: embed.Build(),
|
embed: embed.Build(),
|
||||||
components: component,
|
components: cb.Build(),
|
||||||
messageReference: model.MessageReference);
|
messageReference: model.MessageReference);
|
||||||
|
|
||||||
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 != model.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 && _paginationBuilder.InteractionFunc is null)
|
if (lastPage == 0 && _paginationBuilder.InteractionFunc is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_client.InteractionCreated += OnInteractionAsync;
|
await Task.WhenAll(left.RunAsync(msg), extra?.RunAsync(msg) ?? Task.CompletedTask, right.RunAsync(msg));
|
||||||
|
|
||||||
await Task.Delay(30_000);
|
|
||||||
|
|
||||||
_client.InteractionCreated -= OnInteractionAsync;
|
|
||||||
|
|
||||||
await msg.ModifyAsync(mp => mp.Components = new ComponentBuilder().Build());
|
await msg.ModifyAsync(mp => mp.Components = new ComponentBuilder().Build());
|
||||||
}
|
}
|
||||||
|
@@ -395,7 +395,7 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
|
|||||||
return Task.FromResult<IReadOnlyCollection<T>>(ReadOnlyCollection<T>.Empty);
|
return Task.FromResult<IReadOnlyCollection<T>>(ReadOnlyCollection<T>.Empty);
|
||||||
};
|
};
|
||||||
|
|
||||||
public Func<int, Task<SimpleInteractionBase>>? InteractionFunc { get; private set; }
|
public Func<int, Task<NadekoInteraction>>? InteractionFunc { get; private set; }
|
||||||
|
|
||||||
public int? Elems { get; private set; } = 1;
|
public int? Elems { get; private set; } = 1;
|
||||||
public int ItemsPerPage { get; private set; } = 9;
|
public int ItemsPerPage { get; private set; } = 9;
|
||||||
@@ -478,13 +478,13 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
|
|||||||
return paginationSender.SendAsync(IsEphemeral);
|
return paginationSender.SendAsync(IsEphemeral);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourcedPaginatedResponseBuilder<T> Interaction(Func<int, Task<SimpleInteractionBase>> func)
|
public SourcedPaginatedResponseBuilder<T> Interaction(Func<int, Task<NadekoInteraction>> func)
|
||||||
{
|
{
|
||||||
InteractionFunc = func; //async (i) => await func(i);
|
InteractionFunc = func; //async (i) => await func(i);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourcedPaginatedResponseBuilder<T> Interaction(SimpleInteractionBase inter)
|
public SourcedPaginatedResponseBuilder<T> Interaction(NadekoInteraction inter)
|
||||||
{
|
{
|
||||||
InteractionFunc = _ => Task.FromResult(inter);
|
InteractionFunc = _ => Task.FromResult(inter);
|
||||||
return this;
|
return this;
|
||||||
|
@@ -40,19 +40,29 @@ public sealed class CommandsUtilityService : ICommandsUtilityService, INService
|
|||||||
var culture = _loc.GetCultureInfo(guild);
|
var culture = _loc.GetCultureInfo(guild);
|
||||||
|
|
||||||
var em = _sender.CreateEmbed()
|
var em = _sender.CreateEmbed()
|
||||||
.AddField(str, $"{com.RealSummary(_strings, _medusae, culture, prefix)}", true);
|
.AddField(str, $"{com.RealSummary(_strings, _medusae, culture, prefix)}", true);
|
||||||
|
|
||||||
_dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides);
|
_dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides);
|
||||||
var reqs = GetCommandRequirements(com, (GuildPermission?)overrides);
|
var reqs = GetCommandRequirements(com, (GuildPermission?)overrides);
|
||||||
if (reqs.Any())
|
if (reqs.Any())
|
||||||
em.AddField(GetText(strs.requires, guild), string.Join("\n", reqs));
|
em.AddField(GetText(strs.requires, guild), string.Join("\n", reqs));
|
||||||
|
|
||||||
|
var paramList = _strings.GetCommandStrings(com.Name, culture)?.Params;
|
||||||
em
|
em
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.AddField(_strings.GetText(strs.usage),
|
.AddField(_strings.GetText(strs.usage),
|
||||||
string.Join("\n", com.RealRemarksArr(_strings, _medusae, culture, prefix).Map(arg => Format.Code(arg))))
|
string.Join("\n", com.RealRemarksArr(_strings, _medusae, culture, prefix).Map(arg => Format.Code(arg))))
|
||||||
.WithFooter(GetText(strs.module(com.Module.GetTopLevelModule().Name), guild));
|
.WithFooter(GetText(strs.module(com.Module.GetTopLevelModule().Name), guild));
|
||||||
|
|
||||||
|
if (paramList is not null and not [])
|
||||||
|
{
|
||||||
|
var pl = paramList
|
||||||
|
.Select(x => Format.Code($"{prefix}{com.Name} {x.Keys.Select(y => $"<{y}>").Join(' ')}"))
|
||||||
|
.Join('\n');
|
||||||
|
|
||||||
|
em.AddField(GetText(strs.overloads, guild), pl);
|
||||||
|
}
|
||||||
|
|
||||||
var opt = GetNadekoOptionType(com.Attributes);
|
var opt = GetNadekoOptionType(com.Attributes);
|
||||||
if (opt is not null)
|
if (opt is not null)
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
h:
|
h:
|
||||||
- help
|
|
||||||
- h
|
- h
|
||||||
|
- help
|
||||||
gencmdlist:
|
gencmdlist:
|
||||||
- gencmdlist
|
- gencmdlist
|
||||||
donate:
|
donate:
|
||||||
@@ -37,7 +37,7 @@ boost:
|
|||||||
boostmsg:
|
boostmsg:
|
||||||
- boostmsg
|
- boostmsg
|
||||||
boostdel:
|
boostdel:
|
||||||
- boostde
|
- boostdel
|
||||||
logserver:
|
logserver:
|
||||||
- logserver
|
- logserver
|
||||||
logignore:
|
logignore:
|
||||||
|
@@ -211,23 +211,23 @@ repeat:
|
|||||||
desc: "The amount of time between each repetition."
|
desc: "The amount of time between each repetition."
|
||||||
message:
|
message:
|
||||||
desc: "The text to be repeated at the specified intervals or times."
|
desc: "The text to be repeated at the specified intervals or times."
|
||||||
- ch:
|
- channel:
|
||||||
desc: "The channel where the message will be sent."
|
desc: "The channel where the message will be sent."
|
||||||
interval:
|
interval:
|
||||||
desc: "The amount of time between each repetition."
|
desc: "The amount of time between each repetition."
|
||||||
message:
|
message:
|
||||||
desc: "The text to be repeated at the specified intervals or times."
|
desc: "The text to be repeated at the specified intervals or times."
|
||||||
- dt:
|
- timeOfDay:
|
||||||
desc: "The time at which the message should be repeated, either once every specified amount of time or at a specific time of day."
|
desc: "The time at which the message should be repeated, either once every specified amount of time or at a specific time of day."
|
||||||
message:
|
message:
|
||||||
desc: "The text to be repeated at the specified intervals or times."
|
desc: "The text to be repeated at the specified intervals or times."
|
||||||
- channel:
|
- channel:
|
||||||
desc: "The channel where the message will be repeated."
|
desc: "The channel where the message will be repeated."
|
||||||
dt:
|
timeOfDay:
|
||||||
desc: "The time at which the message should be repeated, either once every specified amount of time or at a specific time of day."
|
desc: "The time at which the message should be repeated, either once every specified amount of time or at a specific time of day."
|
||||||
message:
|
message:
|
||||||
desc: "The text to be repeated at the specified intervals or times."
|
desc: "The text to be repeated at the specified intervals or times."
|
||||||
- dt:
|
- timeOfDay:
|
||||||
desc: "The time at which the message should be repeated, either once every specified amount of time or at a specific time of day."
|
desc: "The time at which the message should be repeated, either once every specified amount of time or at a specific time of day."
|
||||||
interval:
|
interval:
|
||||||
desc: "The amount of time between each repetition."
|
desc: "The amount of time between each repetition."
|
||||||
@@ -235,7 +235,7 @@ repeat:
|
|||||||
desc: "The text to be repeated at the specified intervals or times."
|
desc: "The text to be repeated at the specified intervals or times."
|
||||||
- channel:
|
- channel:
|
||||||
desc: "The channel where the message will be repeated."
|
desc: "The channel where the message will be repeated."
|
||||||
dt:
|
timeOfDay:
|
||||||
desc: "The time at which the message should be repeated, either once every specified amount of time or at a specific time of day."
|
desc: "The time at which the message should be repeated, either once every specified amount of time or at a specific time of day."
|
||||||
interval:
|
interval:
|
||||||
desc: "The amount of time between each repetition."
|
desc: "The amount of time between each repetition."
|
||||||
@@ -370,10 +370,10 @@ expradd:
|
|||||||
ex:
|
ex:
|
||||||
- '"hello" Hi there %user.mention%'
|
- '"hello" Hi there %user.mention%'
|
||||||
params:
|
params:
|
||||||
- key:
|
- trigger:
|
||||||
desc: "The trigger word that sets off the response when typed by a user."
|
desc: "The trigger word that sets off the response when typed by a user."
|
||||||
message:
|
response:
|
||||||
desc: "The text of the message that triggers the response when typed by a user."
|
desc: "The text of the message that shows up when a user types the trigger word."
|
||||||
expraddserver:
|
expraddserver:
|
||||||
desc: 'Add an expression with a trigger and a response in this server. Bot will post a response whenever someone types the trigger word. Guide here: <https://nadekobot.readthedocs.io/en/latest/custom-reactions/>'
|
desc: 'Add an expression with a trigger and a response in this server. Bot will post a response whenever someone types the trigger word. Guide here: <https://nadekobot.readthedocs.io/en/latest/custom-reactions/>'
|
||||||
ex:
|
ex:
|
||||||
@@ -1257,7 +1257,7 @@ quoteshow:
|
|||||||
ex:
|
ex:
|
||||||
- 123
|
- 123
|
||||||
params:
|
params:
|
||||||
- id:
|
- quoteId:
|
||||||
desc: "The unique identifier for the quote being queried."
|
desc: "The unique identifier for the quote being queried."
|
||||||
quotesearch:
|
quotesearch:
|
||||||
desc: 'Shows a random quote given a search query. Partially matches in several ways: 1) Only content of any quote, 2) only by author, 3) keyword and content, 3) or keyword and author'
|
desc: 'Shows a random quote given a search query. Partially matches in several ways: 1) Only content of any quote, 2) only by author, 3) keyword and content, 3) or keyword and author'
|
||||||
@@ -1278,14 +1278,14 @@ quoteid:
|
|||||||
ex:
|
ex:
|
||||||
- 123456
|
- 123456
|
||||||
params:
|
params:
|
||||||
- id:
|
- quoteId:
|
||||||
desc: "The unique identifier for the quote to be displayed."
|
desc: "The unique identifier for the quote to be displayed."
|
||||||
quotedelete:
|
quotedelete:
|
||||||
desc: Deletes a quote with the specified ID. You have to either have the Manage Messages permission or be the creator of the quote to delete it.
|
desc: Deletes a quote with the specified ID. You have to either have the Manage Messages permission or be the creator of the quote to delete it.
|
||||||
ex:
|
ex:
|
||||||
- 123456
|
- 123456
|
||||||
params:
|
params:
|
||||||
- id:
|
- quoteId:
|
||||||
desc: "The unique identifier for the quote being deleted."
|
desc: "The unique identifier for the quote being deleted."
|
||||||
quotedeleteauthor:
|
quotedeleteauthor:
|
||||||
desc: Deletes all quotes by the specified author. If the author is not you, then ManageMessage server permission is required.
|
desc: Deletes all quotes by the specified author. If the author is not you, then ManageMessage server permission is required.
|
||||||
@@ -4447,4 +4447,4 @@ cleanupguilddata:
|
|||||||
ex:
|
ex:
|
||||||
- ''
|
- ''
|
||||||
params:
|
params:
|
||||||
- {}
|
- {}
|
@@ -1099,5 +1099,6 @@
|
|||||||
"todo_archive_not_found": "Archived todo list not found.",
|
"todo_archive_not_found": "Archived todo list not found.",
|
||||||
"todo_archived_list": "Archived Todo List",
|
"todo_archived_list": "Archived Todo List",
|
||||||
"search_results": "Search results",
|
"search_results": "Search results",
|
||||||
"queue_search_results": "Type the number of the search result to queue up that track."
|
"queue_search_results": "Type the number of the search result to queue up that track.",
|
||||||
|
"overloads": "Overloads"
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user