Added pagination to .lcr, .lcrg, !!lq. Contact me if you have more ideas where it's needed. It lasts for 30 seconds.
This commit is contained in:
parent
5febe84531
commit
f78188ce19
@ -145,13 +145,17 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
if (customReactions == null || !customReactions.Any())
|
||||
await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
||||
else
|
||||
await Context.Channel.SendConfirmAsync(
|
||||
$"Page {page} of custom reactions:",
|
||||
string.Join("\n", customReactions.OrderBy(cr => cr.Trigger)
|
||||
.Skip((page - 1) * 20)
|
||||
{
|
||||
var lastPage = customReactions.Count / 20;
|
||||
await Context.Channel.SendPaginatedConfirmAsync(page, curPage =>
|
||||
new EmbedBuilder().WithOkColor()
|
||||
.WithTitle("Custom reactions")
|
||||
.WithDescription(string.Join("\n", customReactions.OrderBy(cr => cr.Trigger)
|
||||
.Skip((curPage - 1) * 20)
|
||||
.Take(20)
|
||||
.Select(cr => $"`#{cr.Id}` `Trigger:` {cr.Trigger}")))
|
||||
.Select(cr => $"`#{cr.Id}` `Trigger:` {cr.Trigger}"))), lastPage)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public enum All
|
||||
@ -200,14 +204,22 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
if (customReactions == null || !customReactions.Any())
|
||||
await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
||||
else
|
||||
await Context.Channel.SendConfirmAsync($"Page {page} of custom reactions (grouped):",
|
||||
string.Join("\r\n", customReactions
|
||||
.GroupBy(cr => cr.Trigger)
|
||||
.OrderBy(cr => cr.Key)
|
||||
.Skip((page - 1) * 20)
|
||||
.Take(20)
|
||||
.Select(cr => $"**{cr.Key.Trim().ToLowerInvariant()}** `x{cr.Count()}`")))
|
||||
{
|
||||
var ordered = customReactions
|
||||
.GroupBy(cr => cr.Trigger)
|
||||
.OrderBy(cr => cr.Key)
|
||||
.ToList();
|
||||
|
||||
var lastPage = ordered.Count / 20;
|
||||
await Context.Channel.SendPaginatedConfirmAsync(page, (curPage) =>
|
||||
new EmbedBuilder().WithOkColor()
|
||||
.WithTitle($"Custom Reactions (grouped)")
|
||||
.WithDescription(string.Join("\r\n", ordered
|
||||
.Skip((curPage - 1) * 20)
|
||||
.Take(20)
|
||||
.Select(cr => $"**{cr.Key.Trim().ToLowerInvariant()}** `x{cr.Count()}`"))), lastPage)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -300,13 +312,14 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
{
|
||||
if (page < 1)
|
||||
return;
|
||||
await Context.Channel.EmbedAsync(ReactionStats.OrderByDescending(x => x.Value)
|
||||
.Skip((page - 1) * 9)
|
||||
.Take(9)
|
||||
.Aggregate(new EmbedBuilder().WithOkColor().WithTitle($"Custom Reaction stats page #{page}"),
|
||||
(agg, cur) => agg.AddField(efb => efb.WithName(cur.Key).WithValue(cur.Value.ToString()).WithIsInline(true)))
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
var ordered = ReactionStats.OrderByDescending(x => x.Value).ToList();
|
||||
var lastPage = ordered.Count / 9;
|
||||
await Context.Channel.SendPaginatedConfirmAsync(page,
|
||||
(curPage) => ordered.Skip((curPage - 1) * 9)
|
||||
.Take(9)
|
||||
.Aggregate(new EmbedBuilder().WithOkColor().WithTitle($"Custom Reaction Stats"),
|
||||
(agg, cur) => agg.AddField(efb => efb.WithName(cur.Key).WithValue(cur.Value.ToString()).WithIsInline(true))), lastPage)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -183,36 +183,41 @@ namespace NadekoBot.Modules.Music
|
||||
try { await musicPlayer.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { }
|
||||
|
||||
const int itemsPerPage = 10;
|
||||
int startAt = itemsPerPage * (page - 1);
|
||||
var number = 0 + startAt;
|
||||
|
||||
var total = musicPlayer.TotalPlaytime;
|
||||
var maxPlaytime = musicPlayer.MaxPlaytimeSeconds;
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor(eab => eab.WithName($"Player Queue - Page {page}")
|
||||
.WithMusicIcon())
|
||||
.WithDescription(string.Join("\n", musicPlayer.Playlist
|
||||
.Skip(startAt)
|
||||
.Take(10)
|
||||
.Select(v => $"`{++number}.` {v.PrettyFullName}")))
|
||||
.WithFooter(ef => ef.WithText($"{musicPlayer.PrettyVolume} | {musicPlayer.Playlist.Count} " +
|
||||
$"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {total.Minutes}m {total.Seconds}s | " +
|
||||
(musicPlayer.FairPlay ? "✔️fairplay" : "✖️fairplay") + $" | " + (maxPlaytime == 0 ? "unlimited" : $"{maxPlaytime}s limit")))
|
||||
.WithOkColor();
|
||||
var lastPage = musicPlayer.Playlist.Count / itemsPerPage;
|
||||
Func<int, EmbedBuilder> printAction = (curPage) =>
|
||||
{
|
||||
int startAt = itemsPerPage * (curPage - 1);
|
||||
var number = 0 + startAt;
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor(eab => eab.WithName($"Player Queue")
|
||||
.WithMusicIcon())
|
||||
.WithDescription(string.Join("\n", musicPlayer.Playlist
|
||||
.Skip(startAt)
|
||||
.Take(itemsPerPage)
|
||||
.Select(v => $"`{++number}.` {v.PrettyFullName}")))
|
||||
.WithFooter(ef => ef.WithText($"{musicPlayer.PrettyVolume} | {musicPlayer.Playlist.Count} " +
|
||||
$"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {total.Minutes}m {total.Seconds}s | " +
|
||||
(musicPlayer.FairPlay ? "✔️fairplay" : "✖️fairplay") + $" | " + (maxPlaytime == 0 ? "unlimited" : $"{maxPlaytime}s limit")))
|
||||
.WithOkColor();
|
||||
|
||||
if (musicPlayer.RepeatSong)
|
||||
{
|
||||
embed.WithTitle($"🔂 Repeating Song: {currentSong.SongInfo.Title} | {currentSong.PrettyFullTime}");
|
||||
}
|
||||
else if (musicPlayer.RepeatPlaylist)
|
||||
{
|
||||
embed.WithTitle("🔁 Repeating Playlist");
|
||||
}
|
||||
if (musicPlayer.MaxQueueSize != 0 && musicPlayer.Playlist.Count >= musicPlayer.MaxQueueSize)
|
||||
{
|
||||
embed.WithTitle("🎵 Song queue is full!");
|
||||
}
|
||||
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||
if (musicPlayer.RepeatSong)
|
||||
{
|
||||
embed.WithTitle($"🔂 Repeating Song: {currentSong.SongInfo.Title} | {currentSong.PrettyFullTime}");
|
||||
}
|
||||
else if (musicPlayer.RepeatPlaylist)
|
||||
{
|
||||
embed.WithTitle("🔁 Repeating Playlist");
|
||||
}
|
||||
if (musicPlayer.MaxQueueSize != 0 && musicPlayer.Playlist.Count >= musicPlayer.MaxQueueSize)
|
||||
{
|
||||
embed.WithTitle("🎵 Song queue is full!");
|
||||
}
|
||||
return embed;
|
||||
};
|
||||
await Context.Channel.SendPaginatedConfirmAsync(page, printAction, lastPage).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
|
@ -10,48 +10,60 @@ namespace NadekoBot.Services.Discord
|
||||
{
|
||||
public class ReactionEventWrapper : IDisposable
|
||||
{
|
||||
public SocketMessage Message { get; }
|
||||
public IUserMessage Message { get; }
|
||||
public event Action<SocketReaction> OnReactionAdded = delegate { };
|
||||
public event Action<SocketReaction> OnReactionRemoved = delegate { };
|
||||
public event Action OnReactionsCleared = delegate { };
|
||||
|
||||
public ReactionEventWrapper(SocketMessage msg)
|
||||
public ReactionEventWrapper(IUserMessage msg)
|
||||
{
|
||||
if (msg == null)
|
||||
throw new ArgumentNullException(nameof(msg));
|
||||
Message = msg;
|
||||
|
||||
msg.Discord.ReactionAdded += Discord_ReactionAdded;
|
||||
msg.Discord.ReactionRemoved += Discord_ReactionRemoved;
|
||||
msg.Discord.ReactionsCleared += Discord_ReactionsCleared;
|
||||
NadekoBot.Client.ReactionAdded += Discord_ReactionAdded;
|
||||
NadekoBot.Client.ReactionRemoved += Discord_ReactionRemoved;
|
||||
NadekoBot.Client.ReactionsCleared += Discord_ReactionsCleared;
|
||||
}
|
||||
|
||||
private Task Discord_ReactionsCleared(ulong messageId, Optional<SocketUserMessage> reaction)
|
||||
private void Discord_ReactionsCleared(ulong messageId, Optional<SocketUserMessage> reaction)
|
||||
{
|
||||
if (messageId == Message.Id)
|
||||
OnReactionsCleared?.Invoke();
|
||||
return Task.CompletedTask;
|
||||
try
|
||||
{
|
||||
if (messageId == Message.Id)
|
||||
OnReactionsCleared?.Invoke();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private Task Discord_ReactionRemoved(ulong messageId, Optional<SocketUserMessage> arg2, SocketReaction reaction)
|
||||
private void Discord_ReactionRemoved(ulong messageId, Optional<SocketUserMessage> arg2, SocketReaction reaction)
|
||||
{
|
||||
if (messageId == Message.Id)
|
||||
OnReactionRemoved?.Invoke(reaction);
|
||||
return Task.CompletedTask;
|
||||
try
|
||||
{
|
||||
if (messageId == Message.Id)
|
||||
OnReactionRemoved?.Invoke(reaction);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private Task Discord_ReactionAdded(ulong messageId, Optional<SocketUserMessage> message, SocketReaction reaction)
|
||||
private void Discord_ReactionAdded(ulong messageId, Optional<SocketUserMessage> message, SocketReaction reaction)
|
||||
{
|
||||
if(messageId == Message.Id)
|
||||
OnReactionAdded?.Invoke(reaction);
|
||||
return Task.CompletedTask;
|
||||
try
|
||||
{
|
||||
if (messageId == Message.Id)
|
||||
OnReactionAdded?.Invoke(reaction);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public void UnsubAll()
|
||||
{
|
||||
Message.Discord.ReactionAdded -= Discord_ReactionAdded;
|
||||
Message.Discord.ReactionRemoved -= Discord_ReactionRemoved;
|
||||
Message.Discord.ReactionsCleared -= Discord_ReactionsCleared;
|
||||
NadekoBot.Client.ReactionAdded -= Discord_ReactionAdded;
|
||||
NadekoBot.Client.ReactionRemoved -= Discord_ReactionRemoved;
|
||||
NadekoBot.Client.ReactionsCleared -= Discord_ReactionsCleared;
|
||||
OnReactionAdded = null;
|
||||
OnReactionRemoved = null;
|
||||
OnReactionsCleared = null;
|
||||
}
|
||||
|
||||
private bool disposing = false;
|
||||
|
@ -28,6 +28,9 @@ namespace NadekoBot
|
||||
public event Action<SocketChannel> ChannelCreated = delegate { };
|
||||
public event Action<SocketChannel> ChannelDestroyed = delegate { };
|
||||
public event Action<SocketChannel, SocketChannel> ChannelUpdated = delegate { };
|
||||
public event Action<ulong, Optional<SocketUserMessage>, SocketReaction> ReactionAdded = delegate { };
|
||||
public event Action<ulong, Optional<SocketUserMessage>, SocketReaction> ReactionRemoved = delegate { };
|
||||
public event Action<ulong, Optional<SocketUserMessage>> ReactionsCleared = delegate { };
|
||||
|
||||
public event Action<SocketGuild> JoinedGuild = delegate { };
|
||||
public event Action<SocketGuild> LeftGuild = delegate { };
|
||||
@ -74,6 +77,9 @@ namespace NadekoBot
|
||||
client.ChannelUpdated += (arg1, arg2) => { ChannelUpdated(arg1, arg2); return Task.CompletedTask; };
|
||||
client.JoinedGuild += (arg1) => { JoinedGuild(arg1); ++_guildCount; return Task.CompletedTask; };
|
||||
client.LeftGuild += (arg1) => { LeftGuild(arg1); --_guildCount; return Task.CompletedTask; };
|
||||
client.ReactionAdded += (arg1, arg2, arg3) => { ReactionAdded(arg1, arg2, arg3); return Task.CompletedTask; };
|
||||
client.ReactionRemoved += (arg1, arg2, arg3) => { ReactionRemoved(arg1, arg2, arg3); return Task.CompletedTask; };
|
||||
client.ReactionsCleared += (arg1, arg2) => { ReactionsCleared(arg1, arg2); return Task.CompletedTask; };
|
||||
|
||||
_log.Info($"Shard #{i} initialized.");
|
||||
#if GLOBAL_NADEKO
|
||||
|
@ -18,10 +18,70 @@ namespace NadekoBot.Extensions
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static ReactionEventWrapper OnReactionAdded(this SocketMessage msg, Action<SocketReaction> reactionAdded)
|
||||
private const string arrow_left = "⬅";
|
||||
private const string arrow_right = "➡";
|
||||
|
||||
/// <summary>
|
||||
/// danny kamisama
|
||||
/// </summary>
|
||||
public static async Task SendPaginatedConfirmAsync(this IMessageChannel channel, int currentPage, Func<int, EmbedBuilder> pageFunc, int? lastPage = null)
|
||||
{
|
||||
lastPage += 1;
|
||||
var embed = pageFunc(currentPage).AddPaginatedFooter(currentPage, lastPage);
|
||||
|
||||
var msg = await channel.EmbedAsync(embed) as IUserMessage;
|
||||
|
||||
if (currentPage >= lastPage && lastPage == 1)
|
||||
return;
|
||||
|
||||
await msg.AddReactionAsync(arrow_left).ConfigureAwait(false);
|
||||
await msg.AddReactionAsync(arrow_right).ConfigureAwait(false);
|
||||
|
||||
await Task.Delay(2000).ConfigureAwait(false);
|
||||
|
||||
Action<SocketReaction> changePage = async r =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (r.Emoji.Name == arrow_left)
|
||||
{
|
||||
if (currentPage == 1)
|
||||
return;
|
||||
await msg.ModifyAsync(x => x.Embed = pageFunc(--currentPage).AddPaginatedFooter(currentPage, lastPage).Build()).ConfigureAwait(false);
|
||||
}
|
||||
else if (r.Emoji.Name == arrow_right)
|
||||
{
|
||||
if (lastPage == null || lastPage > currentPage)
|
||||
await msg.ModifyAsync(x => x.Embed = pageFunc(++currentPage).AddPaginatedFooter(currentPage, lastPage).Build()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { Console.WriteLine(ex); }
|
||||
};
|
||||
|
||||
using (msg.OnReaction(changePage, changePage))
|
||||
{
|
||||
await Task.Delay(30000).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await msg.RemoveAllReactionsAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static EmbedBuilder AddPaginatedFooter(this EmbedBuilder embed, int curPage, int? lastPage)
|
||||
{
|
||||
if (lastPage != null)
|
||||
return embed.WithFooter(efb => efb.WithText($"page {curPage} / {lastPage}"));
|
||||
else
|
||||
return embed.WithFooter(efb => efb.WithText($"page {curPage}"));
|
||||
}
|
||||
|
||||
public static ReactionEventWrapper OnReaction(this IUserMessage msg, Action<SocketReaction> reactionAdded, Action<SocketReaction> reactionRemoved = null)
|
||||
{
|
||||
if (reactionRemoved == null)
|
||||
reactionRemoved = delegate { };
|
||||
|
||||
var wrap = new ReactionEventWrapper(msg);
|
||||
wrap.OnReactionAdded += reactionAdded;
|
||||
wrap.OnReactionRemoved += reactionRemoved;
|
||||
return wrap;
|
||||
}
|
||||
|
||||
@ -53,7 +113,8 @@ namespace NadekoBot.Extensions
|
||||
|
||||
public static string GetPrefix(this ModuleInfo module) => NadekoBot.ModulePrefixes[module.GetTopLevelModule().Name];
|
||||
|
||||
public static ModuleInfo GetTopLevelModule(this ModuleInfo module) {
|
||||
public static ModuleInfo GetTopLevelModule(this ModuleInfo module)
|
||||
{
|
||||
while (module.Parent != null)
|
||||
{
|
||||
module = module.Parent;
|
||||
@ -102,7 +163,7 @@ namespace NadekoBot.Extensions
|
||||
|
||||
public static bool IsInteger(this decimal number) => number == Math.Truncate(number);
|
||||
|
||||
public static string SanitizeMentions(this string str) =>
|
||||
public static string SanitizeMentions(this string str) =>
|
||||
str.Replace("@everyone", "@everyοne").Replace("@here", "@һere");
|
||||
|
||||
public static double UnixTimestamp(this DateTime dt) => dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
|
||||
@ -114,7 +175,7 @@ namespace NadekoBot.Extensions
|
||||
=> await (await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(text));
|
||||
|
||||
public static async Task<IUserMessage> SendConfirmAsync(this IUser user, string title, string text, string url = null)
|
||||
=> await(await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(text)
|
||||
=> await (await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(text)
|
||||
.WithTitle(title).WithUrl(url));
|
||||
|
||||
public static async Task<IUserMessage> SendErrorAsync(this IUser user, string title, string error, string url = null)
|
||||
@ -135,7 +196,7 @@ namespace NadekoBot.Extensions
|
||||
|
||||
public static IEnumerable<IUser> Members(this IRole role) =>
|
||||
role.Guild.GetUsersAsync().GetAwaiter().GetResult().Where(u => u.RoleIds.Contains(role.Id)) ?? Enumerable.Empty<IUser>();
|
||||
|
||||
|
||||
public static Task<IUserMessage> EmbedAsync(this IMessageChannel ch, EmbedBuilder embed, string msg = "")
|
||||
=> ch.SendMessageAsync(msg, embed: embed);
|
||||
|
||||
@ -162,7 +223,7 @@ namespace NadekoBot.Extensions
|
||||
```");
|
||||
}
|
||||
|
||||
public static Task<IUserMessage> SendTableAsync<T>(this IMessageChannel ch, IEnumerable<T> items, Func<T, string> howToPrint, int columns = 3) =>
|
||||
public static Task<IUserMessage> SendTableAsync<T>(this IMessageChannel ch, IEnumerable<T> items, Func<T, string> howToPrint, int columns = 3) =>
|
||||
ch.SendTableAsync("", items, howToPrint, columns);
|
||||
|
||||
/// <summary>
|
||||
@ -295,7 +356,7 @@ namespace NadekoBot.Extensions
|
||||
|
||||
}
|
||||
|
||||
public static string ToJson<T>(this T any, Formatting formatting = Formatting.Indented) =>
|
||||
public static string ToJson<T>(this T any, Formatting formatting = Formatting.Indented) =>
|
||||
JsonConvert.SerializeObject(any, formatting);
|
||||
|
||||
public static int KiB(this int value) => value * 1024;
|
||||
@ -326,7 +387,7 @@ namespace NadekoBot.Extensions
|
||||
|
||||
var canvasPixels = canvas.Lock();
|
||||
int offsetX = 0;
|
||||
foreach (var img in imgList.Select(img=>img.Lock()))
|
||||
foreach (var img in imgList.Select(img => img.Lock()))
|
||||
{
|
||||
for (int i = 0; i < img.Width; i++)
|
||||
{
|
||||
@ -335,7 +396,7 @@ namespace NadekoBot.Extensions
|
||||
canvasPixels[i + offsetX, j] = img[i, j];
|
||||
}
|
||||
}
|
||||
offsetX += img.Width;
|
||||
offsetX += img.Width;
|
||||
}
|
||||
|
||||
return canvas;
|
||||
@ -354,4 +415,4 @@ namespace NadekoBot.Extensions
|
||||
public static bool IsDiscordInvite(this string str)
|
||||
=> filterRegex.IsMatch(str);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user