diff --git a/src/main/java/pw/mihou/nexus/features/command/synchronizer/NexusSynchronizer.java b/src/main/java/pw/mihou/nexus/features/command/synchronizer/NexusSynchronizer.java index a42f541e..aaaaf8ca 100644 --- a/src/main/java/pw/mihou/nexus/features/command/synchronizer/NexusSynchronizer.java +++ b/src/main/java/pw/mihou/nexus/features/command/synchronizer/NexusSynchronizer.java @@ -1,21 +1,25 @@ package pw.mihou.nexus.features.command.synchronizer; import org.javacord.api.entity.server.Server; -import org.javacord.api.interaction.SlashCommand; import org.javacord.api.interaction.SlashCommandBuilder; import pw.mihou.nexus.Nexus; import pw.mihou.nexus.core.NexusCore; import pw.mihou.nexus.core.enginex.facade.NexusEngineX; import pw.mihou.nexus.core.managers.facade.NexusCommandManager; import pw.mihou.nexus.features.command.facade.NexusCommand; +import pw.mihou.nexus.features.command.synchronizer.overwrites.NexusSynchronizeMethods; +import pw.mihou.nexus.features.command.synchronizer.overwrites.defaults.NexusDefaultSynchronizeMethods; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; public record NexusSynchronizer( Nexus nexus ) { + public static final AtomicReference SYNCHRONIZE_METHODS = new AtomicReference<>(new NexusDefaultSynchronizeMethods()); + /** * Deletes a command to a specific server. * @@ -33,39 +37,10 @@ public CompletableFuture delete(NexusCommand command, int totalShards, lon serverMappedFutures.put(serverId, new CompletableFuture<>()); } - engineX.queue((int) ((serverId >> 22) % totalShards), (api, store) -> { - if (api.getServerById(serverId).isEmpty()) { - NexusCore.logger.error( - "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? [shard={};id={}]", - api.getCurrentShard(), - serverId - ); - serverMappedFutures.get(serverId).completeExceptionally( - new IllegalStateException( - "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? " + - "[shard=" + api.getCurrentShard() + ";id=" + serverId + "]" - ) - ); - return; - } - - Server server = api.getServerById(serverId).orElseThrow(); - server.getSlashCommands() - .join() - .stream() - .filter(slashCommand -> slashCommand.getName().equalsIgnoreCase(command.getName())) - .findFirst() - .ifPresent(slashCommand -> slashCommand.deleteForServer(server).thenAccept(unused -> { - NexusCore.logger.debug("A command has completed deletion. [server={}, command={}]", serverId, slashCommand.getName()); - serverMappedFutures.get(serverId).complete(null); - }).exceptionally(throwable -> { - if (throwable != null) { - serverMappedFutures.get(serverId).completeExceptionally(throwable); - } - - return null; - })); - }); + engineX.queue( + (int) ((serverId >> 22) % totalShards), + (api, store) -> SYNCHRONIZE_METHODS.get().deleteForServer(api, command, serverId, serverMappedFutures.get(serverId)) + ); } return CompletableFuture.allOf(serverMappedFutures.values().toArray(new CompletableFuture[0])); @@ -92,36 +67,10 @@ public CompletableFuture batchUpdate(long serverId, int totalShards) { NexusEngineX engineX = ((NexusCore) nexus).getEngineX(); List slashCommandBuilders = new ArrayList<>(); serverCommands.forEach(command -> slashCommandBuilders.add(command.asSlashCommand())); - engineX.queue((int) ((serverId >> 22) % totalShards), (api, store) -> { - if (api.getServerById(serverId).isEmpty()) { - NexusCore.logger.error( - "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? [shard={};id={}]", - api.getCurrentShard(), - serverId - ); - future.completeExceptionally( - new IllegalStateException( - "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? " + - "[shard=" + api.getCurrentShard() + ";id=" + serverId + "]" - ) - ); - return; - } - - Server server = api.getServerById(serverId).orElseThrow(); - api.bulkOverwriteServerApplicationCommands(server, slashCommandBuilders) - .thenAccept(applicationCommands -> { - NexusCore.logger.debug("A server has completed synchronization. [server={}, size={}]", serverId, applicationCommands.size()); - future.complete(null); - }) - .exceptionally(throwable -> { - if (throwable != null) { - future.completeExceptionally(throwable); - } - - return null; - }); - }); + engineX.queue( + (int) ((serverId >> 22) % totalShards), + (api, store) -> SYNCHRONIZE_METHODS.get().bulkOverwriteServer(api, slashCommandBuilders, serverId, future) + ); return future; } @@ -143,57 +92,10 @@ public CompletableFuture upsert(NexusCommand command, int totalShards, lon serverMappedFutures.put(serverId, new CompletableFuture<>()); } - engineX.queue((int) ((serverId >> 22) % totalShards), (api, store) -> { - if (api.getServerById(serverId).isEmpty()) { - NexusCore.logger.error( - "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? [shard={};id={}]", - api.getCurrentShard(), - serverId - ); - serverMappedFutures.get(serverId).completeExceptionally( - new IllegalStateException( - "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? " + - "[shard=" + api.getCurrentShard() + ";id=" + serverId + "]" - ) - ); - return; - } - - Server server = api.getServerById(serverId).orElseThrow(); - List commands = server.getSlashCommands().join(); - - Optional matchingCommand = commands.stream() - .filter(slashCommand -> slashCommand.getName().equalsIgnoreCase(command.getName())) - .findFirst(); - - if (matchingCommand.isPresent()) { - command.asSlashCommandUpdater(matchingCommand.get().getId()).updateForServer(server) - .thenAccept(slashCommand -> { - NexusCore.logger.debug("A command has completed synchronization. [server={}, command={}]", serverId, slashCommand.getName()); - serverMappedFutures.get(serverId).complete(null); - }) - .exceptionally(throwable -> { - if (throwable != null) { - serverMappedFutures.get(serverId).completeExceptionally(throwable); - } - - return null; - }); - } else { - command.asSlashCommand().createForServer(server) - .thenAccept(slashCommand -> { - NexusCore.logger.debug("A command has completed synchronization. [server={}, command={}]", serverId, slashCommand.getName()); - serverMappedFutures.get(serverId).complete(null); - }) - .exceptionally(throwable -> { - if (throwable != null) { - serverMappedFutures.get(serverId).completeExceptionally(throwable); - } - - return null; - }); - } - }); + engineX.queue( + (int) ((serverId >> 22) % totalShards), + (api, store) -> SYNCHRONIZE_METHODS.get().updateForServer(api, command, serverId, serverMappedFutures.get(serverId)) + ); } return CompletableFuture.allOf(serverMappedFutures.values().toArray(new CompletableFuture[0])); @@ -222,21 +124,10 @@ public CompletableFuture synchronize(int totalShards) { NexusEngineX engineX = ((NexusCore) nexus).getEngineX(); engineX.queue( - (api, store) -> api.bulkOverwriteGlobalApplicationCommands( - manager.getCommands() - .stream() - .filter(nexusCommand -> nexusCommand.getServerIds().isEmpty()) - .map(NexusCommand::asSlashCommand).toList() - ).thenAccept(applicationCommands -> { - NexusCore.logger.debug("Global commands completed synchronization. [size={}]", applicationCommands.size()); - globalFuture.complete(null); - }).exceptionally(throwable -> { - if (throwable != null) { - globalFuture.completeExceptionally(throwable); - } - - return null; - }) + (api, store) -> SYNCHRONIZE_METHODS.get().bulkOverwriteGlobal(api, manager.getCommands() + .stream() + .filter(nexusCommand -> nexusCommand.getServerIds().isEmpty()) + .map(NexusCommand::asSlashCommand).toList()) ); Map> serverMappedCommands = new HashMap<>(); @@ -262,36 +153,10 @@ public CompletableFuture synchronize(int totalShards) { serverMappedFutures.put(serverId, new CompletableFuture<>()); } - engineX.queue((int) ((serverId >> 22) % totalShards), (api, store) -> { - if (api.getServerById(serverId).isEmpty()) { - NexusCore.logger.error( - "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? [shard={};id={}]", - api.getCurrentShard(), - serverId - ); - serverMappedFutures.get(serverId).completeExceptionally( - new IllegalStateException( - "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? " + - "[shard=" + api.getCurrentShard() + ";id=" + serverId + "]" - ) - ); - return; - } - - Server server = api.getServerById(serverId).orElseThrow(); - api.bulkOverwriteServerApplicationCommands(server, slashCommandBuilders) - .thenAccept(applicationCommands -> { - NexusCore.logger.debug("A server has completed synchronization. [server={}, size={}]", serverId, applicationCommands.size()); - serverMappedFutures.get(serverId).complete(null); - }) - .exceptionally(throwable -> { - if (throwable != null) { - serverMappedFutures.get(serverId).completeExceptionally(throwable); - } - - return null; - }); - }); + engineX.queue((int) ( + (serverId >> 22) % totalShards), + (api, store) -> SYNCHRONIZE_METHODS.get().bulkOverwriteServer(api, slashCommandBuilders, serverId, serverMappedFutures.get(serverId)) + ); }); List> futures = new ArrayList<>(); diff --git a/src/main/java/pw/mihou/nexus/features/command/synchronizer/overwrites/NexusSynchronizeMethods.java b/src/main/java/pw/mihou/nexus/features/command/synchronizer/overwrites/NexusSynchronizeMethods.java new file mode 100644 index 00000000..1e8bbe46 --- /dev/null +++ b/src/main/java/pw/mihou/nexus/features/command/synchronizer/overwrites/NexusSynchronizeMethods.java @@ -0,0 +1,24 @@ +package pw.mihou.nexus.features.command.synchronizer.overwrites; + +import org.javacord.api.DiscordApi; +import org.javacord.api.interaction.ApplicationCommand; +import org.javacord.api.interaction.SlashCommandBuilder; +import pw.mihou.nexus.features.command.facade.NexusCommand; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public interface NexusSynchronizeMethods { + + CompletableFuture bulkOverwriteGlobal(DiscordApi shard, List slashCommands); + + void bulkOverwriteServer(DiscordApi shard, List slashCommands, + long serverId, CompletableFuture future); + + void deleteForServer(DiscordApi shard, NexusCommand command, long serverId, CompletableFuture future); + + void updateForServer(DiscordApi shard, NexusCommand command, long serverId, CompletableFuture future); + + void createForServer(DiscordApi shard, NexusCommand command, long serverId, CompletableFuture future); + +} diff --git a/src/main/java/pw/mihou/nexus/features/command/synchronizer/overwrites/defaults/NexusDefaultSynchronizeMethods.java b/src/main/java/pw/mihou/nexus/features/command/synchronizer/overwrites/defaults/NexusDefaultSynchronizeMethods.java new file mode 100644 index 00000000..d0da5edb --- /dev/null +++ b/src/main/java/pw/mihou/nexus/features/command/synchronizer/overwrites/defaults/NexusDefaultSynchronizeMethods.java @@ -0,0 +1,141 @@ +package pw.mihou.nexus.features.command.synchronizer.overwrites.defaults; + +import org.javacord.api.DiscordApi; +import org.javacord.api.entity.server.Server; +import org.javacord.api.interaction.SlashCommand; +import org.javacord.api.interaction.SlashCommandBuilder; +import pw.mihou.nexus.core.NexusCore; +import pw.mihou.nexus.features.command.facade.NexusCommand; +import pw.mihou.nexus.features.command.synchronizer.overwrites.NexusSynchronizeMethods; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +public class NexusDefaultSynchronizeMethods implements NexusSynchronizeMethods { + + @Override + public CompletableFuture bulkOverwriteGlobal(DiscordApi shard, List slashCommands) { + CompletableFuture globalFuture = new CompletableFuture<>(); + + shard.bulkOverwriteGlobalApplicationCommands(slashCommands).thenAccept(applicationCommands -> { + NexusCore.logger.debug("Global commands completed synchronization. [size={}]", applicationCommands.size()); + globalFuture.complete(null); + }).exceptionally(throwable -> { + globalFuture.completeExceptionally(throwable); + return null; + }); + + return globalFuture; + } + + @Override + public void bulkOverwriteServer(DiscordApi shard, List slashCommands, + long serverId, CompletableFuture future) { + if (shard.getServerById(serverId).isEmpty()) { + future.completeExceptionally( + new IllegalStateException( + "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? " + + "[shard=" + shard.getCurrentShard() + ";id=" + serverId + "]" + ) + ); + return; + } + + Server server = shard.getServerById(serverId).orElseThrow(); + shard.bulkOverwriteServerApplicationCommands(server, slashCommands) + .thenAccept(applicationCommands -> { + NexusCore.logger.debug("A server has completed synchronization. [server={}, size={}]", serverId, applicationCommands.size()); + future.complete(null); + }) + .exceptionally(throwable -> { + future.completeExceptionally(throwable); + return null; + }); + } + + @Override + public void deleteForServer(DiscordApi api, NexusCommand command, long serverId, CompletableFuture future) { + if (api.getServerById(serverId).isEmpty()) { + future.completeExceptionally( + new IllegalStateException( + "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? " + + "[shard=" + api.getCurrentShard() + ";id=" + serverId + "]" + ) + ); + return; + } + + Server server = api.getServerById(serverId).orElseThrow(); + server.getSlashCommands() + .join() + .stream() + .filter(slashCommand -> slashCommand.getName().equalsIgnoreCase(command.getName())) + .findFirst() + .ifPresent(slashCommand -> slashCommand.deleteForServer(server).thenAccept(unused -> { + NexusCore.logger.debug("A command has completed deletion. [server={}, command={}]", serverId, slashCommand.getName()); + future.complete(null); + }).exceptionally(throwable -> { + future.completeExceptionally(throwable); + return null; + })); + } + + @Override + public void updateForServer(DiscordApi api, NexusCommand command, long serverId, CompletableFuture future) { + if (api.getServerById(serverId).isEmpty()) { + future.completeExceptionally( + new IllegalStateException( + "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? " + + "[shard=" + api.getCurrentShard() + ";id=" + serverId + "]" + ) + ); + return; + } + + Server server = api.getServerById(serverId).orElseThrow(); + List commands = server.getSlashCommands().join(); + + Optional matchingCommand = commands.stream() + .filter(slashCommand -> slashCommand.getName().equalsIgnoreCase(command.getName())) + .findFirst(); + + if (matchingCommand.isPresent()) { + command.asSlashCommandUpdater(matchingCommand.get().getId()).updateForServer(server) + .thenAccept(slashCommand -> { + NexusCore.logger.debug("A command has completed synchronization. [server={}, command={}]", serverId, slashCommand.getName()); + future.complete(null); + }) + .exceptionally(throwable -> { + future.completeExceptionally(throwable); + return null; + }); + } else { + createForServer(api, command, serverId, future); + } + } + + @Override + public void createForServer(DiscordApi api, NexusCommand command, long serverId, CompletableFuture future) { + if (api.getServerById(serverId).isEmpty()) { + future.completeExceptionally( + new IllegalStateException( + "Failed to synchronize commands for server, not found on the shard calculated. Is the total shard number value wrong? " + + "[shard=" + api.getCurrentShard() + ";id=" + serverId + "]" + ) + ); + return; + } + + Server server = api.getServerById(serverId).orElseThrow(); + command.asSlashCommand().createForServer(server) + .thenAccept(slashCommand -> { + NexusCore.logger.debug("A command has completed synchronization. [server={}, command={}]", serverId, slashCommand.getName()); + future.complete(null); + }) + .exceptionally(throwable -> { + future.completeExceptionally(throwable); + return null; + }); + } +} diff --git a/src/main/java/pw/mihou/nexus/features/command/synchronizer/requests/NexusSynchronizeRequest.java b/src/main/java/pw/mihou/nexus/features/command/synchronizer/requests/NexusSynchronizeRequest.java new file mode 100644 index 00000000..da7ce8d3 --- /dev/null +++ b/src/main/java/pw/mihou/nexus/features/command/synchronizer/requests/NexusSynchronizeRequest.java @@ -0,0 +1,10 @@ +package pw.mihou.nexus.features.command.synchronizer.requests; + +import org.javacord.api.DiscordApi; +import org.javacord.api.interaction.SlashCommandBuilder; +import java.util.List; + +public record NexusSynchronizeRequest( + DiscordApi shard, + List slashCommands +) { } \ No newline at end of file diff --git a/src/main/java/pw/mihou/nexus/features/command/synchronizer/requests/NexusSynchronizeServerRequest.java b/src/main/java/pw/mihou/nexus/features/command/synchronizer/requests/NexusSynchronizeServerRequest.java new file mode 100644 index 00000000..6d146e10 --- /dev/null +++ b/src/main/java/pw/mihou/nexus/features/command/synchronizer/requests/NexusSynchronizeServerRequest.java @@ -0,0 +1,15 @@ +package pw.mihou.nexus.features.command.synchronizer.requests; + +import org.javacord.api.DiscordApi; +import org.javacord.api.interaction.ApplicationCommand; +import org.javacord.api.interaction.SlashCommandBuilder; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public record NexusSynchronizeServerRequest( + DiscordApi shard, + List slashCommands, + long serverId, + CompletableFuture> future +) { }