Skip to content

Commit 148f7d0

Browse files
committed
feat: overhaul reporting
1 parent 746ee4a commit 148f7d0

File tree

4 files changed

+194
-65
lines changed

4 files changed

+194
-65
lines changed

src/main/java/com/diamondfire/helpbot/bot/events/MessageEvent.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
public class MessageEvent extends ListenerAdapter {
1010

1111
private static final MessageAcceptor[] acceptors = {
12-
new ReportAndFeatureApplicationAcceptor(),
1312
new FilterAcceptor(),
1413
new CommandAcceptor(),
1514
new TagAcceptor(),

src/main/java/com/diamondfire/helpbot/bot/events/ReadyEvent.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.diamondfire.helpbot.bot.HelpBotInstance;
44
import com.diamondfire.helpbot.bot.restart.RestartHandler;
5+
import com.diamondfire.helpbot.sys.report.ReportListener;
56
import com.diamondfire.helpbot.sys.rolereact.RoleReactListener;
67
import net.dv8tion.jda.api.hooks.ListenerAdapter;
78
import org.jetbrains.annotations.NotNull;
@@ -13,6 +14,6 @@ public void onReady(@NotNull net.dv8tion.jda.api.events.session.ReadyEvent event
1314
RestartHandler.recover(event.getJDA());
1415
HelpBotInstance.getScheduler().initialize();
1516

16-
event.getJDA().addEventListener(new RoleReactListener());
17+
event.getJDA().addEventListener(new RoleReactListener(), new ReportListener());
1718
}
1819
}

src/main/java/com/diamondfire/helpbot/sys/message/acceptors/ReportAndFeatureApplicationAcceptor.java

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package com.diamondfire.helpbot.sys.report;
2+
3+
import club.minnced.discord.webhook.WebhookClient;
4+
import club.minnced.discord.webhook.external.JDAWebhookClient;
5+
import club.minnced.discord.webhook.send.*;
6+
import com.diamondfire.helpbot.bot.HelpBotInstance;
7+
import com.diamondfire.helpbot.util.*;
8+
import net.dv8tion.jda.api.EmbedBuilder;
9+
import net.dv8tion.jda.api.components.actionrow.ActionRow;
10+
import net.dv8tion.jda.api.components.attachmentupload.AttachmentUpload;
11+
import net.dv8tion.jda.api.components.buttons.Button;
12+
import net.dv8tion.jda.api.components.label.Label;
13+
import net.dv8tion.jda.api.components.textdisplay.TextDisplay;
14+
import net.dv8tion.jda.api.components.textinput.*;
15+
import net.dv8tion.jda.api.entities.*;
16+
import net.dv8tion.jda.api.entities.emoji.Emoji;
17+
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
18+
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
19+
import net.dv8tion.jda.api.hooks.ListenerAdapter;
20+
import net.dv8tion.jda.api.interactions.modals.*;
21+
import net.dv8tion.jda.api.modals.Modal;
22+
import org.jetbrains.annotations.NotNull;
23+
24+
import java.awt.*;
25+
import java.net.URL;
26+
import java.util.*;
27+
import java.util.List;
28+
import java.util.concurrent.*;
29+
30+
public class ReportListener extends ListenerAdapter {
31+
32+
private static final ExecutorService SERVICE = Executors.newCachedThreadPool();
33+
34+
private static final long MESSAGE_ID = 1433051440410136659L;
35+
private static final long CHANNEL_ID = 849769323166040124L;
36+
private static final long NO_REPORTS_ROLE_ID = 345024090211483648L;
37+
38+
private static final String BUTTON_ID = "create-report";
39+
private static final String USERNAME_FIELD_ID = "username";
40+
private static final String RULE_BROKEN_FIELD_ID = "rule-broken";
41+
private static final String PROOF_FIELD_ID = "proof";
42+
private static final String REPORT_MODAL_FIELD_ID = "report";
43+
44+
public ReportListener() {
45+
if (HelpBotInstance.getConfig().isDevBot()) {
46+
return;
47+
}
48+
49+
HelpBotInstance.getJda().getTextChannelById(CHANNEL_ID).retrieveMessageById(MESSAGE_ID).queue((msg) -> {
50+
51+
Button button = Button.secondary(BUTTON_ID, "Create Report")
52+
.withEmoji(Emoji.fromUnicode("\uD83D\uDEA9")); // 🚩
53+
54+
EmbedBuilder embed = new EmbedBuilder();
55+
embed.setTitle("Reporting");
56+
embed.setDescription("""
57+
Welcome to the reports channel! This is the place where you report rulebreakers. Before you get to that, let's lay down the rules.
58+
59+
1. Use your common sense - don't break server rules.
60+
2. Only report a player if they have legitimately broken a rule.
61+
3. Do not make joke reports.
62+
63+
Breaking these rules may result in the inability to post reports to the reports channel, restricted permissions on Discord, or a Discord server mute.
64+
""");
65+
embed.setColor(0x05E076);
66+
67+
msg.editMessage("")
68+
.setEmbeds(List.of(
69+
embed.build()
70+
))
71+
.setComponents(ActionRow.of(button))
72+
.queue();
73+
});
74+
}
75+
76+
77+
@Override
78+
public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
79+
if (!BUTTON_ID.equals(event.getComponentId())) {
80+
return;
81+
}
82+
83+
Member member = event.getMember();
84+
if (member.getRoles().contains(event.getGuild().getRoleById(NO_REPORTS_ROLE_ID))) {
85+
event.reply(":x: You're currently blocked from making reports").setEphemeral(true).queue();
86+
return;
87+
}
88+
89+
/*
90+
Username of rule breaker:
91+
Rule broken:
92+
Proof (uncropped screenshot):
93+
*/
94+
95+
TextDisplay body = TextDisplay.of("""
96+
**Thank you for helping keep DiamondFire safe!**
97+
* Multiple proofs are allowed.
98+
* Proofs can be both **videos and screenshots**.
99+
* Uploaded screenshots should be **uncropped**
100+
> Meaning, take a __full screenshot__ of your screen.
101+
* Make sure reports are made in **good faith with valid proof**.
102+
""");
103+
104+
TextInput username = TextInput.create(USERNAME_FIELD_ID, TextInputStyle.SHORT)
105+
.setPlaceholder("Minecraft Username")
106+
.setRequiredRange(3, 16)
107+
.setRequired(true)
108+
.build();
109+
110+
TextInput ruleBroken = TextInput.create(RULE_BROKEN_FIELD_ID, TextInputStyle.PARAGRAPH)
111+
.setPlaceholder("Which rule did they break?")
112+
.setRequired(true)
113+
.build();
114+
115+
AttachmentUpload proof = AttachmentUpload.create(PROOF_FIELD_ID)
116+
.setMinValues(1)
117+
.setMaxValues(10)
118+
.setRequired(true)
119+
.build();
120+
121+
Modal modal = Modal.create(REPORT_MODAL_FIELD_ID, "Report")
122+
.addComponents(body, Label.of("Username of Rule Breaker", username), Label.of("Rule Broken", ruleBroken), Label.of("Proof (uncropped)", proof))
123+
.build();
124+
125+
event.replyModal(modal).queue();
126+
}
127+
128+
129+
@Override
130+
public void onModalInteraction(ModalInteractionEvent event) {
131+
if (!REPORT_MODAL_FIELD_ID.equals(event.getModalId())) {
132+
return;
133+
}
134+
135+
String username = getValue(event, USERNAME_FIELD_ID).getAsString();
136+
String message = getValue(event, RULE_BROKEN_FIELD_ID).getAsString();
137+
List<Message.Attachment> proofs = getValue(event, PROOF_FIELD_ID).getAsAttachmentList();
138+
139+
final var webhookUrl = HelpBotInstance.getConfig().getForwardingChannels().get("" + CHANNEL_ID);
140+
if (webhookUrl == null) {
141+
event.reply(":x: Internal error").queue();
142+
}
143+
144+
SERVICE.submit(() -> {
145+
try (WebhookClient client = JDAWebhookClient.withUrl(webhookUrl.getAsString())) {
146+
boolean tooLong = message.length() > 2000;
147+
String content = tooLong ? "See content.txt for message (too long)" : message;
148+
149+
WebhookMessageBuilder builder = new WebhookMessageBuilder()
150+
.setContent(String.format("""
151+
**Offender**: %s
152+
**Rule Broken**:
153+
%s
154+
""", username, content))
155+
.setAllowedMentions(AllowedMentions.none())
156+
.setUsername(event.getMember().getEffectiveName())
157+
.setAvatarUrl(event.getUser().getEffectiveAvatarUrl());
158+
159+
for (Message.Attachment attachment : proofs) {
160+
URL url = new URL(attachment.getProxyUrl());
161+
builder.addFile(attachment.getFileName(), url.openStream().readAllBytes());
162+
}
163+
if (tooLong) {
164+
builder.addFile("content.txt", message.getBytes());
165+
}
166+
167+
System.out.println("Sending to webhook");
168+
client.send(builder.build()).whenComplete((msg, exception) -> {
169+
if (exception != null) exception.printStackTrace();
170+
if (exception != null) {
171+
event.reply(":x: Uh oh! An error occurred while submitting your report. Please try resending it later.").setEphemeral(true).queue();
172+
} else {
173+
event.reply(":mega: Your report has been successfully submitted!").setEphemeral(true).queue();
174+
}
175+
});
176+
} catch (Throwable ignored) {
177+
ignored.printStackTrace();
178+
}
179+
});
180+
181+
}
182+
183+
private ModalMapping getValue(ModalInteraction event, String customId) {
184+
// Instead of event#getValue since it returns null when not found,
185+
// we just assume the components always exist as we already confirm
186+
// it's the report modal.
187+
return event.getValues().stream()
188+
.filter(mapping -> mapping.getCustomId().equals(customId))
189+
.findFirst().orElseThrow();
190+
}
191+
192+
}

0 commit comments

Comments
 (0)