From 177cac5985ab0c5105710516d566f846051eabb8 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Fri, 18 Mar 2022 11:29:10 -0300 Subject: [PATCH 01/31] Created helper classes to aid Pages methods' customization; Removed `boolean cache` from lazyPaginate methods, replaced with `List<Page> pageCache` to allow cache modification on the go. --- .../com/github/ygimenez/method/Pages.java | 157 +++++++++++++++--- .../ygimenez/model/helper/BaseHelper.java | 81 +++++++++ .../model/helper/ButtonizeHelper.java | 36 ++++ .../model/helper/CategorizeHelper.java | 23 +++ .../model/helper/LazyPaginateHelper.java | 36 ++++ .../ygimenez/model/helper/PaginateHelper.java | 43 +++++ 6 files changed, 352 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/github/ygimenez/model/helper/BaseHelper.java create mode 100644 src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java create mode 100644 src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java create mode 100644 src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java create mode 100644 src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index bf6f264..fb1a4cf 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -6,6 +6,10 @@ import com.github.ygimenez.exception.NullPageException; import com.github.ygimenez.listener.MessageHandler; import com.github.ygimenez.model.*; +import com.github.ygimenez.model.helper.ButtonizeHelper; +import com.github.ygimenez.model.helper.CategorizeHelper; +import com.github.ygimenez.model.helper.LazyPaginateHelper; +import com.github.ygimenez.model.helper.PaginateHelper; import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; @@ -113,6 +117,32 @@ public static MessageHandler getHandler() { return handler; } + /** + * Adds navigation buttons to the specified {@link Message}/{@link MessageEmbed} + * which will navigate through a given {@link List} of pages. This versions uses a helper class + * to aid customization and allow reusage of configurations. + * + * @param helper A {@link PaginateHelper} holding desired pagination settings. + * @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 void paginate(@Nonnull PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + paginate( + helper.getMessage(), + helper.getContent(), + helper.isUsingButtons(), + helper.getTime(), + helper.getUnit(), + helper.getSkipAmount(), + helper.isFastForward(), + helper.getCanInteract() + ); + } + /** * Adds navigation buttons to the specified {@link Message}/{@link MessageEmbed} * which will navigate through a given {@link List} of pages. @@ -620,6 +650,32 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe }); } + /** + * 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}. This versions uses a helper class + * to aid customization and allow reusage of configurations. + * + * @param helper A {@link CategorizeHelper} holding desired categorization settings. + * @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 void categorize(@Nonnull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { + categorize( + helper.getMessage(), + helper.getContent(), + helper.isUsingButtons(), + helper.getTime(), + helper.getUnit(), + helper.getCanInteract() + ); + } + /** * 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 @@ -836,6 +892,34 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe }); } + /** + * 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}. This versions uses a helper class + * to aid customization and allow reusage of configurations. + * + * @param helper A {@link ButtonizeHelper} holding desired buttonization settings. + * @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 void buttonize(@Nonnull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { + buttonize( + helper.getMessage(), + helper.getContent(), + helper.isUsingButtons(), + helper.isCancellable(), + helper.getTime(), + helper.getUnit(), + helper.getCanInteract(), + helper.getOnCancel() + ); + } + /** * Adds buttons to the specified {@link Message}/{@link MessageEmbed}, with each * executing a specific task on click. You may only specify one {@link Runnable} @@ -1129,7 +1213,33 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe /** * 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 + * this pagination type cannot have skip nor fast-forward buttons given the unknown page limit. + * This versions uses a helper class to aid customization and allow reusage of configurations. + * + * @param helper A {@link LazyPaginateHelper} holding desired lazy pagination settings. + * @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 void lazyPaginate(@Nonnull LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + lazyPaginate( + helper.getMessage(), + helper.getContent(), + helper.getPageLoader(), + helper.isUsingButtons(), + helper.getTime(), + helper.getUnit(), + helper.getCanInteract() + ); + } + + /** + * 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. * * @param msg The {@link Message} sent which will be paginated. * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> to generate the next page. If this @@ -1144,7 +1254,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageLoader, useButtons, false, 0, null, null); + lazyPaginate(msg, null, pageLoader, useButtons, 0, null, null); } /** @@ -1171,13 +1281,13 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageLoader, useButtons, false, time, unit, null); + lazyPaginate(msg, null, pageLoader, useButtons, time, unit, null); } /** * 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 + * this pagination type cannot have skip nor fast-forward buttons given the unknown page limit. * * @param msg The {@link Message} sent which will be paginated. * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> to generate the next page. If this @@ -1194,13 +1304,13 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageLoader, useButtons, false, 0, null, canInteract); + lazyPaginate(msg, null, pageLoader, useButtons, 0, null, canInteract); } /** * 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 + * 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. * @@ -1223,20 +1333,20 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageLoader, useButtons, false, time, unit, canInteract); + lazyPaginate(msg, null, pageLoader, useButtons, time, unit, canInteract); } /** * 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 + * this pagination type cannot have skip nor fast-forward buttons given the unknown page limit. * * @param msg The {@link Message} sent which will be paginated. + * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> 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. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1244,23 +1354,23 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, boolean cache) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageLoader, useButtons, cache, 0, null, null); + public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, null); } /** * 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 + * 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 pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> 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: @@ -1272,21 +1382,21 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, boolean cache, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageLoader, useButtons, cache, time, unit, null); + public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + lazyPaginate(msg, pageCache, pageLoader, useButtons, time, unit, null); } /** * 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 + * this pagination type cannot have skip nor fast-forward buttons given the unknown page limit. * * @param msg The {@link Message} sent which will be paginated. + * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> 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 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 @@ -1296,23 +1406,23 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, boolean cache, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageLoader, useButtons, cache, 0, null, canInteract); + public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, canInteract); } /** * 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 + * 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 pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> 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: @@ -1326,17 +1436,16 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, boolean cache, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, 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()); + boolean cache = pageCache != null; if (!msg.getAuthor().equals(paginator.getHandler())) clearButtons(msg); clearReactions(msg); - List<Page> pageCache = cache ? new ArrayList<>() : null; - Page pg = pageLoader.apply(0); if (pg == null) { throw new InvalidStateException(); diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java new file mode 100644 index 0000000..e781583 --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -0,0 +1,81 @@ +package com.github.ygimenez.model.helper; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.User; + +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; + +abstract class BaseHelper<Sub extends BaseHelper<Sub, T>, T> { + private final Class<Sub> subClass; + + private final Message message; + private final T content; + private final boolean useButtons; + + private boolean cancellable = true; + private int time = 0; + private TimeUnit unit = null; + private Predicate<User> canInteract = null; + + public BaseHelper(Class<Sub> subClass, Message message, T buttons, boolean useButtons) { + this.subClass = subClass; + this.message = message; + this.content = buttons; + this.useButtons = useButtons; + } + + public Message getMessage() { + return message; + } + + public T getContent() { + return content; + } + + public boolean isUsingButtons() { + return useButtons; + } + + public boolean isCancellable() { + return cancellable; + } + + public int getTime() { + return time; + } + + public TimeUnit getUnit() { + return unit; + } + + public Predicate<User> getCanInteract() { + return canInteract; + } + + protected Sub setCancellable(boolean cancellable) { + this.cancellable = cancellable; + return subClass.cast(this); + } + + protected Sub setTime(int time) { + this.time = time; + return subClass.cast(this); + } + + protected Sub setUnit(TimeUnit unit) { + this.unit = unit; + return subClass.cast(this); + } + + protected Sub setTimeUnit(int time, TimeUnit unit) { + this.time = time; + this.unit = unit; + return subClass.cast(this); + } + + protected Sub setCanInteract(Predicate<User> canInteract) { + this.canInteract = canInteract; + return subClass.cast(this); + } +} diff --git a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java new file mode 100644 index 0000000..6e9884d --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java @@ -0,0 +1,36 @@ +package com.github.ygimenez.model.helper; + +import com.github.ygimenez.model.ButtonWrapper; +import com.github.ygimenez.model.ThrowingConsumer; +import net.dv8tion.jda.api.entities.Emoji; +import net.dv8tion.jda.api.entities.Message; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Consumer; + +public class ButtonizeHelper extends BaseHelper<ButtonizeHelper, Map<Emoji, ThrowingConsumer<ButtonWrapper>>> { + private Consumer<Message> onCancel = null; + + public ButtonizeHelper(Message message, boolean useButtons) { + super(ButtonizeHelper.class, message, new LinkedHashMap<>(), useButtons); + } + + public ButtonizeHelper(Message message, Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons) { + super(ButtonizeHelper.class, message, buttons, useButtons); + } + + public ButtonizeHelper addCategory(Emoji emoji, ThrowingConsumer<ButtonWrapper> action) { + getContent().put(emoji, action); + return this; + } + + public Consumer<Message> getOnCancel() { + return onCancel; + } + + public ButtonizeHelper setOnCancel(Consumer<Message> onCancel) { + this.onCancel = onCancel; + return this; + } +} diff --git a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java new file mode 100644 index 0000000..f1d0157 --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java @@ -0,0 +1,23 @@ +package com.github.ygimenez.model.helper; + +import com.github.ygimenez.model.Page; +import net.dv8tion.jda.api.entities.Emoji; +import net.dv8tion.jda.api.entities.Message; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class CategorizeHelper extends BaseHelper<CategorizeHelper, Map<Emoji, Page>> { + public CategorizeHelper(Message message, boolean useButtons) { + super(CategorizeHelper.class, message, new LinkedHashMap<>(), useButtons); + } + + public CategorizeHelper(Message message, Map<Emoji, Page> categories, boolean useButtons) { + super(CategorizeHelper.class, message, categories, useButtons); + } + + public CategorizeHelper addCategory(Emoji emoji, Page page) { + getContent().put(emoji, page); + return this; + } +} diff --git a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java new file mode 100644 index 0000000..4efd320 --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java @@ -0,0 +1,36 @@ +package com.github.ygimenez.model.helper; + +import com.github.ygimenez.model.Page; +import com.github.ygimenez.model.ThrowingFunction; +import net.dv8tion.jda.api.entities.Message; + +import java.util.ArrayList; +import java.util.List; + +public class LazyPaginateHelper extends PaginateHelper { + private final ThrowingFunction<Integer, Page> pageLoader; + + public LazyPaginateHelper(Message message, ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) { + super(message, new ArrayList<>(), useButtons); + this.pageLoader = pageLoader; + } + + public LazyPaginateHelper(Message message, ThrowingFunction<Integer, Page> pageLoader, List<Page> initialPages, boolean useButtons) { + super(message, initialPages, useButtons); + this.pageLoader = pageLoader; + } + + public LazyPaginateHelper addPage(Page page) { + getContent().add(page); + return this; + } + + public ThrowingFunction<Integer, Page> getPageLoader() { + return pageLoader; + } + + public LazyPaginateHelper load(int page) { + getContent().set(page, pageLoader.apply(page)); + return this; + } +} diff --git a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java new file mode 100644 index 0000000..16394e3 --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java @@ -0,0 +1,43 @@ +package com.github.ygimenez.model.helper; + +import com.github.ygimenez.model.Page; +import net.dv8tion.jda.api.entities.Message; + +import java.util.ArrayList; +import java.util.List; + +public class PaginateHelper extends BaseHelper<PaginateHelper, List<Page>> { + private int skipAmount = 0; + private boolean fastForward = false; + + public PaginateHelper(Message message, boolean useButtons) { + super(PaginateHelper.class, message, new ArrayList<>(), useButtons); + } + + public PaginateHelper(Message message, List<Page> pages, boolean useButtons) { + super(PaginateHelper.class, message, pages, useButtons); + } + + public PaginateHelper addPage(Page page) { + getContent().add(page); + return this; + } + + public int getSkipAmount() { + return skipAmount; + } + + public PaginateHelper setSkipAmount(int skipAmount) { + this.skipAmount = skipAmount; + return this; + } + + public boolean isFastForward() { + return fastForward; + } + + public PaginateHelper setFastForward(boolean fastForward) { + this.fastForward = fastForward; + return this; + } +} From c1f25705ee93259927832bbd2c92c8c1b252e267 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Fri, 18 Mar 2022 11:33:20 -0300 Subject: [PATCH 02/31] Changed BaseHelper methods visibility to public. --- .../com/github/ygimenez/model/helper/BaseHelper.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java index e781583..b0b45c0 100644 --- a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -53,28 +53,28 @@ public Predicate<User> getCanInteract() { return canInteract; } - protected Sub setCancellable(boolean cancellable) { + public Sub setCancellable(boolean cancellable) { this.cancellable = cancellable; return subClass.cast(this); } - protected Sub setTime(int time) { + public Sub setTime(int time) { this.time = time; return subClass.cast(this); } - protected Sub setUnit(TimeUnit unit) { + public Sub setUnit(TimeUnit unit) { this.unit = unit; return subClass.cast(this); } - protected Sub setTimeUnit(int time, TimeUnit unit) { + public Sub setTimeUnit(int time, TimeUnit unit) { this.time = time; this.unit = unit; return subClass.cast(this); } - protected Sub setCanInteract(Predicate<User> canInteract) { + public Sub setCanInteract(Predicate<User> canInteract) { this.canInteract = canInteract; return subClass.cast(this); } From 5243a77d574af271f58ea6569a503b47c2afaf9b Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Fri, 18 Mar 2022 11:33:42 -0300 Subject: [PATCH 03/31] Changed BaseHelper methods visibility to public. --- src/main/java/com/github/ygimenez/model/helper/BaseHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java index b0b45c0..dbe9e5a 100644 --- a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -18,7 +18,7 @@ abstract class BaseHelper<Sub extends BaseHelper<Sub, T>, T> { private TimeUnit unit = null; private Predicate<User> canInteract = null; - public BaseHelper(Class<Sub> subClass, Message message, T buttons, boolean useButtons) { + protected BaseHelper(Class<Sub> subClass, Message message, T buttons, boolean useButtons) { this.subClass = subClass; this.message = message; this.content = buttons; From 58d189691f3fae4848e3e12560dfd29e876be9bb Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Fri, 18 Mar 2022 11:45:52 -0300 Subject: [PATCH 04/31] Fixed dumb icon not aligning properly on README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c55926..2c2f13b 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ [ ![license-shield][] ][license] [ ![issue-shield][] ][issue] -<img style="float: right" src="https://raw.githubusercontent.com/ygimenez/Pagination-Utils/master/icon.png" height=225 width=225 alt="Pagination Utils logo"> +<img align="right" src="https://raw.githubusercontent.com/ygimenez/Pagination-Utils/master/icon.png" height=225 width=225 alt="Pagination Utils logo"> # Pagination Utils - JDA Pagination made easier! From a6c324d14eb347fe82ebe2facd1ac1d1a1ecdf9b Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Fri, 18 Mar 2022 11:47:28 -0300 Subject: [PATCH 05/31] Fixed dumb icon not aligning properly on README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c2f13b..d1ff85c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ # Pagination Utils - JDA Pagination made easier! -With this library you will be using pages and categories in your bot commands in no time! +With this library you will be using pages, categories and buttons in your bot in no time! ## What is a page/category/button? From d80945d02e41c8d903b015f5c909e743fbd96068 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Fri, 18 Mar 2022 11:47:28 -0300 Subject: [PATCH 06/31] Fixed dumb icon not aligning properly on README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2c2f13b..3f3c25f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ # Pagination Utils - JDA Pagination made easier! -With this library you will be using pages and categories in your bot commands in no time! +With this library you will be using pages, categories and buttons in your bot in no time! ## What is a page/category/button? @@ -38,7 +38,7 @@ With this library you will be using pages and categories in your bot commands in  Have you been using a bot and came across one of those three GIFs and thought: "That must've been hard to make." or "I'd -like one of those in my bot!". Fear no more, KuuHaKu to the rescue! +like one of those in my bot!"? Fear no more, KuuHaKu to the rescue! ## How do I paginate? From fa9b81c0ef923392f51aaac9eb9e802cbe56b1a9 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Fri, 18 Mar 2022 11:51:59 -0300 Subject: [PATCH 07/31] Fixed dumb icon not aligning properly on README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f3c25f..9bc0045 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ With this library you will be using pages, categories and buttons in your bot in  Have you been using a bot and came across one of those three GIFs and thought: "That must've been hard to make." or "I'd -like one of those in my bot!"? Fear no more, KuuHaKu to the rescue! +like one of those in my bot!"? Fear no more, Pagination Utils to the rescue! ## How do I paginate? From fd049c3555b08b95d6428882909248d18913dd1d Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Mon, 21 Mar 2022 11:40:10 -0300 Subject: [PATCH 08/31] Helpers can now be applied to a `MessageAction` to load buttons (INTERACTION ONLY); `clearReactions` and `clearButtons` are no-op if the message doesn't contain reactions/buttons; Pagination Button style is now controlled by the first Page only. --- .../ygimenez/exception/NullPageException.java | 5 +- .../com/github/ygimenez/method/Pages.java | 511 +++++++----------- .../ygimenez/model/helper/BaseHelper.java | 13 +- .../model/helper/ButtonizeHelper.java | 71 ++- .../model/helper/CategorizeHelper.java | 70 ++- .../model/helper/LazyPaginateHelper.java | 75 ++- .../ygimenez/model/helper/PaginateHelper.java | 81 ++- .../java/com/github/ygimenez/type/Emote.java | 7 + 8 files changed, 489 insertions(+), 344 deletions(-) diff --git a/src/main/java/com/github/ygimenez/exception/NullPageException.java b/src/main/java/com/github/ygimenez/exception/NullPageException.java index 51b5109..92a8fe9 100644 --- a/src/main/java/com/github/ygimenez/exception/NullPageException.java +++ b/src/main/java/com/github/ygimenez/exception/NullPageException.java @@ -1,18 +1,19 @@ package com.github.ygimenez.exception; +import com.github.ygimenez.model.Page; import net.dv8tion.jda.api.entities.Message; import java.util.List; /** - * Exception thrown when trying to paginate an empty {@link List}. + * Exception thrown when trying to paginate an empty {@link List} or action returned a null {@link Page}. */ public class NullPageException extends RuntimeException { /** * Default constructor. */ public NullPageException() { - super("The informed collection does not contain any Page"); + super("The informed collection does not contain any Page or Page is null"); } /** diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index fb1a4cf..8bd42ef 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -117,32 +117,6 @@ public static MessageHandler getHandler() { return handler; } - /** - * Adds navigation buttons to the specified {@link Message}/{@link MessageEmbed} - * which will navigate through a given {@link List} of pages. This versions uses a helper class - * to aid customization and allow reusage of configurations. - * - * @param helper A {@link PaginateHelper} holding desired pagination settings. - * @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 void paginate(@Nonnull PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { - paginate( - helper.getMessage(), - helper.getContent(), - helper.isUsingButtons(), - helper.getTime(), - helper.getUnit(), - helper.getSkipAmount(), - helper.isFastForward(), - helper.getCanInteract() - ); - } - /** * Adds navigation buttons to the specified {@link Message}/{@link MessageEmbed} * which will navigate through a given {@link List} of pages. @@ -525,16 +499,40 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ public static void 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); + paginate(msg, new PaginateHelper(pages, useButtons) + .setTimeUnit(time, unit) + .setSkipAmount(skipAmount) + .setFastForward(fastForward) + .setCanInteract(canInteract) + ); + } - Page pg = pgs.get(0); - if (useBtns) addButtons((InteractPage) pg, msg, skipAmount > 1, fastForward); - else addReactions(msg, skipAmount > 1, fastForward); + /** + * Adds navigation buttons to the specified {@link Message}/{@link MessageEmbed} + * which will navigate through a given {@link List} of pages. This versions uses a helper class + * to aid customization and allow reusage of configurations. + * + * @param msg The {@link Message} sent which will be paginated. + * @param helper A {@link PaginateHelper} holding desired pagination settings. + * @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 void paginate(@Nonnull Message msg, @Nonnull PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + if (!isActivated() || helper.getContent().isEmpty()) throw new InvalidStateException(); + boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); + List<Page> pgs = Collections.unmodifiableList(helper.getContent()); + + if (useBtns && helper.shouldUpdate(msg)) { + helper.apply(msg.editMessageComponents()).submit(); + } else if (!useBtns) { + clearButtons(msg); + clearReactions(msg); + addReactions(msg, helper.getSkipAmount() > 1, helper.isFastForward()); + } handler.addEvent(msg, new ThrowingBiConsumer<>() { private final int maxP = pgs.size() - 1; @@ -551,15 +549,15 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo 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); + if (helper.getTime() > 0 && helper.getUnit() != null) + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); } @Override public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); - if (canInteract == null || canInteract.test(u)) { + if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) return; @@ -592,13 +590,13 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe break; case SKIP_BACKWARD: if (p > 0) { - p -= (p - skipAmount < 0 ? p : skipAmount); + p -= (p - helper.getSkipAmount() < 0 ? p : helper.getSkipAmount()); update = true; } break; case SKIP_FORWARD: if (p < maxP) { - p += (p + skipAmount > maxP ? maxP - p : skipAmount); + p += (p + helper.getSkipAmount() > maxP ? maxP - p : helper.getSkipAmount()); update = true; } break; @@ -622,7 +620,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe if (update) { pg = pgs.get(p); updatePage(m, pg); - updateButtons(m, pg, useBtns, skipAmount > 1, fastForward); + updateButtons(m, helper); if (pg instanceof InteractPage) { modifyButtons(m, Map.of( @@ -639,8 +637,8 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe if (timeout != null) timeout.cancel(true); - if (time > 0 && unit != null) - timeout = executor.schedule(() -> finalizeEvent(m, success), time, unit); + if (helper.getTime() > 0 && helper.getUnit() != null) + timeout = executor.schedule(() -> finalizeEvent(m, success), helper.getTime(), helper.getUnit()); if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { subGet(((MessageReaction) wrapper.getContent()).removeReaction(u)); @@ -650,32 +648,6 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe }); } - /** - * 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}. This versions uses a helper class - * to aid customization and allow reusage of configurations. - * - * @param helper A {@link CategorizeHelper} holding desired categorization settings. - * @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 void categorize(@Nonnull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { - categorize( - helper.getMessage(), - helper.getContent(), - helper.isUsingButtons(), - helper.getTime(), - helper.getUnit(), - helper.getCanInteract() - ); - } - /** * 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 @@ -781,41 +753,40 @@ public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> ca * @throws InvalidStateException Thrown if the library wasn't activated. */ public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + categorize(msg, new CategorizeHelper(categories, useButtons) + .setTimeUnit(time, unit) + .setCanInteract(canInteract) + ); + } + + /** + * 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}. This versions uses a helper class + * to aid customization and allow reusage of configurations. + * + * @param msg The {@link Message} sent which will be categorized. + * @param helper A {@link CategorizeHelper} holding desired categorization settings. + * @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 void categorize(@Nonnull Message msg, @Nonnull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); - boolean useBtns = useButtons && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); + boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); - Map<Emoji, Page> cats = Collections.unmodifiableMap(categories); - clearButtons(msg); - clearReactions(msg); + Map<Emoji, Page> cats = Collections.unmodifiableMap(helper.getContent()); 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(); + helper.apply(msg.editMessageComponents()).submit(); } else { + clearButtons(msg); + clearReactions(msg); + for (Emoji k : cats.keySet()) { msg.addReaction(k.getAsMention().replaceAll("[<>]", "")).submit(); } @@ -834,15 +805,15 @@ public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> ca }; { - if (time > 0 && unit != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), time, unit); + if (helper.getTime() > 0 && helper.getUnit() != null) + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); } @Override public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); - if (canInteract == null || canInteract.test(u)) { + if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) return; @@ -881,8 +852,8 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe if (timeout != null) timeout.cancel(true); - if (time > 0 && unit != null) - timeout = executor.schedule(() -> finalizeEvent(m, success), time, unit); + if (helper.getTime() > 0 && helper.getUnit() != null) + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { subGet(((MessageReaction) wrapper.getContent()).removeReaction(u)); @@ -892,34 +863,6 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe }); } - /** - * 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}. This versions uses a helper class - * to aid customization and allow reusage of configurations. - * - * @param helper A {@link ButtonizeHelper} holding desired buttonization settings. - * @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 void buttonize(@Nonnull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { - buttonize( - helper.getMessage(), - helper.getContent(), - helper.isUsingButtons(), - helper.isCancellable(), - helper.getTime(), - helper.getUnit(), - helper.getCanInteract(), - helper.getOnCancel() - ); - } - /** * Adds buttons to the specified {@link Message}/{@link MessageEmbed}, with each * executing a specific task on click. You may only specify one {@link Runnable} @@ -1072,22 +1015,22 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC * 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}<{@link Member}, {@link Message}, {@link InteractionHook}> - * 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. + * @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}<{@link Member}, {@link Message}, {@link InteractionHook}> + * 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 cancellable 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}. @@ -1095,51 +1038,50 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void 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 { + public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean cancellable, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { + buttonize(msg, new ButtonizeHelper(buttons, useButtons) + .setCancellable(cancellable) + .setTimeUnit(time, unit) + .setCanInteract(canInteract) + .setOnCancel(onCancel) + ); + } + + /** + * 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}. This versions uses a helper class + * to aid customization and allow reusage of configurations. + * + * @param msg The {@link Message} sent which will be buttoned. + * @param helper A {@link ButtonizeHelper} holding desired buttonization settings. + * @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 void buttonize(@Nonnull Message msg, @Nonnull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); - boolean useBtns = useButtons && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); + boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); - Map<Emoji, ThrowingConsumer<ButtonWrapper>> btns = Collections.unmodifiableMap(buttons); - clearButtons(msg); - clearReactions(msg); + Map<Emoji, ThrowingConsumer<ButtonWrapper>> btns = Collections.unmodifiableMap(helper.getContent()); 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(); + helper.apply(msg.editMessageComponents()).submit(); } else { + clearButtons(msg); + clearReactions(msg); + for (Emoji k : btns.keySet()) { msg.addReaction(k.getAsMention().replaceAll("[<>]", "")).submit(); } - if (!btns.containsKey(paginator.getEmote(CANCEL)) && showCancelButton) + if (!btns.containsKey(paginator.getEmote(CANCEL)) && helper.isCancellable()) { msg.addReaction(paginator.getStringEmote(CANCEL)).submit(); + } } handler.addEvent(msg, new ThrowingBiConsumer<>() { @@ -1148,20 +1090,20 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC if (timeout != null) timeout.cancel(true); handler.removeEvent(msg); - if (onCancel != null) onCancel.accept(msg); + if (helper.getOnCancel() != null) helper.getOnCancel().accept(msg); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; { - if (time > 0 && unit != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), time, unit); + if (helper.getTime() > 0 && helper.getUnit() != null) + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); } @Override public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); - if (canInteract == null || canInteract.test(u)) { + if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) return; @@ -1180,7 +1122,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe } } - if ((!btns.containsKey(paginator.getEmote(CANCEL)) && showCancelButton) && emt == CANCEL) { + if ((!btns.containsKey(paginator.getEmote(CANCEL)) && helper.isCancellable()) && emt == CANCEL) { finalizeEvent(m, success); return; } @@ -1199,8 +1141,8 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe if (timeout != null) timeout.cancel(true); - if (time > 0 && unit != null) - timeout = executor.schedule(() -> finalizeEvent(m, success), time, unit); + if (helper.getTime() > 0 && helper.getUnit() != null) + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { subGet(((MessageReaction) wrapper.getContent()).removeReaction(u)); @@ -1210,32 +1152,6 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe }); } - /** - * 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. - * This versions uses a helper class to aid customization and allow reusage of configurations. - * - * @param helper A {@link LazyPaginateHelper} holding desired lazy pagination settings. - * @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 void lazyPaginate(@Nonnull LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate( - helper.getMessage(), - helper.getContent(), - helper.getPageLoader(), - helper.isUsingButtons(), - helper.getTime(), - helper.getUnit(), - helper.getCanInteract() - ); - } - /** * Adds navigation buttons to the specified {@link Message}/{@link MessageEmbed} * which will lazily load content by using supplied {@link ThrowingFunction}. For this reason, @@ -1342,7 +1258,7 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * this pagination type cannot have skip nor fast-forward buttons given the unknown page limit. * * @param msg The {@link Message} sent which will be paginated. - * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). + * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> 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 @@ -1366,7 +1282,7 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non * no-activity interval. * * @param msg The {@link Message} sent which will be paginated. - * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). + * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> 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 @@ -1392,7 +1308,7 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non * this pagination type cannot have skip nor fast-forward buttons given the unknown page limit. * * @param msg The {@link Message} sent which will be paginated. - * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). + * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> 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 @@ -1418,7 +1334,7 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non * no-activity interval. * * @param msg The {@link Message} sent which will be paginated. - * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). + * @param pageCache The {@link List} that'll hold previously visited pages (can be pre-filled or edited anytime). * @param pageLoader {@link ThrowingFunction}<{@link Integer}, {@link Page}> 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 @@ -1437,25 +1353,40 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, 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()); - boolean cache = pageCache != null; + lazyPaginate(msg, new LazyPaginateHelper(pageLoader, pageCache, useButtons) + .setTimeUnit(time, unit) + .setCanInteract(canInteract) + ); + } - if (!msg.getAuthor().equals(paginator.getHandler())) + /** + * 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. + * This versions uses a helper class to aid customization and allow reusage of configurations. + * + * @param msg The {@link Message} sent which will be paginated. + * @param helper A {@link LazyPaginateHelper} holding desired lazy pagination settings. + * @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 void lazyPaginate(@Nonnull Message msg, @Nonnull LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + if (!isActivated()) throw new InvalidStateException(); + boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); + boolean cache = helper.getContent() != null; + if (useBtns && helper.shouldUpdate(msg)) { + helper.apply(msg.editMessageComponents()).submit(); + } else if (!useBtns) { clearButtons(msg); - clearReactions(msg); - - Page pg = pageLoader.apply(0); - if (pg == null) { - throw new InvalidStateException(); + clearReactions(msg); + addReactions(msg, false, false); } - if (cache) pageCache.add(pg); - - if (useBtns) addButtons((InteractPage) pg, msg, false, false); - else addReactions(msg, false, false); - handler.addEvent(msg, new ThrowingBiConsumer<>() { private int p = 0; private ScheduledFuture<?> timeout; @@ -1467,15 +1398,15 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non }; { - if (time > 0 && unit != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), time, unit); + if (helper.getTime() > 0 && helper.getUnit() != null) + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); } @Override public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); - if (canInteract == null || canInteract.test(u)) { + if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) return; @@ -1496,18 +1427,25 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe case PREVIOUS: if (p > 0) { p--; - pg = cache ? pageCache.get(p) : pageLoader.apply(p); + pg = cache ? helper.getContent().get(p) : helper.getPageLoader().apply(p); updatePage(m, pg); - updateButtons(m, pg, useBtns, false, false); + updateButtons(m, helper); } break; case NEXT: p++; - if (cache && pageCache.size() > p) { - pg = pageCache.get(p); + if (cache && helper.getContent().size() > p) { + pg = helper.getContent().get(p); + if (pg == null) { + pg = helper.getPageLoader().apply(p); + if (pg == null) { + p--; + return; + } + } } else { - pg = pageLoader.apply(p); + pg = helper.getPageLoader().apply(p); if (pg == null) { p--; return; @@ -1515,9 +1453,9 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe } updatePage(m, pg); - updateButtons(m, pg, useBtns, false, false); + updateButtons(m, helper); - if (cache) pageCache.add(pg); + if (cache) helper.getContent().add(pg); break; case CANCEL: finalizeEvent(m, success); @@ -1526,8 +1464,8 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe if (timeout != null) timeout.cancel(true); - if (time > 0 && unit != null) - timeout = executor.schedule(() -> finalizeEvent(m, success), time, unit); + if (helper.getTime() > 0 && helper.getUnit() != null) + timeout = executor.schedule(() -> finalizeEvent(m, success), helper.getTime(), helper.getUnit()); if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { subGet(((MessageReaction) wrapper.getContent()).removeReaction(u)); @@ -1554,11 +1492,19 @@ private static void updatePage(@Nonnull Message msg, Page p) { } } - private static void updateButtons(Message msg, Page pg, boolean useButtons, boolean withSkip, boolean withGoto) { - if (useButtons) { - addButtons((InteractPage) pg, msg, withSkip, withGoto); + private static void updateButtons(Message msg, PaginateHelper helper) { + if (helper.isUsingButtons()) { + helper.apply(msg.editMessageComponents()).submit(); } else { - addReactions(msg, withSkip, withGoto); + addReactions(msg, helper.getSkipAmount() > 1, helper.isFastForward()); + } + } + + private static void updateButtons(Message msg, LazyPaginateHelper helper) { + if (helper.isUsingButtons()) { + helper.apply(msg.editMessageComponents()).submit(); + } else { + addReactions(msg, false, false); } } @@ -1619,6 +1565,8 @@ private static Emoji toEmoji(MessageReaction.ReactionEmote reaction) { * @param msg The {@link Message} to have reactions/buttons removed from. */ public static void clearReactions(Message msg) { + if (msg.getReactions().isEmpty()) return; + try { if (msg.getChannel().getType().isGuild()) msg.clearReactions().submit(); @@ -1638,6 +1586,8 @@ else for (MessageReaction r : msg.getReactions()) { * @param msg The {@link Message} to have reactions/buttons removed from. */ public static void clearButtons(Message msg) { + if (msg.getButtons().isEmpty()) return; + try { subGet(msg.editMessageComponents()); } catch (InsufficientPermissionException | IllegalStateException e) { @@ -1703,65 +1653,4 @@ public static void addReactions(Message msg, boolean withSkip, boolean withGoto) RestAction.allOf(acts).submit(); } - - /** - * Utility method to add navigation buttons. - * - * @param page The {@link InteractPage} containing button styles and captions. - * @param msg The {@link Message} to have reactions removed from. - * @param withSkip Whether to include {@link Emote#SKIP_BACKWARD} and {@link Emote#SKIP_FORWARD} buttons. - * @param withGoto Whether to include {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons. - */ - public static void addButtons(InteractPage page, Message msg, boolean withSkip, boolean withGoto) { - clearReactions(msg); - - List<ActionRow> rows = new ArrayList<>(); - - List<Component> row; - if (withSkip && withGoto) { - row = List.of( - page.makeButton(NONE), - page.makeButton(PREVIOUS), - page.makeButton(CANCEL), - page.makeButton(NEXT), - page.makeButton(NONE) - ); - } else if (withSkip) { - row = List.of( - page.makeButton(SKIP_BACKWARD), - page.makeButton(PREVIOUS), - page.makeButton(CANCEL), - page.makeButton(NEXT), - page.makeButton(SKIP_FORWARD) - ); - } else if (withGoto) { - row = List.of( - page.makeButton(GOTO_FIRST), - page.makeButton(PREVIOUS), - page.makeButton(CANCEL), - page.makeButton(NEXT), - page.makeButton(GOTO_LAST) - ); - } else { - row = List.of( - page.makeButton(PREVIOUS), - page.makeButton(CANCEL), - page.makeButton(NEXT) - ); - } - rows.add(ActionRow.of(row)); - - if (withSkip && withGoto) { - row = List.of( - page.makeButton(GOTO_FIRST), - page.makeButton(SKIP_BACKWARD), - page.makeButton(NONE), - page.makeButton(SKIP_FORWARD), - page.makeButton(GOTO_LAST) - ); - rows.add(ActionRow.of(row)); - } - - subGet(msg.editMessageComponents(rows)); - } } diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java index dbe9e5a..48ea6d5 100644 --- a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -2,6 +2,7 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.requests.restaction.MessageAction; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; @@ -9,7 +10,6 @@ abstract class BaseHelper<Sub extends BaseHelper<Sub, T>, T> { private final Class<Sub> subClass; - private final Message message; private final T content; private final boolean useButtons; @@ -18,17 +18,12 @@ abstract class BaseHelper<Sub extends BaseHelper<Sub, T>, T> { private TimeUnit unit = null; private Predicate<User> canInteract = null; - protected BaseHelper(Class<Sub> subClass, Message message, T buttons, boolean useButtons) { + protected BaseHelper(Class<Sub> subClass, T buttons, boolean useButtons) { this.subClass = subClass; - this.message = message; this.content = buttons; this.useButtons = useButtons; } - public Message getMessage() { - return message; - } - public T getContent() { return content; } @@ -78,4 +73,8 @@ public Sub setCanInteract(Predicate<User> canInteract) { this.canInteract = canInteract; return subClass.cast(this); } + + public abstract MessageAction apply(MessageAction action); + + public abstract boolean shouldUpdate(Message msg); } diff --git a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java index 6e9884d..931d382 100644 --- a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java @@ -1,23 +1,32 @@ package com.github.ygimenez.model.helper; +import com.github.ygimenez.method.Pages; import com.github.ygimenez.model.ButtonWrapper; import com.github.ygimenez.model.ThrowingConsumer; +import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.Button; +import net.dv8tion.jda.api.interactions.components.Component; +import net.dv8tion.jda.api.requests.restaction.MessageAction; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static com.github.ygimenez.type.Emote.CANCEL; public class ButtonizeHelper extends BaseHelper<ButtonizeHelper, Map<Emoji, ThrowingConsumer<ButtonWrapper>>> { private Consumer<Message> onCancel = null; - public ButtonizeHelper(Message message, boolean useButtons) { - super(ButtonizeHelper.class, message, new LinkedHashMap<>(), useButtons); + public ButtonizeHelper(boolean useButtons) { + super(ButtonizeHelper.class, new LinkedHashMap<>(), useButtons); } - public ButtonizeHelper(Message message, Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons) { - super(ButtonizeHelper.class, message, buttons, useButtons); + public ButtonizeHelper(Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons) { + super(ButtonizeHelper.class, buttons, useButtons); } public ButtonizeHelper addCategory(Emoji emoji, ThrowingConsumer<ButtonWrapper> action) { @@ -33,4 +42,54 @@ public ButtonizeHelper setOnCancel(Consumer<Message> onCancel) { this.onCancel = onCancel; return this; } + + @Override + public MessageAction apply(MessageAction action) { + if (!isUsingButtons()) return action; + + List<ActionRow> rows = new ArrayList<>(); + + List<Component> row = new ArrayList<>(); + for (Emoji k : getContent().keySet()) { + if (row.size() == 5) { + rows.add(ActionRow.of(row)); + row = new ArrayList<>(); + } + + row.add(Button.secondary(Emote.getId(k), k)); + } + + if (!getContent().containsKey(Pages.getPaginator().getEmote(CANCEL)) && isCancellable()) { + Button button = Button.danger(CANCEL.name(), Pages.getPaginator().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)); + + return action.setActionRows(rows); + } + + @Override + public boolean shouldUpdate(Message msg) { + if (!isUsingButtons()) return false; + + Predicate<Set<Emoji>> checks = e -> !isCancellable() || e.contains(Pages.getPaginator().getEmote(CANCEL)); + Set<Emoji> emojis = msg.getButtons().stream() + .map(Button::getEmoji) + .collect(Collectors.toSet()); + + checks = checks.and(e -> e.containsAll(getContent().keySet())); + + return checks.test(emojis); + } } diff --git a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java index f1d0157..3057d96 100644 --- a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java @@ -1,23 +1,81 @@ package com.github.ygimenez.model.helper; +import com.github.ygimenez.method.Pages; import com.github.ygimenez.model.Page; +import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.Button; +import net.dv8tion.jda.api.interactions.components.Component; +import net.dv8tion.jda.api.requests.restaction.MessageAction; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static com.github.ygimenez.type.Emote.*; public class CategorizeHelper extends BaseHelper<CategorizeHelper, Map<Emoji, Page>> { - public CategorizeHelper(Message message, boolean useButtons) { - super(CategorizeHelper.class, message, new LinkedHashMap<>(), useButtons); + public CategorizeHelper(boolean useButtons) { + super(CategorizeHelper.class, new LinkedHashMap<>(), useButtons); } - public CategorizeHelper(Message message, Map<Emoji, Page> categories, boolean useButtons) { - super(CategorizeHelper.class, message, categories, useButtons); + public CategorizeHelper(Map<Emoji, Page> categories, boolean useButtons) { + super(CategorizeHelper.class, categories, useButtons); } public CategorizeHelper addCategory(Emoji emoji, Page page) { getContent().put(emoji, page); return this; } + + @Override + public MessageAction apply(MessageAction action) { + if (!isUsingButtons()) return action; + + List<ActionRow> rows = new ArrayList<>(); + + List<Component> row = new ArrayList<>(); + for (Emoji k : getContent().keySet()) { + if (row.size() == 5) { + rows.add(ActionRow.of(row)); + row = new ArrayList<>(); + } + + row.add(Button.secondary(Emote.getId(k), k)); + } + + if (isCancellable()) { + Button button = Button.danger(CANCEL.name(), Pages.getPaginator().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)); + + return action.setActionRows(rows); + } + + @Override + public boolean shouldUpdate(Message msg) { + if (!isUsingButtons()) return false; + + Predicate<Set<Emoji>> checks = e -> !isCancellable() || e.contains(Pages.getPaginator().getEmote(CANCEL)); + Set<Emoji> emojis = msg.getButtons().stream() + .map(Button::getEmoji) + .collect(Collectors.toSet()); + + checks = checks.and(e -> e.containsAll(getContent().keySet())); + + return checks.test(emojis); + } } diff --git a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java index 4efd320..848b529 100644 --- a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java @@ -1,26 +1,46 @@ package com.github.ygimenez.model.helper; +import com.github.ygimenez.exception.InvalidStateException; +import com.github.ygimenez.exception.NullPageException; +import com.github.ygimenez.model.InteractPage; import com.github.ygimenez.model.Page; import com.github.ygimenez.model.ThrowingFunction; +import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.requests.restaction.MessageAction; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; -public class LazyPaginateHelper extends PaginateHelper { +import static com.github.ygimenez.type.Emote.*; +import static com.github.ygimenez.type.Emote.GOTO_LAST; + +public class LazyPaginateHelper extends BaseHelper<LazyPaginateHelper, List<Page>> { private final ThrowingFunction<Integer, Page> pageLoader; + private final boolean cache; - public LazyPaginateHelper(Message message, ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) { - super(message, new ArrayList<>(), useButtons); + public LazyPaginateHelper(ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) { + super(LazyPaginateHelper.class, new ArrayList<>(), useButtons); this.pageLoader = pageLoader; + this.cache = true; + load(0); } - public LazyPaginateHelper(Message message, ThrowingFunction<Integer, Page> pageLoader, List<Page> initialPages, boolean useButtons) { - super(message, initialPages, useButtons); + public LazyPaginateHelper(ThrowingFunction<Integer, Page> pageLoader, @Nullable List<Page> initialPages, boolean useButtons) { + super(LazyPaginateHelper.class, initialPages, useButtons); this.pageLoader = pageLoader; + this.cache = initialPages != null; + load(0); } public LazyPaginateHelper addPage(Page page) { + if (!cache) throw new IllegalStateException(); + getContent().add(page); return this; } @@ -29,8 +49,47 @@ public ThrowingFunction<Integer, Page> getPageLoader() { return pageLoader; } - public LazyPaginateHelper load(int page) { - getContent().set(page, pageLoader.apply(page)); - return this; + public @Nullable Page load(int page) { + if (cache) { + int maxIndex = getContent().size() - 1; + while (maxIndex < page) { + getContent().add(null); + maxIndex++; + } + } + + Page p = pageLoader.apply(page); + if (cache) getContent().set(page, p); + return p; + } + + @Override + public MessageAction apply(MessageAction action) { + if (!isUsingButtons()) return action; + + InteractPage p = (InteractPage) load(0); + if (p == null) throw new NullPageException(); + + return action.setActionRows(ActionRow.of(new ArrayList<>() {{ + add(p.makeButton(PREVIOUS)); + if (isCancellable()) add(p.makeButton(CANCEL)); + add(p.makeButton(NEXT)); + }})); + } + + @Override + public boolean shouldUpdate(Message msg) { + if (!isUsingButtons()) return true; + + Predicate<Set<Emote>> checks = e -> e.containsAll(Set.of(PREVIOUS, NEXT)); + Set<Emote> emotes = msg.getButtons().stream() + .map(Emote::fromButton) + .collect(Collectors.toSet()); + + if (isCancellable()) { + checks = checks.and(e -> e.contains(CANCEL)); + } + + return !checks.test(emotes); } } diff --git a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java index 16394e3..3ff9b84 100644 --- a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java @@ -1,21 +1,33 @@ package com.github.ygimenez.model.helper; +import com.github.ygimenez.exception.NullPageException; +import com.github.ygimenez.model.InteractPage; import com.github.ygimenez.model.Page; +import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.Component; +import net.dv8tion.jda.api.requests.restaction.MessageAction; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static com.github.ygimenez.type.Emote.*; public class PaginateHelper extends BaseHelper<PaginateHelper, List<Page>> { private int skipAmount = 0; private boolean fastForward = false; - public PaginateHelper(Message message, boolean useButtons) { - super(PaginateHelper.class, message, new ArrayList<>(), useButtons); + public PaginateHelper(boolean useButtons) { + super(PaginateHelper.class, new ArrayList<>(), useButtons); } - public PaginateHelper(Message message, List<Page> pages, boolean useButtons) { - super(PaginateHelper.class, message, pages, useButtons); + public PaginateHelper(List<Page> pages, boolean useButtons) { + super(PaginateHelper.class, pages, useButtons); } public PaginateHelper addPage(Page page) { @@ -40,4 +52,65 @@ public PaginateHelper setFastForward(boolean fastForward) { this.fastForward = fastForward; return this; } + + @Override + public MessageAction apply(MessageAction action) { + if (!isUsingButtons()) return action; + + if (getContent().isEmpty()) throw new NullPageException(); + InteractPage p = (InteractPage) getContent().get(0); + + List<ActionRow> rows = new ArrayList<>(); + + LinkedList<Component> row = new LinkedList<>() {{ + add(p.makeButton(PREVIOUS)); + if (isCancellable()) add(p.makeButton(CANCEL)); + add(p.makeButton(NEXT)); + }}; + if (skipAmount > 1 && fastForward) { + row.addFirst(p.makeButton(NONE)); + row.addLast(p.makeButton(NONE)); + } else if (skipAmount > 1) { + row.addFirst(p.makeButton(SKIP_BACKWARD)); + row.addLast(p.makeButton(SKIP_FORWARD)); + } else if (fastForward) { + row.addFirst(p.makeButton(GOTO_FIRST)); + row.addLast(p.makeButton(GOTO_LAST)); + } + rows.add(ActionRow.of(row)); + + if (skipAmount > 1 && fastForward) { + rows.add(ActionRow.of(new ArrayList<>() {{ + add(p.makeButton(GOTO_FIRST)); + add(p.makeButton(SKIP_BACKWARD)); + if (isCancellable()) add(p.makeButton(NONE)); + add(p.makeButton(SKIP_FORWARD)); + add(p.makeButton(GOTO_LAST)); + }})); + } + + return action.setActionRows(rows); + } + + @Override + public boolean shouldUpdate(Message msg) { + if (isUsingButtons()) return true; + + Predicate<Set<Emote>> checks = e -> e.containsAll(Set.of(PREVIOUS, NEXT)); + Set<Emote> emotes = msg.getButtons().stream() + .map(Emote::fromButton) + .collect(Collectors.toSet()); + + if (isCancellable()) { + checks = checks.and(e -> e.contains(CANCEL)); + } + if (skipAmount > 1) { + checks = checks.and(e -> e.containsAll(Set.of(SKIP_BACKWARD, SKIP_FORWARD))); + } + if (fastForward) { + checks = checks.and(e -> e.containsAll(Set.of(GOTO_FIRST, GOTO_LAST))); + } + + return !checks.test(emotes); + } } diff --git a/src/main/java/com/github/ygimenez/type/Emote.java b/src/main/java/com/github/ygimenez/type/Emote.java index 4962722..1b02994 100644 --- a/src/main/java/com/github/ygimenez/type/Emote.java +++ b/src/main/java/com/github/ygimenez/type/Emote.java @@ -7,6 +7,7 @@ import net.dv8tion.jda.api.interactions.components.Button; import net.dv8tion.jda.api.interactions.components.ButtonStyle; +import java.util.Arrays; import java.util.Map; import java.util.Objects; @@ -134,4 +135,10 @@ public static boolean isNative(MessageReaction react) { public static String getId(Emoji emj) { return emj.isCustom() ? emj.getId() : emj.getName(); } + + public static Emote fromButton(Button btn) { + return Arrays.stream(values()) + .filter(e -> btn.getId() != null && btn.getId().contains(e.name())) + .findFirst().orElse(null); + } } From 741ebb38af3d6ffaedad67dee012b3d26278e350 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Wed, 23 Mar 2022 09:42:04 -0300 Subject: [PATCH 09/31] Methods now return a WeakReference of their actions, allowing tracking of whether an event is still ongoing or was already removed and collected. --- .../ygimenez/listener/MessageHandler.java | 7 +- .../com/github/ygimenez/method/Pages.java | 181 +++++++++++------- 2 files changed, 113 insertions(+), 75 deletions(-) diff --git a/src/main/java/com/github/ygimenez/listener/MessageHandler.java b/src/main/java/com/github/ygimenez/listener/MessageHandler.java index 1b594dd..18aff89 100644 --- a/src/main/java/com/github/ygimenez/listener/MessageHandler.java +++ b/src/main/java/com/github/ygimenez/listener/MessageHandler.java @@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; +import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Map; @@ -40,11 +41,15 @@ public class MessageHandler extends ListenerAdapter { * * @param msg The {@link Message} to hold the event. * @param act The action to be executed when the button is pressed. + * @return A {@link WeakReference} pointing to this event. This is useful if you need to track whether an event + * is still being processed or was already removed (ie. garbage collected). */ - public void addEvent(Message msg, ThrowingBiConsumer<User, PaginationEventWrapper> act) { + public WeakReference<String> addEvent(Message msg, ThrowingBiConsumer<User, PaginationEventWrapper> act) { String id = getEventId(msg); Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Added event with ID " + id + " and Consumer hash " + Integer.toHexString(act.hashCode())); events.put(id, act); + + return new WeakReference<>(id); } /** diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 8bd42ef..4ddcc48 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -26,6 +26,7 @@ import net.dv8tion.jda.api.sharding.ShardManager; import javax.annotation.Nonnull; +import java.lang.ref.WeakReference; import java.util.*; import java.util.concurrent.*; import java.util.function.Consumer; @@ -126,6 +127,8 @@ public static MessageHandler getHandler() { * 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. + * @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}. @@ -133,8 +136,8 @@ public static MessageHandler getHandler() { * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, 0, null, 0, false, null); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, 0, null, 0, false, null); } /** @@ -152,6 +155,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * for further events (recommended: 60). * @param unit The time's {@link TimeUnit} (recommended: * {@link TimeUnit#SECONDS}). + * @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}. @@ -159,8 +164,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, time, unit, 0, false, null); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, time, unit, 0, false, null); } /** @@ -174,6 +179,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * {@link Message} was not sent by the bot. * @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}. @@ -181,8 +188,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, 0, null, 0, false, canInteract); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, 0, null, 0, false, canInteract); } /** @@ -202,6 +209,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * {@link TimeUnit#SECONDS}). * @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}. @@ -209,8 +218,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, time, unit, 0, false, canInteract); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, time, unit, 0, false, canInteract); } /** @@ -223,6 +232,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * @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 fastForward Whether the {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons should be shown. + * @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}. @@ -230,8 +241,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, 0, null, 0, fastForward, null); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, 0, null, 0, fastForward, null); } /** @@ -250,6 +261,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * @param unit The time's {@link TimeUnit} (recommended: * {@link TimeUnit#SECONDS}). * @param fastForward Whether the {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons should be shown. + * @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}. @@ -257,8 +270,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, time, unit, 0, fastForward, null); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, time, unit, 0, fastForward, null); } /** @@ -273,6 +286,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * @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}. @@ -280,8 +295,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, 0, null, 0, fastForward, canInteract); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, 0, null, 0, fastForward, canInteract); } /** @@ -302,6 +317,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * @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}. @@ -309,8 +326,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, time, unit, 0, fastForward, canInteract); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, time, unit, 0, fastForward, canInteract); } /** @@ -324,6 +341,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * {@link Message} was not sent by the bot. * @param skipAmount The amount of pages to be skipped when clicking {@link Emote#SKIP_BACKWARD} * and {@link Emote#SKIP_FORWARD} buttons. + * @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}. @@ -331,8 +350,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, 0, null, skipAmount, false, null); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, 0, null, skipAmount, false, null); } /** @@ -352,6 +371,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * {@link TimeUnit#SECONDS}). * @param skipAmount The amount of pages to be skipped when clicking {@link Emote#SKIP_BACKWARD} * and {@link Emote#SKIP_FORWARD} buttons. + * @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}. @@ -359,8 +380,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, time, unit, skipAmount, false, null); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, time, unit, skipAmount, false, null); } /** @@ -376,6 +397,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * and {@link Emote#SKIP_FORWARD} buttons. * @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}. @@ -383,8 +406,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, 0, null, skipAmount, false, canInteract); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, 0, null, skipAmount, false, canInteract); } /** @@ -406,6 +429,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * and {@link Emote#SKIP_FORWARD} buttons. * @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}. @@ -413,8 +438,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, time, unit, skipAmount, false, canInteract); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, time, unit, skipAmount, false, canInteract); } /** @@ -431,6 +456,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * @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}. @@ -438,8 +465,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, 0, null, skipAmount, fastForward, canInteract); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, 0, null, skipAmount, fastForward, canInteract); } /** @@ -460,6 +487,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * @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. + * @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}. @@ -467,8 +496,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, pages, useButtons, time, unit, skipAmount, fastForward, null); + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { + return paginate(msg, pages, useButtons, time, unit, skipAmount, fastForward, null); } /** @@ -491,6 +520,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * @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}. @@ -498,8 +529,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - paginate(msg, new PaginateHelper(pages, useButtons) + 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 { + return paginate(msg, new PaginateHelper(pages, useButtons) .setTimeUnit(time, unit) .setSkipAmount(skipAmount) .setFastForward(fastForward) @@ -514,6 +545,8 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * * @param msg The {@link Message} sent which will be paginated. * @param helper A {@link PaginateHelper} holding desired pagination settings. + * @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}. @@ -521,7 +554,7 @@ public static void paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boo * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static void paginate(@Nonnull Message msg, @Nonnull PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated() || helper.getContent().isEmpty()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); List<Page> pgs = Collections.unmodifiableList(helper.getContent()); @@ -534,7 +567,7 @@ public static void paginate(@Nonnull Message msg, @Nonnull PaginateHelper helper addReactions(msg, helper.getSkipAmount() > 1, helper.isFastForward()); } - handler.addEvent(msg, new ThrowingBiConsumer<>() { + return handler.addEvent(msg, new ThrowingBiConsumer<>() { private final int maxP = pgs.size() - 1; private int p = 0; private ScheduledFuture<?> timeout; @@ -667,8 +700,8 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { - categorize(msg, categories, useButtons, 0, null, null); + public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + return categorize(msg, categories, useButtons, 0, null, null); } /** @@ -696,8 +729,8 @@ public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> ca * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { - categorize(msg, categories, useButtons, time, unit, null); + public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + return categorize(msg, categories, useButtons, time, unit, null); } /** @@ -721,8 +754,8 @@ public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> ca * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - categorize(msg, categories, useButtons, 0, null, canInteract); + public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return categorize(msg, categories, useButtons, 0, null, canInteract); } /** @@ -752,8 +785,8 @@ public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> ca * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - categorize(msg, new CategorizeHelper(categories, useButtons) + 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 { + return categorize(msg, new CategorizeHelper(categories, useButtons) .setTimeUnit(time, unit) .setCanInteract(canInteract) ); @@ -775,7 +808,7 @@ public static void categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> ca * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void categorize(@Nonnull Message msg, @Nonnull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); @@ -794,7 +827,7 @@ public static void categorize(@Nonnull Message msg, @Nonnull CategorizeHelper he msg.addReaction(paginator.getStringEmote(CANCEL)).submit(); } - handler.addEvent(msg, new ThrowingBiConsumer<>() { + return handler.addEvent(msg, new ThrowingBiConsumer<>() { private Emoji currCat = null; private ScheduledFuture<?> timeout; private final Consumer<Void> success = s -> { @@ -884,8 +917,8 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton) throws ErrorResponseException, InsufficientPermissionException { - buttonize(msg, buttons, useButtons, showCancelButton, 0, null, null, null); + public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton) throws ErrorResponseException, InsufficientPermissionException { + return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, null, null); } /** @@ -914,8 +947,8 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { - buttonize(msg, buttons, useButtons, showCancelButton, time, unit, null, null); + public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + return buttonize(msg, buttons, useButtons, showCancelButton, time, unit, null, null); } /** @@ -942,8 +975,8 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - buttonize(msg, buttons, useButtons, showCancelButton, 0, null, canInteract, null); + public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, canInteract, null); } /** @@ -975,8 +1008,8 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - buttonize(msg, buttons, useButtons, showCancelButton, time, unit, canInteract, null); + 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) throws ErrorResponseException, InsufficientPermissionException { + return buttonize(msg, buttons, useButtons, showCancelButton, time, unit, canInteract, null); } /** @@ -1004,8 +1037,8 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { - buttonize(msg, buttons, useButtons, showCancelButton, 0, null, canInteract, onCancel); + public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { + return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, canInteract, onCancel); } /** @@ -1038,8 +1071,8 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean cancellable, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { - buttonize(msg, new ButtonizeHelper(buttons, useButtons) + public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean cancellable, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { + return buttonize(msg, new ButtonizeHelper(buttons, useButtons) .setCancellable(cancellable) .setTimeUnit(time, unit) .setCanInteract(canInteract) @@ -1063,7 +1096,7 @@ public static void buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingC * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static void buttonize(@Nonnull Message msg, @Nonnull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); @@ -1084,7 +1117,7 @@ public static void buttonize(@Nonnull Message msg, @Nonnull ButtonizeHelper help } } - handler.addEvent(msg, new ThrowingBiConsumer<>() { + return handler.addEvent(msg, new ThrowingBiConsumer<>() { private ScheduledFuture<?> timeout; private final Consumer<Void> success = s -> { if (timeout != null) @@ -1169,8 +1202,8 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, null, pageLoader, useButtons, 0, null, null); + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + return lazyPaginate(msg, null, pageLoader, useButtons, 0, null, null); } /** @@ -1196,8 +1229,8 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, null, pageLoader, useButtons, time, unit, null); + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + return lazyPaginate(msg, null, pageLoader, useButtons, time, unit, null); } /** @@ -1219,8 +1252,8 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, null, pageLoader, useButtons, 0, null, canInteract); + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return lazyPaginate(msg, null, pageLoader, useButtons, 0, null, canInteract); } /** @@ -1248,8 +1281,8 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, null, pageLoader, useButtons, time, unit, canInteract); + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return lazyPaginate(msg, null, pageLoader, useButtons, time, unit, canInteract); } /** @@ -1270,8 +1303,8 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction< * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, null); + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + return lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, null); } /** @@ -1298,8 +1331,8 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageCache, pageLoader, useButtons, time, unit, null); + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + return lazyPaginate(msg, pageCache, pageLoader, useButtons, time, unit, null); } /** @@ -1322,8 +1355,8 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, canInteract); + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, canInteract); } /** @@ -1352,8 +1385,8 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { - lazyPaginate(msg, new LazyPaginateHelper(pageLoader, pageCache, useButtons) + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + return lazyPaginate(msg, new LazyPaginateHelper(pageLoader, pageCache, useButtons) .setTimeUnit(time, unit) .setCanInteract(canInteract) ); @@ -1374,7 +1407,7 @@ public static void lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Non * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static void lazyPaginate(@Nonnull Message msg, @Nonnull LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); boolean cache = helper.getContent() != null; @@ -1387,7 +1420,7 @@ public static void lazyPaginate(@Nonnull Message msg, @Nonnull LazyPaginateHelpe addReactions(msg, false, false); } - handler.addEvent(msg, new ThrowingBiConsumer<>() { + return handler.addEvent(msg, new ThrowingBiConsumer<>() { private int p = 0; private ScheduledFuture<?> timeout; private final Consumer<Void> success = s -> { From c6b6a2544213d5194b46f061e86b2e8f625f0c64 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Wed, 23 Mar 2022 10:38:38 -0300 Subject: [PATCH 10/31] Replaced WeakReference with a custom ActionReference that checks for not-collected-yet cases. --- .../ygimenez/listener/MessageHandler.java | 7 +- .../com/github/ygimenez/method/Pages.java | 106 +++++++++--------- .../ygimenez/model/ActionReference.java | 26 +++++ 3 files changed, 83 insertions(+), 56 deletions(-) create mode 100644 src/main/java/com/github/ygimenez/model/ActionReference.java diff --git a/src/main/java/com/github/ygimenez/listener/MessageHandler.java b/src/main/java/com/github/ygimenez/listener/MessageHandler.java index 18aff89..f662f8e 100644 --- a/src/main/java/com/github/ygimenez/listener/MessageHandler.java +++ b/src/main/java/com/github/ygimenez/listener/MessageHandler.java @@ -1,6 +1,7 @@ package com.github.ygimenez.listener; import com.github.ygimenez.method.Pages; +import com.github.ygimenez.model.ActionReference; import com.github.ygimenez.model.PUtilsConfig; import com.github.ygimenez.model.PaginationEventWrapper; import com.github.ygimenez.model.ThrowingBiConsumer; @@ -41,15 +42,15 @@ public class MessageHandler extends ListenerAdapter { * * @param msg The {@link Message} to hold the event. * @param act The action to be executed when the button is pressed. - * @return A {@link WeakReference} pointing to this event. This is useful if you need to track whether an event + * @return An {@link ActionReference} pointing to this event. This is useful if you need to track whether an event * is still being processed or was already removed (ie. garbage collected). */ - public WeakReference<String> addEvent(Message msg, ThrowingBiConsumer<User, PaginationEventWrapper> act) { + public ActionReference addEvent(Message msg, ThrowingBiConsumer<User, PaginationEventWrapper> act) { String id = getEventId(msg); Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Added event with ID " + id + " and Consumer hash " + Integer.toHexString(act.hashCode())); events.put(id, act); - return new WeakReference<>(id); + return new ActionReference(id); } /** diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 4ddcc48..0533199 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -127,7 +127,7 @@ public static MessageHandler getHandler() { * 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. - * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event + * @return An {@link ActionReference} 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 @@ -136,7 +136,7 @@ public static MessageHandler getHandler() { * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, 0, false, null); } @@ -155,7 +155,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * for further events (recommended: 60). * @param unit The time's {@link TimeUnit} (recommended: * {@link TimeUnit#SECONDS}). - * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event + * @return An {@link ActionReference} 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 @@ -164,7 +164,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, 0, false, null); } @@ -179,7 +179,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * {@link Message} was not sent by the bot. * @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 + * @return An {@link ActionReference} 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 @@ -188,7 +188,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, 0, false, canInteract); } @@ -209,7 +209,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * {@link TimeUnit#SECONDS}). * @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 + * @return An {@link ActionReference} 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 @@ -218,7 +218,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, 0, false, canInteract); } @@ -232,7 +232,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * @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 fastForward Whether the {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons should be shown. - * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event + * @return An {@link ActionReference} 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 @@ -241,7 +241,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, 0, fastForward, null); } @@ -261,7 +261,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * @param unit The time's {@link TimeUnit} (recommended: * {@link TimeUnit#SECONDS}). * @param fastForward Whether the {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons should be shown. - * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event + * @return An {@link ActionReference} 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 @@ -270,7 +270,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, 0, fastForward, null); } @@ -286,7 +286,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * @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 + * @return An {@link ActionReference} 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 @@ -295,7 +295,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, 0, fastForward, canInteract); } @@ -317,7 +317,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * @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 + * @return An {@link ActionReference} 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 @@ -326,7 +326,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, 0, fastForward, canInteract); } @@ -341,7 +341,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * {@link Message} was not sent by the bot. * @param skipAmount The amount of pages to be skipped when clicking {@link Emote#SKIP_BACKWARD} * and {@link Emote#SKIP_FORWARD} buttons. - * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event + * @return An {@link ActionReference} 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 @@ -350,7 +350,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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 skipAmount) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, skipAmount, false, null); } @@ -371,7 +371,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * {@link TimeUnit#SECONDS}). * @param skipAmount The amount of pages to be skipped when clicking {@link Emote#SKIP_BACKWARD} * and {@link Emote#SKIP_FORWARD} buttons. - * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event + * @return An {@link ActionReference} 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 @@ -380,7 +380,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, skipAmount, false, null); } @@ -397,7 +397,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * and {@link Emote#SKIP_FORWARD} buttons. * @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 + * @return An {@link ActionReference} 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 @@ -406,7 +406,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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 skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, skipAmount, false, canInteract); } @@ -429,7 +429,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * and {@link Emote#SKIP_FORWARD} buttons. * @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 + * @return An {@link ActionReference} 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 @@ -438,7 +438,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, skipAmount, false, canInteract); } @@ -456,7 +456,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * @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 + * @return An {@link ActionReference} 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 @@ -465,7 +465,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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 skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, skipAmount, fastForward, canInteract); } @@ -487,7 +487,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * @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. - * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event + * @return An {@link ActionReference} 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 @@ -496,7 +496,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, skipAmount, fastForward, null); } @@ -520,7 +520,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * @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 + * @return An {@link ActionReference} 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 @@ -529,7 +529,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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 { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, new PaginateHelper(pages, useButtons) .setTimeUnit(time, unit) .setSkipAmount(skipAmount) @@ -545,7 +545,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * * @param msg The {@link Message} sent which will be paginated. * @param helper A {@link PaginateHelper} holding desired pagination settings. - * @return A {@link WeakReference} pointing to this action. This is useful if you need to track whether an event + * @return An {@link ActionReference} 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 @@ -554,7 +554,7 @@ public static WeakReference<String> paginate(@Nonnull Message msg, @Nonnull List * 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 PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@Nonnull Message msg, @Nonnull PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated() || helper.getContent().isEmpty()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); List<Page> pgs = Collections.unmodifiableList(helper.getContent()); @@ -700,7 +700,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, categories, useButtons, 0, null, null); } @@ -729,7 +729,7 @@ public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull Ma * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, categories, useButtons, time, unit, null); } @@ -754,7 +754,7 @@ public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull Ma * 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, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, categories, useButtons, 0, null, canInteract); } @@ -785,7 +785,7 @@ public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull Ma * 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 { + public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, new CategorizeHelper(categories, useButtons) .setTimeUnit(time, unit) .setCanInteract(canInteract) @@ -808,7 +808,7 @@ public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull Ma * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static WeakReference<String> categorize(@Nonnull Message msg, @Nonnull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@Nonnull Message msg, @Nonnull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); @@ -917,7 +917,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, null, null); } @@ -947,7 +947,7 @@ public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, time, unit, null, null); } @@ -975,7 +975,7 @@ public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map * 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, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, canInteract, null); } @@ -1008,7 +1008,7 @@ public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, time, unit, canInteract, null); } @@ -1037,7 +1037,7 @@ public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map * 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, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, canInteract, onCancel); } @@ -1071,7 +1071,7 @@ public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map * 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 cancellable, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean cancellable, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, new ButtonizeHelper(buttons, useButtons) .setCancellable(cancellable) .setTimeUnit(time, unit) @@ -1096,7 +1096,7 @@ public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull Map * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static WeakReference<String> buttonize(@Nonnull Message msg, @Nonnull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@Nonnull Message msg, @Nonnull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); @@ -1202,7 +1202,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * 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) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, null, pageLoader, useButtons, 0, null, null); } @@ -1229,7 +1229,7 @@ public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull * 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, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, null, pageLoader, useButtons, time, unit, null); } @@ -1252,7 +1252,7 @@ public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull * 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, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, null, pageLoader, useButtons, 0, null, canInteract); } @@ -1281,7 +1281,7 @@ public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull * 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, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, null, pageLoader, useButtons, time, unit, canInteract); } @@ -1303,7 +1303,7 @@ public static WeakReference<String> lazyPaginate(@Nonnull Message msg, @Nonnull * 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, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, null); } @@ -1331,7 +1331,7 @@ public static WeakReference<String> lazyPaginate(@Nonnull Message msg, List<Page * 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, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, pageCache, pageLoader, useButtons, time, unit, null); } @@ -1355,7 +1355,7 @@ public static WeakReference<String> lazyPaginate(@Nonnull Message msg, List<Page * 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, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, canInteract); } @@ -1385,7 +1385,7 @@ public static WeakReference<String> lazyPaginate(@Nonnull Message msg, List<Page * 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, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, new LazyPaginateHelper(pageLoader, pageCache, useButtons) .setTimeUnit(time, unit) .setCanInteract(canInteract) @@ -1407,7 +1407,7 @@ public static WeakReference<String> lazyPaginate(@Nonnull Message msg, List<Page * 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 LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); boolean cache = helper.getContent() != null; diff --git a/src/main/java/com/github/ygimenez/model/ActionReference.java b/src/main/java/com/github/ygimenez/model/ActionReference.java new file mode 100644 index 0000000..f67ecc4 --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/ActionReference.java @@ -0,0 +1,26 @@ +package com.github.ygimenez.model; + +import com.github.ygimenez.method.Pages; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; + +public class ActionReference extends WeakReference<String> { + public ActionReference(String referent) { + super(referent); + } + + public ActionReference(String referent, ReferenceQueue<? super String> q) { + super(referent, q); + } + + @Nullable + @Override + public String get() { + if (!Pages.getHandler().getEventMap().containsKey(super.get())) + enqueue(); + + return super.get(); + } +} From 8635ee7f4c8eccef4aec9127530dc337def711e1 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Wed, 23 Mar 2022 10:48:13 -0300 Subject: [PATCH 11/31] Replaced WeakReference with a custom ActionReference that checks for not-collected-yet cases. --- .../ygimenez/listener/MessageHandler.java | 24 ++++++++++++++----- .../ygimenez/model/ActionReference.java | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/github/ygimenez/listener/MessageHandler.java b/src/main/java/com/github/ygimenez/listener/MessageHandler.java index f662f8e..23b14d8 100644 --- a/src/main/java/com/github/ygimenez/listener/MessageHandler.java +++ b/src/main/java/com/github/ygimenez/listener/MessageHandler.java @@ -19,6 +19,7 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.util.Collections; @@ -45,7 +46,7 @@ public class MessageHandler extends ListenerAdapter { * @return An {@link ActionReference} pointing to this event. This is useful if you need to track whether an event * is still being processed or was already removed (ie. garbage collected). */ - public ActionReference addEvent(Message msg, ThrowingBiConsumer<User, PaginationEventWrapper> act) { + public ActionReference addEvent(@Nonnull Message msg, @Nonnull ThrowingBiConsumer<User, PaginationEventWrapper> act) { String id = getEventId(msg); Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Added event with ID " + id + " and Consumer hash " + Integer.toHexString(act.hashCode())); events.put(id, act); @@ -58,12 +59,23 @@ public ActionReference addEvent(Message msg, ThrowingBiConsumer<User, Pagination * * @param msg The {@link Message} which had attached events. */ - public void removeEvent(Message msg) { + public void removeEvent(@Nonnull Message msg) { String id = getEventId(msg); Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Removed event with ID " + id); events.remove(id); } + /** + * Checks if an event hash is still present in the map. + * + * @param hash The event hash. + * @return Whether the hash exists in the events map (will be always false if hash is null). + */ + public boolean checkEvent(@Nullable String hash) { + if (hash == null) return false; + return events.containsKey(hash); + } + /** * Retrieves the event handler map. This will contain all currently active events being handled by * the library mapped by {@link Guild} ID ({@link PrivateChannel} ID for DM) plus the {@link Message} ID. @@ -84,21 +96,21 @@ public void clear() { events.clear(); } - private void lock(String id) { + private void lock(@Nonnull String id) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Locked event with ID " + id); locks.add(id); } - private void unlock(String id) { + private void unlock(@Nonnull String id) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Unlocked event with ID " + id); locks.remove(id); } - private boolean isLocked(GenericMessageReactionEvent evt) { + private boolean isLocked(@Nonnull GenericMessageReactionEvent evt) { return locks.contains(getEventId(evt)); } - private boolean isLocked(String id) { + private boolean isLocked(@Nonnull String id) { return locks.contains(id); } diff --git a/src/main/java/com/github/ygimenez/model/ActionReference.java b/src/main/java/com/github/ygimenez/model/ActionReference.java index f67ecc4..e5fc5a2 100644 --- a/src/main/java/com/github/ygimenez/model/ActionReference.java +++ b/src/main/java/com/github/ygimenez/model/ActionReference.java @@ -18,7 +18,7 @@ public ActionReference(String referent, ReferenceQueue<? super String> q) { @Nullable @Override public String get() { - if (!Pages.getHandler().getEventMap().containsKey(super.get())) + if (!Pages.getHandler().checkEvent(super.get())) enqueue(); return super.get(); From 2953cb2ca67309ce34f2b6a372d351eb732623a4 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Wed, 23 Mar 2022 11:02:01 -0300 Subject: [PATCH 12/31] Added method to check ActionReference validity without risking creating a new strong reference to it. --- src/main/java/com/github/ygimenez/model/ActionReference.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/github/ygimenez/model/ActionReference.java b/src/main/java/com/github/ygimenez/model/ActionReference.java index e5fc5a2..69a517a 100644 --- a/src/main/java/com/github/ygimenez/model/ActionReference.java +++ b/src/main/java/com/github/ygimenez/model/ActionReference.java @@ -23,4 +23,8 @@ public String get() { return super.get(); } + + public boolean check() { + return get() != null; + } } From 58f0f6aee48ad4184bc6d2bc60d4af8423334df7 Mon Sep 17 00:00:00 2001 From: ygimenez <yagogimenez1@hotmail.com> Date: Tue, 19 Apr 2022 10:11:02 -0300 Subject: [PATCH 13/31] Added missing `createPaginator` signatures --- .idea/misc.xml | 5 +++++ pom.xml | 4 ++-- .../ygimenez/model/PaginatorBuilder.java | 20 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index e2b9406..caf365b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -85,4 +85,9 @@ <component name="ProjectType"> <option name="id" value="jpab" /> </component> + <component name="SwUserDefinedSpecifications"> + <option name="specTypeByUrl"> + <map /> + </option> + </component> </project> \ No newline at end of file diff --git a/pom.xml b/pom.xml index 548c0c6..867be46 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ <groupId>com.github.ygimenez</groupId> <artifactId>Pagination-Utils</artifactId> - <version>3.0.8</version> + <version>4.0.0</version> <packaging>jar</packaging> <name>Pagination Utils</name> @@ -33,7 +33,7 @@ <url>https://github.com/ygimenez/Pagination-Utils</url> <connection>scm:git:git@github.com:ygimenez/Pagination-Utils.git</connection> <developerConnection>scm:git:git@github.com:ygimenez/Pagination-Utils.git</developerConnection> - <tag>Pagination-Utils-3.0.8</tag> + <tag>Pagination-Utils-4.0.0</tag> </scm> <distributionManagement> diff --git a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java index 6698b5b..1b200e9 100644 --- a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java +++ b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java @@ -42,6 +42,26 @@ public static PaginatorBuilder createPaginator() { return new PaginatorBuilder(new Paginator()); } + /** + * Creates a new {@link PaginatorBuilder} instance and begin customization, use {@link #build()} to finish. + * + * @param handler The {@link JDA} instance that'll be used for event processing. + * @return The {@link PaginatorBuilder} instance for chaining convenience. + */ + public static PaginatorBuilder createPaginator(@Nonnull JDA handler) { + return new PaginatorBuilder(new Paginator(handler)); + } + + /** + * Creates a new {@link PaginatorBuilder} instance and begin customization, use {@link #build()} to finish. + * + * @param handler The {@link ShardManager} instance that'll be used for event processing. + * @return The {@link PaginatorBuilder} instance for chaining convenience. + */ + public static PaginatorBuilder createPaginator(@Nonnull ShardManager handler) { + return new PaginatorBuilder(new Paginator(handler)); + } + /** * Creates a new {@link Paginator} instance using default settings. * From 1c18ecb446a4e065b118e9414701581908016ea7 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Fri, 6 Jan 2023 01:42:36 -0300 Subject: [PATCH 14/31] Initial migration of library to JDA 5. --- .idea/jpa-buddy.xml | 6 + .idea/misc.xml | 5 - pom.xml | 8 +- .../ygimenez/listener/MessageHandler.java | 43 ++--- .../com/github/ygimenez/method/Pages.java | 170 +++++++++--------- .../github/ygimenez/model/InteractPage.java | 21 ++- .../java/com/github/ygimenez/model/Page.java | 5 +- .../model/PaginationEventWrapper.java | 14 +- .../com/github/ygimenez/model/Paginator.java | 22 +-- .../ygimenez/model/PaginatorBuilder.java | 22 +-- .../ygimenez/model/helper/BaseHelper.java | 4 +- .../model/helper/ButtonizeHelper.java | 20 +-- .../model/helper/CategorizeHelper.java | 20 +-- .../model/helper/LazyPaginateHelper.java | 10 +- .../ygimenez/model/helper/PaginateHelper.java | 10 +- .../ygimenez/model/helper/ReadyMessage.java | 7 + .../ygimenez/model/helper/SendWrapper.java | 72 ++++++++ .../java/com/github/ygimenez/type/Emote.java | 16 +- 18 files changed, 277 insertions(+), 198 deletions(-) create mode 100644 .idea/jpa-buddy.xml create mode 100644 src/main/java/com/github/ygimenez/model/helper/ReadyMessage.java create mode 100644 src/main/java/com/github/ygimenez/model/helper/SendWrapper.java diff --git a/.idea/jpa-buddy.xml b/.idea/jpa-buddy.xml new file mode 100644 index 0000000..966d5f5 --- /dev/null +++ b/.idea/jpa-buddy.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="JpaBuddyIdeaProjectConfig"> + <option name="renamerInitialized" value="true" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index caf365b..e2b9406 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -85,9 +85,4 @@ <component name="ProjectType"> <option name="id" value="jpab" /> </component> - <component name="SwUserDefinedSpecifications"> - <option name="specTypeByUrl"> - <map /> - </option> - </component> </project> \ No newline at end of file diff --git a/pom.xml b/pom.xml index 867be46..85d7fe7 100644 --- a/pom.xml +++ b/pom.xml @@ -118,9 +118,9 @@ <repositories> <repository> - <id>jcenter</id> - <name>jcenter-bintray</name> - <url>https://jcenter.bintray.com</url> + <id>central</id> + <name>maven-central</name> + <url>https://repo1.maven.org/maven2/</url> </repository> <repository> <id>dv8tion</id> @@ -133,7 +133,7 @@ <dependency> <groupId>net.dv8tion</groupId> <artifactId>JDA</artifactId> - <version>4.4.0_350</version> + <version>5.0.0-beta.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> diff --git a/src/main/java/com/github/ygimenez/listener/MessageHandler.java b/src/main/java/com/github/ygimenez/listener/MessageHandler.java index 23b14d8..518574f 100644 --- a/src/main/java/com/github/ygimenez/listener/MessageHandler.java +++ b/src/main/java/com/github/ygimenez/listener/MessageHandler.java @@ -5,11 +5,10 @@ import com.github.ygimenez.model.PUtilsConfig; import com.github.ygimenez.model.PaginationEventWrapper; import com.github.ygimenez.model.ThrowingBiConsumer; -import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.PrivateChannel; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.events.message.GenericMessageEvent; import net.dv8tion.jda.api.events.message.MessageDeleteEvent; import net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent; @@ -17,10 +16,8 @@ import net.dv8tion.jda.api.events.message.react.MessageReactionRemoveEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Map; @@ -46,7 +43,7 @@ public class MessageHandler extends ListenerAdapter { * @return An {@link ActionReference} pointing to this event. This is useful if you need to track whether an event * is still being processed or was already removed (ie. garbage collected). */ - public ActionReference addEvent(@Nonnull Message msg, @Nonnull ThrowingBiConsumer<User, PaginationEventWrapper> act) { + public ActionReference addEvent(@NotNull Message msg, @NotNull ThrowingBiConsumer<User, PaginationEventWrapper> act) { String id = getEventId(msg); Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Added event with ID " + id + " and Consumer hash " + Integer.toHexString(act.hashCode())); events.put(id, act); @@ -59,7 +56,7 @@ public ActionReference addEvent(@Nonnull Message msg, @Nonnull ThrowingBiConsume * * @param msg The {@link Message} which had attached events. */ - public void removeEvent(@Nonnull Message msg) { + public void removeEvent(@NotNull Message msg) { String id = getEventId(msg); Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Removed event with ID " + id); events.remove(id); @@ -78,7 +75,7 @@ public boolean checkEvent(@Nullable String hash) { /** * Retrieves the event handler map. This will contain all currently active events being handled by - * the library mapped by {@link Guild} ID ({@link PrivateChannel} ID for DM) plus the {@link Message} ID. + * the library mapped by {@link MessageChannel} ID plus the {@link Message} ID. * * @return An unmodifiable {@link Map} containing events handled by the library. */ @@ -96,37 +93,37 @@ public void clear() { events.clear(); } - private void lock(@Nonnull String id) { + private void lock(@NotNull String id) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Locked event with ID " + id); locks.add(id); } - private void unlock(@Nonnull String id) { + private void unlock(@NotNull String id) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Unlocked event with ID " + id); locks.remove(id); } - private boolean isLocked(@Nonnull GenericMessageReactionEvent evt) { + private boolean isLocked(@NotNull GenericMessageReactionEvent evt) { return locks.contains(getEventId(evt)); } - private boolean isLocked(@Nonnull String id) { + private boolean isLocked(@NotNull String id) { return locks.contains(id); } @Override - public void onMessageReactionAdd(@Nonnull MessageReactionAddEvent evt) { + public void onMessageReactionAdd(@NotNull MessageReactionAddEvent evt) { execute(evt); } @Override - public void onMessageReactionRemove(@Nonnull MessageReactionRemoveEvent evt) { + public void onMessageReactionRemove(@NotNull MessageReactionRemoveEvent evt) { if (!Pages.getPaginator().isRemoveOnReact() || !evt.isFromGuild()) execute(evt); } @Override - public void onMessageDelete(@Nonnull MessageDeleteEvent evt) { + public void onMessageDelete(@NotNull MessageDeleteEvent evt) { events.remove(getEventId(evt)); } @@ -136,15 +133,13 @@ private void execute(GenericMessageReactionEvent evt) { evt.retrieveUser().submit() .whenComplete((u, t) -> processEvent( - t, - id, - u, + t, id, u, new PaginationEventWrapper(evt, u, evt.getChannel(), evt.getMessageId(), evt.getReaction(), evt.isFromGuild()) )); } @Override - public void onButtonClick(@NotNull ButtonClickEvent evt) { + public void onButtonInteraction(@NotNull ButtonInteractionEvent evt) { User u = evt.getUser(); String id = getEventId(evt); if (!events.containsKey(id)) return; @@ -191,15 +186,15 @@ private void processEvent(Throwable t, String id, User u, PaginationEventWrapper private String getEventId(GenericMessageEvent evt) { crc.reset(); - String rawId = (evt.isFromGuild() ? "GUILD_" + evt.getGuild().getId() : "PRIVATE_" + evt.getPrivateChannel().getId()) + "_" + evt.getMessageId(); + String rawId = (evt.isFromGuild() ? "GUILD_" : "PRIVATE_") + evt.getChannel().getId() + "_" + evt.getMessageId(); crc.update(rawId.getBytes(StandardCharsets.UTF_8)); return Long.toHexString(crc.getValue()); } - private String getEventId(ButtonClickEvent evt) { + private String getEventId(ButtonInteractionEvent evt) { crc.reset(); - String rawId = (evt.getGuild() != null ? "GUILD_" + evt.getGuild().getId() : "PRIVATE_" + evt.getPrivateChannel().getId()) + "_" + evt.getMessageId(); + String rawId = (evt.isFromGuild() ? "GUILD_" : "PRIVATE_") + evt.getChannel().getId() + "_" + evt.getId(); crc.update(rawId.getBytes(StandardCharsets.UTF_8)); return Long.toHexString(crc.getValue()); @@ -207,7 +202,7 @@ private String getEventId(ButtonClickEvent evt) { private String getEventId(Message msg) { crc.reset(); - String rawId = (msg.isFromGuild() ? "GUILD_" + msg.getGuild().getId() : "PRIVATE_" + msg.getPrivateChannel().getId()) + "_" + msg.getId(); + String rawId = (msg.isFromGuild() ? "GUILD_" : "PRIVATE_") + msg.getChannel().getId() + "_" + msg.getId(); crc.update(rawId.getBytes(StandardCharsets.UTF_8)); return Long.toHexString(crc.getValue()); diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 0533199..c35a871 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -13,20 +13,23 @@ import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; -import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent; import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; import net.dv8tion.jda.api.exceptions.ErrorResponseException; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.interactions.InteractionHook; import net.dv8tion.jda.api.interactions.components.ActionRow; -import net.dv8tion.jda.api.interactions.components.Button; -import net.dv8tion.jda.api.interactions.components.Component; +import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.sharding.ShardManager; +import net.dv8tion.jda.api.utils.messages.MessageEditBuilder; +import net.dv8tion.jda.api.utils.messages.MessageEditData; +import org.jetbrains.annotations.NotNull; -import javax.annotation.Nonnull; -import java.lang.ref.WeakReference; import java.util.*; import java.util.concurrent.*; import java.util.function.Consumer; @@ -57,7 +60,7 @@ public class Pages { * @throws InvalidHandlerException Thrown if the handler isn't either a {@link JDA} * or {@link ShardManager} object. */ - public static void activate(@Nonnull Paginator paginator) throws InvalidHandlerException { + public static void activate(@NotNull Paginator paginator) throws InvalidHandlerException { if (isActivated()) throw new AlreadyActivatedException(); @@ -136,7 +139,7 @@ public static MessageHandler getHandler() { * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, 0, false, null); } @@ -164,7 +167,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, 0, false, null); } @@ -188,7 +191,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, 0, false, canInteract); } @@ -218,7 +221,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, 0, false, canInteract); } @@ -241,7 +244,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, 0, fastForward, null); } @@ -270,7 +273,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, 0, fastForward, null); } @@ -295,7 +298,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, 0, fastForward, canInteract); } @@ -326,7 +329,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, 0, fastForward, canInteract); } @@ -350,7 +353,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, skipAmount, false, null); } @@ -380,7 +383,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, skipAmount, false, null); } @@ -406,7 +409,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, skipAmount, false, canInteract); } @@ -438,7 +441,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, skipAmount, false, canInteract); } @@ -465,7 +468,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, 0, null, skipAmount, fastForward, canInteract); } @@ -496,7 +499,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, pages, useButtons, time, unit, skipAmount, fastForward, null); } @@ -529,7 +532,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, new PaginateHelper(pages, useButtons) .setTimeUnit(time, unit) .setSkipAmount(skipAmount) @@ -554,7 +557,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull List<Page> * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or the page list is empty. */ - public static ActionReference paginate(@Nonnull Message msg, @Nonnull PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference paginate(@NotNull Message msg, @NotNull PaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated() || helper.getContent().isEmpty()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); List<Page> pgs = Collections.unmodifiableList(helper.getContent()); @@ -587,7 +590,7 @@ public static ActionReference paginate(@Nonnull Message msg, @Nonnull PaginateHe } @Override - public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) { + public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { @@ -596,7 +599,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe Emote emt = NONE; if (wrapper.getContent() instanceof MessageReaction) { - MessageReaction.ReactionEmote reaction = ((MessageReaction) wrapper.getContent()).getReactionEmote(); + EmojiUnion reaction = ((MessageReaction) wrapper.getContent()).getEmoji(); emt = toEmote(reaction); } else if (wrapper.getContent() instanceof Button) { Button btn = (Button) wrapper.getContent(); @@ -700,7 +703,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoji, Page> categories, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, categories, useButtons, 0, null, null); } @@ -729,7 +732,7 @@ public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoj * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, categories, useButtons, time, unit, null); } @@ -754,7 +757,7 @@ public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoj * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoji, Page> categories, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, categories, useButtons, 0, null, canInteract); } @@ -785,7 +788,7 @@ public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoj * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, new CategorizeHelper(categories, useButtons) .setTimeUnit(time, unit) .setCanInteract(canInteract) @@ -808,7 +811,7 @@ public static ActionReference categorize(@Nonnull Message msg, @Nonnull Map<Emoj * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference categorize(@Nonnull Message msg, @Nonnull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference categorize(@NotNull Message msg, @NotNull CategorizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); @@ -821,10 +824,10 @@ public static ActionReference categorize(@Nonnull Message msg, @Nonnull Categori clearReactions(msg); for (Emoji k : cats.keySet()) { - msg.addReaction(k.getAsMention().replaceAll("[<>]", "")).submit(); + msg.addReaction(k).submit(); } - msg.addReaction(paginator.getStringEmote(CANCEL)).submit(); + msg.addReaction(paginator.getEmoji(CANCEL)).submit(); } return handler.addEvent(msg, new ThrowingBiConsumer<>() { @@ -843,7 +846,7 @@ public static ActionReference categorize(@Nonnull Message msg, @Nonnull Categori } @Override - public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) { + public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { @@ -853,7 +856,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe Emoji emoji = null; Emote emt = NONE; if (wrapper.getContent() instanceof MessageReaction) { - MessageReaction.ReactionEmote reaction = ((MessageReaction) wrapper.getContent()).getReactionEmote(); + EmojiUnion reaction = ((MessageReaction) wrapper.getContent()).getEmoji(); emoji = toEmoji(reaction); emt = toEmote(reaction); } else if (wrapper.getContent() instanceof Button) { @@ -917,7 +920,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, null, null); } @@ -947,7 +950,7 @@ public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, time, unit, null, null); } @@ -975,7 +978,7 @@ public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, canInteract, null); } @@ -1008,7 +1011,7 @@ public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, time, unit, canInteract, null); } @@ -1037,7 +1040,7 @@ public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean showCancelButton, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, buttons, useButtons, showCancelButton, 0, null, canInteract, onCancel); } @@ -1071,7 +1074,7 @@ public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean cancellable, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean cancellable, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, new ButtonizeHelper(buttons, useButtons) .setCancellable(cancellable) .setTimeUnit(time, unit) @@ -1096,7 +1099,7 @@ public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Map<Emoji * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated. */ - public static ActionReference buttonize(@Nonnull Message msg, @Nonnull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference buttonize(@NotNull Message msg, @NotNull ButtonizeHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); @@ -1109,11 +1112,11 @@ public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Buttonize clearReactions(msg); for (Emoji k : btns.keySet()) { - msg.addReaction(k.getAsMention().replaceAll("[<>]", "")).submit(); + msg.addReaction(k).submit(); } - if (!btns.containsKey(paginator.getEmote(CANCEL)) && helper.isCancellable()) { - msg.addReaction(paginator.getStringEmote(CANCEL)).submit(); + if (!btns.containsKey(paginator.getEmoji(CANCEL)) && helper.isCancellable()) { + msg.addReaction(paginator.getEmoji(CANCEL)).submit(); } } @@ -1133,7 +1136,7 @@ public static ActionReference buttonize(@Nonnull Message msg, @Nonnull Buttonize } @Override - public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) { + public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { @@ -1143,7 +1146,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe Emoji emoji = null; Emote emt = NONE; if (wrapper.getContent() instanceof MessageReaction) { - MessageReaction.ReactionEmote reaction = ((MessageReaction) wrapper.getContent()).getReactionEmote(); + EmojiUnion reaction = ((MessageReaction) wrapper.getContent()).getEmoji(); emoji = toEmoji(reaction); emt = toEmote(reaction); } else if (wrapper.getContent() instanceof Button) { @@ -1155,14 +1158,14 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe } } - if ((!btns.containsKey(paginator.getEmote(CANCEL)) && helper.isCancellable()) && emt == CANCEL) { + if ((!btns.containsKey(paginator.getEmoji(CANCEL)) && helper.isCancellable()) && emt == CANCEL) { finalizeEvent(m, success); return; } InteractionHook hook; - if (wrapper.getSource() instanceof ButtonClickEvent) { - hook = ((ButtonClickEvent) wrapper.getSource()).getHook(); + if (wrapper.getSource() instanceof ButtonInteractionEvent) { + hook = ((ButtonInteractionEvent) wrapper.getSource()).getHook(); } else { hook = null; } @@ -1202,7 +1205,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, null, pageLoader, useButtons, 0, null, null); } @@ -1229,7 +1232,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull Throwi * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, null, pageLoader, useButtons, time, unit, null); } @@ -1252,7 +1255,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull Throwi * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, null, pageLoader, useButtons, 0, null, canInteract); } @@ -1281,7 +1284,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull Throwi * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, null, pageLoader, useButtons, time, unit, canInteract); } @@ -1303,7 +1306,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull Throwi * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> pageCache, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, null); } @@ -1331,7 +1334,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> page * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> pageCache, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, pageCache, pageLoader, useButtons, time, unit, null); } @@ -1355,7 +1358,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> page * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> pageCache, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, pageCache, pageLoader, useButtons, 0, null, canInteract); } @@ -1385,7 +1388,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> page * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> pageCache, @Nonnull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> pageCache, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, new LazyPaginateHelper(pageLoader, pageCache, useButtons) .setTimeUnit(time, unit) .setCanInteract(canInteract) @@ -1407,7 +1410,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, List<Page> page * due to lack of bot permission. * @throws InvalidStateException Thrown if the library wasn't activated or first page cannot be generated. */ - public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { + public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull LazyPaginateHelper helper) throws ErrorResponseException, InsufficientPermissionException { if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); boolean cache = helper.getContent() != null; @@ -1436,7 +1439,7 @@ public static ActionReference lazyPaginate(@Nonnull Message msg, @Nonnull LazyPa } @Override - public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrapper) { + public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { @@ -1445,7 +1448,7 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe Emote emt = NONE; if (wrapper.getContent() instanceof MessageReaction) { - MessageReaction.ReactionEmote reaction = ((MessageReaction) wrapper.getContent()).getReactionEmote(); + EmojiUnion reaction = ((MessageReaction) wrapper.getContent()).getEmoji(); emt = toEmote(reaction); } else if (wrapper.getContent() instanceof Button) { Button btn = (Button) wrapper.getContent(); @@ -1515,17 +1518,21 @@ public void acceptThrows(@Nonnull User u, @Nonnull PaginationEventWrapper wrappe * @param msg The current {@link Message} object. * @param p The current {@link Page}. */ - private static void updatePage(@Nonnull Message msg, Page p) { + private static void updatePage(@NotNull Message msg, Page p) { if (p == null) throw new NullPageException(msg); if (p.getContent() instanceof Message) { - msg.editMessage((Message) p.getContent()).submit(); + MessageEditData data = MessageEditBuilder.fromMessage((Message) p.getContent()).build(); + + try (data) { + msg.editMessage(data).submit(); + } } else if (p.getContent() instanceof MessageEmbed) { msg.editMessageEmbeds((MessageEmbed) p.getContent()).submit(); } } - private static void updateButtons(Message msg, PaginateHelper helper) { + private static void updateButtons(@NotNull Message msg, @NotNull PaginateHelper helper) { if (helper.isUsingButtons()) { helper.apply(msg.editMessageComponents()).submit(); } else { @@ -1533,7 +1540,7 @@ private static void updateButtons(Message msg, PaginateHelper helper) { } } - private static void updateButtons(Message msg, LazyPaginateHelper helper) { + private static void updateButtons(@NotNull Message msg, @NotNull LazyPaginateHelper helper) { if (helper.isUsingButtons()) { helper.apply(msg.editMessageComponents()).submit(); } else { @@ -1547,7 +1554,7 @@ private static void updateButtons(Message msg, LazyPaginateHelper helper) { * @param msg The {@link Message} to be reloaded. * @return The updated message instance. */ - public static Message reloadMessage(Message msg) { + public static Message reloadMessage(@NotNull Message msg) { return subGet(msg.getChannel().retrieveMessageById(msg.getId()), msg); } @@ -1558,7 +1565,7 @@ public static Message reloadMessage(Message msg) { * @param <T> Return type for the {@link RestAction}. * @return The {@link RestAction} result, or null should it fail. */ - public static <T> T subGet(RestAction<T> future) { + public static <T> T subGet(@NotNull RestAction<T> future) { try { return future.submit().get(); } catch (InterruptedException | ExecutionException e) { @@ -1575,7 +1582,7 @@ public static <T> T subGet(RestAction<T> future) { * @param <T> Return type for the {@link RestAction}. * @return The {@link RestAction} result. */ - public static <T> T subGet(RestAction<T> future, T or) { + public static <T> T subGet(@NotNull RestAction<T> future, @NotNull T or) { try { return future.submit().get(); } catch (InterruptedException | ExecutionException e) { @@ -1584,12 +1591,12 @@ public static <T> T subGet(RestAction<T> future, T or) { } } - private static Emote toEmote(MessageReaction.ReactionEmote reaction) { + private static Emote toEmote(EmojiUnion reaction) { return Emote.getByEmoji(toEmoji(reaction)); } - private static Emoji toEmoji(MessageReaction.ReactionEmote reaction) { - return reaction.isEmoji() ? Emoji.fromUnicode(reaction.getEmoji()) : Emoji.fromEmote(reaction.getEmote()); + private static Emoji toEmoji(EmojiUnion reaction) { + return Emoji.fromFormatted(reaction.getFormatted()); } /** @@ -1651,11 +1658,14 @@ public static void modifyButtons(Message msg, Map<String, Function<Button, Butto List<ActionRow> rows = new ArrayList<>(msg.getActionRows()); for (ActionRow ar : rows) { - List<Component> row = ar.getComponents(); + List<ItemComponent> row = ar.getComponents(); for (int i = 0; i < row.size(); i++) { - Component c = row.get(i); - if (c instanceof Button && changes.containsKey(c.getId())) { - row.set(i, changes.get(c.getId()).apply((Button) c)); + ItemComponent c = row.get(i); + if (c instanceof Button) { + Button b = (Button) c; + if (changes.containsKey(b.getId())) { + row.set(i, changes.get(b.getId()).apply((Button) c)); + } } } } @@ -1674,15 +1684,15 @@ public static void addReactions(Message msg, boolean withSkip, boolean withGoto) clearButtons(msg); List<RestAction<Void>> acts = new ArrayList<>(); - if (withGoto) acts.add(msg.addReaction(paginator.getStringEmote(GOTO_FIRST))); - if (withSkip) acts.add(msg.addReaction(paginator.getStringEmote(SKIP_BACKWARD))); + if (withGoto) acts.add(msg.addReaction(paginator.getEmoji(GOTO_FIRST))); + if (withSkip) acts.add(msg.addReaction(paginator.getEmoji(SKIP_BACKWARD))); - acts.add(msg.addReaction(paginator.getStringEmote(PREVIOUS))); - acts.add(msg.addReaction(paginator.getStringEmote(CANCEL))); - acts.add(msg.addReaction(paginator.getStringEmote(NEXT))); + acts.add(msg.addReaction(paginator.getEmoji(PREVIOUS))); + acts.add(msg.addReaction(paginator.getEmoji(CANCEL))); + acts.add(msg.addReaction(paginator.getEmoji(NEXT))); - if (withSkip) acts.add(msg.addReaction(paginator.getStringEmote(SKIP_FORWARD))); - if (withGoto) acts.add(msg.addReaction(paginator.getStringEmote(GOTO_LAST))); + if (withSkip) acts.add(msg.addReaction(paginator.getEmoji(SKIP_FORWARD))); + if (withGoto) acts.add(msg.addReaction(paginator.getEmoji(GOTO_LAST))); RestAction.allOf(acts).submit(); } diff --git a/src/main/java/com/github/ygimenez/model/InteractPage.java b/src/main/java/com/github/ygimenez/model/InteractPage.java index 13fa559..5a02458 100644 --- a/src/main/java/com/github/ygimenez/model/InteractPage.java +++ b/src/main/java/com/github/ygimenez/model/InteractPage.java @@ -2,14 +2,13 @@ import com.github.ygimenez.method.Pages; import com.github.ygimenez.type.Emote; -import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.interactions.components.Button; -import net.dv8tion.jda.api.interactions.components.ButtonStyle; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle; import org.jetbrains.annotations.NotNull; -import javax.annotation.Nonnull; import java.util.EnumMap; import java.util.Map; import java.util.Objects; @@ -70,13 +69,13 @@ public Map<Emote, String> getCaptions() { * If you supply {@link Emote#NONE} a blank disabled button will be created. * @return The created {@link Button}. */ - public Button makeButton(@Nonnull Emote emt) { - ButtonStyle style = styles.getOrDefault(emt.getStyle(), emt.getStyle()); + public Button makeButton(@NotNull Emote emt) { + ButtonStyle style = styles.getOrDefault(emt.getStyle(), ButtonStyle.SECONDARY); if (emt == Emote.NONE) { return Button.secondary(emt.name() + "." + Objects.hash(Math.random()), "\u200B").asDisabled(); } else { - return Button.of(style, (ephemeral ? "*" : "") + emt.name(), caption.get(emt), Pages.getPaginator().getEmote(emt)); + return Button.of(style, (ephemeral ? "*" : "") + emt.name(), caption.get(emt), Pages.getPaginator().getEmoji(emt)); } } @@ -86,8 +85,8 @@ public Button makeButton(@Nonnull Emote emt) { * @param emj The {@link Emoji} representing the {@link Button}, must never be null since it is also the ID. * @return The created {@link Button}. */ - public Button makeButton(@Nonnull Emoji emj) { - return Button.secondary((ephemeral ? "*" : "") + emj.getId(), emj); + public Button makeButton(@NotNull Emoji emj) { + return Button.secondary((ephemeral ? "*" : "") + Emote.getId(emj), emj); } /** @@ -97,8 +96,8 @@ public Button makeButton(@Nonnull Emoji emj) { * @param caption The desired caption for the {@link Button}. * @return The created {@link Button}. */ - public Button makeButton(@Nonnull Emoji emj, String caption) { - return Button.of(ButtonStyle.SECONDARY, (ephemeral ? "*" : "") + emj.getId(), caption, emj); + public Button makeButton(@NotNull Emoji emj, String caption) { + return Button.of(ButtonStyle.SECONDARY, (ephemeral ? "*" : "") + Emote.getId(emj), caption, emj); } /** diff --git a/src/main/java/com/github/ygimenez/model/Page.java b/src/main/java/com/github/ygimenez/model/Page.java index b6c88ea..d80b887 100644 --- a/src/main/java/com/github/ygimenez/model/Page.java +++ b/src/main/java/com/github/ygimenez/model/Page.java @@ -2,8 +2,7 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.MessageEmbed; - -import javax.annotation.Nonnull; +import org.jetbrains.annotations.NotNull; /** * Class representing either a {@link Message} or {@link MessageEmbed} object. @@ -18,7 +17,7 @@ public class Page { * @param content The {@link Message}/{@link MessageEmbed} object to be used as pages. * @throws IllegalArgumentException Thrown if argument is not a {@link Message} nor {@link MessageEmbed}. */ - public Page(@Nonnull Object content) throws IllegalArgumentException { + public Page(@NotNull Object content) throws IllegalArgumentException { if (!(content instanceof Message) && !(content instanceof MessageEmbed)) throw new IllegalArgumentException("Page content must be either a Message or a MessageEmbed"); diff --git a/src/main/java/com/github/ygimenez/model/PaginationEventWrapper.java b/src/main/java/com/github/ygimenez/model/PaginationEventWrapper.java index 8d97e80..a99a88e 100644 --- a/src/main/java/com/github/ygimenez/model/PaginationEventWrapper.java +++ b/src/main/java/com/github/ygimenez/model/PaginationEventWrapper.java @@ -1,9 +1,13 @@ package com.github.ygimenez.model; -import net.dv8tion.jda.api.entities.*; -import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageReaction; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent; -import net.dv8tion.jda.api.interactions.components.Button; +import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.requests.RestAction; /** @@ -20,9 +24,9 @@ public class PaginationEventWrapper { /** * Constructs a new {@link PaginationEventWrapper} instance. You probably shouldn't be creating one yourself. * - * @param source The source event, will be either a {@link GenericMessageReactionEvent} or a {@link ButtonClickEvent}. + * @param source The source event, will be either a {@link GenericMessageReactionEvent} or a {@link ButtonInteractionEvent}. * @param user The {@link User} who triggered the event. - * @param channel The {@link TextChannel} where the event happened. + * @param channel The {@link MessageChannel} where the event happened. * @param messageId The {@link Message} ID. * @param content The button which was pressed, will be either a {@link MessageReaction} or a {@link Button}. * @param isFromGuild Whether the event happened on a {@link Guild} or not. diff --git a/src/main/java/com/github/ygimenez/model/Paginator.java b/src/main/java/com/github/ygimenez/model/Paginator.java index b021392..6652794 100644 --- a/src/main/java/com/github/ygimenez/model/Paginator.java +++ b/src/main/java/com/github/ygimenez/model/Paginator.java @@ -4,13 +4,15 @@ import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.sharding.ShardManager; import net.dv8tion.jda.internal.utils.JDALogger; import org.slf4j.Logger; -import java.util.*; +import java.util.Collections; +import java.util.EnumMap; +import java.util.Map; /** * This is the core object for Pagination-Utils' settings.<br> @@ -138,27 +140,15 @@ public Map<Emote, Emoji> getEmotes() { } /** - * Same as {@link #getEmotes()} but this method will turn {@link net.dv8tion.jda.api.entities.Emote} mentions - * into IDs. + * Retrieves the {@link Emoji} assigned to the supplied {@link Emote}. * * @param emote The {@link Emote} to be defined. * @return The {@link Emoji} representing this {@link Emote}. */ - public Emoji getEmote(Emote emote) { + public Emoji getEmoji(Emote emote) { return emotes.getOrDefault(emote, emote.getDefault()); } - /** - * Same as {@link #getEmotes()} but this method will turn {@link net.dv8tion.jda.api.entities.Emote} mentions - * into IDs. - * - * @param emote The {@link Emote} to be defined. - * @return The {@link Emoji} representing this {@link Emote}. - */ - public String getStringEmote(Emote emote) { - return getEmote(emote).getAsMention().replaceAll("[<>]", ""); - } - /** * Make configured {@link Emote}s final. * <strong>This must only be called by {@link PaginatorBuilder}</strong>. diff --git a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java index 1b200e9..c291a5b 100644 --- a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java +++ b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java @@ -29,7 +29,7 @@ public class PaginatorBuilder { * * @param paginator The raw {@link Paginator} object to start building. */ - private PaginatorBuilder(@Nonnull Paginator paginator) { + private PaginatorBuilder(@NotNull Paginator paginator) { this.paginator = paginator; } @@ -48,7 +48,7 @@ public static PaginatorBuilder createPaginator() { * @param handler The {@link JDA} instance that'll be used for event processing. * @return The {@link PaginatorBuilder} instance for chaining convenience. */ - public static PaginatorBuilder createPaginator(@Nonnull JDA handler) { + public static PaginatorBuilder createPaginator(@NotNull JDA handler) { return new PaginatorBuilder(new Paginator(handler)); } @@ -58,7 +58,7 @@ public static PaginatorBuilder createPaginator(@Nonnull JDA handler) { * @param handler The {@link ShardManager} instance that'll be used for event processing. * @return The {@link PaginatorBuilder} instance for chaining convenience. */ - public static PaginatorBuilder createPaginator(@Nonnull ShardManager handler) { + public static PaginatorBuilder createPaginator(@NotNull ShardManager handler) { return new PaginatorBuilder(new Paginator(handler)); } @@ -68,7 +68,7 @@ public static PaginatorBuilder createPaginator(@Nonnull ShardManager handler) { * @param handler The {@link JDA} instance that'll be used for event processing. * @return The {@link PaginatorBuilder} instance for chaining convenience. */ - public static Paginator createSimplePaginator(@Nonnull JDA handler) { + public static Paginator createSimplePaginator(@NotNull JDA handler) { Paginator p = new Paginator(handler); p.finishEmotes(); @@ -81,7 +81,7 @@ public static Paginator createSimplePaginator(@Nonnull JDA handler) { * @param handler The {@link ShardManager} instance that'll be used for event processing. * @return The {@link PaginatorBuilder} instance for chaining convenience. */ - public static Paginator createSimplePaginator(@Nonnull ShardManager handler) { + public static Paginator createSimplePaginator(@NotNull ShardManager handler) { Paginator p = new Paginator(handler); p.finishEmotes(); @@ -103,7 +103,7 @@ public Object getHandler() { * @param handler The {@link JDA} instance that'll be used for event processing. * @return The {@link PaginatorBuilder} instance for chaining convenience. */ - public PaginatorBuilder setHandler(@Nonnull JDA handler) { + public PaginatorBuilder setHandler(@NotNull JDA handler) { paginator.setHandler(handler); return this; } @@ -114,7 +114,7 @@ public PaginatorBuilder setHandler(@Nonnull JDA handler) { * @param handler The {@link ShardManager} instance that'll be used for event processing. * @return The {@link PaginatorBuilder} instance for chaining convenience. */ - public PaginatorBuilder setHandler(@Nonnull ShardManager handler) { + public PaginatorBuilder setHandler(@NotNull ShardManager handler) { paginator.setHandler(handler); return this; } @@ -193,8 +193,8 @@ public PaginatorBuilder setDeleteOnCancel(boolean deleteOnCancel) { * @param emote The {@link Emote} to be retrieved. * @return The {@link Emote}'s code. */ - public Emoji getEmote(@Nonnull Emote emote) { - return paginator.getEmote(emote); + public Emoji getEmote(@NotNull Emote emote) { + return paginator.getEmoji(emote); } /** @@ -208,7 +208,7 @@ public Emoji getEmote(@Nonnull Emote emote) { * @throws InvalidHandlerException If the configured handler is not a {@link JDA} or {@link ShardManager} * object. */ - public PaginatorBuilder setEmote(@Nonnull Emote emote, @Nonnull String code) throws InvalidHandlerException { + public PaginatorBuilder setEmote(@NotNull Emote emote, @NotNull String code) throws InvalidHandlerException { return setEmote(emote, Emoji.fromMarkdown(code)); } @@ -221,7 +221,7 @@ public PaginatorBuilder setEmote(@Nonnull Emote emote, @Nonnull String code) thr * @throws InvalidHandlerException If the configured handler is not a {@link JDA} or {@link ShardManager} * object. */ - public PaginatorBuilder setEmote(@Nonnull Emote emote, @Nonnull Emoji emoji) throws InvalidHandlerException { + public PaginatorBuilder setEmote(@NotNull Emote emote, @NotNull Emoji emoji) throws InvalidHandlerException { if (paginator.getHandler() == null) throw new InvalidHandlerException(); else if (paginator.getEmotes().containsValue(emoji)) throw new AlreadyAssignedException(); diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java index 48ea6d5..d4b192a 100644 --- a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -2,7 +2,7 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.requests.restaction.MessageAction; +import net.dv8tion.jda.api.utils.messages.MessageRequest; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; @@ -74,7 +74,7 @@ public Sub setCanInteract(Predicate<User> canInteract) { return subClass.cast(this); } - public abstract MessageAction apply(MessageAction action); + public abstract <Out extends MessageRequest<Out>> Out apply(Out action); public abstract boolean shouldUpdate(Message msg); } diff --git a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java index 931d382..c434d61 100644 --- a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java @@ -4,12 +4,12 @@ import com.github.ygimenez.model.ButtonWrapper; import com.github.ygimenez.model.ThrowingConsumer; import com.github.ygimenez.type.Emote; -import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.interactions.components.ActionRow; -import net.dv8tion.jda.api.interactions.components.Button; -import net.dv8tion.jda.api.interactions.components.Component; -import net.dv8tion.jda.api.requests.restaction.MessageAction; +import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import net.dv8tion.jda.api.utils.messages.MessageRequest; import java.util.*; import java.util.function.Consumer; @@ -44,12 +44,12 @@ public ButtonizeHelper setOnCancel(Consumer<Message> onCancel) { } @Override - public MessageAction apply(MessageAction action) { + public <Out extends MessageRequest<Out>> Out apply(Out action) { if (!isUsingButtons()) return action; List<ActionRow> rows = new ArrayList<>(); - List<Component> row = new ArrayList<>(); + List<ItemComponent> row = new ArrayList<>(); for (Emoji k : getContent().keySet()) { if (row.size() == 5) { rows.add(ActionRow.of(row)); @@ -59,8 +59,8 @@ public MessageAction apply(MessageAction action) { row.add(Button.secondary(Emote.getId(k), k)); } - if (!getContent().containsKey(Pages.getPaginator().getEmote(CANCEL)) && isCancellable()) { - Button button = Button.danger(CANCEL.name(), Pages.getPaginator().getEmote(CANCEL)); + if (!getContent().containsKey(Pages.getPaginator().getEmoji(CANCEL)) && isCancellable()) { + Button button = Button.danger(CANCEL.name(), Pages.getPaginator().getEmoji(CANCEL)); if (rows.size() == 5 && row.size() == 5) { row.set(4, button); @@ -76,14 +76,14 @@ public MessageAction apply(MessageAction action) { rows.add(ActionRow.of(row)); - return action.setActionRows(rows); + return action.setComponents(rows); } @Override public boolean shouldUpdate(Message msg) { if (!isUsingButtons()) return false; - Predicate<Set<Emoji>> checks = e -> !isCancellable() || e.contains(Pages.getPaginator().getEmote(CANCEL)); + Predicate<Set<Emoji>> checks = e -> !isCancellable() || e.contains(Pages.getPaginator().getEmoji(CANCEL)); Set<Emoji> emojis = msg.getButtons().stream() .map(Button::getEmoji) .collect(Collectors.toSet()); diff --git a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java index 3057d96..c392af7 100644 --- a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java @@ -3,18 +3,18 @@ import com.github.ygimenez.method.Pages; import com.github.ygimenez.model.Page; import com.github.ygimenez.type.Emote; -import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.interactions.components.ActionRow; -import net.dv8tion.jda.api.interactions.components.Button; -import net.dv8tion.jda.api.interactions.components.Component; -import net.dv8tion.jda.api.requests.restaction.MessageAction; +import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import net.dv8tion.jda.api.utils.messages.MessageRequest; import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; -import static com.github.ygimenez.type.Emote.*; +import static com.github.ygimenez.type.Emote.CANCEL; public class CategorizeHelper extends BaseHelper<CategorizeHelper, Map<Emoji, Page>> { public CategorizeHelper(boolean useButtons) { @@ -31,12 +31,12 @@ public CategorizeHelper addCategory(Emoji emoji, Page page) { } @Override - public MessageAction apply(MessageAction action) { + public <Out extends MessageRequest<Out>> Out apply(Out action) { if (!isUsingButtons()) return action; List<ActionRow> rows = new ArrayList<>(); - List<Component> row = new ArrayList<>(); + List<ItemComponent> row = new ArrayList<>(); for (Emoji k : getContent().keySet()) { if (row.size() == 5) { rows.add(ActionRow.of(row)); @@ -47,7 +47,7 @@ public MessageAction apply(MessageAction action) { } if (isCancellable()) { - Button button = Button.danger(CANCEL.name(), Pages.getPaginator().getEmote(CANCEL)); + Button button = Button.danger(CANCEL.name(), Pages.getPaginator().getEmoji(CANCEL)); if (rows.size() == 5 && row.size() == 5) { row.set(4, button); } else if (row.size() == 5) { @@ -62,14 +62,14 @@ public MessageAction apply(MessageAction action) { rows.add(ActionRow.of(row)); - return action.setActionRows(rows); + return action.setComponents(rows); } @Override public boolean shouldUpdate(Message msg) { if (!isUsingButtons()) return false; - Predicate<Set<Emoji>> checks = e -> !isCancellable() || e.contains(Pages.getPaginator().getEmote(CANCEL)); + Predicate<Set<Emoji>> checks = e -> !isCancellable() || e.contains(Pages.getPaginator().getEmoji(CANCEL)); Set<Emoji> emojis = msg.getButtons().stream() .map(Button::getEmoji) .collect(Collectors.toSet()); diff --git a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java index 848b529..b9b7471 100644 --- a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java @@ -1,6 +1,5 @@ package com.github.ygimenez.model.helper; -import com.github.ygimenez.exception.InvalidStateException; import com.github.ygimenez.exception.NullPageException; import com.github.ygimenez.model.InteractPage; import com.github.ygimenez.model.Page; @@ -8,9 +7,9 @@ import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.interactions.components.ActionRow; -import net.dv8tion.jda.api.requests.restaction.MessageAction; +import net.dv8tion.jda.api.utils.messages.MessageRequest; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -18,7 +17,6 @@ import java.util.stream.Collectors; import static com.github.ygimenez.type.Emote.*; -import static com.github.ygimenez.type.Emote.GOTO_LAST; public class LazyPaginateHelper extends BaseHelper<LazyPaginateHelper, List<Page>> { private final ThrowingFunction<Integer, Page> pageLoader; @@ -64,13 +62,13 @@ public ThrowingFunction<Integer, Page> getPageLoader() { } @Override - public MessageAction apply(MessageAction action) { + public <Out extends MessageRequest<Out>> Out apply(Out action) { if (!isUsingButtons()) return action; InteractPage p = (InteractPage) load(0); if (p == null) throw new NullPageException(); - return action.setActionRows(ActionRow.of(new ArrayList<>() {{ + return action.setComponents(ActionRow.of(new ArrayList<>() {{ add(p.makeButton(PREVIOUS)); if (isCancellable()) add(p.makeButton(CANCEL)); add(p.makeButton(NEXT)); diff --git a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java index 3ff9b84..161b446 100644 --- a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java @@ -6,8 +6,8 @@ import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.interactions.components.ActionRow; -import net.dv8tion.jda.api.interactions.components.Component; -import net.dv8tion.jda.api.requests.restaction.MessageAction; +import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.utils.messages.MessageRequest; import java.util.ArrayList; import java.util.LinkedList; @@ -54,7 +54,7 @@ public PaginateHelper setFastForward(boolean fastForward) { } @Override - public MessageAction apply(MessageAction action) { + public <Out extends MessageRequest<Out>> Out apply(Out action) { if (!isUsingButtons()) return action; if (getContent().isEmpty()) throw new NullPageException(); @@ -62,7 +62,7 @@ public MessageAction apply(MessageAction action) { List<ActionRow> rows = new ArrayList<>(); - LinkedList<Component> row = new LinkedList<>() {{ + LinkedList<ItemComponent> row = new LinkedList<>() {{ add(p.makeButton(PREVIOUS)); if (isCancellable()) add(p.makeButton(CANCEL)); add(p.makeButton(NEXT)); @@ -89,7 +89,7 @@ public MessageAction apply(MessageAction action) { }})); } - return action.setActionRows(rows); + return action.setComponents(rows); } @Override diff --git a/src/main/java/com/github/ygimenez/model/helper/ReadyMessage.java b/src/main/java/com/github/ygimenez/model/helper/ReadyMessage.java new file mode 100644 index 0000000..ccc4c91 --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/helper/ReadyMessage.java @@ -0,0 +1,7 @@ +package com.github.ygimenez.model.helper; + +import net.dv8tion.jda.api.entities.Message; + +public interface ReadyMessage extends Message { + +} diff --git a/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java b/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java new file mode 100644 index 0000000..b685038 --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java @@ -0,0 +1,72 @@ +package com.github.ygimenez.model.helper; + +import com.github.ygimenez.exception.InvalidStateException; +import com.github.ygimenez.method.Pages; +import com.github.ygimenez.model.InteractPage; +import com.github.ygimenez.model.Page; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.requests.restaction.MessageCreateAction; +import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; + +public class SendWrapper<T extends BaseHelper<T, ?>> { + private final T helper; + private final Op type; + private MessageCreateAction action; + + private enum Op { + PAGINATE, LAZY_PAGINATE, CATEGORIZE, BUTTONIZE + } + + public SendWrapper(T helper) { + this.helper = helper; + + if (helper instanceof LazyPaginateHelper) { + this.type = Op.LAZY_PAGINATE; + } else if (helper instanceof PaginateHelper) { + this.type = Op.PAGINATE; + } else if (helper instanceof CategorizeHelper) { + this.type = Op.CATEGORIZE; + } else if (helper instanceof ButtonizeHelper) { + this.type = Op.BUTTONIZE; + } else { + this.type = null; + } + } + + public T getHelper() { + return helper; + } + + public Message send(MessageChannel channel) throws IllegalCallerException { + InteractPage page; + if (type == Op.PAGINATE) { + PaginateHelper helper = (PaginateHelper) this.helper; + page = (InteractPage) helper.getContent().get(0); + } else if (type == Op.LAZY_PAGINATE) { + LazyPaginateHelper helper = (LazyPaginateHelper) this.helper; + Page pg = helper.getPageLoader().apply(0); + if (pg == null) { + throw new InvalidStateException(); + } + + page = (InteractPage) helper.getContent().get(0); + } else { + throw new IllegalCallerException("This method cannot be used for categories or buttons. Use '" + helper.getClass().getSimpleName() + ".apply(MessageCreateEvent)' instead."); + } + + if (page.getContent() instanceof Message) { + MessageCreateData data = MessageCreateBuilder.fromMessage((Message) page.getContent()).build(); + + try (data) { + action = helper.apply(channel.sendMessage(data)); + } + } else if (page.getContent() instanceof MessageEmbed) { + action = helper.apply(channel.sendMessageEmbeds((MessageEmbed) page.getContent())); + } + + return Pages.subGet(action); + } +} diff --git a/src/main/java/com/github/ygimenez/type/Emote.java b/src/main/java/com/github/ygimenez/type/Emote.java index 1b02994..94a087b 100644 --- a/src/main/java/com/github/ygimenez/type/Emote.java +++ b/src/main/java/com/github/ygimenez/type/Emote.java @@ -1,11 +1,11 @@ package com.github.ygimenez.type; import com.github.ygimenez.method.Pages; -import com.github.ygimenez.model.Paginator; -import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.MessageReaction; -import net.dv8tion.jda.api.interactions.components.Button; -import net.dv8tion.jda.api.interactions.components.ButtonStyle; +import net.dv8tion.jda.api.entities.emoji.CustomEmoji; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle; import java.util.Arrays; import java.util.Map; @@ -118,7 +118,7 @@ else for (Emote emt : values()) { * @return Whether it uses a {@link Emote} value or not. */ public static boolean isNative(MessageReaction react) { - Emoji emj = Emoji.fromMarkdown(react.getReactionEmote().getAsReactionCode()); + Emoji emj = Emoji.fromFormatted(react.getEmoji().getAsReactionCode()); for (Emote emt : values()) { if (emt.emj.equals(emj)) return false; } @@ -133,7 +133,11 @@ public static boolean isNative(MessageReaction react) { * @return The supplied {@link Emoji}'s effective ID. */ public static String getId(Emoji emj) { - return emj.isCustom() ? emj.getId() : emj.getName(); + if (emj instanceof CustomEmoji) { + return ((CustomEmoji) emj).getId(); + } else { + return emj.getName(); + } } public static Emote fromButton(Button btn) { From c634fdc36241c190b04279b5585227c8a9c75bb1 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Sat, 7 Jan 2023 16:25:22 -0300 Subject: [PATCH 15/31] Fixed build issues. --- .../java/com/github/ygimenez/model/ButtonWrapper.java | 7 +++++-- .../java/com/github/ygimenez/model/PaginatorBuilder.java | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/ygimenez/model/ButtonWrapper.java b/src/main/java/com/github/ygimenez/model/ButtonWrapper.java index 0a205ad..b8880d7 100644 --- a/src/main/java/com/github/ygimenez/model/ButtonWrapper.java +++ b/src/main/java/com/github/ygimenez/model/ButtonWrapper.java @@ -1,9 +1,12 @@ package com.github.ygimenez.model; import com.github.ygimenez.method.Pages; -import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.interactions.InteractionHook; -import net.dv8tion.jda.api.interactions.components.Button; /** * Wrapper for {@link Pages#buttonize} arguments containing necessary data for processing. diff --git a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java index c291a5b..ec26193 100644 --- a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java +++ b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java @@ -8,11 +8,12 @@ import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.Emoji; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.emoji.CustomEmoji; +import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.sharding.ShardManager; +import org.jetbrains.annotations.NotNull; -import javax.annotation.Nonnull; import java.util.Map; /** @@ -199,7 +200,7 @@ public Emoji getEmote(@NotNull Emote emote) { /** * Modify an {@link Emote}'s code from the {@link Map}. Beware, the code must be either unicode or - * {@link net.dv8tion.jda.api.entities.Emote}'s mention, + * {@link CustomEmoji}'s mention, * else the buttons <strong>WILL NOT BE ADDED</strong> and will lead to errors. * * @param emote The {@link Emote} to be set. @@ -209,7 +210,7 @@ public Emoji getEmote(@NotNull Emote emote) { * object. */ public PaginatorBuilder setEmote(@NotNull Emote emote, @NotNull String code) throws InvalidHandlerException { - return setEmote(emote, Emoji.fromMarkdown(code)); + return setEmote(emote, Emoji.fromFormatted(code)); } /** From 11622f63abc3618399d1d035d088921a7b5e5428 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 10:40:25 -0300 Subject: [PATCH 16/31] Updated to JDA beta 5 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 85d7fe7..d2430c3 100644 --- a/pom.xml +++ b/pom.xml @@ -133,7 +133,7 @@ <dependency> <groupId>net.dv8tion</groupId> <artifactId>JDA</artifactId> - <version>5.0.0-beta.2</version> + <version>5.0.0-beta.5</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> From 18ea245074e8952bab0c0f520fb8f79ba968b597 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 10:44:03 -0300 Subject: [PATCH 17/31] Moved try-with-resources variables to local scope --- src/main/java/com/github/ygimenez/method/Pages.java | 4 +--- .../java/com/github/ygimenez/model/helper/SendWrapper.java | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index c35a871..23c8d22 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -1522,9 +1522,7 @@ private static void updatePage(@NotNull Message msg, Page p) { if (p == null) throw new NullPageException(msg); if (p.getContent() instanceof Message) { - MessageEditData data = MessageEditBuilder.fromMessage((Message) p.getContent()).build(); - - try (data) { + try (MessageEditData data = MessageEditBuilder.fromMessage((Message) p.getContent()).build()) { msg.editMessage(data).submit(); } } else if (p.getContent() instanceof MessageEmbed) { diff --git a/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java b/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java index b685038..1b51563 100644 --- a/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java +++ b/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java @@ -58,9 +58,7 @@ public Message send(MessageChannel channel) throws IllegalCallerException { } if (page.getContent() instanceof Message) { - MessageCreateData data = MessageCreateBuilder.fromMessage((Message) page.getContent()).build(); - - try (data) { + try (MessageCreateData data = MessageCreateBuilder.fromMessage((Message) page.getContent()).build()) { action = helper.apply(channel.sendMessage(data)); } } else if (page.getContent() instanceof MessageEmbed) { From 51295bdf9e29239d872570de3a4260aa8e69bc7e Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 13:54:38 -0300 Subject: [PATCH 18/31] Added missing javadocs; Removed unused ReadyMessage and SendWrapper. --- .../ygimenez/listener/MessageHandler.java | 9 +- .../com/github/ygimenez/method/Pages.java | 188 ++++++++++++------ .../ygimenez/model/ActionReference.java | 36 +++- .../github/ygimenez/model/ButtonWrapper.java | 1 + .../github/ygimenez/model/PUtilsConfig.java | 5 +- .../java/com/github/ygimenez/model/Page.java | 3 +- .../com/github/ygimenez/model/Paginator.java | 6 +- .../ygimenez/model/PaginatorBuilder.java | 6 +- .../ygimenez/model/helper/BaseHelper.java | 107 +++++++--- .../model/helper/ButtonizeHelper.java | 46 ++++- .../model/helper/CategorizeHelper.java | 23 +++ .../model/helper/LazyPaginateHelper.java | 38 ++++ .../ygimenez/model/helper/PaginateHelper.java | 52 ++++- .../ygimenez/model/helper/ReadyMessage.java | 7 - .../ygimenez/model/helper/SendWrapper.java | 70 ------- .../java/com/github/ygimenez/type/Emote.java | 23 ++- 16 files changed, 421 insertions(+), 199 deletions(-) delete mode 100644 src/main/java/com/github/ygimenez/model/helper/ReadyMessage.java delete mode 100644 src/main/java/com/github/ygimenez/model/helper/SendWrapper.java diff --git a/src/main/java/com/github/ygimenez/listener/MessageHandler.java b/src/main/java/com/github/ygimenez/listener/MessageHandler.java index 518574f..3b750eb 100644 --- a/src/main/java/com/github/ygimenez/listener/MessageHandler.java +++ b/src/main/java/com/github/ygimenez/listener/MessageHandler.java @@ -34,6 +34,12 @@ public class MessageHandler extends ListenerAdapter { private final Set<String> locks = ConcurrentHashMap.newKeySet(); private final CRC32 crc = new CRC32(); + /** + * Creates a new {@link MessageHandler} instance. + */ + public MessageHandler() { + } + /** * Adds an event to the handler, which will be executed whenever a button with the same * ID is pressed. @@ -118,8 +124,9 @@ public void onMessageReactionAdd(@NotNull MessageReactionAddEvent evt) { @Override public void onMessageReactionRemove(@NotNull MessageReactionRemoveEvent evt) { - if (!Pages.getPaginator().isRemoveOnReact() || !evt.isFromGuild()) + if (!Pages.getPaginator().isRemoveOnReact() || !evt.isFromGuild()) { execute(evt); + } } @Override diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 23c8d22..e8b1fd9 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -42,14 +42,17 @@ * The main class containing all pagination-related methods, including but not limited * to {@link #paginate}, {@link #categorize}, {@link #buttonize} and {@link #lazyPaginate}. */ -public class Pages { +public abstract class Pages { private static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private static final MessageHandler handler = new MessageHandler(); private static Paginator paginator; + private Pages() { + } + /** - * Sets a {@link Paginator} object to handle incoming reactions. This is - * required only once unless you want to use another client as the handler. <br> + * Sets a {@link Paginator} object to handle incoming events. This is + * required only once unless you want to change which client is handling events. <br> * <br> * Before calling this method again, you must use {@link #deactivate()} to * remove current {@link Paginator}, else this method will throw @@ -61,15 +64,16 @@ public class Pages { * or {@link ShardManager} object. */ public static void activate(@NotNull Paginator paginator) throws InvalidHandlerException { - if (isActivated()) - throw new AlreadyActivatedException(); + if (isActivated()) throw new AlreadyActivatedException(); Object hand = paginator.getHandler(); - if (hand instanceof JDA) + if (hand instanceof JDA) { ((JDA) hand).addEventListener(handler); - else if (hand instanceof ShardManager) + } else if (hand instanceof ShardManager) { ((ShardManager) hand).addEventListener(handler); - else throw new InvalidHandlerException(); + } else { + throw new InvalidHandlerException(); + } Pages.paginator = paginator; paginator.log(PUtilsConfig.LogLevel.LEVEL_2, "Pagination Utils activated successfully"); @@ -81,14 +85,14 @@ else if (hand instanceof ShardManager) * Using this method without activating beforehand will do nothing. */ public static void deactivate() { - if (!isActivated()) - return; + if (!isActivated()) return; Object hand = paginator.getHandler(); - if (hand instanceof JDA) + if (hand instanceof JDA) { ((JDA) hand).removeEventListener(handler); - else if (hand instanceof ShardManager) + } else if (hand instanceof ShardManager) { ((ShardManager) hand).removeEventListener(handler); + } paginator.log(PUtilsConfig.LogLevel.LEVEL_2, "Pagination Utils deactivated successfully"); paginator = null; @@ -534,7 +538,7 @@ public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> */ public static ActionReference paginate(@NotNull Message msg, @NotNull List<Page> pages, boolean useButtons, int time, TimeUnit unit, int skipAmount, boolean fastForward, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return paginate(msg, new PaginateHelper(pages, useButtons) - .setTimeUnit(time, unit) + .setTimeout(time, unit) .setSkipAmount(skipAmount) .setFastForward(fastForward) .setCanInteract(canInteract) @@ -562,9 +566,9 @@ public static ActionReference paginate(@NotNull Message msg, @NotNull PaginateHe boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); List<Page> pgs = Collections.unmodifiableList(helper.getContent()); - if (useBtns && helper.shouldUpdate(msg)) { + if (useBtns) { helper.apply(msg.editMessageComponents()).submit(); - } else if (!useBtns) { + } else { clearButtons(msg); clearReactions(msg); addReactions(msg, helper.getSkipAmount() > 1, helper.isFastForward()); @@ -575,8 +579,10 @@ public static ActionReference paginate(@NotNull Message msg, @NotNull PaginateHe private int p = 0; private ScheduledFuture<?> timeout; private final Consumer<Void> success = s -> { - if (timeout != null) + if (timeout != null) { timeout.cancel(true); + } + handler.removeEvent(msg); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; @@ -585,17 +591,17 @@ public static ActionReference paginate(@NotNull Message msg, @NotNull PaginateHe private final Function<Button, Button> UPPER_BOUNDARY_CHECK = b -> b.withDisabled(p == maxP); { - if (helper.getTime() > 0 && helper.getUnit() != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); + if (helper.getTimeout() > 0) { + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + } } @Override public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); - if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { - if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) - return; + if (helper.canInteract(u)) { + if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) return; Emote emt = NONE; if (wrapper.getContent() instanceof MessageReaction) { @@ -671,10 +677,12 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe } } - if (timeout != null) + if (timeout != null) { timeout.cancel(true); - if (helper.getTime() > 0 && helper.getUnit() != null) - timeout = executor.schedule(() -> finalizeEvent(m, success), helper.getTime(), helper.getUnit()); + } + if (helper.getTimeout() > 0) { + timeout = executor.schedule(() -> finalizeEvent(m, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + } if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { subGet(((MessageReaction) wrapper.getContent()).removeReaction(u)); @@ -696,6 +704,8 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe * {@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. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -725,6 +735,8 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoj * for further events (recommended: 60). * @param unit The time's {@link TimeUnit} (recommended: * {@link TimeUnit#SECONDS}). + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -750,6 +762,8 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoj * {@link Message} was not sent by the bot. * @param canInteract {@link Predicate} to determine whether the {@link User} * that pressed the button can interact with it or not. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -781,6 +795,8 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoj * {@link TimeUnit#SECONDS}). * @param canInteract {@link Predicate} to determine whether the {@link User} * that pressed the button can interact with it or not. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -790,7 +806,7 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoj */ public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoji, Page> categories, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return categorize(msg, new CategorizeHelper(categories, useButtons) - .setTimeUnit(time, unit) + .setTimeout(time, unit) .setCanInteract(canInteract) ); } @@ -804,6 +820,8 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Map<Emoj * * @param msg The {@link Message} sent which will be categorized. * @param helper A {@link CategorizeHelper} holding desired categorization settings. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -834,24 +852,26 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Categori private Emoji currCat = null; private ScheduledFuture<?> timeout; private final Consumer<Void> success = s -> { - if (timeout != null) + if (timeout != null) { timeout.cancel(true); + } + handler.removeEvent(msg); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; { - if (helper.getTime() > 0 && helper.getUnit() != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); + if (helper.getTimeout() > 0) { + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + } } @Override public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); - if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { - if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) - return; + if (helper.canInteract(u)) { + if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) return; Emoji emoji = null; Emote emt = NONE; @@ -886,10 +906,12 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe } } - if (timeout != null) + if (timeout != null) { timeout.cancel(true); - if (helper.getTime() > 0 && helper.getUnit() != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); + } + if (helper.getTimeout() > 0) { + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + } if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { subGet(((MessageReaction) wrapper.getContent()).removeReaction(u)); @@ -913,6 +935,8 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe * @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? + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -943,6 +967,8 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji * listening for further events (recommended: 60). * @param unit The time's {@link TimeUnit} (recommended: * {@link TimeUnit#SECONDS}). + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -971,6 +997,8 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji * @param canInteract {@link Predicate} to determine whether the * {@link User} that pressed the button can interact * with it or not. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1004,6 +1032,8 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji * @param canInteract {@link Predicate} to determine whether the * {@link User} that pressed the button can interact * with it or not. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1033,6 +1063,8 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji * {@link User} that pressed the button can interact * with it or not. * @param onCancel Action to be run after the listener is removed. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1067,6 +1099,8 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji * {@link User} that pressed the button can interact * with it or not. * @param onCancel Action to be run after the listener is removed. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1077,9 +1111,9 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons, boolean cancellable, int time, TimeUnit unit, Predicate<User> canInteract, Consumer<Message> onCancel) throws ErrorResponseException, InsufficientPermissionException { return buttonize(msg, new ButtonizeHelper(buttons, useButtons) .setCancellable(cancellable) - .setTimeUnit(time, unit) + .setTimeout(time, unit) .setCanInteract(canInteract) - .setOnCancel(onCancel) + .setOnFinalization(onCancel) ); } @@ -1092,6 +1126,8 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Map<Emoji * * @param msg The {@link Message} sent which will be buttoned. * @param helper A {@link ButtonizeHelper} holding desired buttonization settings. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1123,25 +1159,27 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Buttonize return handler.addEvent(msg, new ThrowingBiConsumer<>() { private ScheduledFuture<?> timeout; private final Consumer<Void> success = s -> { - if (timeout != null) + if (timeout != null) { timeout.cancel(true); + } + handler.removeEvent(msg); - if (helper.getOnCancel() != null) helper.getOnCancel().accept(msg); + if (helper.getOnFinalization() != null) helper.getOnFinalization().accept(msg); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; { - if (helper.getTime() > 0 && helper.getUnit() != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); + if (helper.getTimeout() > 0) { + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + } } @Override public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); - if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { - if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) - return; + if (helper.canInteract(u)) { + if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) return; Emoji emoji = null; Emote emt = NONE; @@ -1175,10 +1213,12 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe act.accept(new ButtonWrapper(wrapper.getUser(), hook, m)); } - if (timeout != null) + if (timeout != null) { timeout.cancel(true); - if (helper.getTime() > 0 && helper.getUnit() != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); + } + if (helper.getTimeout() > 0) { + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + } if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { subGet(((MessageReaction) wrapper.getContent()).removeReaction(u)); @@ -1198,6 +1238,8 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe * 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. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1225,6 +1267,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull Throwi * for further events (recommended: 60). * @param unit The time's {@link TimeUnit} (recommended: * {@link TimeUnit#SECONDS}). + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1248,6 +1292,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull Throwi * {@link Message} was not sent by the bot. * @param canInteract {@link Predicate} to determine whether the {@link User} * that pressed the button can interact with it or not. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1277,6 +1323,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull Throwi * {@link TimeUnit#SECONDS}). * @param canInteract {@link Predicate} to determine whether the {@link User} * that pressed the button can interact with it or not. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1299,6 +1347,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull Throwi * 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. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1327,6 +1377,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> page * for further events (recommended: 60). * @param unit The time's {@link TimeUnit} (recommended: * {@link TimeUnit#SECONDS}). + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1351,6 +1403,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> page * {@link Message} was not sent by the bot. * @param canInteract {@link Predicate} to determine whether the {@link User} * that pressed the button can interact with it or not. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1381,6 +1435,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> page * {@link TimeUnit#SECONDS}). * @param canInteract {@link Predicate} to determine whether the {@link User} * that pressed the button can interact with it or not. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1390,7 +1446,7 @@ public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> page */ public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> pageCache, @NotNull ThrowingFunction<Integer, Page> pageLoader, boolean useButtons, int time, TimeUnit unit, Predicate<User> canInteract) throws ErrorResponseException, InsufficientPermissionException { return lazyPaginate(msg, new LazyPaginateHelper(pageLoader, pageCache, useButtons) - .setTimeUnit(time, unit) + .setTimeout(time, unit) .setCanInteract(canInteract) ); } @@ -1403,6 +1459,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, List<Page> page * * @param msg The {@link Message} sent which will be paginated. * @param helper A {@link LazyPaginateHelper} holding desired lazy pagination settings. + * @return an {@link ActionReference} pointing to the newly created event, can be used for checking when it gets + * disposed of. * @throws ErrorResponseException Thrown if the {@link Message} no longer exists * or cannot be accessed when triggering a * {@link GenericMessageReactionEvent}. @@ -1415,9 +1473,9 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull LazyPa boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); boolean cache = helper.getContent() != null; - if (useBtns && helper.shouldUpdate(msg)) { + if (useBtns) { helper.apply(msg.editMessageComponents()).submit(); - } else if (!useBtns) { + } else { clearButtons(msg); clearReactions(msg); addReactions(msg, false, false); @@ -1427,24 +1485,26 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull LazyPa private int p = 0; private ScheduledFuture<?> timeout; private final Consumer<Void> success = s -> { - if (timeout != null) + if (timeout != null) { timeout.cancel(true); + } + handler.removeEvent(msg); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; { - if (helper.getTime() > 0 && helper.getUnit() != null) - timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTime(), helper.getUnit()); + if (helper.getTimeout() > 0) { + timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + } } @Override public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrapper) { Message m = subGet(wrapper.retrieveMessage()); - if (helper.getCanInteract() == null || helper.getCanInteract().test(u)) { - if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) - return; + if (helper.canInteract(u)) { + if (u.isBot() || m == null || !wrapper.getMessageId().equals(msg.getId())) return; Emote emt = NONE; if (wrapper.getContent() instanceof MessageReaction) { @@ -1498,10 +1558,12 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe return; } - if (timeout != null) + if (timeout != null) { timeout.cancel(true); - if (helper.getTime() > 0 && helper.getUnit() != null) - timeout = executor.schedule(() -> finalizeEvent(m, success), helper.getTime(), helper.getUnit()); + } + if (helper.getTimeout() > 0) { + timeout = executor.schedule(() -> finalizeEvent(m, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + } if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { subGet(((MessageReaction) wrapper.getContent()).removeReaction(u)); @@ -1567,7 +1629,7 @@ public static <T> T subGet(@NotNull RestAction<T> future) { try { return future.submit().get(); } catch (InterruptedException | ExecutionException e) { - Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Exception during future execution:", e); + paginator.log(PUtilsConfig.LogLevel.LEVEL_4, "Exception during future execution:", e); return null; } } @@ -1584,7 +1646,7 @@ public static <T> T subGet(@NotNull RestAction<T> future, @NotNull T or) { try { return future.submit().get(); } catch (InterruptedException | ExecutionException e) { - Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Exception during future execution:", e); + paginator.log(PUtilsConfig.LogLevel.LEVEL_4, "Exception during future execution:", e); return or; } } @@ -1606,9 +1668,9 @@ public static void clearReactions(Message msg) { if (msg.getReactions().isEmpty()) return; try { - if (msg.getChannel().getType().isGuild()) + if (msg.getChannel().getType().isGuild()) { msg.clearReactions().submit(); - else for (MessageReaction r : msg.getReactions()) { + } else for (MessageReaction r : msg.getReactions()) { r.removeReaction().submit(); } } catch (InsufficientPermissionException | IllegalStateException e) { @@ -1629,7 +1691,7 @@ public static void clearButtons(Message msg) { try { subGet(msg.editMessageComponents()); } catch (InsufficientPermissionException | IllegalStateException e) { - Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Not enough permissions to clear message reactions:", e); + paginator.log(PUtilsConfig.LogLevel.LEVEL_3, "Not enough permissions to clear message reactions:", e); } } diff --git a/src/main/java/com/github/ygimenez/model/ActionReference.java b/src/main/java/com/github/ygimenez/model/ActionReference.java index 69a517a..80fa58b 100644 --- a/src/main/java/com/github/ygimenez/model/ActionReference.java +++ b/src/main/java/com/github/ygimenez/model/ActionReference.java @@ -1,29 +1,51 @@ package com.github.ygimenez.model; import com.github.ygimenez.method.Pages; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; +/** + * Class used for checking whether a library action (read: paginate, categorize, buttonize or lazy-paginate action) + * was already disposed of. + * <br> + * This is a weak reference, so its value might become null at any moment. + * @see java.lang.ref.WeakReference + */ public class ActionReference extends WeakReference<String> { - public ActionReference(String referent) { - super(referent); - } - public ActionReference(String referent, ReferenceQueue<? super String> q) { - super(referent, q); + /** + * Creates a new {@link ActionReference} for tracking a specific event key. Not for external usage. + * + * @param referent The key referring to an existing library event. + */ + public ActionReference(@NotNull String referent) { + super(referent); } + /** + * Retrieves the referred action key if it is still active, or null otherwise. + * + * @return They key used to represent the library action in the event map. + */ @Nullable @Override public String get() { - if (!Pages.getHandler().checkEvent(super.get())) + if (!Pages.getHandler().checkEvent(super.get())) { enqueue(); + } return super.get(); } + /** + * Utility method to check whether the referred action is still active. + * <br> + * Same as doing {@code get() != null}. + * + * @return Whether the action is still active or not. + */ public boolean check() { return get() != null; } diff --git a/src/main/java/com/github/ygimenez/model/ButtonWrapper.java b/src/main/java/com/github/ygimenez/model/ButtonWrapper.java index b8880d7..3f76ad8 100644 --- a/src/main/java/com/github/ygimenez/model/ButtonWrapper.java +++ b/src/main/java/com/github/ygimenez/model/ButtonWrapper.java @@ -7,6 +7,7 @@ import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.interactions.InteractionHook; +import net.dv8tion.jda.api.interactions.components.buttons.Button; /** * Wrapper for {@link Pages#buttonize} arguments containing necessary data for processing. diff --git a/src/main/java/com/github/ygimenez/model/PUtilsConfig.java b/src/main/java/com/github/ygimenez/model/PUtilsConfig.java index baea1d2..0a7353d 100644 --- a/src/main/java/com/github/ygimenez/model/PUtilsConfig.java +++ b/src/main/java/com/github/ygimenez/model/PUtilsConfig.java @@ -3,9 +3,12 @@ /** * Utility class holding library-wide settings. */ -public class PUtilsConfig { +public abstract class PUtilsConfig { private static LogLevel logLevel = LogLevel.LEVEL_1; + private PUtilsConfig() { + } + /** * Levels used to filter what events are logged to the console by the library. */ diff --git a/src/main/java/com/github/ygimenez/model/Page.java b/src/main/java/com/github/ygimenez/model/Page.java index d80b887..ca986ae 100644 --- a/src/main/java/com/github/ygimenez/model/Page.java +++ b/src/main/java/com/github/ygimenez/model/Page.java @@ -18,8 +18,9 @@ public class Page { * @throws IllegalArgumentException Thrown if argument is not a {@link Message} nor {@link MessageEmbed}. */ public Page(@NotNull Object content) throws IllegalArgumentException { - if (!(content instanceof Message) && !(content instanceof MessageEmbed)) + if (!(content instanceof Message) && !(content instanceof MessageEmbed)) { throw new IllegalArgumentException("Page content must be either a Message or a MessageEmbed"); + } this.content = content; } diff --git a/src/main/java/com/github/ygimenez/model/Paginator.java b/src/main/java/com/github/ygimenez/model/Paginator.java index 6652794..ec15afa 100644 --- a/src/main/java/com/github/ygimenez/model/Paginator.java +++ b/src/main/java/com/github/ygimenez/model/Paginator.java @@ -177,8 +177,9 @@ public Logger getLogger() { * @param t The {@link Throwable} to be added for more detailed information. */ public void log(LogLevel level, String msg, Throwable t) { - if (PUtilsConfig.getLogLevel().compareTo(level) >= 0) + if (PUtilsConfig.getLogLevel().compareTo(level) >= 0) { logger.error("[" + level.name().replace("_", " ") + "] " + msg, t); + } } /** @@ -190,7 +191,8 @@ public void log(LogLevel level, String msg, Throwable t) { * @param msg The message to be logged. */ public void log(LogLevel level, String msg) { - if (PUtilsConfig.getLogLevel().compareTo(level) >= 0) + if (PUtilsConfig.getLogLevel().compareTo(level) >= 0) { logger.error("[" + level.name().replace("_", " ") + "] " + msg); + } } } diff --git a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java index ec26193..fb31552 100644 --- a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java +++ b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java @@ -236,8 +236,9 @@ public PaginatorBuilder setEmote(@NotNull Emote emote, @NotNull Emoji emoji) thr * @return The {@link Paginator} instance. */ public Paginator build() { - if (paginator.getHandler() == null) + if (paginator.getHandler() == null) { throw new InvalidStateException(); + } paginator.finishEmotes(); return paginator; @@ -250,8 +251,9 @@ public Paginator build() { * @throws InvalidHandlerException Thrown if the handler isn't either a {@link JDA} or {@link ShardManager} object. */ public void activate() throws InvalidHandlerException { - if (paginator.getHandler() == null) + if (paginator.getHandler() == null) { throw new InvalidStateException(); + } paginator.finishEmotes(); Pages.activate(paginator); diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java index d4b192a..90a46f1 100644 --- a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -1,80 +1,131 @@ package com.github.ygimenez.model.helper; +import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.utils.messages.MessageRequest; +import org.jetbrains.annotations.Nullable; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; -abstract class BaseHelper<Sub extends BaseHelper<Sub, T>, T> { - private final Class<Sub> subClass; +abstract class BaseHelper<Helper extends BaseHelper<Helper, T>, T> { + private final Class<Helper> subClass; private final T content; private final boolean useButtons; private boolean cancellable = true; - private int time = 0; - private TimeUnit unit = null; + private long time = 0; private Predicate<User> canInteract = null; - protected BaseHelper(Class<Sub> subClass, T buttons, boolean useButtons) { + protected BaseHelper(Class<Helper> subClass, T buttons, boolean useButtons) { this.subClass = subClass; this.content = buttons; this.useButtons = useButtons; } + /** + * Retrieves the collection used by this helper to store the pages. + * + * @return The underlying collection. + */ public T getContent() { return content; } + /** + * Returns whether the event is configured to use buttons or not. + * + * @return Whether the event is configured to use buttons or not. + */ public boolean isUsingButtons() { return useButtons; } + /** + * Returns whether the {@link Emote#CANCEL} button will be included or not. + * + * @return Whether the event is cancellable or not. + */ public boolean isCancellable() { return cancellable; } - public int getTime() { - return time; - } - - public TimeUnit getUnit() { - return unit; - } - - public Predicate<User> getCanInteract() { - return canInteract; - } - - public Sub setCancellable(boolean cancellable) { + /** + * Sets whether the event is cancellable through {@link Emote#CANCEL}. + * + * @param cancellable Whether the event can be cancelled or not (default: true). + * @return The {@link Helper} instance for chaining convenience. + */ + public Helper setCancellable(boolean cancellable) { this.cancellable = cancellable; return subClass.cast(this); } - public Sub setTime(int time) { - this.time = time; - return subClass.cast(this); + /** + * Retrieves the timeout for the event, in milliseconds. + * + * @return The timeout for the event. + */ + public long getTimeout() { + return time; } - public Sub setUnit(TimeUnit unit) { - this.unit = unit; + /** + * Sets the timeout for automatically cancelling the event. Values less than or equal to zero will disable the + * timeout. + * + * @param time The time for the timeout. + * @param unit The unit for the timeout. + * @return The {@link Helper} instance for chaining convenience. + */ + public Helper setTimeout(int time, TimeUnit unit) { + this.time = TimeUnit.MILLISECONDS.convert(time, unit); return subClass.cast(this); } - public Sub setTimeUnit(int time, TimeUnit unit) { - this.time = time; - this.unit = unit; - return subClass.cast(this); + /** + * Checks whether the supplied {@link User} can interact with the event. + * + * @param user The {@link User} to check. + * @return Whether the suppied user can interact with the event. + */ + public boolean canInteract(User user) { + return canInteract == null || canInteract.test(user); } - public Sub setCanInteract(Predicate<User> canInteract) { + /** + * Sets the condition used to check if a given user can interact with the event buttons. + * + * @param canInteract A {@link Predicate} for checking if a given user can interact with the buttons (default: null). + * @return The {@link Helper} instance for chaining convenience. + */ + public Helper setCanInteract(@Nullable Predicate<User> canInteract) { this.canInteract = canInteract; return subClass.cast(this); } + /** + * Prepares the message for being used by the library. This doesn't need to be called manually, this will + * be called during normal flow. + * <br> + * This is no-op when using reaction buttons. + * <br><br> + * Example: + * <pre>{@code helper.apply(channel.sendMessage("Hello world!")).queue();}</pre> + * + * @param action A message event (either create or edit). + * @return The same event, but modified to include the buttons. + * @param <Out> Generic for a {@link MessageRequest} + */ public abstract <Out extends MessageRequest<Out>> Out apply(Out action); + /** + * Calculates whether the {@link Message} needs to have buttons applied onto or not. + * + * @param msg The {@link Message} to be checked. + * @return Whether it needs to be updated or not. + */ public abstract boolean shouldUpdate(Message msg); } diff --git a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java index c434d61..9a111ef 100644 --- a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java @@ -18,31 +18,64 @@ import static com.github.ygimenez.type.Emote.CANCEL; +/** + * Helper class for building buttonize events, safe for reuse. + */ public class ButtonizeHelper extends BaseHelper<ButtonizeHelper, Map<Emoji, ThrowingConsumer<ButtonWrapper>>> { - private Consumer<Message> onCancel = null; + private Consumer<Message> onFinalization = null; + /** + * Creates a new buttonize event helper with the default map implementation ({@link LinkedHashMap}). + * + * @param useButtons Whether to use interaction buttons or legacy reaction-based buttons. + */ public ButtonizeHelper(boolean useButtons) { super(ButtonizeHelper.class, new LinkedHashMap<>(), useButtons); } + /** + * Creates a new buttonize event helper with the supplied map. + * + * @param buttons A map containing the initial buttons. + * @param useButtons Whether to use interaction buttons or legacy reaction-based buttons. + */ public ButtonizeHelper(Map<Emoji, ThrowingConsumer<ButtonWrapper>> buttons, boolean useButtons) { super(ButtonizeHelper.class, buttons, useButtons); } - public ButtonizeHelper addCategory(Emoji emoji, ThrowingConsumer<ButtonWrapper> action) { + /** + * Adds a new button to the map. + * + * @param emoji The emoji representing this button. + * @param action The action to be performed on click. + * @return The {@link ButtonizeHelper} instance for chaining convenience. + */ + public ButtonizeHelper addAction(Emoji emoji, ThrowingConsumer<ButtonWrapper> action) { getContent().put(emoji, action); return this; } - public Consumer<Message> getOnCancel() { - return onCancel; + /** + * Retrieves the {@link Consumer} that'll be executed when the event ends. + * + * @return The action to be performed during finalization. + */ + public Consumer<Message> getOnFinalization() { + return onFinalization; } - public ButtonizeHelper setOnCancel(Consumer<Message> onCancel) { - this.onCancel = onCancel; + /** + * Defines an action to be executed when the event finishes, either by user action or timed finalization. + * + * @param onFinalization The action to be performed. + * @return The {@link ButtonizeHelper} instance for chaining convenience. + */ + public ButtonizeHelper setOnFinalization(Consumer<Message> onFinalization) { + this.onFinalization = onFinalization; return this; } + /** {@inheritDoc} **/ @Override public <Out extends MessageRequest<Out>> Out apply(Out action) { if (!isUsingButtons()) return action; @@ -79,6 +112,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { return action.setComponents(rows); } + /** {@inheritDoc} **/ @Override public boolean shouldUpdate(Message msg) { if (!isUsingButtons()) return false; diff --git a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java index c392af7..f6bbe58 100644 --- a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java @@ -16,20 +16,42 @@ import static com.github.ygimenez.type.Emote.CANCEL; +/** + * Helper class for building categorize events, safe for reuse. + */ public class CategorizeHelper extends BaseHelper<CategorizeHelper, Map<Emoji, Page>> { + /** + * Creates a new categorize event helper with the default map implementation ({@link LinkedHashMap}). + * + * @param useButtons Whether to use interaction buttons or legacy reaction-based buttons. + */ public CategorizeHelper(boolean useButtons) { super(CategorizeHelper.class, new LinkedHashMap<>(), useButtons); } + /** + * Creates a new categorize event helper with the supplied map. + * + * @param categories A map containing the initial categories. + * @param useButtons Whether to use interaction buttons or legacy reaction-based buttons. + */ public CategorizeHelper(Map<Emoji, Page> categories, boolean useButtons) { super(CategorizeHelper.class, categories, useButtons); } + /** + * Adds a new category to the map. + * + * @param emoji The emoji representing this category. + * @param page The page linked to this category. + * @return The {@link CategorizeHelper} instance for chaining convenience. + */ public CategorizeHelper addCategory(Emoji emoji, Page page) { getContent().put(emoji, page); return this; } + /** {@inheritDoc} **/ @Override public <Out extends MessageRequest<Out>> Out apply(Out action) { if (!isUsingButtons()) return action; @@ -65,6 +87,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { return action.setComponents(rows); } + /** {@inheritDoc} **/ @Override public boolean shouldUpdate(Message msg) { if (!isUsingButtons()) return false; diff --git a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java index b9b7471..648be25 100644 --- a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java @@ -13,15 +13,26 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import static com.github.ygimenez.type.Emote.*; +/** + * Helper class for building lazy-paginate events, safe for reuse. + */ public class LazyPaginateHelper extends BaseHelper<LazyPaginateHelper, List<Page>> { private final ThrowingFunction<Integer, Page> pageLoader; private final boolean cache; + /** + * Creates a new lazy-paginate event helper with the supplied page loader and default list implementation + * ({@link ArrayList}). + * + * @param pageLoader The lazy loader used to generate pages. The value supplied is the current page number. + * @param useButtons Whether to use interaction buttons or legacy reaction-based buttons. + */ public LazyPaginateHelper(ThrowingFunction<Integer, Page> pageLoader, boolean useButtons) { super(LazyPaginateHelper.class, new ArrayList<>(), useButtons); this.pageLoader = pageLoader; @@ -29,6 +40,13 @@ public LazyPaginateHelper(ThrowingFunction<Integer, Page> pageLoader, boolean us load(0); } + /** + * Creates a new lazy-paginate event helper with the supplied page loader and a list of initially loaded pages. + * + * @param pageLoader The lazy loader used to generate pages. The value supplied is the current page number. + * @param initialPages A {@link List} containing the initially available pages. + * @param useButtons Whether to use interaction buttons or legacy reaction-based buttons. + */ public LazyPaginateHelper(ThrowingFunction<Integer, Page> pageLoader, @Nullable List<Page> initialPages, boolean useButtons) { super(LazyPaginateHelper.class, initialPages, useButtons); this.pageLoader = pageLoader; @@ -36,6 +54,12 @@ public LazyPaginateHelper(ThrowingFunction<Integer, Page> pageLoader, @Nullable load(0); } + /** + * Adds a new page to the list. + * + * @param page The page to be added. + * @return The {@link LazyPaginateHelper} instance for chaining convenience. + */ public LazyPaginateHelper addPage(Page page) { if (!cache) throw new IllegalStateException(); @@ -43,10 +67,22 @@ public LazyPaginateHelper addPage(Page page) { return this; } + /** + * Retrieves the configured page loader for this helper. + * + * @return The page loader {@link Function} + */ public ThrowingFunction<Integer, Page> getPageLoader() { return pageLoader; } + /** + * Loads the page represented by the specified index. Might be null, meaning there's no page available for that + * index. + * + * @param page The page index. + * @return The page returned by the loader. + */ public @Nullable Page load(int page) { if (cache) { int maxIndex = getContent().size() - 1; @@ -61,6 +97,7 @@ public ThrowingFunction<Integer, Page> getPageLoader() { return p; } + /** {@inheritDoc} **/ @Override public <Out extends MessageRequest<Out>> Out apply(Out action) { if (!isUsingButtons()) return action; @@ -75,6 +112,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { }})); } + /** {@inheritDoc} **/ @Override public boolean shouldUpdate(Message msg) { if (!isUsingButtons()) return true; diff --git a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java index 161b446..3c61ba8 100644 --- a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java @@ -9,50 +9,93 @@ import net.dv8tion.jda.api.interactions.components.ItemComponent; import net.dv8tion.jda.api.utils.messages.MessageRequest; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; import static com.github.ygimenez.type.Emote.*; +/** + * Helper class for building paginate events, safe for reuse. + */ public class PaginateHelper extends BaseHelper<PaginateHelper, List<Page>> { private int skipAmount = 0; private boolean fastForward = false; + /** + * Creates a new paginate event helper with the default list implementation ({@link ArrayList}). + * + * @param useButtons Whether to use interaction buttons or legacy reaction-based buttons. + */ public PaginateHelper(boolean useButtons) { super(PaginateHelper.class, new ArrayList<>(), useButtons); } + /** + * Creates a new paginate event helper with the supplied list. + * + * @param pages A list containing the initial pages. + * @param useButtons Whether to use interaction buttons or legacy reaction-based buttons. + */ public PaginateHelper(List<Page> pages, boolean useButtons) { super(PaginateHelper.class, pages, useButtons); } + /** + * Adds a new page to the list. + * + * @param page The page to be added. + * @return The {@link ButtonizeHelper} instance for chaining convenience. + */ public PaginateHelper addPage(Page page) { getContent().add(page); return this; } + /** + * Retrieves the configured amount of pages to be skipped on pressing {@link Emote#SKIP_BACKWARD} or + * {@link Emote#SKIP_FORWARD}. + * + * @return The configured amount of pages to skip. + */ public int getSkipAmount() { return skipAmount; } + /** + * Sets the amount of pages to be skipped on pressing {@link Emote#SKIP_BACKWARD} or {@link Emote#SKIP_FORWARD}. + * + * @param skipAmount The amount of pages to skip (default: 0). + * @return The {@link ButtonizeHelper} instance for chaining convenience. + */ public PaginateHelper setSkipAmount(int skipAmount) { this.skipAmount = skipAmount; return this; } + /** + * Retrives whether this helper is configured to include {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} + * buttons. + * + * @return Whether to include fast-forward buttons. + */ public boolean isFastForward() { return fastForward; } + /** + * Sets whether to include {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons for quick navigation + * through the pages. + * + * @param fastForward Whether to include fast-forward buttons (default: false). + * @return The {@link ButtonizeHelper} instance for chaining convenience. + */ public PaginateHelper setFastForward(boolean fastForward) { this.fastForward = fastForward; return this; } + /** {@inheritDoc} **/ @Override public <Out extends MessageRequest<Out>> Out apply(Out action) { if (!isUsingButtons()) return action; @@ -92,6 +135,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { return action.setComponents(rows); } + /** {@inheritDoc} **/ @Override public boolean shouldUpdate(Message msg) { if (isUsingButtons()) return true; diff --git a/src/main/java/com/github/ygimenez/model/helper/ReadyMessage.java b/src/main/java/com/github/ygimenez/model/helper/ReadyMessage.java deleted file mode 100644 index ccc4c91..0000000 --- a/src/main/java/com/github/ygimenez/model/helper/ReadyMessage.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.github.ygimenez.model.helper; - -import net.dv8tion.jda.api.entities.Message; - -public interface ReadyMessage extends Message { - -} diff --git a/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java b/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java deleted file mode 100644 index 1b51563..0000000 --- a/src/main/java/com/github/ygimenez/model/helper/SendWrapper.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.github.ygimenez.model.helper; - -import com.github.ygimenez.exception.InvalidStateException; -import com.github.ygimenez.method.Pages; -import com.github.ygimenez.model.InteractPage; -import com.github.ygimenez.model.Page; -import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; -import net.dv8tion.jda.api.requests.restaction.MessageCreateAction; -import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; -import net.dv8tion.jda.api.utils.messages.MessageCreateData; - -public class SendWrapper<T extends BaseHelper<T, ?>> { - private final T helper; - private final Op type; - private MessageCreateAction action; - - private enum Op { - PAGINATE, LAZY_PAGINATE, CATEGORIZE, BUTTONIZE - } - - public SendWrapper(T helper) { - this.helper = helper; - - if (helper instanceof LazyPaginateHelper) { - this.type = Op.LAZY_PAGINATE; - } else if (helper instanceof PaginateHelper) { - this.type = Op.PAGINATE; - } else if (helper instanceof CategorizeHelper) { - this.type = Op.CATEGORIZE; - } else if (helper instanceof ButtonizeHelper) { - this.type = Op.BUTTONIZE; - } else { - this.type = null; - } - } - - public T getHelper() { - return helper; - } - - public Message send(MessageChannel channel) throws IllegalCallerException { - InteractPage page; - if (type == Op.PAGINATE) { - PaginateHelper helper = (PaginateHelper) this.helper; - page = (InteractPage) helper.getContent().get(0); - } else if (type == Op.LAZY_PAGINATE) { - LazyPaginateHelper helper = (LazyPaginateHelper) this.helper; - Page pg = helper.getPageLoader().apply(0); - if (pg == null) { - throw new InvalidStateException(); - } - - page = (InteractPage) helper.getContent().get(0); - } else { - throw new IllegalCallerException("This method cannot be used for categories or buttons. Use '" + helper.getClass().getSimpleName() + ".apply(MessageCreateEvent)' instead."); - } - - if (page.getContent() instanceof Message) { - try (MessageCreateData data = MessageCreateBuilder.fromMessage((Message) page.getContent()).build()) { - action = helper.apply(channel.sendMessage(data)); - } - } else if (page.getContent() instanceof MessageEmbed) { - action = helper.apply(channel.sendMessageEmbeds((MessageEmbed) page.getContent())); - } - - return Pages.subGet(action); - } -} diff --git a/src/main/java/com/github/ygimenez/type/Emote.java b/src/main/java/com/github/ygimenez/type/Emote.java index 94a087b..62be207 100644 --- a/src/main/java/com/github/ygimenez/type/Emote.java +++ b/src/main/java/com/github/ygimenez/type/Emote.java @@ -6,6 +6,8 @@ import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.Map; @@ -84,7 +86,7 @@ public ButtonStyle getStyle() { * @param emoji The {@link Emoji} to be searched for. * @return The respective {@link Emote}, or {@link #NONE} if it didn't match any. */ - public static Emote getByEmoji(Emoji emoji) { + public static Emote getByEmoji(@NotNull Emoji emoji) { for (Map.Entry<Emote, Emoji> entry : Pages.getPaginator().getEmotes().entrySet()) { if (Objects.equals(entry.getValue(), emoji)) return entry.getKey(); } @@ -97,12 +99,12 @@ public static Emote getByEmoji(Emoji emoji) { } /** - * Checks whether the supplied {@link Button} is referenced by a library native emote or not. + * Checks whether the supplied {@link Button} is referenced by a library emote or not. * * @param btn The {@link Button} to be checked. * @return Whether it uses a {@link Emote} value or not. */ - public static boolean isNative(Button btn) { + public static boolean isNative(@NotNull Button btn) { if (btn.getId() == null) return false; else for (Emote emt : values()) { if (emt.name().equals(btn.getId())) return true; @@ -112,12 +114,12 @@ else for (Emote emt : values()) { } /** - * Checks whether the supplied {@link MessageReaction} is referenced by a library native emote or not. + * Checks whether the supplied {@link MessageReaction} is referenced by a library emote or not. * * @param react The {@link MessageReaction} to be checked. * @return Whether it uses a {@link Emote} value or not. */ - public static boolean isNative(MessageReaction react) { + public static boolean isNative(@NotNull MessageReaction react) { Emoji emj = Emoji.fromFormatted(react.getEmoji().getAsReactionCode()); for (Emote emt : values()) { if (emt.emj.equals(emj)) return false; @@ -132,7 +134,7 @@ public static boolean isNative(MessageReaction react) { * @param emj The {@link Emoji} to be used. * @return The supplied {@link Emoji}'s effective ID. */ - public static String getId(Emoji emj) { + public static String getId(@NotNull Emoji emj) { if (emj instanceof CustomEmoji) { return ((CustomEmoji) emj).getId(); } else { @@ -140,7 +142,14 @@ public static String getId(Emoji emj) { } } - public static Emote fromButton(Button btn) { + /** + * Returns the {@link Emote} represented by the supplied {@link Button}, if any. + * + * @param btn The {@link Button} to be checked. + * @return The {@link Emote} linked to the supplied {@link Button}, or null if none. + */ + @Nullable + public static Emote fromButton(@NotNull Button btn) { return Arrays.stream(values()) .filter(e -> btn.getId() != null && btn.getId().contains(e.name())) .findFirst().orElse(null); From 53298feac045ed1dff9167802b2af193fa598f1c Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 15:04:29 -0300 Subject: [PATCH 19/31] Fixed minor issues --- .../ygimenez/listener/MessageHandler.java | 35 +++++++++++-------- .../com/github/ygimenez/method/Pages.java | 16 ++++----- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/github/ygimenez/listener/MessageHandler.java b/src/main/java/com/github/ygimenez/listener/MessageHandler.java index 3b750eb..973a637 100644 --- a/src/main/java/com/github/ygimenez/listener/MessageHandler.java +++ b/src/main/java/com/github/ygimenez/listener/MessageHandler.java @@ -99,21 +99,21 @@ public void clear() { events.clear(); } - private void lock(@NotNull String id) { + private synchronized void lock(@NotNull String id) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Locked event with ID " + id); locks.add(id); } - private void unlock(@NotNull String id) { + private synchronized void unlock(@NotNull String id) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Unlocked event with ID " + id); locks.remove(id); } - private boolean isLocked(@NotNull GenericMessageReactionEvent evt) { + private synchronized boolean isLocked(@NotNull GenericMessageReactionEvent evt) { return locks.contains(getEventId(evt)); } - private boolean isLocked(@NotNull String id) { + private synchronized boolean isLocked(@NotNull String id) { return locks.contains(id); } @@ -136,7 +136,11 @@ public void onMessageDelete(@NotNull MessageDeleteEvent evt) { private void execute(GenericMessageReactionEvent evt) { String id = getEventId(evt); - if (!events.containsKey(id)) return; + Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Received event with ID " + id); + if (!events.containsKey(id)) { + Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Event not mapped, skipping"); + return; + } evt.retrieveUser().submit() .whenComplete((u, t) -> processEvent( @@ -147,17 +151,21 @@ private void execute(GenericMessageReactionEvent evt) { @Override public void onButtonInteraction(@NotNull ButtonInteractionEvent evt) { - User u = evt.getUser(); String id = getEventId(evt); - if (!events.containsKey(id)) return; + Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Received event with ID " + id); + if (!events.containsKey(id)) { + Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Event not mapped, skipping"); + return; + } evt.deferEdit().submit() - .whenComplete((hook, t) -> processEvent( - t, - id, - u, - new PaginationEventWrapper(evt, u, evt.getChannel(), evt.getMessageId(), evt.getButton(), evt.isFromGuild()) - )); + .whenComplete((hook, t) -> { + User u = hook.getInteraction().getUser(); + processEvent( + t, id, u, + new PaginationEventWrapper(evt, u, evt.getChannel(), evt.getMessageId(), evt.getButton(), evt.isFromGuild()) + ); + }); } private void processEvent(Throwable t, String id, User u, PaginationEventWrapper evt) { @@ -166,7 +174,6 @@ private void processEvent(Throwable t, String id, User u, PaginationEventWrapper return; } - Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Received event with ID " + id); if (u.isBot() || isLocked(id)) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Event" + id + " was triggered by a bot or is locked. Ignored"); return; diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index e8b1fd9..29b4922 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -566,9 +566,9 @@ public static ActionReference paginate(@NotNull Message msg, @NotNull PaginateHe boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); List<Page> pgs = Collections.unmodifiableList(helper.getContent()); - if (useBtns) { + if (useBtns && helper.shouldUpdate(msg)) { helper.apply(msg.editMessageComponents()).submit(); - } else { + } else if (!useBtns) { clearButtons(msg); clearReactions(msg); addReactions(msg, helper.getSkipAmount() > 1, helper.isFastForward()); @@ -835,9 +835,9 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Categori Map<Emoji, Page> cats = Collections.unmodifiableMap(helper.getContent()); - if (useBtns) { + if (useBtns && helper.shouldUpdate(msg)) { helper.apply(msg.editMessageComponents()).submit(); - } else { + } else if (!useBtns) { clearButtons(msg); clearReactions(msg); @@ -1141,9 +1141,9 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Buttonize Map<Emoji, ThrowingConsumer<ButtonWrapper>> btns = Collections.unmodifiableMap(helper.getContent()); - if (useBtns) { + if (useBtns && helper.shouldUpdate(msg)) { helper.apply(msg.editMessageComponents()).submit(); - } else { + } else if (!useBtns) { clearButtons(msg); clearReactions(msg); @@ -1473,9 +1473,9 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull LazyPa boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); boolean cache = helper.getContent() != null; - if (useBtns) { + if (useBtns && helper.shouldUpdate(msg)) { helper.apply(msg.editMessageComponents()).submit(); - } else { + } else if (!useBtns) { clearButtons(msg); clearReactions(msg); addReactions(msg, false, false); From a688d1c951379d686ad8b46c0101eed2da939e47 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 15:20:04 -0300 Subject: [PATCH 20/31] Fixed minor issues --- .../ygimenez/listener/MessageHandler.java | 1 + .../com/github/ygimenez/method/Pages.java | 2 +- .../github/ygimenez/model/PUtilsConfig.java | 22 +++++++++++++++++++ .../com/github/ygimenez/model/Paginator.java | 8 +++---- .../ygimenez/model/PaginatorBuilder.java | 10 ++++----- .../ygimenez/model/helper/BaseHelper.java | 6 ++--- .../model/helper/ButtonizeHelper.java | 2 +- .../model/helper/CategorizeHelper.java | 2 +- .../ygimenez/model/helper/PaginateHelper.java | 4 ++-- 9 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/github/ygimenez/listener/MessageHandler.java b/src/main/java/com/github/ygimenez/listener/MessageHandler.java index 973a637..d21e24d 100644 --- a/src/main/java/com/github/ygimenez/listener/MessageHandler.java +++ b/src/main/java/com/github/ygimenez/listener/MessageHandler.java @@ -154,6 +154,7 @@ public void onButtonInteraction(@NotNull ButtonInteractionEvent evt) { String id = getEventId(evt); Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Received event with ID " + id); if (!events.containsKey(id)) { + evt.deferEdit().submit().whenComplete((hook, t) -> PUtilsConfig.getOnRemove().accept(evt.getHook())); Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_4, "Event not mapped, skipping"); return; } diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 29b4922..593ebc0 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -51,7 +51,7 @@ private Pages() { } /** - * Sets a {@link Paginator} object to handle incoming events. This is + * Set a {@link Paginator} object to handle incoming events. This is * required only once unless you want to change which client is handling events. <br> * <br> * Before calling this method again, you must use {@link #deactivate()} to diff --git a/src/main/java/com/github/ygimenez/model/PUtilsConfig.java b/src/main/java/com/github/ygimenez/model/PUtilsConfig.java index 0a7353d..6e93229 100644 --- a/src/main/java/com/github/ygimenez/model/PUtilsConfig.java +++ b/src/main/java/com/github/ygimenez/model/PUtilsConfig.java @@ -1,10 +1,13 @@ package com.github.ygimenez.model; +import net.dv8tion.jda.api.interactions.InteractionHook; + /** * Utility class holding library-wide settings. */ public abstract class PUtilsConfig { private static LogLevel logLevel = LogLevel.LEVEL_1; + private static ThrowingConsumer<InteractionHook> onRemove = hook -> hook.editOriginalComponents().submit(); private PUtilsConfig() { } @@ -52,4 +55,23 @@ public static LogLevel getLogLevel() { public static void setLogLevel(LogLevel logLevel) { PUtilsConfig.logLevel = logLevel; } + + /** + * Retrieve the action performed when encounteing an unmapped event. + * + * @return The action to be performed. + */ + public static ThrowingConsumer<InteractionHook> getOnRemove() { + return onRemove; + } + + /** + * Set the action to be performed when encountering an unmapped event. This defaults to simply removing the + * message buttons. + * + * @param onRemove The action to be performed (the interaction is automatically acknowledged). + */ + public static void setOnRemove(ThrowingConsumer<InteractionHook> onRemove) { + PUtilsConfig.onRemove = onRemove; + } } diff --git a/src/main/java/com/github/ygimenez/model/Paginator.java b/src/main/java/com/github/ygimenez/model/Paginator.java index ec15afa..cf7e4d1 100644 --- a/src/main/java/com/github/ygimenez/model/Paginator.java +++ b/src/main/java/com/github/ygimenez/model/Paginator.java @@ -56,7 +56,7 @@ public Object getHandler() { } /** - * Sets the handler used for event processing. + * Set the handler used for event processing. * <strong>This must only be called by {@link PaginatorBuilder}</strong>. * * @param handler The handler that'll be used for event processing @@ -79,7 +79,7 @@ public boolean isRemoveOnReact() { } /** - * Sets whether user reactions will be removed after pressing the button or not. + * Set whether user reactions will be removed after pressing the button or not. * <strong>This must only be called by {@link PaginatorBuilder}</strong>. * * @param removeOnReact Whether reactions will be removed on press or not. @@ -99,7 +99,7 @@ public boolean isEventLocked() { } /** - * Sets whether evens should be locked to prevent double-activation. + * Set whether evens should be locked to prevent double-activation. * <strong>This must only be called by {@link PaginatorBuilder}</strong>. * * @param hashLocking Whether events should be locked. @@ -120,7 +120,7 @@ public boolean isDeleteOnCancel() { } /** - * Sets whether {@link Message} should be deleted or not when the button handler is removed. + * Set whether {@link Message} should be deleted or not when the button handler is removed. * <strong>This must only be called by {@link PaginatorBuilder}</strong>. * * @param deleteOnCancel Whether the {@link Message} will be deleted or not. diff --git a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java index fb31552..ba939b4 100644 --- a/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java +++ b/src/main/java/com/github/ygimenez/model/PaginatorBuilder.java @@ -99,7 +99,7 @@ public Object getHandler() { } /** - * Sets the handler used for event processing. + * Set the handler used for event processing. * * @param handler The {@link JDA} instance that'll be used for event processing. * @return The {@link PaginatorBuilder} instance for chaining convenience. @@ -110,7 +110,7 @@ public PaginatorBuilder setHandler(@NotNull JDA handler) { } /** - * Sets the handler used for event processing. + * Set the handler used for event processing. * * @param handler The {@link ShardManager} instance that'll be used for event processing. * @return The {@link PaginatorBuilder} instance for chaining convenience. @@ -132,7 +132,7 @@ public boolean willRemoveOnReact() { } /** - * Sets whether user reactions will be removed after pressing the button or not. + * Set whether user reactions will be removed after pressing the button or not. * If this is enabled, the bot will require {@link Permission#MESSAGE_MANAGE} permission * for the buttons to work. * @@ -154,7 +154,7 @@ public boolean isEventLocking() { } /** - * Sets whether evens should be locked to prevent double-activation of buttons before + * Set whether evens should be locked to prevent double-activation of buttons before * it finished previous processing (can help if experiencing race condition). * * @param shouldLock Whether events should be locked (default: false). @@ -177,7 +177,7 @@ public boolean shouldDeleteOnCancel() { } /** - * Sets whether {@link Message} should be deleted or not when the button handler is removed. + * Set whether {@link Message} should be deleted or not when the button handler is removed. * <strong>This must only be called by {@link PaginatorBuilder}</strong>. * * @param deleteOnCancel Whether the {@link Message} will be deleted or not (default: false). diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java index 90a46f1..0950ddf 100644 --- a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -53,7 +53,7 @@ public boolean isCancellable() { } /** - * Sets whether the event is cancellable through {@link Emote#CANCEL}. + * Set whether the event is cancellable through {@link Emote#CANCEL}. * * @param cancellable Whether the event can be cancelled or not (default: true). * @return The {@link Helper} instance for chaining convenience. @@ -73,7 +73,7 @@ public long getTimeout() { } /** - * Sets the timeout for automatically cancelling the event. Values less than or equal to zero will disable the + * Set the timeout for automatically cancelling the event. Values less than or equal to zero will disable the * timeout. * * @param time The time for the timeout. @@ -96,7 +96,7 @@ public boolean canInteract(User user) { } /** - * Sets the condition used to check if a given user can interact with the event buttons. + * Set the condition used to check if a given user can interact with the event buttons. * * @param canInteract A {@link Predicate} for checking if a given user can interact with the buttons (default: null). * @return The {@link Helper} instance for chaining convenience. diff --git a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java index 9a111ef..f440315 100644 --- a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java @@ -124,6 +124,6 @@ public boolean shouldUpdate(Message msg) { checks = checks.and(e -> e.containsAll(getContent().keySet())); - return checks.test(emojis); + return !checks.test(emojis); } } diff --git a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java index f6bbe58..328779f 100644 --- a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java @@ -99,6 +99,6 @@ public boolean shouldUpdate(Message msg) { checks = checks.and(e -> e.containsAll(getContent().keySet())); - return checks.test(emojis); + return !checks.test(emojis); } } diff --git a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java index 3c61ba8..2af3e0e 100644 --- a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java @@ -63,7 +63,7 @@ public int getSkipAmount() { } /** - * Sets the amount of pages to be skipped on pressing {@link Emote#SKIP_BACKWARD} or {@link Emote#SKIP_FORWARD}. + * Set the amount of pages to be skipped on pressing {@link Emote#SKIP_BACKWARD} or {@link Emote#SKIP_FORWARD}. * * @param skipAmount The amount of pages to skip (default: 0). * @return The {@link ButtonizeHelper} instance for chaining convenience. @@ -84,7 +84,7 @@ public boolean isFastForward() { } /** - * Sets whether to include {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons for quick navigation + * Set whether to include {@link Emote#GOTO_FIRST} and {@link Emote#GOTO_LAST} buttons for quick navigation * through the pages. * * @param fastForward Whether to include fast-forward buttons (default: false). From 5af0a1d8ea7edea49354cb2cb3668ba9df2b0481 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 15:56:52 -0300 Subject: [PATCH 21/31] Fixed minor issues --- src/main/java/com/github/ygimenez/listener/MessageHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/ygimenez/listener/MessageHandler.java b/src/main/java/com/github/ygimenez/listener/MessageHandler.java index d21e24d..d5ab40b 100644 --- a/src/main/java/com/github/ygimenez/listener/MessageHandler.java +++ b/src/main/java/com/github/ygimenez/listener/MessageHandler.java @@ -209,7 +209,7 @@ private String getEventId(GenericMessageEvent evt) { private String getEventId(ButtonInteractionEvent evt) { crc.reset(); - String rawId = (evt.isFromGuild() ? "GUILD_" : "PRIVATE_") + evt.getChannel().getId() + "_" + evt.getId(); + String rawId = (evt.isFromGuild() ? "GUILD_" : "PRIVATE_") + evt.getChannel().getId() + "_" + evt.getMessageId(); crc.update(rawId.getBytes(StandardCharsets.UTF_8)); return Long.toHexString(crc.getValue()); From aa3ffd40857c4925fccf698cd528c27527f67508 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 18:01:34 -0300 Subject: [PATCH 22/31] Fixed minor issues --- src/main/java/com/github/ygimenez/method/Pages.java | 5 ++++- .../java/com/github/ygimenez/model/helper/BaseHelper.java | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 593ebc0..28496cd 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -35,6 +35,7 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Collectors; import static com.github.ygimenez.type.Emote.*; @@ -833,7 +834,9 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Categori if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); - Map<Emoji, Page> cats = Collections.unmodifiableMap(helper.getContent()); + Map<Emoji, Page> cats = helper.getContent().entrySet().stream() + .map(e -> Map.entry(e.getKey().getFormatted(), e.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); if (useBtns && helper.shouldUpdate(msg)) { helper.apply(msg.editMessageComponents()).submit(); diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java index 0950ddf..eaa6986 100644 --- a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -81,7 +81,10 @@ public long getTimeout() { * @return The {@link Helper} instance for chaining convenience. */ public Helper setTimeout(int time, TimeUnit unit) { - this.time = TimeUnit.MILLISECONDS.convert(time, unit); + if (unit != null) { + this.time = TimeUnit.MILLISECONDS.convert(time, unit); + } + return subClass.cast(this); } From 852e6772e23fb6a53b3386997a2e1e88b4577947 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 19:02:35 -0300 Subject: [PATCH 23/31] Fixed build issues. --- .../com/github/ygimenez/method/Pages.java | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 28496cd..e9073b5 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -13,6 +13,7 @@ import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.emoji.CustomEmoji; import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.entities.emoji.EmojiUnion; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; @@ -35,7 +36,6 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; import static com.github.ygimenez.type.Emote.*; @@ -834,9 +834,7 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Categori if (!isActivated()) throw new InvalidStateException(); boolean useBtns = helper.isUsingButtons() && msg.getAuthor().getId().equals(msg.getJDA().getSelfUser().getId()); - Map<Emoji, Page> cats = helper.getContent().entrySet().stream() - .map(e -> Map.entry(e.getKey().getFormatted(), e.getValue())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + Map<Emoji, Page> cats = Collections.unmodifiableMap(helper.getContent()); if (useBtns && helper.shouldUpdate(msg)) { helper.apply(msg.editMessageComponents()).submit(); @@ -895,7 +893,7 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe finalizeEvent(m, success); return; } else if (emoji != null && !Objects.equals(emoji, currCat)) { - Page pg = cats.get(emoji); + Page pg = lookupValue(cats, emoji); if (pg != null) { if (currCat != null && pg instanceof InteractPage) { modifyButtons(m, Map.of(Emote.getId(currCat), Button::asEnabled)); @@ -1211,7 +1209,7 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe hook = null; } - ThrowingConsumer<ButtonWrapper> act = btns.get(emoji); + ThrowingConsumer<ButtonWrapper> act = lookupValue(btns, emoji); if (act != null) { act.accept(new ButtonWrapper(wrapper.getUser(), hook, m)); } @@ -1662,6 +1660,27 @@ private static Emoji toEmoji(EmojiUnion reaction) { return Emoji.fromFormatted(reaction.getFormatted()); } + private static <T> T lookupValue(Map<Emoji, T> map, Emoji emoji) { + String id; + if (emoji instanceof CustomEmoji) { + id = ((CustomEmoji) emoji).getId(); + } else { + id = emoji.getFormatted(); + } + + return map.entrySet().stream() + .filter(e -> { + Emoji emj = e.getKey(); + if (emj instanceof CustomEmoji) { + return ((CustomEmoji) emj).getId().equals(id); + } + + return emj.getFormatted().equals(id); + }) + .map(Map.Entry::getValue) + .findFirst().orElse(null); + } + /** * Utility method to clear all reactions of a message. * From 7cd6825dfd988dc4fb5d968ed44d5f474d8fb7b2 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Mon, 6 Mar 2023 21:39:39 -0300 Subject: [PATCH 24/31] Fixed build issues. --- .../github/ygimenez/model/InteractPage.java | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/github/ygimenez/model/InteractPage.java b/src/main/java/com/github/ygimenez/model/InteractPage.java index 5a02458..bc69aa2 100644 --- a/src/main/java/com/github/ygimenez/model/InteractPage.java +++ b/src/main/java/com/github/ygimenez/model/InteractPage.java @@ -20,7 +20,6 @@ public class InteractPage extends Page { private final Map<ButtonStyle, ButtonStyle> styles = new EnumMap<>(ButtonStyle.class); private final Map<Emote, String> caption = new EnumMap<>(Emote.class); - private final boolean ephemeral; /** * An {@link InteractPage} object to be used in this library's methods. Currently, only {@link Message} @@ -31,7 +30,6 @@ public class InteractPage extends Page { */ public InteractPage(@NotNull Object content) throws IllegalArgumentException { super(content); - this.ephemeral = false; //Attribute currently unused } /** @@ -75,7 +73,7 @@ public Button makeButton(@NotNull Emote emt) { if (emt == Emote.NONE) { return Button.secondary(emt.name() + "." + Objects.hash(Math.random()), "\u200B").asDisabled(); } else { - return Button.of(style, (ephemeral ? "*" : "") + emt.name(), caption.get(emt), Pages.getPaginator().getEmoji(emt)); + return Button.of(style, emt.name(), caption.get(emt), Pages.getPaginator().getEmoji(emt)); } } @@ -86,7 +84,7 @@ public Button makeButton(@NotNull Emote emt) { * @return The created {@link Button}. */ public Button makeButton(@NotNull Emoji emj) { - return Button.secondary((ephemeral ? "*" : "") + Emote.getId(emj), emj); + return Button.secondary( Emote.getId(emj), emj); } /** @@ -97,16 +95,6 @@ public Button makeButton(@NotNull Emoji emj) { * @return The created {@link Button}. */ public Button makeButton(@NotNull Emoji emj, String caption) { - return Button.of(ButtonStyle.SECONDARY, (ephemeral ? "*" : "") + Emote.getId(emj), caption, emj); - } - - /** - * Whether the button is intended to be used in ephemeral messages or not. Currently, it serves no purpose other - * than a placeholder for future features. - * - * @return Whether the {@link Button} will be used in ephemeral messages or not. - */ - public boolean isEphemeral() { - return ephemeral; + return Button.of(ButtonStyle.SECONDARY, Emote.getId(emj), caption, emj); } } From 7a1cbb302c7bbf65fdd27baaf341aef057a3bb75 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Tue, 7 Mar 2023 00:36:49 -0300 Subject: [PATCH 25/31] Fixed build issues. --- .../github/ygimenez/model/InteractPage.java | 6 +++--- .../model/helper/CategorizeHelper.java | 20 ++++++++++++++++--- .../model/helper/LazyPaginateHelper.java | 2 +- .../ygimenez/model/helper/PaginateHelper.java | 10 +++++----- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/github/ygimenez/model/InteractPage.java b/src/main/java/com/github/ygimenez/model/InteractPage.java index bc69aa2..de09a87 100644 --- a/src/main/java/com/github/ygimenez/model/InteractPage.java +++ b/src/main/java/com/github/ygimenez/model/InteractPage.java @@ -73,7 +73,7 @@ public Button makeButton(@NotNull Emote emt) { if (emt == Emote.NONE) { return Button.secondary(emt.name() + "." + Objects.hash(Math.random()), "\u200B").asDisabled(); } else { - return Button.of(style, emt.name(), caption.get(emt), Pages.getPaginator().getEmoji(emt)); + return Button.of(style, emt.name(), caption.get(emt), Pages.getPaginator().getEmoji(emt)); } } @@ -84,7 +84,7 @@ public Button makeButton(@NotNull Emote emt) { * @return The created {@link Button}. */ public Button makeButton(@NotNull Emoji emj) { - return Button.secondary( Emote.getId(emj), emj); + return Button.secondary(Emote.getId(emj), emj); } /** @@ -95,6 +95,6 @@ public Button makeButton(@NotNull Emoji emj) { * @return The created {@link Button}. */ public Button makeButton(@NotNull Emoji emj, String caption) { - return Button.of(ButtonStyle.SECONDARY, Emote.getId(emj), caption, emj); + return Button.of(ButtonStyle.SECONDARY, Emote.getId(emj), caption, emj); } } diff --git a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java index 328779f..e1aead5 100644 --- a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java @@ -1,9 +1,10 @@ package com.github.ygimenez.model.helper; import com.github.ygimenez.method.Pages; +import com.github.ygimenez.model.InteractPage; import com.github.ygimenez.model.Page; -import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ItemComponent; @@ -59,13 +60,26 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { List<ActionRow> rows = new ArrayList<>(); List<ItemComponent> row = new ArrayList<>(); - for (Emoji k : getContent().keySet()) { + for (Map.Entry<Emoji, Page> e : getContent().entrySet()) { if (row.size() == 5) { rows.add(ActionRow.of(row)); row = new ArrayList<>(); } - row.add(Button.secondary(Emote.getId(k), k)); + InteractPage p = (InteractPage) e.getValue(); + Button b = p.makeButton(e.getKey()); + if (p.getContent() instanceof MessageEmbed) { + for (MessageEmbed embed : action.getEmbeds()) { + if (embed.equals(p.getContent())) { + b = b.asDisabled(); + break; + } + } + } else if (action.getContent().equals(p.getContent())) { + b = b.asDisabled(); + } + + row.add(b); } if (isCancellable()) { diff --git a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java index 648be25..45d2169 100644 --- a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java @@ -106,7 +106,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { if (p == null) throw new NullPageException(); return action.setComponents(ActionRow.of(new ArrayList<>() {{ - add(p.makeButton(PREVIOUS)); + add(p.makeButton(PREVIOUS).asDisabled()); if (isCancellable()) add(p.makeButton(CANCEL)); add(p.makeButton(NEXT)); }})); diff --git a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java index 2af3e0e..0af9783 100644 --- a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java @@ -106,7 +106,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { List<ActionRow> rows = new ArrayList<>(); LinkedList<ItemComponent> row = new LinkedList<>() {{ - add(p.makeButton(PREVIOUS)); + add(p.makeButton(PREVIOUS).asDisabled()); if (isCancellable()) add(p.makeButton(CANCEL)); add(p.makeButton(NEXT)); }}; @@ -114,18 +114,18 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { row.addFirst(p.makeButton(NONE)); row.addLast(p.makeButton(NONE)); } else if (skipAmount > 1) { - row.addFirst(p.makeButton(SKIP_BACKWARD)); + row.addFirst(p.makeButton(SKIP_BACKWARD).asDisabled()); row.addLast(p.makeButton(SKIP_FORWARD)); } else if (fastForward) { - row.addFirst(p.makeButton(GOTO_FIRST)); + row.addFirst(p.makeButton(GOTO_FIRST).asDisabled()); row.addLast(p.makeButton(GOTO_LAST)); } rows.add(ActionRow.of(row)); if (skipAmount > 1 && fastForward) { rows.add(ActionRow.of(new ArrayList<>() {{ - add(p.makeButton(GOTO_FIRST)); - add(p.makeButton(SKIP_BACKWARD)); + add(p.makeButton(GOTO_FIRST).asDisabled()); + add(p.makeButton(SKIP_BACKWARD).asDisabled()); if (isCancellable()) add(p.makeButton(NONE)); add(p.makeButton(SKIP_FORWARD)); add(p.makeButton(GOTO_LAST)); From 2dfb597c8aa21a4c09b8ebc54c8a3d71751f74be Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Tue, 7 Mar 2023 00:59:38 -0300 Subject: [PATCH 26/31] Fixed build issues. --- .../com/github/ygimenez/method/Pages.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index e9073b5..0b9806e 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -616,7 +616,7 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe } } - Page pg; + Page pg = null; boolean update = false; switch (emt) { case PREVIOUS: @@ -1494,6 +1494,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull LazyPa if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; + private final Function<Button, Button> LOWER_BOUNDARY_CHECK = b -> b.withDisabled(p == 0); + { if (helper.getTimeout() > 0) { timeout = executor.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); @@ -1519,19 +1521,20 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe } } - Page pg; + Page pg = null; + boolean update = false; switch (emt) { case PREVIOUS: if (p > 0) { p--; + update = true; pg = cache ? helper.getContent().get(p) : helper.getPageLoader().apply(p); - - updatePage(m, pg); - updateButtons(m, helper); } break; case NEXT: p++; + update = true; + if (cache && helper.getContent().size() > p) { pg = helper.getContent().get(p); if (pg == null) { @@ -1549,9 +1552,6 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe } } - updatePage(m, pg); - updateButtons(m, helper); - if (cache) helper.getContent().add(pg); break; case CANCEL: @@ -1559,6 +1559,19 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe return; } + if (update) { + updatePage(m, pg); + updateButtons(m, helper); + + 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 + )); + } + } + if (timeout != null) { timeout.cancel(true); } From 5d08acc6d063e7fcdba38cf31c182f581893e1af Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Tue, 7 Mar 2023 09:43:29 -0300 Subject: [PATCH 27/31] Removed unnecessary API calls --- .../com/github/ygimenez/method/Pages.java | 129 ++++++------------ .../ygimenez/model/helper/BaseHelper.java | 24 +++- .../model/helper/ButtonizeHelper.java | 10 +- .../model/helper/CategorizeHelper.java | 10 +- .../model/helper/LazyPaginateHelper.java | 18 +-- .../ygimenez/model/helper/PaginateHelper.java | 17 +-- 6 files changed, 92 insertions(+), 116 deletions(-) diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 0b9806e..c9efa96 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -3,13 +3,9 @@ import com.github.ygimenez.exception.AlreadyActivatedException; import com.github.ygimenez.exception.InvalidHandlerException; import com.github.ygimenez.exception.InvalidStateException; -import com.github.ygimenez.exception.NullPageException; import com.github.ygimenez.listener.MessageHandler; import com.github.ygimenez.model.*; -import com.github.ygimenez.model.helper.ButtonizeHelper; -import com.github.ygimenez.model.helper.CategorizeHelper; -import com.github.ygimenez.model.helper.LazyPaginateHelper; -import com.github.ygimenez.model.helper.PaginateHelper; +import com.github.ygimenez.model.helper.*; import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; @@ -22,13 +18,12 @@ import net.dv8tion.jda.api.exceptions.ErrorResponseException; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.interactions.InteractionHook; -import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.requests.RestAction; +import net.dv8tion.jda.api.requests.restaction.MessageEditAction; import net.dv8tion.jda.api.sharding.ShardManager; -import net.dv8tion.jda.api.utils.messages.MessageEditBuilder; -import net.dv8tion.jda.api.utils.messages.MessageEditData; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -662,20 +657,15 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe if (update) { pg = pgs.get(p); - updatePage(m, pg); - updateButtons(m, helper); - - 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 - )); - } + modifyButtons(m, pg, helper, 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) { @@ -895,15 +885,8 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe } else if (emoji != null && !Objects.equals(emoji, currCat)) { Page pg = lookupValue(cats, 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)); - } + modifyButtons(m, pg, helper, Map.of(Emote.getId(currCat), Button::asDisabled)); } } @@ -1560,16 +1543,11 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe } if (update) { - updatePage(m, pg); - updateButtons(m, helper); - - 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 - )); - } + modifyButtons(m, pg, helper, Map.of( + PREVIOUS.name(), LOWER_BOUNDARY_CHECK, + SKIP_BACKWARD.name(), LOWER_BOUNDARY_CHECK, + GOTO_FIRST.name(), LOWER_BOUNDARY_CHECK + )); } if (timeout != null) { @@ -1587,41 +1565,6 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe }); } - /** - * Method used to update the current page. - * <strong>Must not be called outside of {@link Pages}</strong>. - * - * @param msg The current {@link Message} object. - * @param p The current {@link Page}. - */ - private static void updatePage(@NotNull Message msg, Page p) { - if (p == null) throw new NullPageException(msg); - - if (p.getContent() instanceof Message) { - try (MessageEditData data = MessageEditBuilder.fromMessage((Message) p.getContent()).build()) { - msg.editMessage(data).submit(); - } - } else if (p.getContent() instanceof MessageEmbed) { - msg.editMessageEmbeds((MessageEmbed) p.getContent()).submit(); - } - } - - private static void updateButtons(@NotNull Message msg, @NotNull PaginateHelper helper) { - if (helper.isUsingButtons()) { - helper.apply(msg.editMessageComponents()).submit(); - } else { - addReactions(msg, helper.getSkipAmount() > 1, helper.isFastForward()); - } - } - - private static void updateButtons(@NotNull Message msg, @NotNull LazyPaginateHelper helper) { - if (helper.isUsingButtons()) { - helper.apply(msg.editMessageComponents()).submit(); - } else { - addReactions(msg, false, false); - } - } - /** * Utility method for re-fetching a message. * @@ -1744,28 +1687,38 @@ public static void finalizeEvent(Message msg, Consumer<Void> callback) { } /** - * Utility method for modifying message buttons. + * Utility method for switching pages and applying message button states. * * @param msg The {@link Message} holding the buttons. * @param changes {@link Map} containing desired changes, indexed by {@link Button} ID. */ - public static void modifyButtons(Message msg, Map<String, Function<Button, Button>> changes) { - List<ActionRow> rows = new ArrayList<>(msg.getActionRows()); - - for (ActionRow ar : rows) { - List<ItemComponent> row = ar.getComponents(); - for (int i = 0; i < row.size(); i++) { - ItemComponent c = row.get(i); - if (c instanceof Button) { - Button b = (Button) c; - if (changes.containsKey(b.getId())) { - row.set(i, changes.get(b.getId()).apply((Button) c)); + public static void modifyButtons(Message msg, Page p, BaseHelper<?, ?> helper, Map<String, Function<Button, Button>> changes) { + MessageEditAction act = msg.editMessageComponents(); + + if (p.getContent() instanceof Message) { + act = act.setContent(((Message) p.getContent()).getContentRaw()); + } else if (p.getContent() instanceof MessageEmbed) { + act = act.setEmbeds((MessageEmbed) p.getContent()); + } + + if (p instanceof InteractPage) { + List<LayoutComponent> rows = helper.getComponents(act); + + for (LayoutComponent lc : rows) { + List<ItemComponent> row = lc.getComponents(); + for (int i = 0; i < row.size(); i++) { + ItemComponent c = row.get(i); + if (c instanceof Button) { + Button b = (Button) c; + if (changes.containsKey(b.getId())) { + row.set(i, changes.get(b.getId()).apply((Button) c)); + } } } } } - subGet(msg.editMessageComponents(rows)); + act.submit(); } /** diff --git a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java index eaa6986..46f4408 100644 --- a/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/BaseHelper.java @@ -1,15 +1,26 @@ package com.github.ygimenez.model.helper; +import com.github.ygimenez.method.Pages; import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.interactions.components.Component; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; import net.dv8tion.jda.api.utils.messages.MessageRequest; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; -abstract class BaseHelper<Helper extends BaseHelper<Helper, T>, T> { +/** + * Abstract class meant to be extended by builder-like classes, allowing reusability of parameters passed to + * {@link Pages} methods. + * + * @param <Helper> A class that extends {@link BaseHelper}. + * @param <T> The type of collection used to store pages. + */ +public abstract class BaseHelper<Helper extends BaseHelper<Helper, T>, T> { private final Class<Helper> subClass; private final T content; @@ -109,6 +120,13 @@ public Helper setCanInteract(@Nullable Predicate<User> canInteract) { return subClass.cast(this); } + /** + * Retrieves the {@link List} of {@link Component}s generated by this helper. + * + * @return The list of components. + */ + public abstract <Out extends MessageRequest<Out>> List<LayoutComponent> getComponents(Out action); + /** * Prepares the message for being used by the library. This doesn't need to be called manually, this will * be called during normal flow. @@ -122,7 +140,9 @@ public Helper setCanInteract(@Nullable Predicate<User> canInteract) { * @return The same event, but modified to include the buttons. * @param <Out> Generic for a {@link MessageRequest} */ - public abstract <Out extends MessageRequest<Out>> Out apply(Out action); + public <Out extends MessageRequest<Out>> Out apply(Out action) { + return action.setComponents(getComponents(action)); + } /** * Calculates whether the {@link Message} needs to have buttons applied onto or not. diff --git a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java index f440315..863c36f 100644 --- a/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/ButtonizeHelper.java @@ -8,6 +8,7 @@ import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.utils.messages.MessageRequest; @@ -75,12 +76,11 @@ public ButtonizeHelper setOnFinalization(Consumer<Message> onFinalization) { return this; } - /** {@inheritDoc} **/ @Override - public <Out extends MessageRequest<Out>> Out apply(Out action) { - if (!isUsingButtons()) return action; + public <Out extends MessageRequest<Out>> List<LayoutComponent> getComponents(Out action) { + if (!isUsingButtons()) return List.of(); - List<ActionRow> rows = new ArrayList<>(); + List<LayoutComponent> rows = new ArrayList<>(); List<ItemComponent> row = new ArrayList<>(); for (Emoji k : getContent().keySet()) { @@ -109,7 +109,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { rows.add(ActionRow.of(row)); - return action.setComponents(rows); + return rows; } /** {@inheritDoc} **/ diff --git a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java index e1aead5..85653c3 100644 --- a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java @@ -8,6 +8,7 @@ import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.utils.messages.MessageRequest; @@ -52,12 +53,11 @@ public CategorizeHelper addCategory(Emoji emoji, Page page) { return this; } - /** {@inheritDoc} **/ @Override - public <Out extends MessageRequest<Out>> Out apply(Out action) { - if (!isUsingButtons()) return action; + public <Out extends MessageRequest<Out>> List<LayoutComponent> getComponents(Out action) { + if (!isUsingButtons()) return List.of(); - List<ActionRow> rows = new ArrayList<>(); + List<LayoutComponent> rows = new ArrayList<>(); List<ItemComponent> row = new ArrayList<>(); for (Map.Entry<Emoji, Page> e : getContent().entrySet()) { @@ -98,7 +98,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { rows.add(ActionRow.of(row)); - return action.setComponents(rows); + return rows; } /** {@inheritDoc} **/ diff --git a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java index 45d2169..a156488 100644 --- a/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/LazyPaginateHelper.java @@ -7,6 +7,7 @@ import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; import net.dv8tion.jda.api.utils.messages.MessageRequest; import org.jetbrains.annotations.Nullable; @@ -97,19 +98,20 @@ public ThrowingFunction<Integer, Page> getPageLoader() { return p; } - /** {@inheritDoc} **/ @Override - public <Out extends MessageRequest<Out>> Out apply(Out action) { - if (!isUsingButtons()) return action; + public <Out extends MessageRequest<Out>> List<LayoutComponent> getComponents(Out action) { + if (!isUsingButtons()) return List.of(); InteractPage p = (InteractPage) load(0); if (p == null) throw new NullPageException(); - return action.setComponents(ActionRow.of(new ArrayList<>() {{ - add(p.makeButton(PREVIOUS).asDisabled()); - if (isCancellable()) add(p.makeButton(CANCEL)); - add(p.makeButton(NEXT)); - }})); + return List.of( + ActionRow.of(new ArrayList<>() {{ + add(p.makeButton(PREVIOUS).asDisabled()); + if (isCancellable()) add(p.makeButton(CANCEL)); + add(p.makeButton(NEXT)); + }}) + ); } /** {@inheritDoc} **/ diff --git a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java index 0af9783..2ae3812 100644 --- a/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/PaginateHelper.java @@ -1,15 +1,18 @@ package com.github.ygimenez.model.helper; -import com.github.ygimenez.exception.NullPageException; import com.github.ygimenez.model.InteractPage; import com.github.ygimenez.model.Page; import com.github.ygimenez.type.Emote; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ItemComponent; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; import net.dv8tion.jda.api.utils.messages.MessageRequest; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -95,15 +98,13 @@ public PaginateHelper setFastForward(boolean fastForward) { return this; } - /** {@inheritDoc} **/ @Override - public <Out extends MessageRequest<Out>> Out apply(Out action) { - if (!isUsingButtons()) return action; + public <Out extends MessageRequest<Out>> List<LayoutComponent> getComponents(Out action) { + if (!isUsingButtons()) return List.of(); - if (getContent().isEmpty()) throw new NullPageException(); InteractPage p = (InteractPage) getContent().get(0); - List<ActionRow> rows = new ArrayList<>(); + List<LayoutComponent> rows = new ArrayList<>(); LinkedList<ItemComponent> row = new LinkedList<>() {{ add(p.makeButton(PREVIOUS).asDisabled()); @@ -132,7 +133,7 @@ public <Out extends MessageRequest<Out>> Out apply(Out action) { }})); } - return action.setComponents(rows); + return rows; } /** {@inheritDoc} **/ From 796ae0e2de51e5adc2d56f6138e76a3cca01d4c6 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Tue, 7 Mar 2023 09:53:39 -0300 Subject: [PATCH 28/31] Removed unnecessary API calls --- .../java/com/github/ygimenez/model/helper/CategorizeHelper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java index 85653c3..9789462 100644 --- a/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java +++ b/src/main/java/com/github/ygimenez/model/helper/CategorizeHelper.java @@ -67,6 +67,8 @@ public <Out extends MessageRequest<Out>> List<LayoutComponent> getComponents(Out } InteractPage p = (InteractPage) e.getValue(); + if (p == null) continue; + Button b = p.makeButton(e.getKey()); if (p.getContent() instanceof MessageEmbed) { for (MessageEmbed embed : action.getEmbeds()) { From 390295b8105d7dcc9f563b8e05d789d63c5d36df Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Tue, 7 Mar 2023 09:56:06 -0300 Subject: [PATCH 29/31] Removed unnecessary API calls --- src/main/java/com/github/ygimenez/method/Pages.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index c9efa96..4eaa193 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -1716,6 +1716,8 @@ public static void modifyButtons(Message msg, Page p, BaseHelper<?, ?> helper, M } } } + + act.setComponents(rows); } act.submit(); From e2958ca9ae0455d86825a70ce3297f4d7f4f97f9 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Tue, 7 Mar 2023 10:31:38 -0300 Subject: [PATCH 30/31] Changed Page builder to use String instead of Message --- README.md | 97 +++++++++---------- .../com/github/ygimenez/method/Pages.java | 4 +- .../java/com/github/ygimenez/model/Page.java | 12 +-- 3 files changed, 54 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 9bc0045..6f2a9e0 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,23 @@ -[build]: https://github.com/ygimenez/PaginationUtils/tree/master +[mvncentral]: https://mvnrepository.com/artifact/com.github.ygimenez/Pagination-Utils -[jitpack]: https://jitpack.io/#ygimenez/PaginationUtils +[jitpack]: https://jitpack.io/#ygimenez/Pagination-Utils -[mvncentral]: https://mvnrepository.com/artifact/com.github.ygimenez/Pagination-Utils +[build]: https://github.com/ygimenez/Pagination-Utils/tree/master -[license]: https://github.com/ygimenez/PaginationUtils/blob/master/LICENSE +[license]: https://github.com/ygimenez/Pagination-Utils/blob/master/LICENSE -[issue]: https://github.com/ygimenez/PaginationUtils/issues +[issue]: https://github.com/ygimenez/Pagination-Utils/issues -[build-shield]: https://img.shields.io/github/workflow/status/ygimenez/PaginationUtils/Java%20CI?label=Build +[mvncentral-shield]: https://img.shields.io/maven-central/v/com.github.ygimenez/Pagination-Utils?label=Maven%20Central [jitpack-shield]: https://img.shields.io/badge/Download-Jitpack-success -[mvncentral-shield]: https://img.shields.io/maven-central/v/com.github.ygimenez/Pagination-Utils?label=Maven%20Central +[build-shield]: https://img.shields.io/github/workflow/status/ygimenez/Pagination-Utils/Java%20CI?label=Build -[license-shield]: https://img.shields.io/github/license/ygimenez/PaginationUtils?color=lightgrey&label=License +[license-shield]: https://img.shields.io/github/license/ygimenez/Pagination-Utils?color=lightgrey&label=License + +[issue-shield]: https://img.shields.io/github/issues/ygimenez/Pagination-Utils?label=Issues -[issue-shield]: https://img.shields.io/github/issues/ygimenez/PaginationUtils?label=Issues [ ![mvncentral-shield][] ][mvncentral] [ ![jitpack-shield][] ][jitpack] [ ![build-shield][] ][build] @@ -31,35 +32,34 @@ With this library you will be using pages, categories and buttons in your bot in ## What is a page/category/button? - - - + - + -Have you been using a bot and came across one of those three GIFs and thought: "That must've been hard to make." or "I'd +Have you been using a bot and came across one of those GIFs and thought: "That must've been hard to make." or "I'd like one of those in my bot!"? Fear no more, Pagination Utils to the rescue! ## How do I paginate? -Before we start the fun stuff, there're a few things we need to check: +Before we start the fun stuff, there are a few things we need to check: - You're using Java JDK 9 or above. - Your bot has the following permissions: - - MESSAGE_ADD_REACTION - - MESSAGE_EXT_EMOJI - - MESSAGE_READ/WRITE - - VIEW_CHANNEL + - MESSAGE_READ/WRITE + - VIEW_CHANNEL + - If using reactions: + - MESSAGE_ADD_REACTION + - MESSAGE_EXT_EMOJI - If using `JDABuilder.createLight()`, you added the following gateway intents: - - GUILD_MESSAGES - - GUILD_MESSAGE_REACTIONS + - GUILD_MESSAGES + - GUILD_MESSAGE_REACTIONS -Now we can finally start, which is easier than it seems! The first step is to set a JDA client object as the event +Now we can finally start, which is easier than it seems! The first step is to set a JDA/SharmManager client object as the event holder, which can be done in a single line: ```java JDA bot = ... // Creation of bot client - + Pages.activate(PaginatorBuilder.createSimplePaginator(bot)); ``` @@ -68,13 +68,13 @@ But if you want some customization of the library's behaviour, you can opt to us ```java JDA bot = ... // Creation of bot client -Paginator paginator = PaginatorBuilder.createPaginator() - // Defines which handler will be used - .setHandler(bot) - // Whether reactions will be removed on click - .shouldRemoveOnReaction(false) +Paginator paginator = PaginatorBuilder.createPaginator(bot) + // Whether reactions will be removed on click + .shouldRemoveOnReaction(false) // Prevents double-click on buttons and guarantee an event will only happen when previous processing has finished .shouldEventLock(true) + // Whether to delete the message when the event ends (such as pressing CANCEL or timeout) + .shouldDeleteOnCancel(true) // Finish configuration and activate the library .activate(); ``` @@ -84,17 +84,17 @@ If you want to go even further and change the default buttons' emotes, don't wor ```java JDA bot = ... // Creation of bot client -Paginator paginator = PaginatorBuilder.createPaginator() - // Defines which handler will be used - .setHandler(bot) +Paginator paginator = PaginatorBuilder.createPaginator(bot) // Whether reactions will be removed on click .shouldRemoveOnReaction(false) // Prevents double-click on buttons and guarantee an event will only happen when previous processing has finished .shouldEventLock(true) + // Whether to delete the message when the event ends (such as pressing CANCEL or timeout) + .shouldDeleteOnCancel(true) // Changes the next button to π - .setEmote(Emote.NEXT, Emoji.fromMarkdown("π")) + .setEmote(Emote.NEXT, Emoji.fromFormatted("π")) // Changes the previous button to π© - .setEmote(Emote.PREVIOUS, Emoji.fromMarkdown("π©")) + .setEmote(Emote.PREVIOUS, Emoji.fromFormatted("π©")) // Finish configuration and activate the library .activate(); ``` @@ -111,24 +111,21 @@ mb.setContent("Hello World!"); Page messagePage = new Page(mb.build()); // Example using EmbedBuilder -EmbedBuilder eb = new EmbedBuilder(); -eb.setTitle("Example Embed"); -eb.setDescription("Hello World!"); +EmbedBuilder eb = new EmbedBuilder() + .setTitle("Example Embed") + .setDescription("Hello World"); Page embedPage = new InteractPage(eb.build()); ``` -That said, you might want to create an `ArrayList` of pages to use the pagination, since a single page does not need to be paginated at all: +That said, you might want to create a `List` of pages to use the pagination, since a single page does not need to be paginated at all: ```java -ArrayList<Page> pages = new ArrayList<>(); -MessageBuilder mb = new MessageBuilder(); +List<Page> pages = new ArrayList<>(); // Adding 10 pages to the list for (int i = 0; i < 10; i++) { - mb.clear(); - mb.setContent("This is entry NΒΊ " + i); - pages.add(new InteractPage(mb.build())); + pages.add(new InteractPage("This is entry NΒΊ " + (i + 1))); } ``` @@ -144,6 +141,8 @@ exampleChannel.sendMessage((Message) pages.get(0).getContent()).queue(success -> }); ``` + + That's everything you have to do, the library will automatically add the navigation buttons to the target message, which will change its content based on the list's order. @@ -153,25 +152,24 @@ To categorize it's almost the same process as paginating, however, the type of c of `ArrayList`: ```java -HashMap<Emoji, Page> categories = new HashMap<>(); +Map<Emoji, Page> categories = new HashMap<>(); MessageBuilder mb = new MessageBuilder(); // Manually adding 3 categories to the map, you could use some kind of loop to fill it (see https://emojipedia.org/ for unicodes) mb.setContent("This is category 1"); -categories.put(Emoji.fromMarkdown("\u26f3"), new InteractPage(mb.build())); +categories.put(Emoji.fromFormatted("\u26f3"), new InteractPage(mb.build())); mb.setContent("This is category 2"); -categories.put(Emoji.fromMarkdown("\u26bd"), new InteractPage(mb.build())); +categories.put(Emoji.fromFormatted("\u26bd"), new InteractPage(mb.build())); mb.setContent("This is category 3"); -categories.put(Emoji.fromMarkdown("\u270f"), new InteractPage(mb.build())); +categories.put(Emoji.fromFormatted("\u270f"), new InteractPage(mb.build())); ``` Then just call `Pages.categorize()` method just like you did before: ```java exampleChannel.sendMessage("This is a menu message").queue(success -> { - // Third argument is whether you want to use reactions (false) or interaction buttons (true). Pages.categorize(success, categories, /* Use buttons? */ true); }); ``` @@ -189,10 +187,7 @@ ThrowingConsumer<ButtonWrapper> customFunction = (wrapper) -> { }; exampleChannel.sendMessage("This is a sample message").queue(success -> { - // Same arguments, except the second that must extend map collection - // Third argument is whether you want to use reactions (false) or interaction buttons (true). - // The last argument defines whether to show cancel button or not - Pages.buttonize(success, Collections.singletonMap(Emoji.fromMarkdown("β "), customFunction), /* Use buttons? */ true, /* Show cancel? */false); + Pages.buttonize(success, Collections.singletonMap(Emoji.fromFormatted("β "), customFunction), /* Use buttons? */ true, /* Show cancel? */ true); }); ``` diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 4eaa193..bdbe3a6 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -1695,8 +1695,8 @@ public static void finalizeEvent(Message msg, Consumer<Void> callback) { public static void modifyButtons(Message msg, Page p, BaseHelper<?, ?> helper, Map<String, Function<Button, Button>> changes) { MessageEditAction act = msg.editMessageComponents(); - if (p.getContent() instanceof Message) { - act = act.setContent(((Message) p.getContent()).getContentRaw()); + if (p.getContent() instanceof String) { + act = act.setContent((String) p.getContent()); } else if (p.getContent() instanceof MessageEmbed) { act = act.setEmbeds((MessageEmbed) p.getContent()); } diff --git a/src/main/java/com/github/ygimenez/model/Page.java b/src/main/java/com/github/ygimenez/model/Page.java index ca986ae..a51f866 100644 --- a/src/main/java/com/github/ygimenez/model/Page.java +++ b/src/main/java/com/github/ygimenez/model/Page.java @@ -5,21 +5,21 @@ import org.jetbrains.annotations.NotNull; /** - * Class representing either a {@link Message} or {@link MessageEmbed} object. + * Class representing either a {@link String} or {@link MessageEmbed} object. */ public class Page { private final Object content; /** - * A {@link Page} object to be used in this library's methods. Currently, only {@link Message} + * A {@link Page} object to be used in this library's methods. Currently, only {@link String} * and {@link MessageEmbed} are supported. * - * @param content The {@link Message}/{@link MessageEmbed} object to be used as pages. - * @throws IllegalArgumentException Thrown if argument is not a {@link Message} nor {@link MessageEmbed}. + * @param content The {@link String}/{@link MessageEmbed} object to be used as pages. + * @throws IllegalArgumentException Thrown if argument is not a {@link String} nor {@link MessageEmbed}. */ public Page(@NotNull Object content) throws IllegalArgumentException { - if (!(content instanceof Message) && !(content instanceof MessageEmbed)) { - throw new IllegalArgumentException("Page content must be either a Message or a MessageEmbed"); + if (!(content instanceof String) && !(content instanceof MessageEmbed)) { + throw new IllegalArgumentException("Page content must be either a String or a MessageEmbed"); } this.content = content; From 661f5d30b3dfc71c5323515fccb38eff7721d755 Mon Sep 17 00:00:00 2001 From: Ygimenez <yagogimenez1@hotmail.com> Date: Tue, 7 Mar 2023 11:01:42 -0300 Subject: [PATCH 31/31] Updated README --- README.md | 120 +++++++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 6f2a9e0..19f202a 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Before we start the fun stuff, there are a few things we need to check: - You're using Java JDK 9 or above. - Your bot has the following permissions: - MESSAGE_READ/WRITE - - VIEW_CHANNEL + - VIEW_CHANNEL - If using reactions: - MESSAGE_ADD_REACTION - MESSAGE_EXT_EMOJI @@ -60,7 +60,7 @@ holder, which can be done in a single line: ```java JDA bot = ... // Creation of bot client -Pages.activate(PaginatorBuilder.createSimplePaginator(bot)); + Pages.activate(PaginatorBuilder.createSimplePaginator(bot)); ``` But if you want some customization of the library's behaviour, you can opt to use the full builder: @@ -68,15 +68,15 @@ But if you want some customization of the library's behaviour, you can opt to us ```java JDA bot = ... // Creation of bot client -Paginator paginator = PaginatorBuilder.createPaginator(bot) + Paginator paginator = PaginatorBuilder.createPaginator(bot) // Whether reactions will be removed on click .shouldRemoveOnReaction(false) - // Prevents double-click on buttons and guarantee an event will only happen when previous processing has finished - .shouldEventLock(true) + // Prevents double-click on buttons and guarantee an event will only happen when previous processing has finished + .shouldEventLock(true) // Whether to delete the message when the event ends (such as pressing CANCEL or timeout) .shouldDeleteOnCancel(true) - // Finish configuration and activate the library - .activate(); + // Finish configuration and activate the library + .activate(); ``` If you want to go even further and change the default buttons' emotes, don't worry, we got you covered: @@ -84,19 +84,19 @@ If you want to go even further and change the default buttons' emotes, don't wor ```java JDA bot = ... // Creation of bot client -Paginator paginator = PaginatorBuilder.createPaginator(bot) - // Whether reactions will be removed on click - .shouldRemoveOnReaction(false) - // Prevents double-click on buttons and guarantee an event will only happen when previous processing has finished - .shouldEventLock(true) + Paginator paginator = PaginatorBuilder.createPaginator(bot) + // Whether reactions will be removed on click + .shouldRemoveOnReaction(false) + // Prevents double-click on buttons and guarantee an event will only happen when previous processing has finished + .shouldEventLock(true) // Whether to delete the message when the event ends (such as pressing CANCEL or timeout) .shouldDeleteOnCancel(true) - // Changes the next button to π - .setEmote(Emote.NEXT, Emoji.fromFormatted("π")) - // Changes the previous button to π© - .setEmote(Emote.PREVIOUS, Emoji.fromFormatted("π©")) - // Finish configuration and activate the library - .activate(); + // Changes the next button to π + .setEmote(Emote.NEXT, Emoji.fromFormatted("π")) + // Changes the previous button to π© + .setEmote(Emote.PREVIOUS, Emoji.fromFormatted("π©")) + // Finish configuration and activate the library + .activate(); ``` Then all you need to do is create a `Page` (or `InteractPage` for interaction buttons) collection containing the type of the content and the `Message`/`MessageEmbed` object that you just created. @@ -106,16 +106,16 @@ Example: ```java // Example using MessageBuilder MessageBuilder mb = new MessageBuilder(); -mb.setContent("Hello World!"); + mb.setContent("Hello World!"); -Page messagePage = new Page(mb.build()); + Page messagePage = new Page(mb.build()); // Example using EmbedBuilder -EmbedBuilder eb = new EmbedBuilder() + EmbedBuilder eb = new EmbedBuilder() .setTitle("Example Embed") .setDescription("Hello World"); -Page embedPage = new InteractPage(eb.build()); + Page embedPage = new InteractPage(eb.build()); ``` That said, you might want to create a `List` of pages to use the pagination, since a single page does not need to be paginated at all: @@ -124,24 +124,23 @@ That said, you might want to create a `List` of pages to use the pagination, sin List<Page> pages = new ArrayList<>(); // Adding 10 pages to the list -for (int i = 0; i < 10; i++) { - pages.add(new InteractPage("This is entry NΒΊ " + (i + 1))); -} + for (int i = 0; i < 10; i++) { + pages.add(new InteractPage("This is entry NΒΊ " + (i + 1))); + } ``` Then all you have to do is call `Pages.paginate()` method: ```java -// This method requires 3 arguments: -// The target message -// The list of pages -// Whether you want to use reactions (false) or interaction buttons (true). exampleChannel.sendMessage((Message) pages.get(0).getContent()).queue(success -> { Pages.paginate(success, pages, /* Use buttons? */ true); }); ``` - +<figure class="image"> + <img src="https://i.imgur.com/Ms6ECNY.png" alt="Result"> + <figcaption><i style="color: gray">Wait, that's it?</i></figcaption> +</figure> That's everything you have to do, the library will automatically add the navigation buttons to the target message, which will change its content based on the list's order. @@ -153,82 +152,91 @@ of `ArrayList`: ```java Map<Emoji, Page> categories = new HashMap<>(); -MessageBuilder mb = new MessageBuilder(); // Manually adding 3 categories to the map, you could use some kind of loop to fill it (see https://emojipedia.org/ for unicodes) mb.setContent("This is category 1"); -categories.put(Emoji.fromFormatted("\u26f3"), new InteractPage(mb.build())); +categories.put(Emoji.fromFormatted("\u26f3"), new InteractPage("This is category 1")); mb.setContent("This is category 2"); -categories.put(Emoji.fromFormatted("\u26bd"), new InteractPage(mb.build())); +categories.put(Emoji.fromFormatted("\u26bd"), new InteractPage("This is category 2")); mb.setContent("This is category 3"); -categories.put(Emoji.fromFormatted("\u270f"), new InteractPage(mb.build())); +categories.put(Emoji.fromFormatted("\u270f"), new InteractPage("This is category 3")); ``` Then just call `Pages.categorize()` method just like you did before: ```java -exampleChannel.sendMessage("This is a menu message").queue(success -> { +exampleChannel.sendMessage("This is the main menu").queue(success -> { Pages.categorize(success, categories, /* Use buttons? */ true); }); ``` +<figure class="image"> + <img src="https://i.imgur.com/MeqRUPp.png" alt="Result"> + <figcaption><i style="color: gray">Of course you could be more elaborate.</i></figcaption> +</figure> + ## How do I buttonize? To do it, you first need to setup a few things: ```java // A Consumer is a callback function that uses one arguments and returns nothing -// Here, the member is the one that pressed the button, and message is the buttonized message itself +// Here, wrapper is a class containing useful data related to the click event ThrowingConsumer<ButtonWrapper> customFunction = (wrapper) -> { // Example of giving a role to anyone who presses this button guild.addRoleToMember(wrapper.getMember(), guild.getRoleById("123456789")).queue(); }; -exampleChannel.sendMessage("This is a sample message").queue(success -> { - Pages.buttonize(success, Collections.singletonMap(Emoji.fromFormatted("β "), customFunction), /* Use buttons? */ true, /* Show cancel? */ true); +exampleChannel.sendMessage("Click to get role").queue(success -> { + Pages.buttonize(success, Collections.singletonMap(Emoji.fromFormatted("β "), customFunction), /* Use buttons? */ true, /* Show cancel? */ false); }); ``` +<figure class="image"> + <img src="https://i.imgur.com/fDF6MdO.png" alt="Result"> + <figcaption><i style="color: gray">Useful for self-assigned roles.</i></figcaption> +</figure> + ## I have low memory, what about me? -Yet again, don't worry, Pagination-Utils to the rescue! +Yet again, don't worry, Pagination Utils to the rescue! ```java // Could be anything, this is just an example. List<String> data = new ArrayList<>(); -// Adding 10 values to the list -for (int i = 0; i < 10; i++) { - data.add("This is entry NΒΊ " + i); +// Adding 10 values pages to the list +for (int i = 0; i < 2; i++) { + data.add("This is page number " + (i + 1)); } -MessageBuilder mb = new MessageBuilder(); ThrowingFunction<Integer, Page> func = i -> { - mb.setContent("This is entry NΒΊ " + i); - return new InteractPage(mb.build()); + return new InteractPage(data.get(i)); }; ``` Then just call `Pages.lazyPaginate()` method: ```java -// Second argument must be a function that takes an integer and returns a Page. -// Third argument is whether you want to use reactions (false) or interaction buttons (true). -// The last argument defines whether pages should be cached or not (will keep previously visited pages in memory). -exampleChannel.sendMessage((Message) pages.get(0).getContent()).queue(success -> { +// You can disable page caching, which will prevent the library from saving previously visited pages +exampleChannel.sendMessage((String) pages.get(0).getContent()).queue(success -> { Pages.lazyPaginate(success, func, /* Use buttons? */ true, /* Cache? */ false); }); ``` +<figure class="image"> + <img src="https://i.imgur.com/Ms6ECNY.png" alt="Result"> + <figcaption><i style="color: gray">Same image because...well...both are paginators</i></figcaption> +</figure> + ## Is it really that easy? -Yes, you can focus on creating epic menus, ranking, lists, whatever and leave the boring part for the library to do its -job, isn't that awesome? +Yes, you can focus on creating epic menus, ranking, lists, games, *et cetera* and leave the boring part for the library to do its job, isn't that awesome? ## How do I get it? -This library is available for manual installation and through Jitpack: +This library is available for manual installation and through Maven Central: ### To install manually @@ -255,9 +263,9 @@ Maven: ```xml <dependency> - <groupId>com.github.ygimenez</groupId> - <artifactId>Pagination-Utils</artifactId> - <version>VERSION</version> + <groupId>com.github.ygimenez</groupId> + <artifactId>Pagination-Utils</artifactId> + <version>VERSION</version> </dependency> ``` @@ -266,4 +274,4 @@ Maven: ## Feedback -If you have any issues using this library, feel free to create a new issue and I'll review it as soon as possible! +If you have any issues using this library, feel free to create a new issue and I'll review it as soon as possible! \ No newline at end of file