Skip to content

Commit dc702a1

Browse files
authored
Merge pull request #90 from TheCurle/3.0-improved-help
Improve help command with embeds and pagination.
2 parents bf972d3 + bdc4e31 commit dc702a1

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed

src/main/java/com/mcmoddev/mmdbot/modules/commands/CommandModule.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.jagrosh.jdautilities.command.CommandClientBuilder;
2626
import com.mcmoddev.mmdbot.MMDBot;
2727
import com.mcmoddev.mmdbot.modules.commands.bot.info.CmdAbout;
28+
import com.mcmoddev.mmdbot.modules.commands.bot.info.CmdHelp;
2829
import com.mcmoddev.mmdbot.modules.commands.bot.info.CmdUptime;
2930
import com.mcmoddev.mmdbot.modules.commands.bot.management.CmdAvatar;
3031
import com.mcmoddev.mmdbot.modules.commands.bot.management.CmdRename;
@@ -88,6 +89,7 @@ public static void setupCommandModule() {
8889
.setOwnerId(MMDBot.getConfig().getOwnerID())
8990
.setPrefix(MMDBot.getConfig().getMainPrefix())
9091
.setAlternativePrefix(MMDBot.getConfig().getAlternativePrefix())
92+
.setHelpConsumer(CmdHelp::execute)
9193
.addCommand(new CmdGuild())
9294
.addCommand(new CmdAbout())
9395
.addCommand(new CmdMe())
@@ -131,6 +133,7 @@ public static void setupCommandModule() {
131133
MMDBot.getInstance().addEventListener(CmdTranslateMappings.ButtonListener.INSTANCE);
132134
MMDBot.getInstance().addEventListener(new CmdListTricks.ButtonListener());
133135
MMDBot.getInstance().addEventListener(new CmdListQuotes.ButtonListener());
136+
MMDBot.getInstance().addEventListener(new CmdHelp.ButtonListener());
134137
MMDBot.LOGGER.warn("Command module enabled and loaded.");
135138
} else {
136139
MMDBot.LOGGER.warn("Command module disabled via config, commands will not work at this time!");
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* MMDBot - https://github.com/MinecraftModDevelopment/MMDBot
3+
* Copyright (C) 2016-2021 <MMD - MinecraftModDevelopment>
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18+
* USA
19+
* https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
20+
*/
21+
package com.mcmoddev.mmdbot.modules.commands.bot.info;
22+
23+
import com.jagrosh.jdautilities.command.Command;
24+
import com.jagrosh.jdautilities.command.CommandEvent;
25+
import com.mcmoddev.mmdbot.MMDBot;
26+
import com.mcmoddev.mmdbot.core.References;
27+
import com.mcmoddev.mmdbot.modules.commands.CommandModule;
28+
import net.dv8tion.jda.api.EmbedBuilder;
29+
import net.dv8tion.jda.api.entities.Emoji;
30+
import net.dv8tion.jda.api.events.interaction.ButtonClickEvent;
31+
import net.dv8tion.jda.api.hooks.ListenerAdapter;
32+
import net.dv8tion.jda.api.interactions.components.Button;
33+
import net.dv8tion.jda.api.interactions.components.Component;
34+
import net.dv8tion.jda.api.requests.restaction.MessageAction;
35+
import org.jetbrains.annotations.NotNull;
36+
37+
import java.time.Instant;
38+
import java.util.ArrayList;
39+
import java.util.List;
40+
41+
/**
42+
* This command doesn't use the normal syntax.
43+
* Instead, it provides a single Consumer<CommandEvent> that the CommandClient can use.
44+
*
45+
* This should not be turned into a normal Command.
46+
*
47+
* @author Curle
48+
*/
49+
public class CmdHelp {
50+
51+
private static final int COMMANDS_PER_PAGE = 25;
52+
53+
/**
54+
* Prepare the potential scrolling buttons for a help command,
55+
* and send the message with the proper embeds.
56+
*
57+
* See {@link #getHelpStartingAt(int)} for the implementation.
58+
* @param e
59+
*/
60+
public static void execute(CommandEvent e) {
61+
MessageAction reply = e.getChannel().sendMessageEmbeds(getHelpStartingAt(0).build());
62+
Component[] buttons = createScrollButtons(0);
63+
if (buttons.length > 0)
64+
reply.setActionRow(buttons);
65+
66+
reply.queue();
67+
}
68+
69+
/**
70+
* Create the row of Component interaction buttons.
71+
* <p>
72+
* Currently, this just creates a left and right arrow.
73+
* Left arrow scrolls back a page. Right arrow scrolls forward a page.
74+
*
75+
* @param start The quote number at the start of the current page.
76+
* @return A row of buttons to go back and forth by one page in a quote list.
77+
*/
78+
private static Component[] createScrollButtons(int start) {
79+
List<Component> components = new ArrayList<>();
80+
if (start != 0) {
81+
components.add(Button.secondary(ButtonListener.BUTTON_ID_PREFIX + "-" + start + "-prev",
82+
Emoji.fromUnicode("◀️")));
83+
}
84+
if (start + COMMANDS_PER_PAGE < CommandModule.getCommandClient().getCommands().size() + CommandModule.getCommandClient().getSlashCommands().size()) {
85+
components.add(Button.primary(ButtonListener.BUTTON_ID_PREFIX + "-" + start + "-next",
86+
Emoji.fromUnicode("▶️")));
87+
}
88+
return components.toArray(new Component[0]);
89+
}
90+
91+
/**
92+
* Given a starting index, build an embed that we can display for users
93+
* to summarise all available commands.
94+
* Intended to be used with pagination in the case of servers with LOTS of commands.
95+
*/
96+
private static EmbedBuilder getHelpStartingAt(int index) {
97+
EmbedBuilder embed = new EmbedBuilder();
98+
embed.setAuthor(References.NAME, References.ISSUE_TRACKER, MMDBot.getInstance().getSelfUser().getAvatarUrl());
99+
embed.setDescription("All registered commands:");
100+
101+
List<Command> commandList = CommandModule.getCommandClient().getCommands();
102+
commandList.addAll(CommandModule.getCommandClient().getSlashCommands());
103+
104+
// Embeds have a 25 field limit. We need to make sure we don't exceed that.
105+
if(commandList.size() < 25) {
106+
for (Command c : commandList)
107+
embed.addField(c.getName(), c.getHelp(), true);
108+
} else {
109+
// Make sure we only go up to the limit.
110+
for (int i = index; i < index + 25; i++)
111+
if (i < commandList.size())
112+
embed.addField(commandList.get(i).getName(), commandList.get(i).getHelp(), true);
113+
}
114+
115+
embed.setFooter(References.NAME).setTimestamp(Instant.now());
116+
117+
return embed;
118+
}
119+
120+
public static class ButtonListener extends ListenerAdapter {
121+
private static final String BUTTON_ID_PREFIX = "help";
122+
123+
@Override
124+
public void onButtonClick(@NotNull final ButtonClickEvent event) {
125+
var button = event.getButton();
126+
if (button == null || button.getId() == null) {
127+
return;
128+
}
129+
130+
String[] idParts = button.getId().split("-");
131+
if (idParts.length != 3) {
132+
return;
133+
}
134+
135+
if (!idParts[0].equals(BUTTON_ID_PREFIX)) {
136+
return;
137+
}
138+
139+
int current = Integer.parseInt(idParts[1]);
140+
141+
if (idParts[2].equals("next")) {
142+
event
143+
.editMessageEmbeds(getHelpStartingAt(current + COMMANDS_PER_PAGE).build())
144+
.setActionRow(createScrollButtons(current + COMMANDS_PER_PAGE))
145+
.queue();
146+
} else {
147+
if (idParts[2].equals("prev")) {
148+
event
149+
.editMessageEmbeds(getHelpStartingAt(current - COMMANDS_PER_PAGE).build())
150+
.setActionRow(createScrollButtons(current - COMMANDS_PER_PAGE))
151+
.queue();
152+
}
153+
}
154+
}
155+
}
156+
}
157+

0 commit comments

Comments
 (0)