Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
Expand All @@ -11,6 +12,8 @@
import net.dv8tion.jda.api.entities.emoji.EmojiUnion;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle;
Expand All @@ -21,6 +24,8 @@
import net.javadiscord.javabot.data.config.guild.HelpConfig;
import net.javadiscord.javabot.util.Pair;
import net.javadiscord.javabot.util.Responses;
import net.javadiscord.javabot.util.StringUtils;

import org.jetbrains.annotations.NotNull;
import xyz.dynxsty.dih4jda.interactions.commands.application.SlashCommand;
import xyz.dynxsty.dih4jda.interactions.components.ButtonHandler;
Expand Down Expand Up @@ -55,7 +60,8 @@ public class HelpPingSubcommand extends SlashCommand.Subcommand implements Butto
* @param botConfig The main configuration of the bot
*/
public HelpPingSubcommand(BotConfig botConfig, ScheduledExecutorService asyncPool) {
setCommandData(new SubcommandData("ping", "Notify potential helpers that your question is urgent."));
setCommandData(new SubcommandData("ping", "Notify potential helpers that your question is urgent.")
.addOption(OptionType.STRING, "comment", "Optionally enter the reason you used this to be seen by helpers (e.g. 'no response')", false));
lastPingTimes = new ConcurrentHashMap<>();
this.botConfig = botConfig;
asyncPool.scheduleWithFixedDelay(this::cleanTimeoutCache, CACHE_CLEANUP_DELAY, CACHE_CLEANUP_DELAY, TimeUnit.SECONDS);
Expand Down Expand Up @@ -89,32 +95,19 @@ public void execute(@NotNull SlashCommandInteractionEvent event) {
Responses.warning(event, "Sorry, this command cannot be used directly after a post has been created.").queue();
return;
}

String comment = event.getOption("comment", null, OptionMapping::getAsString);

if (isHelpPingTimeoutElapsed(member.getIdLong(), config)) {
lastPingTimes.put(event.getMember().getIdLong(), new Pair<>(System.currentTimeMillis(), config.getGuild()));
TextChannel notifChannel = config.getHelpConfig().getHelpNotificationChannel();
notifChannel.sendMessageEmbeds(new EmbedBuilder().setDescription("""
%s requested help in %s

Tags:
%s

[Click to view](%s)
"""
.formatted(
event.getUser().getAsMention(),
post.getAsMention(),
getTagString(post),
post.getJumpUrl()
))
.setAuthor(member.getEffectiveName(), null, member.getEffectiveAvatarUrl())
.setFooter(event.getUser().getId())
.setColor(Color.YELLOW)
.build())
.addActionRow(createAcknowledgementButton())

notifChannel.sendMessageEmbeds(createHelpEmbed(comment, post, member))
.addActionRow(createAcknowledgementButton(post.getId()))
.queue();
event.reply("""
Successfully requested help.

Note that this does NOT gurantee that anybody here has the time and knowledge to help you.
Abusing this command might result in moderative action taken against you.
""")
Expand All @@ -125,25 +118,54 @@ public void execute(@NotNull SlashCommandInteractionEvent event) {
}
}

private String getTagString(ThreadChannel post) {
String text = post
.getAppliedTags()
.stream()
.map(this::getForumTagText)
.map(tag -> "- " + tag)
.collect(Collectors.joining("\n"));
if(text.isEmpty()) {
text = "- <no tags>";
private MessageEmbed createHelpEmbed(String comment, ThreadChannel post, Member member) {
EmbedBuilder eb = createBasicHelpEmbedBuilder(post, member);
appendComment(eb, comment);
appendTags(eb, post);
eb.appendDescription("\n\n[Click to view]("+post.getJumpUrl()+")");
return eb.build();
}

private EmbedBuilder createBasicHelpEmbedBuilder(ThreadChannel post, Member member) {
EmbedBuilder eb = new EmbedBuilder()
.setDescription("%s requested help in %s"
.formatted(
member.getAsMention(),
post.getAsMention()
))
.setAuthor(member.getEffectiveName(), null, member.getEffectiveAvatarUrl())
.setFooter(member.getId())
.setColor(Color.YELLOW);
return eb;
}

private void appendTags(EmbedBuilder eb, ThreadChannel post) {
List<ForumTag> tags = post.getAppliedTags();
if (!tags.isEmpty()) {
String text = tags
.stream()
.map(this::getForumTagText)
.map(tag -> "- " + tag)
.collect(Collectors.joining("\n"));
eb.appendDescription("\n\nTags:\n")
.appendDescription(text);
}
return text;
}

private Button createAcknowledgementButton() {
return Button.of(ButtonStyle.SECONDARY, ComponentIdBuilder.build("help-ping", "acknowledge"), "Mark as acknowledged");
private void appendComment(EmbedBuilder eb, String comment) {
if (comment != null) {
eb
.appendDescription("\n\ncomment:\n")
.appendDescription("```\n"+StringUtils.standardSanitizer().compute(comment) + "\n```");
}
}

private Button createUndoAcknowledgementButton() {
return Button.of(ButtonStyle.SECONDARY, ComponentIdBuilder.build("help-ping", "unacknowledge"), "Mark as unacknowledged");

private Button createAcknowledgementButton(String postId) {
return Button.of(ButtonStyle.SECONDARY, ComponentIdBuilder.build("help-ping", "acknowledge", postId), "Mark as acknowledged");
}

private Button createUndoAcknowledgementButton(String postId) {
return Button.of(ButtonStyle.SECONDARY, ComponentIdBuilder.build("help-ping", "unacknowledge", postId), "Mark as unacknowledged");
}

/**
Expand Down Expand Up @@ -199,17 +221,40 @@ private void cleanTimeoutCache() {
@Override
public void handleButton(ButtonInteractionEvent event, Button button) {
String[] id = ComponentIdBuilder.split(event.getComponentId());
String postId = "";
if (id.length > 2) {
postId = id[2];
}
switch(id[1]) {
case "acknowledge" ->
acknowledgeChangeAction(event, true);
case "unacknowledge" ->
acknowledgeChangeAction(event, false);
acknowledgeChangeAction(event, postId, true);
case "unacknowledge" ->
handleUnacknowledge(event, postId);
default -> event.reply("Unknown button").setEphemeral(true).queue();
}

}

private void acknowledgeChangeAction(ButtonInteractionEvent event, boolean acknowledged) {
private void handleUnacknowledge(ButtonInteractionEvent event, String postId) {
if (postId.isEmpty() || isPostOpen(event.getGuild(), postId)) {
acknowledgeChangeAction(event, postId, false);
} else {
Responses.error(event, """
This post is closed or dormant.
If this post is dormant, you can mark it as active by sending a message in the post.
If it is closed and you still need help, please create a new post.
""").queue();
}
}

private boolean isPostOpen(Guild guild, String postId) {
ThreadChannel post = guild.getThreadChannelById(postId);
return post != null &&
post.getParentChannel().getIdLong() == botConfig.get(guild).getHelpConfig().getHelpForumChannelId() &&
!post.isArchived() &&
!post.isLocked();
}

private void acknowledgeChangeAction(ButtonInteractionEvent event, String postId, boolean acknowledged) {
event.editMessageEmbeds(
event.getMessage()
.getEmbeds()
Expand All @@ -221,10 +266,10 @@ private void acknowledgeChangeAction(ButtonInteractionEvent event, boolean ackno
.map(this::removeOldField)
.map(EmbedBuilder::build)
.toList())
.setActionRow(acknowledged?createUndoAcknowledgementButton():createAcknowledgementButton())
.setActionRow(acknowledged?createUndoAcknowledgementButton(postId):createAcknowledgementButton(postId))
.queue();
}

private String getCurrentFormattedTimestamp() {
return TimeFormat.RELATIVE.format(Instant.now().toEpochMilli());
}
Expand All @@ -238,7 +283,7 @@ private String getForumTagText(ForumTag tag) {
.append(" ");
}
sb.append(tag.getName());

return sb.toString();
}

Expand Down