Merge remote-tracking branch 'refs/remotes/Kwoth/dev' into dev
This commit is contained in:
		@@ -145,13 +145,17 @@ namespace NadekoBot.Modules.CustomReactions
 | 
				
			|||||||
            if (customReactions == null || !customReactions.Any())
 | 
					            if (customReactions == null || !customReactions.Any())
 | 
				
			||||||
                await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
 | 
					                await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                await Context.Channel.SendConfirmAsync(
 | 
					            {
 | 
				
			||||||
                    $"Page {page} of custom reactions:",
 | 
					                var lastPage = customReactions.Count / 20;
 | 
				
			||||||
                    string.Join("\n", customReactions.OrderBy(cr => cr.Trigger)
 | 
					                await Context.Channel.SendPaginatedConfirmAsync(page, curPage =>
 | 
				
			||||||
                                                     .Skip((page - 1) * 20)
 | 
					                    new EmbedBuilder().WithOkColor()
 | 
				
			||||||
 | 
					                        .WithTitle("Custom reactions")
 | 
				
			||||||
 | 
					                        .WithDescription(string.Join("\n", customReactions.OrderBy(cr => cr.Trigger)
 | 
				
			||||||
 | 
					                                                     .Skip((curPage - 1) * 20)
 | 
				
			||||||
                                                     .Take(20)
 | 
					                                                     .Take(20)
 | 
				
			||||||
                                                     .Select(cr => $"`#{cr.Id}`  `Trigger:` {cr.Trigger}")))
 | 
					                                                     .Select(cr => $"`#{cr.Id}`  `Trigger:` {cr.Trigger}"))), lastPage)
 | 
				
			||||||
                                 .ConfigureAwait(false);
 | 
					                                 .ConfigureAwait(false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public enum All
 | 
					        public enum All
 | 
				
			||||||
@@ -200,14 +204,22 @@ namespace NadekoBot.Modules.CustomReactions
 | 
				
			|||||||
            if (customReactions == null || !customReactions.Any())
 | 
					            if (customReactions == null || !customReactions.Any())
 | 
				
			||||||
                await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
 | 
					                await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                await Context.Channel.SendConfirmAsync($"Page {page} of custom reactions (grouped):",
 | 
					            {
 | 
				
			||||||
                                    string.Join("\r\n", customReactions
 | 
					                var ordered = customReactions
 | 
				
			||||||
                                                        .GroupBy(cr => cr.Trigger)
 | 
					                    .GroupBy(cr => cr.Trigger)
 | 
				
			||||||
                                                        .OrderBy(cr => cr.Key)
 | 
					                    .OrderBy(cr => cr.Key)
 | 
				
			||||||
                                                        .Skip((page - 1) * 20)
 | 
					                    .ToList();
 | 
				
			||||||
                                                        .Take(20)
 | 
					
 | 
				
			||||||
                                                        .Select(cr => $"**{cr.Key.Trim().ToLowerInvariant()}** `x{cr.Count()}`")))
 | 
					                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);
 | 
					                             .ConfigureAwait(false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
@@ -300,13 +312,14 @@ namespace NadekoBot.Modules.CustomReactions
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (page < 1)
 | 
					            if (page < 1)
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            await Context.Channel.EmbedAsync(ReactionStats.OrderByDescending(x => x.Value)
 | 
					            var ordered = ReactionStats.OrderByDescending(x => x.Value).ToList();
 | 
				
			||||||
                                               .Skip((page - 1) * 9)
 | 
					            var lastPage = ordered.Count / 9;
 | 
				
			||||||
                                               .Take(9)
 | 
					            await Context.Channel.SendPaginatedConfirmAsync(page,
 | 
				
			||||||
                                               .Aggregate(new EmbedBuilder().WithOkColor().WithTitle($"Custom Reaction stats page #{page}"),
 | 
					                (curPage) => ordered.Skip((curPage - 1) * 9)
 | 
				
			||||||
                                                         (agg, cur) => agg.AddField(efb => efb.WithName(cur.Key).WithValue(cur.Value.ToString()).WithIsInline(true)))
 | 
					                                    .Take(9)
 | 
				
			||||||
                                                         )
 | 
					                                    .Aggregate(new EmbedBuilder().WithOkColor().WithTitle($"Custom Reaction Stats"),
 | 
				
			||||||
                              .ConfigureAwait(false);
 | 
					                                            (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 { }
 | 
					            try { await musicPlayer.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const int itemsPerPage = 10;
 | 
					            const int itemsPerPage = 10;
 | 
				
			||||||
            int startAt = itemsPerPage * (page - 1);
 | 
					 | 
				
			||||||
            var number = 0 + startAt;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var total = musicPlayer.TotalPlaytime;
 | 
					            var total = musicPlayer.TotalPlaytime;
 | 
				
			||||||
            var maxPlaytime = musicPlayer.MaxPlaytimeSeconds;
 | 
					            var maxPlaytime = musicPlayer.MaxPlaytimeSeconds;
 | 
				
			||||||
            var embed = new EmbedBuilder()
 | 
					            var lastPage = musicPlayer.Playlist.Count / itemsPerPage;
 | 
				
			||||||
                .WithAuthor(eab => eab.WithName($"Player Queue - Page {page}")
 | 
					            Func<int, EmbedBuilder> printAction = (curPage) =>
 | 
				
			||||||
                                      .WithMusicIcon())
 | 
					            {
 | 
				
			||||||
                .WithDescription(string.Join("\n", musicPlayer.Playlist
 | 
					                int startAt = itemsPerPage * (curPage - 1);
 | 
				
			||||||
                    .Skip(startAt)
 | 
					                var number = 0 + startAt;
 | 
				
			||||||
                    .Take(10)
 | 
					                var embed = new EmbedBuilder()
 | 
				
			||||||
                    .Select(v => $"`{++number}.` {v.PrettyFullName}")))
 | 
					                    .WithAuthor(eab => eab.WithName($"Player Queue")
 | 
				
			||||||
                .WithFooter(ef => ef.WithText($"{musicPlayer.PrettyVolume} | {musicPlayer.Playlist.Count} " +
 | 
					                                          .WithMusicIcon())
 | 
				
			||||||
$"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {total.Minutes}m {total.Seconds}s | " +
 | 
					                    .WithDescription(string.Join("\n", musicPlayer.Playlist
 | 
				
			||||||
(musicPlayer.FairPlay ? "✔️fairplay" : "✖️fairplay") + $" | " + (maxPlaytime == 0 ? "unlimited" : $"{maxPlaytime}s limit")))
 | 
					                        .Skip(startAt)
 | 
				
			||||||
                .WithOkColor();
 | 
					                        .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)
 | 
					                if (musicPlayer.RepeatSong)
 | 
				
			||||||
            {
 | 
					                {
 | 
				
			||||||
                embed.WithTitle($"🔂 Repeating Song: {currentSong.SongInfo.Title} | {currentSong.PrettyFullTime}");
 | 
					                    embed.WithTitle($"🔂 Repeating Song: {currentSong.SongInfo.Title} | {currentSong.PrettyFullTime}");
 | 
				
			||||||
            }
 | 
					                }
 | 
				
			||||||
            else if (musicPlayer.RepeatPlaylist)
 | 
					                else if (musicPlayer.RepeatPlaylist)
 | 
				
			||||||
            {
 | 
					                {
 | 
				
			||||||
                embed.WithTitle("🔁 Repeating Playlist");
 | 
					                    embed.WithTitle("🔁 Repeating Playlist");
 | 
				
			||||||
            }
 | 
					                }
 | 
				
			||||||
            if (musicPlayer.MaxQueueSize != 0 && musicPlayer.Playlist.Count >= musicPlayer.MaxQueueSize)
 | 
					                if (musicPlayer.MaxQueueSize != 0 && musicPlayer.Playlist.Count >= musicPlayer.MaxQueueSize)
 | 
				
			||||||
            {
 | 
					                {
 | 
				
			||||||
                embed.WithTitle("🎵 Song queue is full!");
 | 
					                    embed.WithTitle("🎵 Song queue is full!");
 | 
				
			||||||
            }
 | 
					                }
 | 
				
			||||||
            await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
 | 
					                return embed;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            await Context.Channel.SendPaginatedConfirmAsync(page, printAction, lastPage).ConfigureAwait(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,48 +10,60 @@ namespace NadekoBot.Services.Discord
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class ReactionEventWrapper : IDisposable
 | 
					    public class ReactionEventWrapper : IDisposable
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public SocketMessage Message { get; }
 | 
					        public IUserMessage Message { get; }
 | 
				
			||||||
        public event Action<SocketReaction> OnReactionAdded = delegate { };
 | 
					        public event Action<SocketReaction> OnReactionAdded = delegate { };
 | 
				
			||||||
        public event Action<SocketReaction> OnReactionRemoved = delegate { };
 | 
					        public event Action<SocketReaction> OnReactionRemoved = delegate { };
 | 
				
			||||||
        public event Action OnReactionsCleared = delegate { };
 | 
					        public event Action OnReactionsCleared = delegate { };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ReactionEventWrapper(SocketMessage msg)
 | 
					        public ReactionEventWrapper(IUserMessage msg)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (msg == null)
 | 
					            if (msg == null)
 | 
				
			||||||
                throw new ArgumentNullException(nameof(msg));
 | 
					                throw new ArgumentNullException(nameof(msg));
 | 
				
			||||||
            Message = msg;
 | 
					            Message = msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            msg.Discord.ReactionAdded += Discord_ReactionAdded;
 | 
					            NadekoBot.Client.ReactionAdded += Discord_ReactionAdded;
 | 
				
			||||||
            msg.Discord.ReactionRemoved += Discord_ReactionRemoved;
 | 
					            NadekoBot.Client.ReactionRemoved += Discord_ReactionRemoved;
 | 
				
			||||||
            msg.Discord.ReactionsCleared += Discord_ReactionsCleared;
 | 
					            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)
 | 
					            try
 | 
				
			||||||
                OnReactionsCleared?.Invoke();
 | 
					            {
 | 
				
			||||||
            return Task.CompletedTask;
 | 
					                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)
 | 
					            try
 | 
				
			||||||
                OnReactionRemoved?.Invoke(reaction);
 | 
					            {
 | 
				
			||||||
            return Task.CompletedTask;
 | 
					                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)
 | 
					            try
 | 
				
			||||||
                OnReactionAdded?.Invoke(reaction);
 | 
					            {
 | 
				
			||||||
            return Task.CompletedTask;
 | 
					                if (messageId == Message.Id)
 | 
				
			||||||
 | 
					                    OnReactionAdded?.Invoke(reaction);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch { }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void UnsubAll()
 | 
					        public void UnsubAll()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Message.Discord.ReactionAdded -= Discord_ReactionAdded;
 | 
					            NadekoBot.Client.ReactionAdded -= Discord_ReactionAdded;
 | 
				
			||||||
            Message.Discord.ReactionRemoved -= Discord_ReactionRemoved;
 | 
					            NadekoBot.Client.ReactionRemoved -= Discord_ReactionRemoved;
 | 
				
			||||||
            Message.Discord.ReactionsCleared -= Discord_ReactionsCleared;
 | 
					            NadekoBot.Client.ReactionsCleared -= Discord_ReactionsCleared;
 | 
				
			||||||
 | 
					            OnReactionAdded = null;
 | 
				
			||||||
 | 
					            OnReactionRemoved = null;
 | 
				
			||||||
 | 
					            OnReactionsCleared = null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private bool disposing = false;
 | 
					        private bool disposing = false;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,9 @@ namespace NadekoBot
 | 
				
			|||||||
        public event Action<SocketChannel> ChannelCreated = delegate { };
 | 
					        public event Action<SocketChannel> ChannelCreated = delegate { };
 | 
				
			||||||
        public event Action<SocketChannel> ChannelDestroyed = delegate { };
 | 
					        public event Action<SocketChannel> ChannelDestroyed = delegate { };
 | 
				
			||||||
        public event Action<SocketChannel, SocketChannel> ChannelUpdated = 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> JoinedGuild = delegate { };
 | 
				
			||||||
        public event Action<SocketGuild> LeftGuild = delegate { };
 | 
					        public event Action<SocketGuild> LeftGuild = delegate { };
 | 
				
			||||||
@@ -74,6 +77,9 @@ namespace NadekoBot
 | 
				
			|||||||
                client.ChannelUpdated += (arg1, arg2) => { ChannelUpdated(arg1, arg2); return Task.CompletedTask; };
 | 
					                client.ChannelUpdated += (arg1, arg2) => { ChannelUpdated(arg1, arg2); return Task.CompletedTask; };
 | 
				
			||||||
                client.JoinedGuild += (arg1) => { JoinedGuild(arg1); ++_guildCount; return Task.CompletedTask; };
 | 
					                client.JoinedGuild += (arg1) => { JoinedGuild(arg1); ++_guildCount; return Task.CompletedTask; };
 | 
				
			||||||
                client.LeftGuild += (arg1) => { LeftGuild(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.");
 | 
					                _log.Info($"Shard #{i} initialized.");
 | 
				
			||||||
#if GLOBAL_NADEKO
 | 
					#if GLOBAL_NADEKO
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,10 +18,70 @@ namespace NadekoBot.Extensions
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public static class 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);
 | 
					            var wrap = new ReactionEventWrapper(msg);
 | 
				
			||||||
            wrap.OnReactionAdded += reactionAdded;
 | 
					            wrap.OnReactionAdded += reactionAdded;
 | 
				
			||||||
 | 
					            wrap.OnReactionRemoved += reactionRemoved;
 | 
				
			||||||
            return wrap;
 | 
					            return wrap;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,7 +113,8 @@ namespace NadekoBot.Extensions
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public static string GetPrefix(this ModuleInfo module) => NadekoBot.ModulePrefixes[module.GetTopLevelModule().Name];
 | 
					        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)
 | 
					            while (module.Parent != null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                module = module.Parent;
 | 
					                module = module.Parent;
 | 
				
			||||||
@@ -102,7 +163,7 @@ namespace NadekoBot.Extensions
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public static bool IsInteger(this decimal number) => number == Math.Truncate(number);
 | 
					        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");
 | 
					            str.Replace("@everyone", "@everyοne").Replace("@here", "@һere");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static double UnixTimestamp(this DateTime dt) => dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
 | 
					        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));
 | 
					             => 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)
 | 
					        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));
 | 
					                 .WithTitle(title).WithUrl(url));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static async Task<IUserMessage> SendErrorAsync(this IUser user, string title, string error, string url = null)
 | 
					        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) =>
 | 
					        public static IEnumerable<IUser> Members(this IRole role) =>
 | 
				
			||||||
            role.Guild.GetUsersAsync().GetAwaiter().GetResult().Where(u => u.RoleIds.Contains(role.Id)) ?? Enumerable.Empty<IUser>();
 | 
					            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 = "")
 | 
					        public static Task<IUserMessage> EmbedAsync(this IMessageChannel ch, EmbedBuilder embed, string msg = "")
 | 
				
			||||||
             => ch.SendMessageAsync(msg, embed: embed);
 | 
					             => 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);
 | 
					            ch.SendTableAsync("", items, howToPrint, columns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <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);
 | 
					            JsonConvert.SerializeObject(any, formatting);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static int KiB(this int value) => value * 1024;
 | 
					        public static int KiB(this int value) => value * 1024;
 | 
				
			||||||
@@ -326,7 +387,7 @@ namespace NadekoBot.Extensions
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var canvasPixels = canvas.Lock();
 | 
					            var canvasPixels = canvas.Lock();
 | 
				
			||||||
            int offsetX = 0;
 | 
					            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++)
 | 
					                for (int i = 0; i < img.Width; i++)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@@ -335,7 +396,7 @@ namespace NadekoBot.Extensions
 | 
				
			|||||||
                        canvasPixels[i + offsetX, j] = img[i, j];
 | 
					                        canvasPixels[i + offsetX, j] = img[i, j];
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                offsetX += img.Width;                
 | 
					                offsetX += img.Width;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return canvas;
 | 
					            return canvas;
 | 
				
			||||||
@@ -354,4 +415,4 @@ namespace NadekoBot.Extensions
 | 
				
			|||||||
        public static bool IsDiscordInvite(this string str)
 | 
					        public static bool IsDiscordInvite(this string str)
 | 
				
			||||||
            => filterRegex.IsMatch(str);
 | 
					            => filterRegex.IsMatch(str);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user