Instantly share code, notes, and snippets.
Last active
September 10, 2020 13:25
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save MinnDevelopment/feea5b6ed3687b666b2aace62b806f8f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ActionMenu extends Menu implements Menu.Page { | |
private final Message message; | |
private final List<Button> buttons = new ArrayList<>(); | |
public ActionMenu(Message message) { | |
this.message = message; | |
} | |
public ActionMenu addButton(Button button) { | |
buttons.add(button); | |
return this; | |
} | |
public ActionMenu addAction(String reactionCode, Consumer<? super GenericMessageReactionEvent> action) { | |
return addButton(new ActionButton(reactionCode, action)); | |
} | |
@Override | |
protected List<Page> initializePages() { | |
return Collections.singletonList(this); | |
} | |
@Override | |
public Message getMessage() { | |
return message; | |
} | |
@Override | |
public List<Button> getButtons() { | |
return buttons; | |
} | |
private static final class ActionButton implements Button { | |
private final String code; | |
private final Consumer<? super GenericMessageReactionEvent> action; | |
private ActionButton(String code, Consumer<? super GenericMessageReactionEvent> action) { | |
this.code = code; | |
this.action = action; | |
} | |
@Override | |
public String getReaction() { | |
return code; | |
} | |
@Override | |
public Page onInteraction(Menu menu, GenericMessageReactionEvent event) { | |
action.accept(event); | |
return menu.getCurrentPage(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import net.dv8tion.jda.api.MessageBuilder; | |
import net.dv8tion.jda.api.entities.Message; | |
import net.dv8tion.jda.api.entities.MessageChannel; | |
import net.dv8tion.jda.api.entities.MessageEmbed; | |
import net.dv8tion.jda.api.events.GenericEvent; | |
import net.dv8tion.jda.api.events.message.MessageDeleteEvent; | |
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; | |
import net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent; | |
import net.dv8tion.jda.api.hooks.EventListener; | |
import net.dv8tion.jda.api.hooks.SubscribeEvent; | |
import org.jetbrains.annotations.NotNull; | |
import java.util.*; | |
import java.util.concurrent.ThreadLocalRandom; | |
import java.util.function.BiFunction; | |
import java.util.function.Consumer; | |
import java.util.function.Predicate; | |
public class Menu implements EventListener { | |
private final List<Page> pages; | |
private final String nonce = String.valueOf(ThreadLocalRandom.current().nextLong()); | |
private Page currentPage; | |
private long messageId = 0L; | |
private Predicate<? super GenericMessageReactionEvent> condition = (e) -> true; | |
public Menu() { | |
pages = initializePages(); | |
} | |
public Menu setCondition(Predicate<? super GenericMessageReactionEvent> condition) { | |
this.condition = condition; | |
return this; | |
} | |
public Menu setTargetUser(User user) { | |
long userId = user.getIdLong(); | |
return setCondition(event -> event.getUserIdLong() == userId); | |
} | |
public Menu addPage(Page page) { | |
pages.add(page); | |
return this; | |
} | |
public Page getHomePage() { | |
return pages.get(0); | |
} | |
public List<Page> getPages() { | |
return pages; | |
} | |
public Page getCurrentPage() { | |
return currentPage; | |
} | |
public long getMessageId() { | |
return messageId; | |
} | |
public void send(MessageChannel channel) { | |
Page homePage = getHomePage(); | |
currentPage = homePage; | |
channel.getJDA().addEventListener(this); | |
channel.sendMessage(homePage.getMessage()).nonce(nonce).queue(m -> { | |
messageId = m.getIdLong(); | |
homePage.getButtons().forEach(button -> m.addReaction(button.getReaction()).queue()); | |
}); | |
} | |
protected List<Page> initializePages() { | |
return new ArrayList<>(); | |
} | |
@Override | |
@SubscribeEvent | |
public void onEvent(@NotNull GenericEvent event) { | |
if (event instanceof MessageReceivedEvent) { | |
Message message = ((MessageReceivedEvent) event).getMessage(); | |
String messageNonce = message.getNonce(); | |
if (nonce.equals(messageNonce)) | |
messageId = message.getIdLong(); | |
} | |
else if (event instanceof MessageDeleteEvent) { | |
if (((MessageDeleteEvent) event).getMessageIdLong() == messageId) | |
event.getJDA().removeEventListener(this); | |
} | |
else if (event instanceof GenericMessageReactionEvent) { | |
onReaction((GenericMessageReactionEvent) event); | |
} | |
} | |
private void onReaction(GenericMessageReactionEvent event) { | |
if (event.getMessageIdLong() != messageId) return; | |
if (event.getUserIdLong() == event.getJDA().getSelfUser().getIdLong()) return; | |
if (!condition.test(event)) return; | |
String code = event.getReactionEmote().getAsReactionCode(); | |
currentPage.getButtons() | |
.stream() | |
.filter(b -> b.getReaction().equals(code)) | |
.findFirst() | |
.ifPresent(b -> { | |
currentPage = b.onInteraction(this, event); | |
if (currentPage == null) | |
event.getJDA().removeEventListener(this); | |
else | |
event.getChannel().editMessageById(messageId, currentPage.getMessage()).override(true).queue(); | |
}); | |
} | |
public static List<Button> getNavigationButtons() { | |
return Arrays.asList( | |
new HeadButton(), new PreviousButton(), | |
new NextButton(), new TailButton() | |
); | |
} | |
interface Page { | |
Message getMessage(); | |
List<Button> getButtons(); | |
static Page from(Message message, List<Button> buttons) { | |
return new BasicPage(message).addButtons(buttons); | |
} | |
} | |
interface Button { | |
String getReaction(); | |
Page onInteraction(Menu menu, GenericMessageReactionEvent event); | |
static Button from(String reactionCode, BiFunction<? super Menu, ? super GenericMessageReactionEvent, ? extends Page> action) { | |
return new BasicButton(reactionCode).setAction(action); | |
} | |
} | |
public static class BasicPage implements Page { | |
private final List<Button> buttons = new ArrayList<>(); | |
private final Message message; | |
public BasicPage(Message message) { | |
this.message = message; | |
} | |
@Override | |
public Message getMessage() { | |
return message; | |
} | |
@Override | |
public List<Button> getButtons() { | |
return buttons; | |
} | |
public BasicPage addButtons(Button... buttons) { | |
Collections.addAll(this.buttons, buttons); | |
return this; | |
} | |
public BasicPage addButtons(Collection<? extends Button> buttons) { | |
this.buttons.addAll(buttons); | |
return this; | |
} | |
} | |
public static class BasicButton implements Button { | |
private final String reaction; | |
private BiFunction<? super Menu, ? super GenericMessageReactionEvent, ? extends Page> action = (menu, event) -> menu.getCurrentPage(); | |
public BasicButton(String reaction) { | |
this.reaction = reaction; | |
} | |
@Override | |
public String getReaction() { | |
return reaction; | |
} | |
@Override | |
public Page onInteraction(Menu menu, GenericMessageReactionEvent event) { | |
return action.apply(menu, event); | |
} | |
public BasicButton setAction(BiFunction<? super Menu, ? super GenericMessageReactionEvent, ? extends Page> action) { | |
this.action = action; | |
return this; | |
} | |
} | |
/// Page that renders an embed | |
public static class EmbedPage extends BasicPage { | |
public EmbedPage(MessageEmbed embed) { | |
this(embed, getNavigationButtons()); | |
} | |
public EmbedPage(MessageEmbed embed, Collection<? extends Button> buttons) { | |
super(new MessageBuilder().setEmbed(embed).build()); | |
super.addButtons(buttons); | |
} | |
} | |
/// Jump to next page | |
public static class NextButton implements Button { | |
@Override | |
public String getReaction() { | |
return "▶️"; | |
} | |
@Override | |
public Page onInteraction(Menu menu, GenericMessageReactionEvent event) { | |
int current = menu.getPages().indexOf(menu.getCurrentPage()); | |
int next = (current + 1) % menu.getPages().size(); | |
return menu.getPages().get(next); | |
} | |
} | |
/// Jump to previous page | |
public static class PreviousButton implements Button { | |
@Override | |
public String getReaction() { | |
return "◀️"; | |
} | |
@Override | |
public Page onInteraction(Menu menu, GenericMessageReactionEvent event) { | |
int current = menu.getPages().indexOf(menu.getCurrentPage()); | |
int next = current - 1; | |
if (next < 0) | |
next = menu.getPages().size() + next; | |
return menu.getPages().get(next); | |
} | |
} | |
/// Jump to last page | |
public static class TailButton implements Button { | |
@Override | |
public String getReaction() { | |
return "⏭️"; | |
} | |
@Override | |
public Page onInteraction(Menu menu, GenericMessageReactionEvent event) { | |
return menu.getPages().get(menu.getPages().size() - 1); | |
} | |
} | |
/// Jump to first page | |
public static class HeadButton implements Button { | |
@Override | |
public String getReaction() { | |
return "⏮️"; | |
} | |
@Override | |
public Page onInteraction(Menu menu, GenericMessageReactionEvent event) { | |
return menu.getHomePage(); | |
} | |
} | |
/// Delete message | |
public static class DeleteButton implements Button { | |
@Override | |
public String getReaction() { | |
return "❌"; | |
} | |
@Override | |
public Page onInteraction(Menu menu, GenericMessageReactionEvent event) { | |
event.getChannel().deleteMessageById(event.getMessageId()).queue(); | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment