1- package de .cerus .jdasc ;
1+ package dev .cerus .jdasc ;
22
33import com .google .gson .JsonArray ;
44import com .google .gson .JsonElement ;
55import com .google .gson .JsonObject ;
66import com .google .gson .JsonParser ;
7- import de .cerus .jdasc .command .ApplicationCommand ;
8- import de .cerus .jdasc .command .ApplicationCommandListener ;
9- import de .cerus .jdasc .command .ApplicationCommandOption ;
10- import de .cerus .jdasc .command .ApplicationCommandOptionType ;
11- import de .cerus .jdasc .command .permissions .ApplicationCommandPermissions ;
12- import de .cerus .jdasc .command .permissions .GuildApplicationCommandPermissions ;
13- import de .cerus .jdasc .http .DiscordHttpClient ;
14- import de .cerus .jdasc .interaction .Interaction ;
15- import de .cerus .jdasc .interaction .followup .FollowupMessage ;
16- import de .cerus .jdasc .interaction .response .InteractionApplicationCommandCallbackData ;
17- import de .cerus .jdasc .interaction .response .InteractionResponse ;
18- import de .cerus .jdasc .interaction .response .InteractionResponseOption ;
19- import de .cerus .jdasc .listener .InteractionListener ;
7+ import dev .cerus .jdasc .command .ApplicationCommand ;
8+ import dev .cerus .jdasc .command .ApplicationCommandListener ;
9+ import dev .cerus .jdasc .command .ApplicationCommandOption ;
10+ import dev .cerus .jdasc .command .ApplicationCommandOptionType ;
11+ import dev .cerus .jdasc .command .permissions .ApplicationCommandPermissions ;
12+ import dev .cerus .jdasc .command .permissions .GuildApplicationCommandPermissions ;
13+ import dev .cerus .jdasc .http .DiscordHttpClient ;
14+ import dev .cerus .jdasc .interaction .Interaction ;
15+ import dev .cerus .jdasc .interaction .followup .FollowupMessage ;
16+ import dev .cerus .jdasc .interaction .response .InteractionApplicationCommandCallbackData ;
17+ import dev .cerus .jdasc .interaction .response .InteractionResponse ;
18+ import dev .cerus .jdasc .interaction .response .InteractionResponseOption ;
19+ import dev .cerus .jdasc .listener .InteractionListener ;
2020import java .io .IOException ;
2121import java .util .ArrayList ;
2222import java .util .Arrays ;
2323import java .util .HashMap ;
2424import java .util .List ;
2525import java .util .Map ;
26+ import java .util .Objects ;
2627import java .util .Set ;
2728import java .util .concurrent .CompletableFuture ;
2829import java .util .concurrent .CompletionException ;
4445
4546public class JDASlashCommands {
4647
48+
4749 private static final Map <Long , ApplicationCommand > commandMap = new HashMap <>();
50+ private static final Map <Long , ApplicationCommand > discordCommands = new HashMap <>();
51+ private static final Map <Long , Map <Long , ApplicationCommand >> guildCommands = new HashMap <>();
4852 private static final Map <ApplicationCommand , ApplicationCommandListener > commandListenerMap = new HashMap <>();
4953
5054 private static DiscordHttpClient discordHttpClient ;
@@ -214,20 +218,35 @@ public static CompletableFuture<Message> submitFollowupMessage(final Interaction
214218 * @return The command id
215219 */
216220 public static CompletableFuture <Long > submitGlobalCommand (final ApplicationCommand command , final ApplicationCommandListener listener ) {
217- return discordHttpClient .submitGlobalCommand (command ).thenApply (response -> {
218- final JsonObject object ;
219- try {
220- object = JsonParser .parseString (response .body ().string ()).getAsJsonObject ();
221- } catch (final IOException e ) {
222- throw new CompletionException (e );
223- }
221+ if (discordCommands .containsValue (command )) {
222+ return getLongCompletableFuture (command , listener , discordCommands );
223+ } else {
224+ return discordHttpClient .submitGlobalCommand (command ).thenApply (response -> {
225+ final JsonObject object ;
226+ try {
227+ object = JsonParser .parseString (response .body ().string ()).getAsJsonObject ();
228+ } catch (final IOException e ) {
229+ throw new CompletionException (e );
230+ }
231+
232+ return object .get ("id" ).getAsLong ();
233+ }).thenApply (commandId -> {
234+ commandMap .put (commandId , command );
235+ commandListenerMap .put (command , listener );
236+ return commandId ;
237+ });
238+ }
239+
240+
241+ }
242+
243+ @ NotNull
244+ private static CompletableFuture <Long > getLongCompletableFuture (final ApplicationCommand command , final ApplicationCommandListener listener , final Map <Long , ApplicationCommand > commands ) {
245+ final Long id = Objects .requireNonNull (commands .values ().stream ().filter (applicationCommand -> applicationCommand .equals (command )).findFirst ().orElse (null )).getId ();
246+ commandMap .put (id , command );
247+ commandListenerMap .put (command , listener );
248+ return CompletableFuture .completedFuture (id );
224249
225- return object .get ("id" ).getAsLong ();
226- }).thenApply (commandId -> {
227- commandMap .put (commandId , command );
228- commandListenerMap .put (command , listener );
229- return commandId ;
230- });
231250 }
232251
233252 /**
@@ -257,20 +276,36 @@ public static CompletableFuture<Long> submitGuildCommand(final ApplicationComman
257276 public static CompletableFuture <Long > submitGuildCommand (final ApplicationCommand command ,
258277 final long guildId ,
259278 final ApplicationCommandListener listener ) {
260- return discordHttpClient .submitGuildCommand (command , guildId ).thenApply (response -> {
261- final JsonObject object ;
262- try {
263- object = JsonParser .parseString (response .body ().string ()).getAsJsonObject ();
264- } catch (final IOException e ) {
265- throw new CompletionException (e );
279+
280+ if (guildCommands .get (guildId ) == null || guildCommands .get (guildId ).isEmpty ()) {
281+ final Map <Long , ApplicationCommand > commandMap = new HashMap <>();
282+ for (final ApplicationCommand applicationCommand : getGuildCommands (guildId ).join ()) {
283+ commandMap .put (applicationCommand .getId (), applicationCommand );
266284 }
285+ guildCommands .put (guildId , commandMap );
286+
287+ }
288+
289+ if (guildCommands .get (guildId ).values ().stream ().anyMatch (applicationCommand -> applicationCommand .equals (command ))) {
290+ return getLongCompletableFuture (command , listener , guildCommands .get (guildId ));
291+ } else {
292+ return discordHttpClient .submitGuildCommand (command , guildId ).thenApply (response -> {
293+ final JsonObject object ;
294+ try {
295+ object = JsonParser .parseString (response .body ().string ()).getAsJsonObject ();
296+ } catch (final IOException e ) {
297+ throw new CompletionException (e );
298+ }
299+
300+ return object .get ("id" ).getAsLong ();
301+ }).thenApply (commandId -> {
302+ commandMap .put (commandId , command );
303+ commandListenerMap .put (command , listener );
304+ return commandId ;
305+ });
306+ }
307+
267308
268- return object .get ("id" ).getAsLong ();
269- }).thenApply (commandId -> {
270- commandMap .put (commandId , command );
271- commandListenerMap .put (command , listener );
272- return commandId ;
273- });
274309 }
275310
276311
@@ -506,11 +541,23 @@ private static List<ApplicationCommand> parseCommands(final Response response) {
506541 * @param botToken The bot token
507542 * @param applicationId The bot application id
508543 */
509- public static void initialize (final JDA jda , final String botToken , final String applicationId ) {
544+ public static void initializeBlocking (final JDA jda , final String botToken , final String applicationId ) {
545+ initialize (jda , botToken , applicationId ).join ();
546+ }
547+
548+ /**
549+ * Initialize this library
550+ *
551+ * @param jda The JDA instance
552+ * @param botToken The bot token
553+ * @param applicationId The bot application id
554+ */
555+ public static CompletableFuture <Void > initialize (final JDA jda , final String botToken , final String applicationId ) {
510556 if (jda instanceof JDAImpl && !((JDAImpl ) jda ).isRawEvents ()) {
511557 throw new IllegalStateException ("Slash commands will not work without raw events! See JDABuilder#setRawEventsEnabled()" );
512558 }
513559
560+ final CompletableFuture <Void > future = new CompletableFuture <>();
514561 discordHttpClient = new DiscordHttpClient (botToken , applicationId , jda );
515562 entityBuilder = new EntityBuilder (jda );
516563
@@ -521,6 +568,19 @@ public void onShutdown(@NotNull final ShutdownEvent event) {
521568 discordHttpClient .shutdown ();
522569 }
523570 });
571+
572+ getGlobalCommands ().whenComplete ((applicationCommands , throwable ) ->
573+ applicationCommands .forEach (applicationCommand ->
574+ discordCommands .put (applicationCommand .getId (), applicationCommand )))
575+ .whenComplete ((applicationCommands , throwable ) -> {
576+ if (throwable != null ) {
577+ future .completeExceptionally (throwable );
578+ } else {
579+ future .complete (null );
580+ }
581+ });
582+
583+ return future ;
524584 }
525585
526586 /**
0 commit comments