1010import net .dv8tion .jda .api .entities .channel .concrete .TextChannel ;
1111import net .dv8tion .jda .api .events .interaction .ModalInteractionEvent ;
1212import net .dv8tion .jda .api .events .interaction .command .MessageContextInteractionEvent ;
13+ import net .dv8tion .jda .api .events .interaction .component .ButtonInteractionEvent ;
1314import net .dv8tion .jda .api .interactions .InteractionHook ;
1415import net .dv8tion .jda .api .interactions .commands .build .Commands ;
1516import net .dv8tion .jda .api .interactions .components .buttons .Button ;
2526import org .togetherjava .tjbot .features .BotCommandAdapter ;
2627import org .togetherjava .tjbot .features .CommandVisibility ;
2728import org .togetherjava .tjbot .features .MessageContextCommand ;
29+ import org .togetherjava .tjbot .features .componentids .Lifespan ;
2830import org .togetherjava .tjbot .features .utils .MessageUtils ;
2931
3032import java .awt .Color ;
3638import java .util .concurrent .TimeUnit ;
3739import java .util .function .Predicate ;
3840import java .util .regex .Pattern ;
41+ import java .util .stream .Collectors ;
3942
4043/**
4144 * Implements the /report command, which allows users to report a selected offensive message from
@@ -53,15 +56,19 @@ public final class ReportCommand extends BotCommandAdapter implements MessageCon
5356 private final Predicate <String > modMailChannelNamePredicate ;
5457 private final Predicate <String > configModGroupPattern ;
5558 private final String configModMailChannelPattern ;
59+ private final ModerationActionsStore moderationActionsStore ;
5660
5761 /**
5862 * Creates a new instance.
5963 *
6064 * @param config to get the channel to forward reports to
65+ * @param moderationActionsStore to get the required information of the reported user
6166 */
62- public ReportCommand (Config config ) {
67+ public ReportCommand (Config config , ModerationActionsStore moderationActionsStore ) {
6368 super (Commands .message (COMMAND_NAME ), CommandVisibility .GUILD );
6469
70+ this .moderationActionsStore = Objects .requireNonNull (moderationActionsStore );
71+
6572 modMailChannelNamePredicate =
6673 Pattern .compile (config .getModMailChannelPattern ()).asMatchPredicate ();
6774
@@ -182,9 +189,12 @@ private MessageCreateAction createModMessage(String reportReason,
182189 .setColor (AMBIENT_COLOR )
183190 .build ();
184191
192+ String historyButtonId = generateComponentId (Lifespan .PERMANENT , reportedMessage .authorID );
193+
185194 MessageCreateAction message =
186195 modMailAuditLog .sendMessageEmbeds (reportedMessageEmbed , reportReasonEmbed )
187- .addActionRow (Button .link (reportedMessage .jumpUrl , "Go to message" ));
196+ .addActionRow (Button .link (reportedMessage .jumpUrl , "Go to message" ),
197+ Button .primary (historyButtonId , "View user history" ));
188198
189199 Optional <Role > moderatorRole = guild .getRoles ()
190200 .stream ()
@@ -222,7 +232,7 @@ private static String createUserReply(Result<Message> result) {
222232 }
223233
224234 private record ReportedMessage (String content , String id , String jumpUrl , String channelID ,
225- Instant timestamp , String authorName , String authorAvatarUrl ) {
235+ Instant timestamp , String authorName , String authorAvatarUrl , String authorID ) {
226236 static ReportedMessage ofArgs (List <String > args ) {
227237 String content = args .getFirst ();
228238 String id = args .get (1 );
@@ -231,8 +241,47 @@ static ReportedMessage ofArgs(List<String> args) {
231241 Instant timestamp = Instant .parse (args .get (4 ));
232242 String authorName = args .get (5 );
233243 String authorAvatarUrl = args .get (6 );
244+ String authorID = args .get (7 );
234245 return new ReportedMessage (content , id , jumpUrl , channelID , timestamp , authorName ,
235- authorAvatarUrl );
246+ authorAvatarUrl , authorID );
247+ }
248+ }
249+
250+ @ Override
251+ public void onButtonClick (ButtonInteractionEvent event , List <String > args ) {
252+ if (args .isEmpty ()) {
253+ event .reply ("Error: Target user context lost" ).setEphemeral (true ).queue ();
254+ return ;
255+ }
256+
257+ long guildId = Objects .requireNonNull (event .getGuild ()).getIdLong ();
258+ long targetUserId = Long .parseLong (args .getFirst ());
259+
260+ List <ActionRecord > actions =
261+ moderationActionsStore .getActionsByTargetAscending (guildId , targetUserId );
262+
263+ EmbedBuilder embedBuilder = new EmbedBuilder ()
264+ .setTitle ("Moderation History for User (ID: " + targetUserId + ")" )
265+ .setColor (Color .ORANGE )
266+ .setTimestamp (Instant .now ());
267+
268+ if (actions .isEmpty ()) {
269+ embedBuilder .setDescription ("No mutes, warnings, or punishments found." );
270+ } else {
271+ String historyContent = actions .stream ()
272+ .map (action -> String .format (
273+ "• **%s** (Case #%d) - Reason: *%s* (Issued: <t:%d:R>)" ,
274+ action .actionType (), action .caseId (),
275+ MessageUtils .abbreviate (action .reason (), 100 ),
276+ action .issuedAt ().getEpochSecond ()))
277+ .collect (Collectors .joining ("\n " ));
278+
279+ embedBuilder .setDescription (
280+ MessageUtils .abbreviate (historyContent , MessageEmbed .DESCRIPTION_MAX_LENGTH ));
236281 }
282+
283+ event .replyEmbeds (embedBuilder .build ()).setEphemeral (true ).queue ();
284+
237285 }
286+
238287}
0 commit comments