11package org .togetherjava .tjbot .features .help ;
22
33import net .dv8tion .jda .api .EmbedBuilder ;
4- import net .dv8tion .jda .api .entities .Guild ;
5- import net .dv8tion .jda .api .entities .Message ;
6- import net .dv8tion .jda .api .entities .MessageEmbed ;
7- import net .dv8tion .jda .api .entities .Role ;
4+ import net .dv8tion .jda .api .entities .*;
85import net .dv8tion .jda .api .entities .channel .attribute .IThreadContainer ;
96import net .dv8tion .jda .api .entities .channel .concrete .ForumChannel ;
107import net .dv8tion .jda .api .entities .channel .concrete .ThreadChannel ;
118import net .dv8tion .jda .api .entities .channel .forums .ForumTag ;
129import net .dv8tion .jda .api .entities .channel .forums .ForumTagSnowflake ;
1310import net .dv8tion .jda .api .entities .channel .middleman .GuildChannel ;
1411import net .dv8tion .jda .api .entities .channel .middleman .GuildMessageChannel ;
12+ import net .dv8tion .jda .api .interactions .components .buttons .Button ;
1513import net .dv8tion .jda .api .requests .RestAction ;
1614import net .dv8tion .jda .api .requests .restaction .MessageCreateAction ;
1715import net .dv8tion .jda .api .utils .FileUpload ;
2624import org .togetherjava .tjbot .db .generated .tables .records .HelpThreadsRecord ;
2725import org .togetherjava .tjbot .features .chatgpt .ChatGptCommand ;
2826import org .togetherjava .tjbot .features .chatgpt .ChatGptService ;
27+ import org .togetherjava .tjbot .features .componentids .ComponentIdInteractor ;
2928
3029import javax .annotation .Nullable ;
3130
4039import java .util .Map ;
4140import java .util .Optional ;
4241import java .util .Set ;
42+ import java .util .concurrent .CopyOnWriteArrayList ;
4343import java .util .function .Consumer ;
4444import java .util .function .Function ;
4545import java .util .function .Predicate ;
@@ -59,6 +59,7 @@ public final class HelpSystemHelper {
5959
6060 private static final String CODE_SYNTAX_EXAMPLE_PATH = "codeSyntaxExample.png" ;
6161
62+ private final Predicate <String > hasTagManageRole ;
6263 private final Predicate <String > isHelpForumName ;
6364 private final String helpForumPattern ;
6465 /**
@@ -88,6 +89,7 @@ public HelpSystemHelper(Config config, Database database, ChatGptService chatGpt
8889 this .database = database ;
8990 this .chatGptService = chatGptService ;
9091
92+ hasTagManageRole = Pattern .compile (config .getTagManageRolePattern ()).asMatchPredicate ();
9193 helpForumPattern = helpConfig .getHelpForumPattern ();
9294 isHelpForumName = Pattern .compile (helpForumPattern ).asMatchPredicate ();
9395
@@ -161,7 +163,7 @@ private RestAction<Message> sendExplanationMessage(GuildMessageChannel threadCha
161163 * why the message wasn't used.
162164 */
163165 RestAction <Message > constructChatGptAttempt (ThreadChannel threadChannel ,
164- String originalQuestion ) {
166+ String originalQuestion , ComponentIdInteractor componentIdInteractor ) {
165167 Optional <String > questionOptional = prepareChatGptQuestion (threadChannel , originalQuestion );
166168 Optional <String []> chatGPTAnswer ;
167169
@@ -176,22 +178,39 @@ RestAction<Message> constructChatGptAttempt(ThreadChannel threadChannel,
176178 return useChatGptFallbackMessage (threadChannel );
177179 }
178180
181+ List <String > ids = new CopyOnWriteArrayList <>();
179182 RestAction <Message > message =
180183 mentionGuildSlashCommand (threadChannel .getGuild (), ChatGptCommand .COMMAND_NAME )
181184 .map ("""
182185 Here is an AI assisted attempt to answer your question 🤖. Maybe it helps! \
183186 In any case, a human is on the way 👍. To continue talking to the AI, you can use \
184187 %s.
185188 """ ::formatted )
186- .flatMap (threadChannel ::sendMessage );
189+ .flatMap (threadChannel ::sendMessage )
190+ .onSuccess (m -> ids .add (m .getId ()));
191+ String [] answers = chatGPTAnswer .orElseThrow ();
192+
193+ for (int i = 0 ; i < answers .length ; i ++) {
194+ MessageCreateAction answer = threadChannel .sendMessage (answers [i ]);
195+
196+ if (i == answers .length - 1 ) {
197+ message = message .flatMap (any -> answer
198+ .addActionRow (generateDismissButton (componentIdInteractor , ids )));
199+ continue ;
200+ }
187201
188- for (String aiResponse : chatGPTAnswer .get ()) {
189- message = message .map (aiResponse ::formatted ).flatMap (threadChannel ::sendMessage );
202+ message = message .flatMap (ignored -> answer .onSuccess (m -> ids .add (m .getId ())));
190203 }
191204
192205 return message ;
193206 }
194207
208+ private Button generateDismissButton (ComponentIdInteractor componentIdInteractor ,
209+ List <String > ids ) {
210+ String buttonId = componentIdInteractor .generateComponentId (ids .toArray (String []::new ));
211+ return Button .danger (buttonId , "Dismiss" );
212+ }
213+
195214 private Optional <String > prepareChatGptQuestion (ThreadChannel threadChannel ,
196215 String originalQuestion ) {
197216 String questionTitle = threadChannel .getName ();
@@ -344,6 +363,10 @@ private static ForumTag requireTag(String tagName, ForumChannel forumChannel) {
344363 return matchingTags .get (0 );
345364 }
346365
366+ boolean hasTagManageRole (Member member ) {
367+ return member .getRoles ().stream ().map (Role ::getName ).anyMatch (hasTagManageRole );
368+ }
369+
347370 boolean isHelpForumName (String channelName ) {
348371 return isHelpForumName .test (channelName );
349372 }
0 commit comments