Search in sources :

Example 1 with GenericMessageReactionEvent

use of net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent in project Pagination-Utils by ygimenez.

the class Pages method categorize.

/**
 * Adds menu-like buttons to the specified {@link Message}/{@link MessageEmbed}
 * which will browse through a given {@link Map} of pages. You may only specify
 * one {@link Page} per button, adding another button with an existing unicode
 * will overwrite the current button's {@link Page}. You can specify how long
 * the listener will stay active before shutting down itself after a no-activity
 * interval.
 *
 * @param msg         The {@link Message} sent which will be categorized.
 * @param categories  The categories to be shown. The categories are defined by
 *                    a {@link Map} containing emoji unicodes or emote ids as keys and
 *                    {@link Pages} as values.
 * @param useButtons  Whether to use interaction {@link Button} or reactions. Will fallback to false if the supplied
 *                    {@link Message} was not sent by the bot.
 * @param time        The time before the listener automatically stop listening
 *                    for further events (recommended: 60).
 * @param unit        The time's {@link TimeUnit} (recommended:
 *                    {@link TimeUnit#SECONDS}).
 * @param canInteract {@link Predicate} to determine whether the {@link User}
 *                    that pressed the button can interact with it or not.
 * @throws ErrorResponseException          Thrown if the {@link Message} no longer exists
 *                                         or cannot be accessed when triggering a
 *                                         {@link GenericMessageReactionEvent}.
 * @throws InsufficientPermissionException Thrown if this library cannot remove reactions
 *                                         due to lack of bot permission.
 * @throws InvalidStateException           Thrown if the library wasn't activated.
 */
public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException {
    if (!isActivated())
        throw new InvalidStateException();
    boolean useBtns = useButtons && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId());
    Map<Emoji, Page> cats = Collections.unmodifiableMap(categories);
    clearButtons(msg);
    clearReactions(msg);
    if (useBtns) {
        List<ActionRow> rows = new ArrayList<>();
        List<Component> row = new ArrayList<>();
        for (Emoji k : cats.keySet()) {
            if (row.size() == 5) {
                rows.add(ActionRow.of(row));
                row = new ArrayList<>();
            }
            row.add(Button.secondary(Emote.getId(k), k));
        }
        Button button = Button.danger(CANCEL.name(), paginator.getEmote(CANCEL));
        if (rows.size() == 5 && row.size() == 5) {
            row.set(4, button);
        } else if (row.size() == 5) {
            rows.add(ActionRow.of(row));
            row = new ArrayList<>();
            row.add(button);
        } else {
            row.add(button);
        }
        rows.add(ActionRow.of(row));
        msg.editMessageComponents(rows).submit();
    } else {
        for (Emoji k : cats.keySet()) {
            msg.addReaction(k.getAsMention().replaceAll("[<>]", "")).submit();
        }
        msg.addReaction(paginator.getStringEmote(CANCEL)).submit();
    }
    return handler.addEvent(msg, new ThrowingBiConsumer<>() {

        private Emoji currCat = null;

        private ScheduledFuture<?> timeout;

        private final Consumer<Void> success = s -> {
            if (timeout != null)
                timeout.cancel(true);
            handler.removeEvent(msg);
            if (paginator.isDeleteOnCancel())
                msg.delete().submit();
        };

        {
            if (time > 0 && unit != null)
                timeout = executor.schedule(() -> finalizeEvent(msg, success), time, unit);
        }

        @Override
        public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) {
            Message m = subGet(wrapper.retrieveMessage());
            if (canInteract == null || canInteract.test(u)) {
                if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId()))
                    return;
                Emoji emoji = null;
                Emote emt = NONE;
                if (wrapper.getContent() instanceof MessageReaction) {
                    MessageReaction.ReactionEmote reaction = ((MessageReaction) wrapper.getContent()).getReactionEmote();
                    emoji = toEmoji(reaction);
                    emt = toEmote(reaction);
                } else if (wrapper.getContent() instanceof Button) {
                    Button btn = (Button) wrapper.getContent();
                    emoji = btn.getEmoji();
                    if (btn.getId() != null && Emote.isNative(btn) && !btn.getId().contains(".")) {
                        emt = Emote.valueOf(btn.getId().replace("*", ""));
                    }
                }
                if (emt == CANCEL) {
                    finalizeEvent(m, success);
                    return;
                } else if (emoji != null && !Objects.equals(emoji, currCat)) {
                    Page pg = cats.get(emoji);
                    if (pg != null) {
                        if (currCat != null && pg instanceof InteractPage) {
                            modifyButtons(m, Map.of(Emote.getId(currCat), Button::asEnabled));
                        }
                        updatePage(m, pg);
                        currCat = emoji;
                        if (pg instanceof InteractPage) {
                            modifyButtons(m, Map.of(Emote.getId(currCat), Button::asDisabled));
                        }
                    }
                }
                if (timeout != null)
                    timeout.cancel(true);
                if (time > 0 && unit != null)
                    timeout = executor.schedule(() -> finalizeEvent(m, success), time, unit);
                if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) {
                    subGet(((MessageReaction) wrapper.getContent()).removeReaction(u));
                }
            }
        }
    });
}
Also used : InsufficientPermissionException(net.dv8tion.jda.api.exceptions.InsufficientPermissionException) net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) java.util(java.util) JDA(net.dv8tion.jda.api.JDA) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Function(java.util.function.Function) MessageHandler(com.github.ygimenez.listener.MessageHandler) Component(net.dv8tion.jda.api.interactions.components.Component) GenericMessageReactionEvent(net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent) Button(net.dv8tion.jda.api.interactions.components.Button) ActionRow(net.dv8tion.jda.api.interactions.components.ActionRow) WeakReference(java.lang.ref.WeakReference) Nonnull(javax.annotation.Nonnull) RestAction(net.dv8tion.jda.api.requests.RestAction) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) ShardManager(net.dv8tion.jda.api.sharding.ShardManager) Emote(com.github.ygimenez.type.Emote) java.util.concurrent(java.util.concurrent) Predicate(java.util.function.Predicate) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) InvalidStateException(com.github.ygimenez.exception.InvalidStateException) Consumer(java.util.function.Consumer) InvalidHandlerException(com.github.ygimenez.exception.InvalidHandlerException) NullPageException(com.github.ygimenez.exception.NullPageException) InteractionHook(net.dv8tion.jda.api.interactions.InteractionHook) AlreadyActivatedException(com.github.ygimenez.exception.AlreadyActivatedException) com.github.ygimenez.model(com.github.ygimenez.model) Button(net.dv8tion.jda.api.interactions.components.Button) Component(net.dv8tion.jda.api.interactions.components.Component) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) ActionRow(net.dv8tion.jda.api.interactions.components.ActionRow) Emote(com.github.ygimenez.type.Emote) InvalidStateException(com.github.ygimenez.exception.InvalidStateException)

Example 2 with GenericMessageReactionEvent

use of net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent in project Pagination-Utils by ygimenez.

the class Pages method paginate.

/**
 * Adds navigation buttons to the specified {@link Message}/{@link MessageEmbed}
 * which will navigate through a given {@link List} of pages. You can specify
 * how long the listener will stay active before shutting down itself after a
 * no-activity interval.
 *
 * @param msg         The {@link Message} sent which will be paginated.
 * @param pages       The pages to be shown. The order of the {@link List} will
 *                    define the order of the pages.
 * @param useButtons  Whether to use interaction {@link Button} or reactions. Will fallback to false if the supplied
 *                    {@link Message} was not sent by the bot.
 * @param time        The time before the listener automatically stop listening
 *                    for further events (recommended: 60).
 * @param unit        The time's {@link TimeUnit} (recommended:
 *                    {@link TimeUnit#SECONDS}).
 * @param skipAmount  The amount of pages to be skipped when clicking {@link Emote#SKIP_BACKWARD}
 *                    and {@link Emote#SKIP_FORWARD} buttons.
 * @param fastForward Whether the {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons should be shown.
 * @param canInteract {@link Predicate} to determine whether the {@link User}
 *                    that pressed the button can interact with it or not.
 * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event
 * is still being processed or was already removed (ie. garbage collected).
 * @throws ErrorResponseException          Thrown if the {@link Message} no longer exists
 *                                         or cannot be accessed when triggering a
 *                                         {@link GenericMessageReactionEvent}.
 * @throws InsufficientPermissionException Thrown if this library cannot remove reactions
 *                                         due to lack of bot permission.
 * @throws InvalidStateException           Thrown if the library wasn't activated or the page list is empty.
 */
public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException {
    if (!isActivated() || pages.isEmpty())
        throw new InvalidStateException();
    boolean useBtns = useButtons && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId());
    List<Page> pgs = Collections.unmodifiableList(pages);
    clearButtons(msg);
    clearReactions(msg);
    Page pg = pgs.get(0);
    if (useBtns)
        addButtons((InteractPage) pg, msg, skipAmount > 1, fastForward);
    else
        addReactions(msg, skipAmount > 1, fastForward);
    return handler.addEvent(msg, new ThrowingBiConsumer<>() {

        private final int maxP = pgs.size() - 1;

        private int p = 0;

        private ScheduledFuture<?> timeout;

        private final Consumer<Void> success = s -> {
            if (timeout != null)
                timeout.cancel(true);
            handler.removeEvent(msg);
            if (paginator.isDeleteOnCancel())
                msg.delete().submit();
        };

        private final Function<Button, Button> LOWER_BOUNDARY_CHECK = b -> b.withDisabled(p == 0);

        private final Function<Button, Button> UPPER_BOUNDARY_CHECK = b -> b.withDisabled(p == maxP);

        {
            if (time > 0 && unit != null)
                timeout = executor.schedule(() -> finalizeEvent(msg, success), time, unit);
        }

        @Override
        public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) {
            Message m = subGet(wrapper.retrieveMessage());
            if (canInteract == null || canInteract.test(u)) {
                if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId()))
                    return;
                Emote emt = NONE;
                if (wrapper.getContent() instanceof MessageReaction) {
                    MessageReaction.ReactionEmote reaction = ((MessageReaction) wrapper.getContent()).getReactionEmote();
                    emt = toEmote(reaction);
                } else if (wrapper.getContent() instanceof Button) {
                    Button btn = (Button) wrapper.getContent();
                    if (btn.getId() != null && Emote.isNative(btn) && !btn.getId().contains(".")) {
                        emt = Emote.valueOf(btn.getId().replace("*", ""));
                    }
                }
                Page pg;
                boolean update = false;
                switch(emt) {
                    case PREVIOUS:
                        if (p > 0) {
                            p--;
                            update = true;
                        }
                        break;
                    case NEXT:
                        if (p < maxP) {
                            p++;
                            update = true;
                        }
                        break;
                    case SKIP_BACKWARD:
                        if (p > 0) {
                            p -= (p - skipAmount < 0 ? p : skipAmount);
                            update = true;
                        }
                        break;
                    case SKIP_FORWARD:
                        if (p < maxP) {
                            p += (p + skipAmount > maxP ? maxP - p : skipAmount);
                            update = true;
                        }
                        break;
                    case GOTO_FIRST:
                        if (p > 0) {
                            p = 0;
                            update = true;
                        }
                        break;
                    case GOTO_LAST:
                        if (p < maxP) {
                            p = maxP;
                            update = true;
                        }
                        break;
                    case CANCEL:
                        finalizeEvent(m, success);
                        return;
                }
                if (update) {
                    pg = pgs.get(p);
                    updatePage(m, pg);
                    updateButtons(m, pg, useBtns, skipAmount > 1, fastForward);
                    if (pg instanceof InteractPage) {
                        modifyButtons(m, Map.of(PREVIOUS.name(), LOWER_BOUNDARY_CHECK, SKIP_BACKWARD.name(), LOWER_BOUNDARY_CHECK, GOTO_FIRST.name(), LOWER_BOUNDARY_CHECK, NEXT.name(), UPPER_BOUNDARY_CHECK, SKIP_FORWARD.name(), UPPER_BOUNDARY_CHECK, GOTO_LAST.name(), UPPER_BOUNDARY_CHECK));
                    }
                }
                if (timeout != null)
                    timeout.cancel(true);
                if (time > 0 && unit != null)
                    timeout = executor.schedule(() -> finalizeEvent(m, success), time, unit);
                if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) {
                    subGet(((MessageReaction) wrapper.getContent()).removeReaction(u));
                }
            }
        }
    });
}
Also used : InsufficientPermissionException(net.dv8tion.jda.api.exceptions.InsufficientPermissionException) net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) java.util(java.util) JDA(net.dv8tion.jda.api.JDA) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Function(java.util.function.Function) MessageHandler(com.github.ygimenez.listener.MessageHandler) Component(net.dv8tion.jda.api.interactions.components.Component) GenericMessageReactionEvent(net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent) Button(net.dv8tion.jda.api.interactions.components.Button) ActionRow(net.dv8tion.jda.api.interactions.components.ActionRow) WeakReference(java.lang.ref.WeakReference) Nonnull(javax.annotation.Nonnull) RestAction(net.dv8tion.jda.api.requests.RestAction) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) ShardManager(net.dv8tion.jda.api.sharding.ShardManager) Emote(com.github.ygimenez.type.Emote) java.util.concurrent(java.util.concurrent) Predicate(java.util.function.Predicate) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) InvalidStateException(com.github.ygimenez.exception.InvalidStateException) Consumer(java.util.function.Consumer) InvalidHandlerException(com.github.ygimenez.exception.InvalidHandlerException) NullPageException(com.github.ygimenez.exception.NullPageException) InteractionHook(net.dv8tion.jda.api.interactions.InteractionHook) AlreadyActivatedException(com.github.ygimenez.exception.AlreadyActivatedException) com.github.ygimenez.model(com.github.ygimenez.model) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) Emote(com.github.ygimenez.type.Emote) InvalidStateException(com.github.ygimenez.exception.InvalidStateException) Button(net.dv8tion.jda.api.interactions.components.Button)

Example 3 with GenericMessageReactionEvent

use of net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent in project Pagination-Utils by ygimenez.

the class Pages method lazyPaginate.

/**
 * Adds navigation buttons to the specified {@link Message}/{@link MessageEmbed}
 * which will lazily load content by using supplied {@link ThrowingFunction}. For this reason,
 * this pagination type cannot have skip nor fast-forward buttons given the unknown page limit
 * You can specify how long the listener will stay active before shutting down itself after a
 * no-activity interval.
 *
 * @param msg         The {@link Message} sent which will be paginated.
 * @param pageLoader  {@link ThrowingFunction}&lt;{@link Integer}, {@link Page}&gt; to generate the next page. If this
 *                    returns null the method will treat it as last page, preventing unnecessary updates.
 * @param useButtons  Whether to use interaction {@link Button} or reactions. Will fallback to false if the supplied
 *                    {@link Message} was not sent by the bot.
 * @param cache       Enables {@link Page} caching, saving previously visited pages.
 * @param time        The time before the listener automatically stop listening
 *                    for further events (recommended: 60).
 * @param unit        The time's {@link TimeUnit} (recommended:
 *                    {@link TimeUnit#SECONDS}).
 * @param canInteract {@link Predicate} to determine whether the {@link User}
 *                    that pressed the button can interact with it or not.
 * @throws ErrorResponseException          Thrown if the {@link Message} no longer exists
 *                                         or cannot be accessed when triggering a
 *                                         {@link GenericMessageReactionEvent}.
 * @throws InsufficientPermissionException Thrown if this library cannot remove reactions
 *                                         due to lack of bot permission.
 * @throws InvalidStateException           Thrown if the library wasn't activated or first page cannot be generated.
 */
public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, boolean cache, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException {
    if (!isActivated())
        throw new InvalidStateException();
    boolean useBtns = useButtons && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId());
    clearButtons(msg);
    clearReactions(msg);
    List<Page> pageCache = cache ? new ArrayList<>() : null;
    Page pg = pageLoader.apply(0);
    if (pg == null) {
        throw new InvalidStateException();
    }
    if (cache)
        pageCache.add(pg);
    if (useBtns)
        addButtons((InteractPage) pg, msg, false, false);
    else
        addReactions(msg, false, false);
    return handler.addEvent(msg, new ThrowingBiConsumer<>() {

        private int p = 0;

        private ScheduledFuture<?> timeout;

        private final Consumer<Void> success = s -> {
            if (timeout != null)
                timeout.cancel(true);
            handler.removeEvent(msg);
            if (paginator.isDeleteOnCancel())
                msg.delete().submit();
        };

        {
            if (time > 0 && unit != null)
                timeout = executor.schedule(() -> finalizeEvent(msg, success), time, unit);
        }

        @Override
        public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) {
            Message m = subGet(wrapper.retrieveMessage());
            if (canInteract == null || canInteract.test(u)) {
                if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId()))
                    return;
                Emote emt = NONE;
                if (wrapper.getContent() instanceof MessageReaction) {
                    MessageReaction.ReactionEmote reaction = ((MessageReaction) wrapper.getContent()).getReactionEmote();
                    emt = toEmote(reaction);
                } else if (wrapper.getContent() instanceof Button) {
                    Button btn = (Button) wrapper.getContent();
                    if (btn.getId() != null && Emote.isNative(btn) && !btn.getId().contains(".")) {
                        emt = Emote.valueOf(btn.getId().replace("*", ""));
                    }
                }
                Page pg;
                switch(emt) {
                    case PREVIOUS:
                        if (p > 0) {
                            p--;
                            pg = cache ? pageCache.get(p) : pageLoader.apply(p);
                            updatePage(m, pg);
                            updateButtons(m, pg, useBtns, false, false);
                        }
                        break;
                    case NEXT:
                        p++;
                        if (cache && pageCache.size() > p) {
                            pg = pageCache.get(p);
                        } else {
                            pg = pageLoader.apply(p);
                            if (pg == null) {
                                p--;
                                return;
                            }
                        }
                        updatePage(m, pg);
                        updateButtons(m, pg, useBtns, false, false);
                        if (cache)
                            pageCache.add(pg);
                        break;
                    case CANCEL:
                        finalizeEvent(m, success);
                        return;
                }
                if (timeout != null)
                    timeout.cancel(true);
                if (time > 0 && unit != null)
                    timeout = executor.schedule(() -> finalizeEvent(m, success), time, unit);
                if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) {
                    subGet(((MessageReaction) wrapper.getContent()).removeReaction(u));
                }
            }
        }
    });
}
Also used : InsufficientPermissionException(net.dv8tion.jda.api.exceptions.InsufficientPermissionException) net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) java.util(java.util) JDA(net.dv8tion.jda.api.JDA) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Function(java.util.function.Function) MessageHandler(com.github.ygimenez.listener.MessageHandler) Component(net.dv8tion.jda.api.interactions.components.Component) GenericMessageReactionEvent(net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent) Button(net.dv8tion.jda.api.interactions.components.Button) ActionRow(net.dv8tion.jda.api.interactions.components.ActionRow) WeakReference(java.lang.ref.WeakReference) Nonnull(javax.annotation.Nonnull) RestAction(net.dv8tion.jda.api.requests.RestAction) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) ShardManager(net.dv8tion.jda.api.sharding.ShardManager) Emote(com.github.ygimenez.type.Emote) java.util.concurrent(java.util.concurrent) Predicate(java.util.function.Predicate) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) InvalidStateException(com.github.ygimenez.exception.InvalidStateException) Consumer(java.util.function.Consumer) InvalidHandlerException(com.github.ygimenez.exception.InvalidHandlerException) NullPageException(com.github.ygimenez.exception.NullPageException) InteractionHook(net.dv8tion.jda.api.interactions.InteractionHook) AlreadyActivatedException(com.github.ygimenez.exception.AlreadyActivatedException) com.github.ygimenez.model(com.github.ygimenez.model) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) Emote(com.github.ygimenez.type.Emote) InvalidStateException(com.github.ygimenez.exception.InvalidStateException) Button(net.dv8tion.jda.api.interactions.components.Button)

Example 4 with GenericMessageReactionEvent

use of net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent in project Pagination-Utils by ygimenez.

the class Pages method buttonize.

/**
 * Adds buttons to the specified {@link Message}/{@link MessageEmbed}, with each
 * executing a specific task on click. You may only specify one {@link Runnable}
 * per button, adding another button with an existing unicode will overwrite the
 * current button's {@link Runnable}. You can specify the time in which the
 * listener will automatically stop itself after a no-activity interval.
 *
 * @param msg              The {@link Message} sent which will be buttoned.
 * @param buttons          The buttons to be shown. The buttons are defined by a
 *                         Map containing emoji unicodes or emote ids as keys and
 *                         {@link ThrowingTriConsumer}&lt;{@link Member}, {@link Message}, {@link InteractionHook}&gt;
 *                         containing desired behavior as value.
 * @param useButtons       Whether to use interaction {@link Button} or reactions. Will fallback to false if the supplied
 *                         {@link Message} was not sent by the bot.
 * @param showCancelButton Should the {@link Emote#CANCEL} button be created automatically?
 * @param time             The time before the listener automatically stop
 *                         listening for further events (recommended: 60).
 * @param unit             The time's {@link TimeUnit} (recommended:
 *                         {@link TimeUnit#SECONDS}).
 * @param canInteract      {@link Predicate} to determine whether the
 *                         {@link User} that pressed the button can interact
 *                         with it or not.
 * @param onCancel         Action to be run after the listener is removed.
 * @throws ErrorResponseException          Thrown if the {@link Message} no longer exists
 *                                         or cannot be accessed when triggering a
 *                                         {@link GenericMessageReactionEvent}.
 * @throws InsufficientPermissionException Thrown if this library cannot remove reactions
 *                                         due to lack of bot permission.
 * @throws InvalidStateException           Thrown if the library wasn't activated.
 */
public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException {
    if (!isActivated())
        throw new InvalidStateException();
    boolean useBtns = useButtons && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId());
    Map<Emoji, ThrowingConsumer<ButtonWrapper>> btns = Collections.unmodifiableMap(buttons);
    clearButtons(msg);
    clearReactions(msg);
    if (useBtns) {
        List<ActionRow> rows = new ArrayList<>();
        List<Component> row = new ArrayList<>();
        for (Emoji k : btns.keySet()) {
            if (row.size() == 5) {
                rows.add(ActionRow.of(row));
                row = new ArrayList<>();
            }
            row.add(Button.secondary(Emote.getId(k), k));
        }
        if (!btns.containsKey(paginator.getEmote(CANCEL)) && showCancelButton) {
            Button button = Button.danger(CANCEL.name(), paginator.getEmote(CANCEL));
            if (rows.size() == 5 && row.size() == 5) {
                row.set(4, button);
            } else if (row.size() == 5) {
                rows.add(ActionRow.of(row));
                row = new ArrayList<>();
                row.add(button);
            } else {
                row.add(button);
            }
        }
        rows.add(ActionRow.of(row));
        msg.editMessageComponents(rows).submit();
    } else {
        for (Emoji k : btns.keySet()) {
            msg.addReaction(k.getAsMention().replaceAll("[<>]", "")).submit();
        }
        if (!btns.containsKey(paginator.getEmote(CANCEL)) && showCancelButton)
            msg.addReaction(paginator.getStringEmote(CANCEL)).submit();
    }
    return handler.addEvent(msg, new ThrowingBiConsumer<>() {

        private ScheduledFuture<?> timeout;

        private final Consumer<Void> success = s -> {
            if (timeout != null)
                timeout.cancel(true);
            handler.removeEvent(msg);
            if (onCancel != null)
                onCancel.accept(msg);
            if (paginator.isDeleteOnCancel())
                msg.delete().submit();
        };

        {
            if (time > 0 && unit != null)
                timeout = executor.schedule(() -> finalizeEvent(msg, success), time, unit);
        }

        @Override
        public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) {
            Message m = subGet(wrapper.retrieveMessage());
            if (canInteract == null || canInteract.test(u)) {
                if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId()))
                    return;
                Emoji emoji = null;
                Emote emt = NONE;
                if (wrapper.getContent() instanceof MessageReaction) {
                    MessageReaction.ReactionEmote reaction = ((MessageReaction) wrapper.getContent()).getReactionEmote();
                    emoji = toEmoji(reaction);
                    emt = toEmote(reaction);
                } else if (wrapper.getContent() instanceof Button) {
                    Button btn = (Button) wrapper.getContent();
                    emoji = btn.getEmoji();
                    if (btn.getId() != null && Emote.isNative(btn) && !btn.getId().contains(".")) {
                        emt = Emote.valueOf(btn.getId().replace("*", ""));
                    }
                }
                if ((!btns.containsKey(paginator.getEmote(CANCEL)) && showCancelButton) && emt == CANCEL) {
                    finalizeEvent(m, success);
                    return;
                }
                InteractionHook hook;
                if (wrapper.getSource() instanceof ButtonClickEvent) {
                    hook = ((ButtonClickEvent) wrapper.getSource()).getHook();
                } else {
                    hook = null;
                }
                ThrowingConsumer<ButtonWrapper> act = btns.get(emoji);
                if (act != null) {
                    act.accept(new ButtonWrapper(wrapper.getUser(), hook, m));
                }
                if (timeout != null)
                    timeout.cancel(true);
                if (time > 0 && unit != null)
                    timeout = executor.schedule(() -> finalizeEvent(m, success), time, unit);
                if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) {
                    subGet(((MessageReaction) wrapper.getContent()).removeReaction(u));
                }
            }
        }
    });
}
Also used : InsufficientPermissionException(net.dv8tion.jda.api.exceptions.InsufficientPermissionException) net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) java.util(java.util) JDA(net.dv8tion.jda.api.JDA) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Function(java.util.function.Function) MessageHandler(com.github.ygimenez.listener.MessageHandler) Component(net.dv8tion.jda.api.interactions.components.Component) GenericMessageReactionEvent(net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent) Button(net.dv8tion.jda.api.interactions.components.Button) ActionRow(net.dv8tion.jda.api.interactions.components.ActionRow) WeakReference(java.lang.ref.WeakReference) Nonnull(javax.annotation.Nonnull) RestAction(net.dv8tion.jda.api.requests.RestAction) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) ShardManager(net.dv8tion.jda.api.sharding.ShardManager) Emote(com.github.ygimenez.type.Emote) java.util.concurrent(java.util.concurrent) Predicate(java.util.function.Predicate) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) InvalidStateException(com.github.ygimenez.exception.InvalidStateException) Consumer(java.util.function.Consumer) InvalidHandlerException(com.github.ygimenez.exception.InvalidHandlerException) NullPageException(com.github.ygimenez.exception.NullPageException) InteractionHook(net.dv8tion.jda.api.interactions.InteractionHook) AlreadyActivatedException(com.github.ygimenez.exception.AlreadyActivatedException) com.github.ygimenez.model(com.github.ygimenez.model) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Button(net.dv8tion.jda.api.interactions.components.Button) Component(net.dv8tion.jda.api.interactions.components.Component) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) ActionRow(net.dv8tion.jda.api.interactions.components.ActionRow) Emote(com.github.ygimenez.type.Emote) InvalidStateException(com.github.ygimenez.exception.InvalidStateException) InteractionHook(net.dv8tion.jda.api.interactions.InteractionHook)

Aggregations

AlreadyActivatedException (com.github.ygimenez.exception.AlreadyActivatedException)4 InvalidHandlerException (com.github.ygimenez.exception.InvalidHandlerException)4 InvalidStateException (com.github.ygimenez.exception.InvalidStateException)4 NullPageException (com.github.ygimenez.exception.NullPageException)4 MessageHandler (com.github.ygimenez.listener.MessageHandler)4 com.github.ygimenez.model (com.github.ygimenez.model)4 Emote (com.github.ygimenez.type.Emote)4 WeakReference (java.lang.ref.WeakReference)4 java.util (java.util)4 java.util.concurrent (java.util.concurrent)4 Consumer (java.util.function.Consumer)4 Function (java.util.function.Function)4 Predicate (java.util.function.Predicate)4 Nonnull (javax.annotation.Nonnull)4 JDA (net.dv8tion.jda.api.JDA)4 net.dv8tion.jda.api.entities (net.dv8tion.jda.api.entities)4 ButtonClickEvent (net.dv8tion.jda.api.events.interaction.ButtonClickEvent)4 GenericMessageReactionEvent (net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent)4 MessageReactionAddEvent (net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent)4 ErrorResponseException (net.dv8tion.jda.api.exceptions.ErrorResponseException)4