Example #1
0
        /// <summary>
        ///     Fired whenever someone joins the server.
        ///     <para>Used to log a message to a specific text channel.</para>
        /// </summary>
        public async Task UserJoinedServer(SocketGuildUser user)
        {
            var guild = user.Guild;

            //Retrieve guild settings
            var guildSettings = _botContext.Guilds.AsNoTracking().FirstOrDefault(x => x.GuildId == guild.Id);

            if (guildSettings is null)
            {
                return;
            }

            //Check if guild has moderation channel enabled
            var welcomeChannel = guild.GetTextChannel(guildSettings.WelcomeChannel);

            if (welcomeChannel == null)
            {
                return;
            }

            //Check if there is a valid role and give that role to the user
            if (guildSettings.RoleOnJoin != 0 &&
                Helper.DoesRoleExist(user.Guild, guildSettings.RoleOnJoin) is var role && role != null)
            {
                await user.AddRoleAsync(role, new RequestOptions { AuditLogReason = "Auto role on join" });
            }

            //Announce to WelcomeChannel that the user joined the server
            await welcomeChannel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed("User joined",
                                                                                         $"{user} has joined the server!", Color.Green));
        }
Example #2
0
        /// <summary>Removes X(count) messages from chat.
        /// </summary>
        public async Task CleanMessagesAsync(int count, SocketCommandContext context)
        {
            //We only delete 100 messages at a time to prevent bot from getting overloaded
            if (count <= 100)
            {
                /* Saves all messages user specified in a variable, next
                 * those messages are deleted and a message is sent to the textChannel
                 * saying that X messages were deleted <- this message is deleted 2.3s later */

                //Save messages to delete in a variable
                var messagesToDelete = await context.Channel.GetMessagesAsync(count + 1).FlattenAsync();

                //Delete messages to delete
                await context.Guild.GetTextChannel(context.Channel.Id).DeleteMessagesAsync(messagesToDelete, new RequestOptions()
                {
                    AuditLogReason = "Clean messages command"
                });

                //Send success message that will disappear after 2300 milliseconds
                _interactivityService.DelayedSendMessageAndDeleteAsync(context.Channel, null,
                                                                       TimeSpan.FromMilliseconds(2300), null, false,
                                                                       CustomFormats.CreateBasicEmbed("Messages deleted",
                                                                                                      $":white_check_mark: Deleted **{count}** messages.", 0x268618));
            }
            else
            {
                await context.Channel.SendMessageAsync(embed : CustomFormats.CreateErrorEmbed(context.User.Mention + " You cannot delete more than 100 messages at once"));
            }
        }
Example #3
0
        private async Task RoleOnJoinSetup(SocketCommandContext context)
        {
            var tmpMessage = await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed(
                                                                        "Role on Join Setup",
                                                                        "Cobra will automatically give the specified role when someone joins the server.\n" +
                                                                        "Please type the name or ID of the role you want to setup as the role on join.\n" +
                                                                        "Type `reset` to reset the role on join thus disabling this functionality.", Color.Blue));

            var nextMessageResult = await _interactivityService.NextMessageAsync(x => x.Author == context.User);

            if (nextMessageResult.IsSuccess)
            {
                var msgContent = nextMessageResult.Value.Content;

                if (msgContent == "reset")
                {
                    await ChangeRoleOnJoin(context);

                    await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed("Role on join changed",
                                                                                                  "Role on join was reset.\nYour server doesn't have a role on join setup right now.",
                                                                                                  Color.DarkMagenta));
                }
                else
                {
                    var tr         = new ExtendedRoleTypeReader();
                    var readResult = await tr.ReadAsync(context, msgContent, _serviceProvider);

                    if (!readResult.IsSuccess)
                    {
                        await context.Channel.SendMessageAsync(
                            embed : CustomFormats.CreateErrorEmbed("Unable to find role!"));
                    }
                    else
                    {
                        if (readResult.Values.First().Value is IRole role)
                        {
                            await ChangeRoleOnJoin(context, role);

                            await context.Channel.SendMessageAsync(
                                embed : CustomFormats.CreateBasicEmbed("Role on join changed",
                                                                       $"Role on join was set to **{role.Name}**", 0x268618));
                        }
                        else
                        {
                            await context.Channel.SendMessageAsync(
                                embed : CustomFormats.CreateErrorEmbed("Unable to find role!"));
                        }
                    }
                }

                await nextMessageResult.Value.DeleteAsync();

                await tmpMessage.DeleteAsync();
            }
        }
Example #4
0
        private async Task WelcomeChannelSetup(SocketCommandContext context)
        {
            var tmpMessage = await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed(
                                                                        "Welcome Channel Setup",
                                                                        "Cobra will send messages to this channel when someone joins/leaves the server.\n" +
                                                                        "Please mention the #textChannel you want to setup as the Welcome Channel.\n" +
                                                                        "Type `reset` to reset the Welcome Channel thus disabling this functionality.",
                                                                        Color.Blue));

            var nextMessageResult = await _interactivityService.NextMessageAsync(x => x.Author == context.User);

            if (nextMessageResult.IsSuccess)
            {
                var msgContent = nextMessageResult.Value.Content;

                if (msgContent == "reset")
                {
                    await ChangeWelcomeChannel(context);

                    await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed(
                                                               "Welcome channel changed",
                                                               "Welcome channel was reset.\nYour server doesn't have a welcome channel setup right now.",
                                                               Color.DarkMagenta));
                }
                else
                {
                    if (nextMessageResult.Value.MentionedChannels.Any())
                    {
                        if (nextMessageResult.Value.MentionedChannels.First() is ITextChannel textChannel)
                        {
                            await ChangeWelcomeChannel(context, textChannel);

                            await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed(
                                                                       "Welcome channel changed",
                                                                       $"Welcome channel is now {textChannel.Mention}", 0x268618));
                        }
                        else
                        {
                            await context.Channel.SendMessageAsync(
                                embed : CustomFormats.CreateErrorEmbed("Invalid text channel!"));
                        }
                    }
                    else
                    {
                        await context.Channel.SendMessageAsync(
                            embed : CustomFormats.CreateErrorEmbed("No text channels mentioned!"));
                    }
                }

                await nextMessageResult.Value.DeleteAsync();

                await tmpMessage.DeleteAsync();
            }
        }
Example #5
0
        /// <summary> Generates a random number. </summary>
        public static Embed RandomNumber(int minVal, int maxVal)
        {
            //If minVal > maxVal, Random.Next will throw an exception
            //So we switch minVal with maxVal and vice versa. That way we don't get an exception
            if (minVal > maxVal)
            {
                (minVal, maxVal) = (maxVal, minVal);
            }

            var randomNumber = new Random().Next(minVal, maxVal);

            return(CustomFormats.CreateBasicEmbed("Random number", $":game_die: **{randomNumber}**", 0x268618));
        }
Example #6
0
        /// <summary>Generates a random number.
        /// </summary>
        public static Embed RandomNumber(int minVal, int maxVal)
        {
            //If minVal > maxVal, Random.Next will throw an exception
            //So we switch minVal with maxVal and vice versa. That way we don't get an exception
            if (minVal > maxVal)
            {
                int tmp = minVal; //temporary variable to store minVal because it will be overwritten with maxVal
                minVal = maxVal;
                maxVal = tmp;
            }

            var randomNumber = new Random().Next(minVal, maxVal);

            return(CustomFormats.CreateBasicEmbed("Random number", $":game_die: **{randomNumber}**", 0x268618));
        }
Example #7
0
        /// <summary>Removes specified track from queue and returns an embed.
        /// </summary>
        public Embed RemoveFromQueueAsync(IGuild guild, int index, int indexMax)
        {
            if (!_lavaNode.HasPlayer(guild))
            {
                return(CustomFormats.CreateErrorEmbed("Could not acquire player."));
            }

            var player = _lavaNode.GetPlayer(guild);

            /* We decrement 2 to the index, as queue command shows first song in queue with number 2
             * and first item in queue has an index of 0 */
            index -= 2;

            if (player.Queue.ElementAt(index) == null)
            {
                return(CustomFormats.CreateErrorEmbed("There is no song in queue with specified index!"));
            }

            try
            {
                /*By default indexMax = 0, so the user has the option to use the command with only 'index' which in turn removes
                 * only 1 song from the queue. If the users chooses to use indexMax as well, then the bot knows that the user
                 * wants to remove a range of songs instead of only 1 song. */
                if (indexMax != 0)
                {
                    //We decrement 2 to the indexMax, as queue command shows first song in queue with number 2
                    //and first item in queue has an index of 0
                    indexMax -= 2;

                    int count = indexMax - index;

                    /*We use count+1 because RemoveRange() also counts the first index, for example:
                     * If user wants to remove tracks number 2 to 5, it would only remove tracks 2, 3 and 4
                     * because count would be = to 3 */
                    var tracksToRemove = player.Queue.RemoveRange(index, count + 1);

                    return(CustomFormats.CreateBasicEmbed("", $"Removed {tracksToRemove.Count} songs from queue", Color.Blue));
                }

                var trackToRemove = player.Queue.RemoveAt(index);

                return(CustomFormats.CreateBasicEmbed("", $"Removed {trackToRemove.Title} from queue", Color.Blue));
            }
            catch (Exception ex)
            {
                return(CustomFormats.CreateErrorEmbed(ex.Message));
            }
        }
Example #8
0
        private async Task PrivateChatSetup(SocketCommandContext context)
        {
            var tmpMessage = await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed(
                                                                        "Private Chats Setup",
                                                                        "Paste the ID of the category where you want private chats to be created.\n\n" +
                                                                        "If you don't have that category yet, create one category with the name you like and move it to where you would like the private chats to be created." +
                                                                        "Don't change any channel permissions as Cobra takes care of that\n\n" +
                                                                        "Type `reset` to reset the Private Chat category thus disabling this functionality.", Color.Blue));

            var nextMessageResult = await _interactivityService.NextMessageAsync(x => x.Author == context.User);

            if (nextMessageResult.IsSuccess)
            {
                var msgContent = nextMessageResult.Value.Content;

                if (msgContent == "reset")
                {
                    await ChangePrivateChat(context);

                    await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed(
                                                               "Private Chat changed",
                                                               "Private Chat category was reset.\nYour server doesn't have private chats setup right now.",
                                                               Color.DarkMagenta));
                }
                else
                {
                    if (ulong.TryParse(msgContent, out var categoryId))
                    {
                        var category = context.Guild.GetCategoryChannel(categoryId);

                        await ChangePrivateChat(context, category);

                        await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed(
                                                                   "Private Chat changed",
                                                                   $"Private chats will now appear under the category {category.Name}", 0x268618));
                    }
                    else
                    {
                        await context.Channel.SendMessageAsync(
                            embed : CustomFormats.CreateErrorEmbed("Invalid category id!"));
                    }
                }

                await nextMessageResult.Value.DeleteAsync();

                await tmpMessage.DeleteAsync();
            }
        }
Example #9
0
        private async Task PrefixSetup(SocketCommandContext context)
        {
            var tmpMessage = await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed(
                                                                        "Prefix Setup",
                                                                        "Please type the new prefix for your guild (type `default` to reset it)", Color.Blue));

            var nextMessageResult = await _interactivityService.NextMessageAsync(x => x.Author == context.User);

            if (nextMessageResult.IsSuccess)
            {
                await nextMessageResult.Value.DeleteAsync();

                await tmpMessage.DeleteAsync();

                await context.Channel.SendMessageAsync(embed : await ChangePrefix(context, nextMessageResult.Value.Content));
            }
        }
Example #10
0
        /// <summary>
        ///     Unbans specified user from the server.
        /// </summary>
        public async Task <Embed> UnbanAsync(IUser user, SocketCommandContext context)
        {
            await context.Message.DeleteAsync();

            var isBanned = await context.Guild.GetBanAsync(user);

            if (isBanned == null)
            {
                return(CustomFormats.CreateErrorEmbed($"{user} is not banned!"));
            }

            _banCache.Set(user.Id, new CacheModel(context.Guild.Id, CacheType.UnbanReject), TimeSpan.FromSeconds(5));

            await context.Guild.RemoveBanAsync(user);

            return(CustomFormats.CreateBasicEmbed($"{user} unbanned", $"{user} was unbanned successfully.", 0x268618));
        }
Example #11
0
        //Fired every time the bot joins a new guild
        private static async Task Client_JoinedGuild(SocketGuild guild)
        {
            if (guild.Owner == null)
            {
                return;
            }

            try
            {
                //We send this message for the guild owner
                await guild.Owner.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed("Hello, I'm Cobra! 👋",
                                                                                          "Thank you for adding me to your server!\nTo get started, type `-setup` in any text channel of your guild." +
                                                                                          "\nIf you need help, you can join the [support server](https://discord.gg/pbkdG7gYeu).",
                                                                                          0x268618));
            }
            catch (HttpException)
            {
                //If the user doesn't have DM's enabled, catch the error
            }
        }
Example #12
0
        /// <summary> Updates guilds' prefix. </summary>
        /// <param name="context"> The command context. </param>
        /// <param name="prefix"> The new prefix. </param>
        public async Task <Embed> ChangePrefix(SocketCommandContext context, string prefix)
        {
            var guildSettings = await _botContext.GetGuildSettings(context.Guild.Id);

            //If user input == default
            if (prefix == "default")
            {
                //Check if the guild has custom prefix
                var currentPrefix = guildSettings.CustomPrefix;

                //If the guild doesn't have custom prefix, return
                if (currentPrefix == null)
                {
                    return(CustomFormats.CreateErrorEmbed("Bot prefix is already the default one!"));
                }


                //If they have a custom prefix, set it to null
                guildSettings.CustomPrefix = null;
                await _botContext.SaveChangesAsync();

                return(CustomFormats.CreateBasicEmbed("Custom prefix changed", "Bot prefix was reset to:  **-**",
                                                      (uint)268618));
            }

            //If user input is longer than 5, return
            if (prefix.Length > 5)
            {
                return(CustomFormats.CreateErrorEmbed("Bot prefix can't be longer than 5 characters!"));
            }

            //If every check passes, we add the new custom prefix to the database
            guildSettings.CustomPrefix = prefix;
            await _botContext.SaveChangesAsync();

            return(CustomFormats.CreateBasicEmbed("Custom prefix changed", $"Cobra's prefix is now:  **{prefix}**",
                                                  0x268618));
        }
Example #13
0
        /// <summary>Fired whenever someone leaves the server.
        /// <para>Used to log a message to a specific text channel.</para>
        /// </summary>
        public async Task UserLeftServer(SocketGuildUser user)
        {
            var guild = user.Guild;

            //Retrieve guild settings
            var guildSettings = _botContext.Guilds.AsNoTracking().FirstOrDefault(x => x.GuildId == guild.Id);

            if (guildSettings is null)
            {
                return;
            }

            //Check if guild has moderation channel enabled
            var welcomeChannel = guild.GetTextChannel(guildSettings.WelcomeChannel);

            if (welcomeChannel == null)
            {
                return;
            }

            //If we do have a valid channel, announce that the user left the server
            await welcomeChannel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed("User left", $"{user} has left the server!", Color.DarkGrey));
        }
Example #14
0
        /// <summary> Gives/removes role from specified user. </summary>
        /// <param name="user"> User to update role. </param>
        /// <param name="operation"> Operation (+ adds role, - removes role). </param>
        /// <param name="role"> Role to give/remove from user. </param>
        public static async Task <Embed> UpdateRoleAsync(IGuildUser user, char operation, IRole role)
        {
            //Get role which name equals role
            //var roleToUpdate = Helper.DoesRoleExist(user.Guild, role);

            var roleToUpdate = role;

            switch (operation)
            {
            case '+':
                await user.AddRoleAsync(roleToUpdate);

                return(CustomFormats.CreateBasicEmbed("Role added", $"Role {roleToUpdate.Name} was successfully added to {user.Username}", 0x268618));

            case '-':
                await user.RemoveRoleAsync(roleToUpdate);

                return(CustomFormats.CreateBasicEmbed("Role removed", $"Role {roleToUpdate.Name} was successfully removed from {user.Username}", 0x268618));

            default:
                return(CustomFormats.CreateErrorEmbed("Invalid operation! Available operations are **+** (add) and **-** (remove)."));
            }
        }
Example #15
0
 /// <summary>
 ///     Changes slowmode for specified text channel.
 /// </summary>
 public static async Task SlowmodeAsync(ITextChannel channel, int interval, SocketCommandContext context)
 {
     await((SocketTextChannel)channel).ModifyAsync(x => x.SlowModeInterval = interval);
     await context.Channel.SendMessageAsync(
         embed : CustomFormats.CreateBasicEmbed("Slowmode changed", "", 0x268618));
 }
Example #16
0
        /// <summary>Plays the requested song or adds it to the queue.
        /// <para>It also joins the voice channel if the bot isn't already joined.</para>
        /// </summary>
        public async Task PlayAsync(SocketCommandContext context, string query)
        {
            var user  = (SocketGuildUser)context.User;
            var guild = context.Guild;

            //Check If User Is Connected To Voice channel.
            if (user.VoiceChannel == null)
            {
                await context.Channel.SendMessageAsync(
                    embed : CustomFormats.CreateErrorEmbed("You must be connected to a voice channel!"));

                return;
            }

            //Check the guild has a player available.
            if (!_lavaNode.HasPlayer(guild))
            {
                //If it doesn't, then it means the bot isn't connected to a voice channel,
                //so we make the bot join a voice channel in order for play command to work
                var voiceState  = (IVoiceState)context.User;
                var textChannel = (ITextChannel)context.Channel;
                await _lavaNode.JoinAsync(voiceState.VoiceChannel, textChannel);
            }

            try
            {
                //Get the player for that guild.
                var player = _lavaNode.GetPlayer(guild);

                LavaTrack track;

                //Find The Youtube Track the User requested.
                var search = Uri.IsWellFormedUriString(query, UriKind.Absolute) ?
                             await _lavaNode.SearchAsync(query)
                    : await _lavaNode.SearchYouTubeAsync(query);

                //If we couldn't find anything, tell the user.
                if (search.LoadStatus == LoadStatus.NoMatches)
                {
                    await context.Channel.SendMessageAsync(
                        embed : CustomFormats.CreateErrorEmbed($"No results found for {query}."));

                    return;
                }

                if (search.LoadStatus == LoadStatus.LoadFailed)
                {
                    await context.Channel.SendMessageAsync(embed : CustomFormats.CreateErrorEmbed("**Failed to load song!**"));

                    return;
                }

                //If results derive from search results (ex: ytsearch: some song)
                if (search.LoadStatus == LoadStatus.SearchResult)
                {
                    //Then load the first track of the search results
                    track = search.Tracks[0];

                    //If the Bot is already playing music, or if it is paused but still has music in the playlist, Add the requested track to the queue.
                    if (player.Track != null && (player.PlayerState is PlayerState.Playing || player.PlayerState is PlayerState.Paused))
                    {
                        player.Queue.Enqueue(track);
                        await player.TextChannel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed("Track queued",
                                                                                                         $"**{track.Title}** has been added to queue. [{context.User.Mention}]\nPosition in queue: `{player.Queue.Count}`", Color.Blue));

                        return;
                    }

                    //Player was not playing anything, so lets play the requested track.
                    await player.PlayAsync(track);

                    return;
                }

                //If results derive from a playlist,
                //If the Bot is already playing music, or if it is paused but still has music in the playlist
                if (player.Track != null && (player.PlayerState is PlayerState.Playing || player.PlayerState is PlayerState.Paused))
                {
                    //Then add all the playlist songs to the queue
                    for (int i = 0; i < search.Tracks.Count; i++)
                    {
                        track = search.Tracks.ElementAt(i);
                        player.Queue.Enqueue(track);
                    }

                    //And send a message saying that X tracks have been added to queue
                    await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed("Tracks queued",
                                                                                                  $"**{search.Tracks.Count} tracks** have been added to queue.",
                                                                                                  Color.Blue));

                    return;
                }

                //If the player isn't playing anything
                //Then add all the songs EXCLUDING the first one, because we will play that one next
                for (int i = 1; i < search.Tracks.Count; i++)
                {
                    track = search.Tracks.ElementAt(i);
                    player.Queue.Enqueue(track);
                }

                //After adding every song except the first, we retrieve the first track
                track = search.Tracks[0];

                //And ask the player to play it
                await player.PlayAsync(track);

                //If there is more than 1 song on search results (playlist) then say that we added every track in the playlist to the queue
                if (search.Tracks.Count - 1 > 0) //-1 because there will always be at least 1 song
                {
                    //Send a message saying that X other tracks have been added to queue
                    await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed("",
                                                                                                  $"{search.Tracks.Count - 1} tracks have been added to queue.", Color.Blue));
                }
            }
            //If after all the checks we did, something still goes wrong. Tell the user about it so they can report it back to us.
            catch (Exception ex)
            {
                await context.Channel.SendMessageAsync(embed : CustomFormats.CreateErrorEmbed(ex.Message));
            }
        }
Example #17
0
        /// <summary>Returns an embed containing the player queue.
        /// </summary>
        public async Task QueueAsync(SocketCommandContext context)
        {
            var guild = context.Guild;

            //Checks if bot is connected to a voice channel
            if (!_lavaNode.HasPlayer(guild))
            {
                await context.Channel.SendMessageAsync(embed : CustomFormats.CreateErrorEmbed("Could not acquire player."));

                return;
            }

            //Bot is connected to voice channel, so we get the player associated with the guild
            var player = _lavaNode.GetPlayer(guild);

            //If player isn't playing, then we return
            if (!(player.PlayerState is PlayerState.Playing))
            {
                await context.Channel.SendMessageAsync(embed : CustomFormats.CreateErrorEmbed("I'm not playing anything right now."));

                return;
            }

            //If there are no more songs in queue except for the current playing song, we return with a reply
            //saying the currently playing song and that no more songs are queued
            if (player.Queue.Count < 1 && player.Track != null)
            {
                await context.Channel.SendMessageAsync(embed : CustomFormats.CreateBasicEmbed("",
                                                                                              $"**Now playing: {player.Track.Title}**\nNo more songs queued.", Color.Blue));

                return;
            }

            try
            {
                //After checking if we have tracks in the queue

                //We save the count of tracks in queue to tracksCount variable
                var tracksCount = player.Queue.Count;

                /* We calculate the maximum items per page we want
                 * this will return the minimum number, either 10 or tracksCount*/
                var maxItemsPerPage = Math.Min(10, tracksCount);

                //We calculate how many pages we'll have (used to initialize array)
                var maxPages = tracksCount / maxItemsPerPage;

                //We initialize an array with size of maxPages
                var pages = new PageBuilder[maxPages];

                var trackNum = 2; //trackNum == 2 because we're not including the first track

                //We itterate through all the pages we need
                for (int i = 0; i < maxPages; i++)
                {
                    var descriptionBuilder = new StringBuilder();

                    //We take X items, equal to the number of maxItemsPerPage, so we don't overflow the embed max description length
                    var tracks = player.Queue.Skip(i).Take(maxItemsPerPage);

                    //We itterate through the tracks taken on the previous instruction
                    foreach (var track in tracks)
                    {
                        //We create the description for each page
                        descriptionBuilder.Append($"{trackNum}: [{track.Title}]({track.Url})\n");
                        trackNum++;
                    }

                    //We create the page, with the description created on the previous loop
                    pages[i] = new PageBuilder().WithTitle($"Now playing: {player.Track?.Title}")
                               .WithDescription($"{descriptionBuilder}").WithColor(Color.Blue);
                }

                //We create the paginator to send
                var paginator = new StaticPaginatorBuilder()
                                .WithUsers(context.User)
                                .WithFooter(PaginatorFooter.PageNumber)
                                .WithEmotes(new Dictionary <IEmote, PaginatorAction>()
                {
                    { new Emoji("⏮️"), PaginatorAction.SkipToStart },
                    { new Emoji("⬅️"), PaginatorAction.Backward },
                    { new Emoji("➡️"), PaginatorAction.Forward },
                    { new Emoji("⏭️"), PaginatorAction.SkipToEnd }
                })
                                .WithPages(pages)
                                .WithTimoutedEmbed(pages[0].Build().Embed.ToEmbedBuilder())
                                .Build();

                //Send the paginator to the text channel
                await _interactivityService.SendPaginatorAsync(paginator, context.Channel, TimeSpan.FromSeconds(150));
            }
            catch (Exception ex)
            {
                await context.Channel.SendMessageAsync(embed : CustomFormats.CreateErrorEmbed(ex.Message));
            }
        }