public async Task GeneratePaginationReactions(DiscordMessage message, PaginationEmojis emojis)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            await message.CreateReactionAsync(emojis.SkipLeft).ConfigureAwait(false);

            await message.CreateReactionAsync(emojis.Left).ConfigureAwait(false);

            await message.CreateReactionAsync(emojis.Stop).ConfigureAwait(false);

            await message.CreateReactionAsync(emojis.Right).ConfigureAwait(false);

            await message.CreateReactionAsync(emojis.SkipRight).ConfigureAwait(false);
        }
        /// <summary>
        /// Responds with a paginated message
        /// </summary>
        /// <param name="mes">Message that is responded to</param>
        /// <param name="user">User that is allowed to interact with this paginated message</param>
        /// <param name="pages">Message pages</param>
        /// <param name="emojis">Pagination emojis</param>
        /// <param name="timeoutoverride">Timeout override</param>
        /// <param name="timeoutbehaviouroverride">Timeout behaviour override</param>
        /// <returns></returns>
        public static async Task RespondPaginated(this DiscordMessage mes, DiscordUser user, IEnumerable <Page> pages,
                                                  PaginationEmojis emojis = null, TimeSpan?timeoutoverride = null, TimeoutBehaviour?timeoutbehaviouroverride = null)
        {
            if (mes.Discord.GetType() != typeof(DiscordClient))
            {
                throw new InvalidOperationException("Your client is not a default DiscordClient!");
            }

            var client = (DiscordClient)mes.Discord;

            if (client.GetInteractivity() == null)
            {
                throw new NullReferenceException("Your interactivity module has not been initialized for this client!");
            }

            var interactivity = client.GetInteractivity();

            await interactivity.SendPaginatedMessage(mes.Channel, user, pages, timeoutoverride, timeoutbehaviouroverride, emojis);
        }
Example #3
0
 /// <summary>
 /// Sends a paginated message
 /// </summary>
 /// <param name="c">Channel to send message in.</param>
 /// <param name="user">User to control pagination.</param>
 /// <param name="pages">Pages to send.</param>
 /// <param name="emojis">Pagination emojis (emojis set to null will be disabled)</param>
 /// <param name="behaviour">Pagination behaviour.</param>
 /// <param name="deletion">Deletion behaviour.</param>
 /// <param name="timeoutoverride">Override timeout period.</param>
 /// <returns></returns>
 public static async Task SendPaginatedMessageAsync(this DiscordChannel c, DiscordUser user, Page[] pages, PaginationEmojis emojis,
                                                    PaginationBehaviour behaviour = PaginationBehaviour.Default, PaginationDeletion deletion = PaginationDeletion.Default,
                                                    TimeSpan?timeoutoverride      = null)
 => await((DiscordClient)c.Discord).GetInteractivity().SendPaginatedMessageAsync(c, user, pages, emojis, behaviour, deletion, timeoutoverride);
        /// <summary>
        /// Sends a paginated message.
        /// </summary>
        /// <param name="c">Channel to send paginated message in.</param>
        /// <param name="u">User to give control.</param>
        /// <param name="pages">Pages.</param>
        /// <param name="emojis">Pagination emojis (emojis set to null get disabled).</param>
        /// <param name="behaviour">Pagination behaviour (when hitting max and min indices).</param>
        /// <param name="deletion">Deletion behaviour.</param>
        /// <param name="timeoutoverride">Override timeout period.</param>
        /// <returns></returns>
        public async Task SendPaginatedMessageAsync(DiscordChannel c, DiscordUser u, IEnumerable <Page> pages, PaginationEmojis emojis = null,
                                                    PaginationBehaviour behaviour = PaginationBehaviour.Default, PaginationDeletion deletion = PaginationDeletion.Default, TimeSpan?timeoutoverride = null)
        {
            var m = await c.SendMessageAsync(pages.First().Content, false, pages.First().Embed);

            var timeout = timeoutoverride ?? Config.Timeout;

            var bhv = behaviour == PaginationBehaviour.Default ? this.Config.PaginationBehaviour : behaviour;
            var del = deletion == PaginationDeletion.Default ? this.Config.PaginationDeletion : deletion;
            var ems = emojis ?? this.Config.PaginationEmojis;

            var prequest = new PaginationRequest(m, u, bhv, del, ems, timeout, pages.ToArray());

            await Paginator.DoPaginationAsync(prequest);
        }
        /// <summary>
        /// Sends a paginated message.
        /// For this Event you need the <see cref="DiscordIntents.GuildMessageReactions"/> intent specified in <seealso cref="DiscordConfiguration.Intents"/>
        /// </summary>
        /// <param name="c">Channel to send paginated message in.</param>
        /// <param name="u">User to give control.</param>
        /// <param name="pages">Pages.</param>
        /// <param name="emojis">Pagination emojis (emojis set to null get disabled).</param>
        /// <param name="behaviour">Pagination behaviour (when hitting max and min indices).</param>
        /// <param name="deletion">Deletion behaviour.</param>
        /// <param name="timeoutoverride">Override timeout period.</param>
        /// <returns></returns>
        public async Task SendPaginatedMessageAsync(DiscordChannel c, DiscordUser u, IEnumerable <Page> pages, PaginationEmojis emojis = null,
                                                    PaginationBehaviour?behaviour = default, PaginationDeletion?deletion = default, TimeSpan?timeoutoverride = null)
        {
            var builder = new DiscordMessageBuilder()
                          .WithContent(pages.First().Content)
                          .WithEmbed(pages.First().Embed);
            var m = await builder.SendAsync(c).ConfigureAwait(false);

            var timeout = timeoutoverride ?? this.Config.Timeout;

            var bhv = behaviour ?? this.Config.PaginationBehaviour;
            var del = deletion ?? this.Config.PaginationDeletion;
            var ems = emojis ?? this.Config.PaginationEmojis;

            var prequest = new PaginationRequest(m, u, bhv, del, ems, timeout, pages.ToArray());

            await Paginator.DoPaginationAsync(prequest).ConfigureAwait(false);
        }
        public async Task SendPaginatedMessage(DiscordChannel channel, DiscordUser user, IEnumerable <Page> message_pages, TimeSpan?timeoutoverride = null,
                                               TimeoutBehaviour?timeoutbehaviouroverride = null, PaginationEmojis emojis = null)
        {
            if (channel == null)
            {
                throw new ArgumentNullException(nameof(channel));
            }
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }
            if (message_pages == null)
            {
                throw new ArgumentNullException(nameof(message_pages));
            }
            if (message_pages.Count() < 1)
            {
                throw new InvalidOperationException("This method can only be executed with a minimum of one page!");
            }

            if (message_pages.Count() == 1)
            {
                await this.Client.SendMessageAsync(channel, string.IsNullOrEmpty(message_pages.First().Content)? "" : message_pages.First().Content, embed : message_pages.First().Embed).ConfigureAwait(false);

                return;
            }

            TimeSpan timeout = Config.Timeout;

            if (timeoutoverride != null)
            {
                timeout = (TimeSpan)timeoutoverride;
            }

            TimeoutBehaviour timeout_behaviour = Config.PaginationBehavior;

            if (timeoutbehaviouroverride != null)
            {
                timeout_behaviour = (TimeoutBehaviour)timeoutbehaviouroverride;
            }

            List <Page> pages = message_pages.ToList();

            if (pages.Count() == 0)
            {
                throw new ArgumentException("You need to provide at least 1 page!");
            }

            var tsc = new TaskCompletionSource <string>();
            var ct  = new CancellationTokenSource(timeout);

            ct.Token.Register(() => tsc.TrySetResult(null));

            DiscordMessage m = await this.Client.SendMessageAsync(channel, string.IsNullOrEmpty(pages.First().Content)? "" : pages.First().Content, embed : pages.First().Embed).ConfigureAwait(false);

            PaginatedMessage pm = new PaginatedMessage()
            {
                CurrentIndex = 0,
                Pages        = pages,
                Timeout      = timeout
            };

            emojis = emojis ?? new PaginationEmojis(this.Client);

            await this.GeneratePaginationReactions(m, emojis).ConfigureAwait(false);

            try
            {
                this.Client.MessageReactionsCleared += ReactionClearHandler;
                this.Client.MessageReactionAdded    += ReactionAddHandler;
                this.Client.MessageReactionRemoved  += ReactionRemoveHandler;

                await tsc.Task.ConfigureAwait(false);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                this.Client.MessageReactionsCleared -= ReactionClearHandler;
                this.Client.MessageReactionAdded    -= ReactionAddHandler;
                this.Client.MessageReactionRemoved  -= ReactionRemoveHandler;

                switch (timeout_behaviour)
                {
                case TimeoutBehaviour.Ignore:
                    await m.DeleteAllReactionsAsync().ConfigureAwait(false);

                    break;

                case TimeoutBehaviour.DeleteMessage:
                    // deleting a message deletes all reactions anyway
                    //await m.DeleteAllReactionsAsync().ConfigureAwait(false);
                    await m.DeleteAsync().ConfigureAwait(false);

                    break;

                case TimeoutBehaviour.DeleteReactions:
                    await m.DeleteAllReactionsAsync().ConfigureAwait(false);

                    break;
                }
            }

            #region Handlers
            async Task ReactionAddHandler(MessageReactionAddEventArgs e)
            {
                if (e.Message.Id == m.Id && e.User.Id != this.Client.CurrentUser.Id && e.User.Id == user.Id)
                {
                    ct.Dispose();
                    ct = new CancellationTokenSource(timeout);
                    ct.Token.Register(() => tsc.TrySetResult(null));
                    await this.DoPagination(e.Emoji, m, pm, ct, emojis).ConfigureAwait(false);
                }
            }

            async Task ReactionRemoveHandler(MessageReactionRemoveEventArgs e)
            {
                if (e.Message.Id == m.Id && e.User.Id != this.Client.CurrentUser.Id && e.User.Id == user.Id)
                {
                    ct.Dispose();
                    ct = new CancellationTokenSource(timeout);
                    ct.Token.Register(() => tsc.TrySetResult(null));
                    await this.DoPagination(e.Emoji, m, pm, ct, emojis).ConfigureAwait(false);
                }
            }

            async Task ReactionClearHandler(MessageReactionsClearEventArgs e)
            {
                await this.GeneratePaginationReactions(m, emojis).ConfigureAwait(false);
            }

            #endregion
        }
        public async Task DoPagination(DiscordEmoji emoji, DiscordMessage message, PaginatedMessage paginatedmessage, CancellationTokenSource canceltoken, PaginationEmojis emojis)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            if (paginatedmessage == null)
            {
                throw new ArgumentNullException(nameof(paginatedmessage));
            }
            if (emoji == null)
            {
                throw new ArgumentNullException(nameof(emoji));
            }
            if (canceltoken == null)
            {
                throw new ArgumentNullException(nameof(canceltoken));
            }

            #region The "good" shit
            // used brackets everywhere for the sake of consistency
            if (emoji == emojis.SkipLeft)
            {
                paginatedmessage.CurrentIndex = 0;
            }
            else if (emoji == emojis.Left)
            {
                if (paginatedmessage.CurrentIndex != 0)
                {
                    paginatedmessage.CurrentIndex--;
                }
            }
            else if (emoji == emojis.Stop)
            {
                canceltoken.Cancel();
            }
            else if (emoji == emojis.Right)
            {
                if (paginatedmessage.CurrentIndex != paginatedmessage.Pages.Count() - 1)
                {
                    paginatedmessage.CurrentIndex++;
                }
            }
            else if (emoji == emojis.SkipRight)
            {
                paginatedmessage.CurrentIndex = paginatedmessage.Pages.Count() - 1;
            }
            else
            {
                return;
            }

            await message.ModifyAsync((string.IsNullOrEmpty(paginatedmessage.Pages.ToArray()[paginatedmessage.CurrentIndex].Content))? "" : paginatedmessage.Pages.ToArray()[paginatedmessage.CurrentIndex].Content,
                                      embed : paginatedmessage.Pages.ToArray()[paginatedmessage.CurrentIndex].Embed ?? null).ConfigureAwait(false);

            #endregion
        }