diff --git a/api/src/main/java/com/discordsrv/api/events/discord/interaction/AbstractInteractionEvent.java b/api/src/main/java/com/discordsrv/api/events/discord/interaction/AbstractInteractionEvent.java index e8a2040d..17c1a2c9 100644 --- a/api/src/main/java/com/discordsrv/api/events/discord/interaction/AbstractInteractionEvent.java +++ b/api/src/main/java/com/discordsrv/api/events/discord/interaction/AbstractInteractionEvent.java @@ -33,6 +33,8 @@ import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Locale; + public abstract class AbstractInteractionEvent extends AbstractDiscordEvent { protected final ComponentIdentifier identifier; @@ -58,6 +60,16 @@ public abstract class AbstractInteractionEvent texts, Collection extra); - default void send(MinecraftComponent minecraft, String discord) { + default void send(MinecraftComponent minecraft, SendableDiscordMessage discord) { send(ComponentUtil.fromAPI(minecraft), discord); } - void send(Component minecraft, String discord); + void send(Component minecraft, SendableDiscordMessage discord); void runAsync(Runnable runnable); } diff --git a/common/src/main/java/com/discordsrv/common/command/combined/abstraction/DiscordCommandExecution.java b/common/src/main/java/com/discordsrv/common/command/combined/abstraction/DiscordCommandExecution.java index c6890da0..867e1ffc 100644 --- a/common/src/main/java/com/discordsrv/common/command/combined/abstraction/DiscordCommandExecution.java +++ b/common/src/main/java/com/discordsrv/common/command/combined/abstraction/DiscordCommandExecution.java @@ -18,16 +18,19 @@ package com.discordsrv.common.command.combined.abstraction; +import com.discordsrv.api.discord.entity.DiscordUser; +import com.discordsrv.api.discord.entity.message.SendableDiscordMessage; +import com.discordsrv.api.events.discord.interaction.AbstractInteractionEvent; import com.discordsrv.api.events.discord.interaction.command.DiscordChatInputInteractionEvent; import com.discordsrv.api.events.discord.interaction.command.DiscordCommandAutoCompleteInteractionEvent; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.config.messages.MessagesConfig; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent; +import com.discordsrv.common.discord.api.entity.message.util.SendableDiscordMessageUtil; import net.dv8tion.jda.api.interactions.InteractionHook; import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; import net.dv8tion.jda.api.interactions.commands.CommandInteractionPayload; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.kyori.adventure.text.Component; import org.apache.commons.lang3.StringUtils; @@ -40,8 +43,8 @@ import java.util.concurrent.atomic.AtomicReference; public class DiscordCommandExecution implements CommandExecution { private final DiscordSRV discordSRV; + private final AbstractInteractionEvent event; - private final GenericInteractionCreateEvent createEvent; private final CommandInteractionPayload interactionPayload; private final IReplyCallback replyCallback; @@ -50,21 +53,25 @@ public class DiscordCommandExecution implements CommandExecution { public DiscordCommandExecution(DiscordSRV discordSRV, DiscordChatInputInteractionEvent event) { this.discordSRV = discordSRV; - this.createEvent = event.asJDA(); + this.event = event; this.interactionPayload = event.asJDA(); this.replyCallback = event.asJDA(); } public DiscordCommandExecution(DiscordSRV discordSRV, DiscordCommandAutoCompleteInteractionEvent event) { this.discordSRV = discordSRV; - this.createEvent = event.asJDA(); + this.event = event; this.interactionPayload = event.asJDA(); this.replyCallback = null; } + public DiscordUser getUser() { + return event.getUser(); + } + @Override public Locale locale() { - return createEvent.getUserLocale().toLocale(); + return event.getUserLocale(); } @Override @@ -101,25 +108,26 @@ public class DiscordCommandExecution implements CommandExecution { verifyStyle(builder, formats, null); } - sendResponse(builder.toString()); + sendResponse(SendableDiscordMessage.builder().setContent(builder.toString()).build()); } @Override - public void send(Component minecraft, String discord) { + public void send(Component minecraft, SendableDiscordMessage discord) { sendResponse(discord); } - private void sendResponse(String content) { + private void sendResponse(SendableDiscordMessage message) { if (replyCallback == null) { throw new IllegalStateException("May not be used on auto completions"); } InteractionHook interactionHook = hook.get(); boolean ephemeral = isEphemeral.get(); + MessageCreateData data = SendableDiscordMessageUtil.toJDASend(message); if (interactionHook != null) { - interactionHook.sendMessage(content).setEphemeral(ephemeral).queue(); + interactionHook.sendMessage(data).setEphemeral(ephemeral).queue(); } else { - replyCallback.reply(content).setEphemeral(ephemeral).queue(); + replyCallback.reply(data).setEphemeral(ephemeral).queue(); } } @@ -150,8 +158,4 @@ public class DiscordCommandExecution implements CommandExecution { discordSRV.scheduler().run(runnable); }); } - - public User getUser() { - return createEvent.getUser(); - } } diff --git a/common/src/main/java/com/discordsrv/common/command/combined/abstraction/GameCommandExecution.java b/common/src/main/java/com/discordsrv/common/command/combined/abstraction/GameCommandExecution.java index f0d8911d..6947e3bd 100644 --- a/common/src/main/java/com/discordsrv/common/command/combined/abstraction/GameCommandExecution.java +++ b/common/src/main/java/com/discordsrv/common/command/combined/abstraction/GameCommandExecution.java @@ -18,10 +18,11 @@ package com.discordsrv.common.command.combined.abstraction; +import com.discordsrv.api.discord.entity.message.SendableDiscordMessage; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.abstraction.player.IPlayer; -import com.discordsrv.common.command.game.abstraction.GameCommandArguments; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.command.GameCommandArguments; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.common.config.messages.MessagesConfig; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; @@ -85,7 +86,7 @@ public class GameCommandExecution implements CommandExecution { } @Override - public void send(Component minecraft, String discord) { + public void send(Component minecraft, SendableDiscordMessage discord) { sender.sendMessage(minecraft); } diff --git a/common/src/main/java/com/discordsrv/common/command/combined/commands/DebugCommand.java b/common/src/main/java/com/discordsrv/common/command/combined/commands/DebugCommand.java index 20819882..7e35a95d 100644 --- a/common/src/main/java/com/discordsrv/common/command/combined/commands/DebugCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/combined/commands/DebugCommand.java @@ -25,7 +25,7 @@ import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.command.combined.abstraction.CombinedCommand; import com.discordsrv.common.command.combined.abstraction.CommandExecution; import com.discordsrv.common.command.combined.abstraction.Text; -import com.discordsrv.common.command.game.abstraction.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; import com.discordsrv.common.core.paste.Paste; import com.discordsrv.common.core.paste.PasteService; import com.discordsrv.common.core.paste.service.AESEncryptedPasteService; diff --git a/common/src/main/java/com/discordsrv/common/command/combined/commands/LinkInitCommand.java b/common/src/main/java/com/discordsrv/common/command/combined/commands/LinkOtherCommand.java similarity index 65% rename from common/src/main/java/com/discordsrv/common/command/combined/commands/LinkInitCommand.java rename to common/src/main/java/com/discordsrv/common/command/combined/commands/LinkOtherCommand.java index d8ee6daa..76b2c2c2 100644 --- a/common/src/main/java/com/discordsrv/common/command/combined/commands/LinkInitCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/combined/commands/LinkOtherCommand.java @@ -22,52 +22,51 @@ import com.discordsrv.api.discord.entity.interaction.command.CommandOption; import com.discordsrv.api.discord.entity.interaction.command.DiscordCommand; import com.discordsrv.api.discord.entity.interaction.component.ComponentIdentifier; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.abstraction.player.IPlayer; import com.discordsrv.common.command.combined.abstraction.CombinedCommand; import com.discordsrv.common.command.combined.abstraction.CommandExecution; import com.discordsrv.common.command.combined.abstraction.GameCommandExecution; import com.discordsrv.common.command.combined.abstraction.Text; -import com.discordsrv.common.command.game.abstraction.GameCommand; -import com.discordsrv.common.command.game.sender.ICommandSender; -import com.discordsrv.common.config.messages.MessagesConfig; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommandExecutor; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; +import com.discordsrv.common.command.game.commands.subcommand.LinkInitGameCommand; import com.discordsrv.common.core.logging.Logger; import com.discordsrv.common.core.logging.NamedLogger; import com.discordsrv.common.feature.linking.LinkProvider; import com.discordsrv.common.feature.linking.LinkStore; import com.discordsrv.common.permission.game.Permission; import com.discordsrv.common.util.CommandUtil; -import com.discordsrv.common.util.ComponentUtil; -import com.github.benmanes.caffeine.cache.Cache; import net.kyori.adventure.text.format.NamedTextColor; -import org.apache.commons.lang3.StringUtils; import java.util.UUID; import java.util.concurrent.CompletableFuture; -public class LinkInitCommand extends CombinedCommand { +public class LinkOtherCommand extends CombinedCommand { - private static LinkInitCommand INSTANCE; + private static LinkOtherCommand INSTANCE; private static GameCommand GAME; private static DiscordCommand DISCORD; - private static LinkInitCommand getInstance(DiscordSRV discordSRV) { - return INSTANCE != null ? INSTANCE : (INSTANCE = new LinkInitCommand(discordSRV)); + private static LinkOtherCommand getInstance(DiscordSRV discordSRV) { + return INSTANCE != null ? INSTANCE : (INSTANCE = new LinkOtherCommand(discordSRV)); } public static GameCommand getGame(DiscordSRV discordSRV) { if (GAME == null) { - LinkInitCommand command = getInstance(discordSRV); + GameCommandExecutor initCommand = LinkInitGameCommand.getExecutor(discordSRV); + LinkOtherCommand otherCommand = getInstance(discordSRV); + GAME = GameCommand.literal("link") .then( GameCommand.stringWord("player") .then( GameCommand.stringWord("user") .requiredPermission(Permission.COMMAND_LINK_OTHER) - .executor(command) + .executor(otherCommand) ) ) .requiredPermission(Permission.COMMAND_LINK) - .executor(command); + .executor(initCommand); } return GAME; @@ -75,8 +74,10 @@ public class LinkInitCommand extends CombinedCommand { public static DiscordCommand getDiscord(DiscordSRV discordSRV) { if (DISCORD == null) { - LinkInitCommand command = getInstance(discordSRV); - DISCORD = DiscordCommand.chatInput(ComponentIdentifier.of("DiscordSRV", "link"), "link", "Link players") + LinkOtherCommand command = getInstance(discordSRV); + ComponentIdentifier identifier = ComponentIdentifier.of("DiscordSRV", "link-other"); + + DISCORD = DiscordCommand.chatInput(identifier, "link", "Link players") .addOption( CommandOption.builder(CommandOption.Type.USER, "user", "The user to link") .setRequired(true) @@ -97,45 +98,31 @@ public class LinkInitCommand extends CombinedCommand { private final DiscordSRV discordSRV; private final Logger logger; - private final Cache linkCheckRateLimit; - public LinkInitCommand(DiscordSRV discordSRV) { + public LinkOtherCommand(DiscordSRV discordSRV) { super(discordSRV); this.discordSRV = discordSRV; - this.logger = new NamedLogger(discordSRV, "LINK_COMMAND"); - this.linkCheckRateLimit = discordSRV.caffeineBuilder() - .expireAfterWrite(LinkStore.LINKING_CODE_RATE_LIMIT) - .build(); + this.logger = new NamedLogger(discordSRV, "LINK_OTHER_COMMAND"); } @Override public void execute(CommandExecution execution) { - String playerArgument = execution.getArgument("player"); - String userArgument = execution.getArgument("user"); - if (execution instanceof GameCommandExecution) { - ICommandSender sender = ((GameCommandExecution) execution).getSender(); - - if (StringUtils.isEmpty(playerArgument)) { - if (sender instanceof IPlayer) { - startLinking((IPlayer) sender, ((GameCommandExecution) execution).getLabel()); - } else { - sender.sendMessage(discordSRV.messagesConfig(sender).pleaseSpecifyPlayerAndUserToLink.asComponent()); - } - return; - } - - if (!sender.hasPermission(Permission.COMMAND_LINK_OTHER)) { - sender.sendMessage(discordSRV.messagesConfig(sender).noPermission.asComponent()); - return; - } - } - LinkProvider linkProvider = discordSRV.linkProvider(); if (!(linkProvider instanceof LinkStore)) { execution.send(new Text("Cannot create links using this link provider").withGameColor(NamedTextColor.DARK_RED)); return; } + String playerArgument = execution.getArgument("player"); + String userArgument = execution.getArgument("user"); + if (execution instanceof GameCommandExecution) { + ICommandSender sender = ((GameCommandExecution) execution).getSender(); + if (!sender.hasPermission(Permission.COMMAND_LINK_OTHER)) { + sender.sendMessage(discordSRV.messagesConfig(sender).noPermission.asComponent()); + return; + } + } + CompletableFuture playerUUIDFuture = CommandUtil.lookupPlayer(discordSRV, logger, execution, false, playerArgument, null); CompletableFuture userIdFuture = CommandUtil.lookupUser(discordSRV, logger, execution, false, userArgument, null); @@ -156,7 +143,6 @@ public class LinkInitCommand extends CombinedCommand { return; } if (linkedUser.isPresent()) { - execution.messages().playerAlreadyLinked3rd(execution); return; } @@ -167,7 +153,6 @@ public class LinkInitCommand extends CombinedCommand { return; } if (linkedPlayer.isPresent()) { - execution.messages().userAlreadyLinked3rd(execution); return; } @@ -176,7 +161,7 @@ public class LinkInitCommand extends CombinedCommand { logger.error("Failed to create link", t3); execution.send( execution.messages().minecraft.unableToLinkAtThisTime.asComponent(), - execution.messages().discord.unableToCheckLinkingStatus + execution.messages().discord.unableToCheckLinkingStatus.get() ); return; } @@ -187,43 +172,4 @@ public class LinkInitCommand extends CombinedCommand { }); })); } - - private void startLinking(IPlayer player, String label) { - MessagesConfig.Minecraft messages = discordSRV.messagesConfig(player); - - LinkProvider linkProvider = discordSRV.linkProvider(); - if (linkProvider.getCachedUserId(player.uniqueId()).isPresent()) { - player.sendMessage(messages.alreadyLinked1st.asComponent()); - return; - } - - if (linkCheckRateLimit.getIfPresent(player.uniqueId()) != null) { - player.sendMessage(messages.pleaseWaitBeforeRunningThatCommandAgain.asComponent()); - return; - } - linkCheckRateLimit.put(player.uniqueId(), true); - - player.sendMessage(discordSRV.messagesConfig(player).checkingLinkStatus.asComponent()); - linkProvider.queryUserId(player.uniqueId(), true).whenComplete((userId, t1) -> { - if (t1 != null) { - logger.error("Failed to check linking status", t1); - player.sendMessage(messages.unableToLinkAtThisTime.asComponent()); - return; - } - if (userId.isPresent()) { - player.sendMessage(messages.nowLinked1st.asComponent()); - return; - } - - linkProvider.getLinkingInstructions(player, label).whenComplete((comp, t2) -> { - if (t2 != null) { - logger.error("Failed to link account", t2); - player.sendMessage(messages.unableToLinkAtThisTime.asComponent()); - return; - } - - player.sendMessage(ComponentUtil.fromAPI(comp)); - }); - }); - } } diff --git a/common/src/main/java/com/discordsrv/common/command/combined/commands/LinkedCommand.java b/common/src/main/java/com/discordsrv/common/command/combined/commands/LinkedCommand.java index c338e81b..f355c38d 100644 --- a/common/src/main/java/com/discordsrv/common/command/combined/commands/LinkedCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/combined/commands/LinkedCommand.java @@ -24,7 +24,7 @@ import com.discordsrv.api.discord.entity.interaction.component.ComponentIdentifi import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.command.combined.abstraction.CombinedCommand; import com.discordsrv.common.command.combined.abstraction.CommandExecution; -import com.discordsrv.common.command.game.abstraction.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; import com.discordsrv.common.core.logging.Logger; import com.discordsrv.common.core.logging.NamedLogger; import com.discordsrv.common.permission.game.Permission; @@ -129,7 +129,7 @@ public class LinkedCommand extends CombinedCommand { logger.error("Failed to check linking status during linked command", t); execution.send( execution.messages().minecraft.unableToCheckLinkingStatus.asComponent(), - execution.messages().discord.unableToCheckLinkingStatus + execution.messages().discord.unableToCheckLinkingStatus.get() ); return; } diff --git a/common/src/main/java/com/discordsrv/common/command/combined/commands/ResyncCommand.java b/common/src/main/java/com/discordsrv/common/command/combined/commands/ResyncCommand.java index 12a90876..2ad49b87 100644 --- a/common/src/main/java/com/discordsrv/common/command/combined/commands/ResyncCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/combined/commands/ResyncCommand.java @@ -30,7 +30,7 @@ import com.discordsrv.common.command.combined.abstraction.CombinedCommand; import com.discordsrv.common.command.combined.abstraction.CommandExecution; import com.discordsrv.common.command.combined.abstraction.GameCommandExecution; import com.discordsrv.common.command.combined.abstraction.Text; -import com.discordsrv.common.command.game.abstraction.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; import com.discordsrv.common.feature.groupsync.GroupSyncModule; import com.discordsrv.common.helper.Someone; import com.discordsrv.common.permission.game.Permission; diff --git a/common/src/main/java/com/discordsrv/common/command/combined/commands/UnlinkCommand.java b/common/src/main/java/com/discordsrv/common/command/combined/commands/UnlinkCommand.java index b691ef0d..f394d79a 100644 --- a/common/src/main/java/com/discordsrv/common/command/combined/commands/UnlinkCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/combined/commands/UnlinkCommand.java @@ -25,7 +25,7 @@ import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.command.combined.abstraction.CombinedCommand; import com.discordsrv.common.command.combined.abstraction.CommandExecution; import com.discordsrv.common.command.combined.abstraction.Text; -import com.discordsrv.common.command.game.abstraction.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; import com.discordsrv.common.core.logging.Logger; import com.discordsrv.common.core.logging.NamedLogger; import com.discordsrv.common.feature.linking.LinkProvider; @@ -157,7 +157,7 @@ public class UnlinkCommand extends CombinedCommand { logger.error("Failed to remove link", t2); execution.send( execution.messages().minecraft.unableToLinkAtThisTime.asComponent(), - execution.messages().discord.unableToCheckLinkingStatus + execution.messages().discord.unableToCheckLinkingStatus.get() ); return; } diff --git a/common/src/main/java/com/discordsrv/common/command/combined/commands/VersionCommand.java b/common/src/main/java/com/discordsrv/common/command/combined/commands/VersionCommand.java index ffe2a3f5..a5bcd5e3 100644 --- a/common/src/main/java/com/discordsrv/common/command/combined/commands/VersionCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/combined/commands/VersionCommand.java @@ -25,7 +25,7 @@ import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.command.combined.abstraction.CombinedCommand; import com.discordsrv.common.command.combined.abstraction.CommandExecution; import com.discordsrv.common.command.combined.abstraction.Text; -import com.discordsrv.common.command.game.abstraction.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; import com.discordsrv.common.feature.debug.data.VersionInfo; import com.discordsrv.common.permission.game.Permission; import net.kyori.adventure.text.format.NamedTextColor; diff --git a/common/src/main/java/com/discordsrv/common/command/discord/commands/DiscordSRVDiscordCommand.java b/common/src/main/java/com/discordsrv/common/command/discord/commands/DiscordSRVDiscordCommand.java index 529ee283..809c4669 100644 --- a/common/src/main/java/com/discordsrv/common/command/discord/commands/DiscordSRVDiscordCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/discord/commands/DiscordSRVDiscordCommand.java @@ -47,7 +47,7 @@ public class DiscordSRVDiscordCommand { } if (discordSRV.linkProvider() instanceof LinkStore) { builder = builder - .addSubCommand(LinkInitCommand.getDiscord(discordSRV)) + .addSubCommand(LinkOtherCommand.getDiscord(discordSRV)) .addSubCommand(UnlinkCommand.getDiscord(discordSRV)); } diff --git a/common/src/main/java/com/discordsrv/common/command/discord/commands/MinecraftDiscordCommand.java b/common/src/main/java/com/discordsrv/common/command/discord/commands/MinecraftDiscordCommand.java new file mode 100644 index 00000000..1077d9bd --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/command/discord/commands/MinecraftDiscordCommand.java @@ -0,0 +1,53 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.discordsrv.common.command.discord.commands; + +import com.discordsrv.api.discord.entity.interaction.command.DiscordCommand; +import com.discordsrv.api.discord.entity.interaction.component.ComponentIdentifier; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.command.combined.commands.UnlinkCommand; +import com.discordsrv.common.command.discord.commands.subcommand.LinkInitDiscordCommand; +import com.discordsrv.common.config.main.DiscordCommandConfig; +import com.discordsrv.common.feature.linking.LinkStore; + +public class MinecraftDiscordCommand { + + private static DiscordCommand INSTANCE; + + public static DiscordCommand get(DiscordSRV discordSRV) { + if (INSTANCE == null) { + DiscordCommandConfig config = discordSRV.config().discordCommand; + + ComponentIdentifier identifier = ComponentIdentifier.of("DiscordSRV", "minecraft"); + DiscordCommand.ChatInputBuilder builder = DiscordCommand.chatInput(identifier, "minecraft", "Minecraft server commands"); + + if (discordSRV.linkProvider() instanceof LinkStore) { + builder = builder + .addSubCommand(LinkInitDiscordCommand.getInstance(discordSRV)) + .addSubCommand(UnlinkCommand.getDiscord(discordSRV)); // TODO: no other user unlinking option + } + + INSTANCE = builder + .setGuildOnly(false) + .build(); + } + + return INSTANCE; + } +} diff --git a/common/src/main/java/com/discordsrv/common/command/discord/commands/subcommand/ExecuteCommand.java b/common/src/main/java/com/discordsrv/common/command/discord/commands/subcommand/ExecuteCommand.java index 32f95dfc..4bb6f922 100644 --- a/common/src/main/java/com/discordsrv/common/command/discord/commands/subcommand/ExecuteCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/discord/commands/subcommand/ExecuteCommand.java @@ -28,7 +28,7 @@ import com.discordsrv.api.discord.entity.message.SendableDiscordMessage; import com.discordsrv.api.events.discord.interaction.command.DiscordChatInputInteractionEvent; import com.discordsrv.api.events.discord.interaction.command.DiscordCommandAutoCompleteInteractionEvent; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.command.game.GameCommandExecutionHelper; +import com.discordsrv.common.command.game.abstraction.GameCommandExecutionHelper; import com.discordsrv.common.config.main.DiscordCommandConfig; import com.discordsrv.common.config.main.generic.GameCommandExecutionConditionConfig; import com.discordsrv.common.core.logging.Logger; diff --git a/common/src/main/java/com/discordsrv/common/command/discord/commands/subcommand/LinkInitDiscordCommand.java b/common/src/main/java/com/discordsrv/common/command/discord/commands/subcommand/LinkInitDiscordCommand.java new file mode 100644 index 00000000..23f5652f --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/command/discord/commands/subcommand/LinkInitDiscordCommand.java @@ -0,0 +1,167 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.discordsrv.common.command.discord.commands.subcommand; + +import com.discordsrv.api.discord.entity.DiscordUser; +import com.discordsrv.api.discord.entity.interaction.DiscordInteractionHook; +import com.discordsrv.api.discord.entity.interaction.command.CommandOption; +import com.discordsrv.api.discord.entity.interaction.command.DiscordCommand; +import com.discordsrv.api.discord.entity.interaction.component.ComponentIdentifier; +import com.discordsrv.api.discord.entity.message.SendableDiscordMessage; +import com.discordsrv.api.events.discord.interaction.command.DiscordChatInputInteractionEvent; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.abstraction.player.IPlayer; +import com.discordsrv.common.config.messages.MessagesConfig; +import com.discordsrv.common.core.logging.Logger; +import com.discordsrv.common.core.logging.NamedLogger; +import com.discordsrv.common.feature.linking.LinkProvider; +import com.discordsrv.common.feature.linking.LinkStore; +import com.github.benmanes.caffeine.cache.Cache; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +public class LinkInitDiscordCommand implements Consumer { + + private static DiscordCommand INSTANCE; + + public static DiscordCommand getInstance(DiscordSRV discordSRV) { + if (INSTANCE == null) { + LinkInitDiscordCommand command = new LinkInitDiscordCommand(discordSRV); + ComponentIdentifier identifier = ComponentIdentifier.of("DiscordSRV", "link-init"); + + INSTANCE = DiscordCommand.chatInput(identifier, "link", "Link your Minecraft account to your Discord account") + .addOption( + CommandOption.builder(CommandOption.Type.STRING, "code", "The code provided by the in-game command") + .setRequired(true) + .build() + ) + .setEventHandler(command) + .build(); + } + return INSTANCE; + } + + private final DiscordSRV discordSRV; + private final Logger logger; + private final Cache linkCheckRateLimit; + + public LinkInitDiscordCommand(DiscordSRV discordSRV) { + this.discordSRV = discordSRV; + this.logger = new NamedLogger(discordSRV, "LINK_INIT_COMMAND"); + this.linkCheckRateLimit = discordSRV.caffeineBuilder() + .expireAfterWrite(LinkStore.LINKING_CODE_RATE_LIMIT) + .build(); + } + + @Override + public void accept(DiscordChatInputInteractionEvent event) { + DiscordUser user = event.getUser(); + MessagesConfig.Discord messagesConfig = discordSRV.messagesConfig(event.getUserLocale()).discord; + + LinkProvider linkProvider = discordSRV.linkProvider(); + if (!(linkProvider instanceof LinkStore)) { + event.reply(SendableDiscordMessage.builder().setContent("Cannot create links using this link provider").build()); + return; + } + LinkStore linkStore = (LinkStore) linkProvider; + + String code = event.getOptionAsString("code"); + if (StringUtils.isEmpty(code) || !linkStore.isValidCode(code)) { + event.reply(messagesConfig.invalidLinkingCode.get(), true); + return; + } + + if (linkProvider.getCachedPlayerUUID(user.getId()).isPresent()) { + event.reply(messagesConfig.alreadyLinked1st.get(), true); + return; + } + + if (linkCheckRateLimit.getIfPresent(user.getId()) != null) { + event.reply(messagesConfig.pleaseWaitBeforeRunningThatCommandAgain.get(), true); + return; + } + linkCheckRateLimit.put(user.getId(), true); + + event.deferReply(true).whenComplete((interactionHook, t1) -> { + if (t1 != null) { + logger.error("Failed to defer reply", t1); + return; + } + + linkProvider.queryPlayerUUID(user.getId()).whenComplete((linkedPlayer, t2) -> { + if (t2 != null) { + logger.error("Failed to check linking status", t2); + interactionHook.editOriginal(messagesConfig.unableToCheckLinkingStatus.get()); + return; + } + if (linkedPlayer.isPresent()) { + interactionHook.editOriginal(messagesConfig.alreadyLinked1st.get()); + return; + } + + linkStore.getCodeLinking(user.getId(), code) + .thenCompose(player -> linkStore.createLink(player.getKey(), user.getId()).thenApply(__ -> player)) + .whenComplete((player, t3) -> { + if (t3 != null) { + logger.error("Failed to link", t3); + interactionHook.editOriginal(messagesConfig.unableToCheckLinkingStatus.get()); + return; + } + + linkSuccess(interactionHook, linkStore, messagesConfig, player); + }); + }); + }); + + } + + private void linkSuccess( + DiscordInteractionHook interactionHook, + LinkStore linkStore, + MessagesConfig.Discord messagesConfig, + Pair pair + ) { + UUID playerUUID = pair.getKey(); + String username = pair.getValue(); + + linkStore.removeLinkingCode(playerUUID).exceptionally(t -> { + logger.error("Failed to remove linking code from storage", t); + return null; + }); + + IPlayer onlinePlayer = discordSRV.playerProvider().player(playerUUID); + (onlinePlayer != null + ? CompletableFuture.completedFuture(onlinePlayer) + : discordSRV.playerProvider().lookupOfflinePlayer(playerUUID) + ).whenComplete((player, __) -> interactionHook + .editOriginal( + messagesConfig.accountLinked.format() + .addContext(player) + .addPlaceholder("%player_name%", username) + .addPlaceholder("%player_uuid%", playerUUID) + .applyPlaceholderService() + .build() + ) + ); + } +} diff --git a/common/src/main/java/com/discordsrv/common/command/game/GameCommandModule.java b/common/src/main/java/com/discordsrv/common/command/game/GameCommandModule.java index 54872f66..5aff6090 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/GameCommandModule.java +++ b/common/src/main/java/com/discordsrv/common/command/game/GameCommandModule.java @@ -20,10 +20,10 @@ package com.discordsrv.common.command.game; import com.discordsrv.api.DiscordSRVApi; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.command.combined.commands.LinkInitCommand; -import com.discordsrv.common.command.game.abstraction.GameCommand; +import com.discordsrv.common.command.combined.commands.LinkOtherCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; import com.discordsrv.common.command.game.commands.DiscordSRVGameCommand; -import com.discordsrv.common.command.game.handler.ICommandHandler; +import com.discordsrv.common.command.game.abstraction.handler.ICommandHandler; import com.discordsrv.common.config.main.GameCommandConfig; import com.discordsrv.common.core.module.type.AbstractModule; @@ -57,7 +57,7 @@ public class GameCommandModule extends AbstractModule { registerCommand(DiscordSRVGameCommand.get(discordSRV, "discord")); } if (config.useLinkAlias) { - registerCommand(LinkInitCommand.getGame(discordSRV)); + registerCommand(LinkOtherCommand.getGame(discordSRV)); } } diff --git a/common/src/main/java/com/discordsrv/common/command/game/GameCommandExecutionHelper.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandExecutionHelper.java similarity index 95% rename from common/src/main/java/com/discordsrv/common/command/game/GameCommandExecutionHelper.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandExecutionHelper.java index f9739472..3baef96b 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/GameCommandExecutionHelper.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandExecutionHelper.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game; +package com.discordsrv.common.command.game.abstraction; import java.util.List; import java.util.concurrent.CompletableFuture; diff --git a/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommand.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommand.java similarity index 99% rename from common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommand.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommand.java index c981b099..5eb54a37 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommand.java @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.abstraction; +package com.discordsrv.common.command.game.abstraction.command; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.common.permission.game.Permission; import com.discordsrv.common.util.function.CheckedFunction; import net.kyori.adventure.text.Component; diff --git a/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandArguments.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandArguments.java similarity index 95% rename from common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandArguments.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandArguments.java index 317e997c..2d7ab431 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandArguments.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandArguments.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.abstraction; +package com.discordsrv.common.command.game.abstraction.command; @FunctionalInterface public interface GameCommandArguments { diff --git a/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandExecutor.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandExecutor.java similarity index 87% rename from common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandExecutor.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandExecutor.java index 52196ea8..a8f69de5 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandExecutor.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandExecutor.java @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.abstraction; +package com.discordsrv.common.command.game.abstraction.command; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; @FunctionalInterface public interface GameCommandExecutor { diff --git a/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandSuggester.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandSuggester.java similarity index 88% rename from common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandSuggester.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandSuggester.java index c8b46da1..3f30e40f 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/abstraction/GameCommandSuggester.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/command/GameCommandSuggester.java @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.abstraction; +package com.discordsrv.common.command.game.abstraction.command; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import java.util.List; diff --git a/common/src/main/java/com/discordsrv/common/command/game/executor/AdventureCommandExecutorProxyTemplate.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/AdventureCommandExecutorProxyTemplate.java similarity index 98% rename from common/src/main/java/com/discordsrv/common/command/game/executor/AdventureCommandExecutorProxyTemplate.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/AdventureCommandExecutorProxyTemplate.java index 37bc90c9..b14d0e62 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/executor/AdventureCommandExecutorProxyTemplate.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/AdventureCommandExecutorProxyTemplate.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.executor; +package com.discordsrv.common.command.game.abstraction.executor; import dev.vankka.dynamicproxy.processor.Original; import dev.vankka.dynamicproxy.processor.Proxy; diff --git a/common/src/main/java/com/discordsrv/common/command/game/executor/CommandExecutor.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/CommandExecutor.java similarity index 95% rename from common/src/main/java/com/discordsrv/common/command/game/executor/CommandExecutor.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/CommandExecutor.java index 2c6fb678..a49bb2be 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/executor/CommandExecutor.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/CommandExecutor.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.executor; +package com.discordsrv.common.command.game.abstraction.executor; import com.discordsrv.api.discord.entity.DiscordUser; import com.discordsrv.common.DiscordSRV; diff --git a/common/src/main/java/com/discordsrv/common/command/game/executor/CommandExecutorProvider.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/CommandExecutorProvider.java similarity index 94% rename from common/src/main/java/com/discordsrv/common/command/game/executor/CommandExecutorProvider.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/CommandExecutorProvider.java index 1eeb64c7..26ba3629 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/executor/CommandExecutorProvider.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/executor/CommandExecutorProvider.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.executor; +package com.discordsrv.common.command.game.abstraction.executor; import net.kyori.adventure.text.Component; diff --git a/common/src/main/java/com/discordsrv/common/command/game/handler/BasicCommandHandler.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/BasicCommandHandler.java similarity index 96% rename from common/src/main/java/com/discordsrv/common/command/game/handler/BasicCommandHandler.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/BasicCommandHandler.java index 7075e823..048ce755 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/handler/BasicCommandHandler.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/BasicCommandHandler.java @@ -16,11 +16,11 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.handler; +package com.discordsrv.common.command.game.abstraction.handler; -import com.discordsrv.common.command.game.abstraction.GameCommand; -import com.discordsrv.common.command.game.abstraction.GameCommandArguments; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommandArguments; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; diff --git a/common/src/main/java/com/discordsrv/common/command/game/handler/ICommandHandler.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/ICommandHandler.java similarity index 86% rename from common/src/main/java/com/discordsrv/common/command/game/handler/ICommandHandler.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/ICommandHandler.java index ea6f6aa8..f2736f03 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/handler/ICommandHandler.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/ICommandHandler.java @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.handler; +package com.discordsrv.common.command.game.abstraction.handler; -import com.discordsrv.common.command.game.abstraction.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; public interface ICommandHandler { diff --git a/common/src/main/java/com/discordsrv/common/command/game/handler/util/BrigadierUtil.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/util/BrigadierUtil.java similarity index 93% rename from common/src/main/java/com/discordsrv/common/command/game/handler/util/BrigadierUtil.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/util/BrigadierUtil.java index 5b904423..312c9c48 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/handler/util/BrigadierUtil.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/handler/util/BrigadierUtil.java @@ -16,12 +16,12 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.handler.util; +package com.discordsrv.common.command.game.abstraction.handler.util; -import com.discordsrv.common.command.game.abstraction.GameCommand; -import com.discordsrv.common.command.game.abstraction.GameCommandExecutor; -import com.discordsrv.common.command.game.abstraction.GameCommandSuggester; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommandExecutor; +import com.discordsrv.common.command.game.abstraction.command.GameCommandSuggester; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.mojang.brigadier.Command; import com.mojang.brigadier.arguments.*; import com.mojang.brigadier.builder.ArgumentBuilder; diff --git a/common/src/main/java/com/discordsrv/common/command/game/sender/ICommandSender.java b/common/src/main/java/com/discordsrv/common/command/game/abstraction/sender/ICommandSender.java similarity index 89% rename from common/src/main/java/com/discordsrv/common/command/game/sender/ICommandSender.java rename to common/src/main/java/com/discordsrv/common/command/game/abstraction/sender/ICommandSender.java index 27f6f36f..4de162bf 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/sender/ICommandSender.java +++ b/common/src/main/java/com/discordsrv/common/command/game/abstraction/sender/ICommandSender.java @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.discordsrv.common.command.game.sender; +package com.discordsrv.common.command.game.abstraction.sender; -import com.discordsrv.common.command.game.executor.CommandExecutor; +import com.discordsrv.common.command.game.abstraction.executor.CommandExecutor; import com.discordsrv.common.permission.game.Permission; import net.kyori.adventure.audience.ForwardingAudience; diff --git a/common/src/main/java/com/discordsrv/common/command/game/commands/DiscordSRVGameCommand.java b/common/src/main/java/com/discordsrv/common/command/game/commands/DiscordSRVGameCommand.java index b8b6e609..53de0d5e 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/commands/DiscordSRVGameCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/game/commands/DiscordSRVGameCommand.java @@ -21,12 +21,12 @@ package com.discordsrv.common.command.game.commands; import com.discordsrv.api.component.MinecraftComponent; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.command.combined.commands.*; -import com.discordsrv.common.command.game.abstraction.GameCommand; -import com.discordsrv.common.command.game.abstraction.GameCommandArguments; -import com.discordsrv.common.command.game.abstraction.GameCommandExecutor; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommandArguments; +import com.discordsrv.common.command.game.abstraction.command.GameCommandExecutor; import com.discordsrv.common.command.game.commands.subcommand.BroadcastCommand; import com.discordsrv.common.command.game.commands.subcommand.reload.ReloadCommand; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.common.feature.linking.LinkStore; import com.discordsrv.common.permission.game.Permission; import com.discordsrv.common.util.ComponentUtil; @@ -51,7 +51,7 @@ public class DiscordSRVGameCommand implements GameCommandExecutor { .then(BroadcastCommand.minecraft(discordSRV)) .then(BroadcastCommand.json(discordSRV)) .then(DebugCommand.getGame(discordSRV)) - .then(LinkInitCommand.getGame(discordSRV)) + .then(LinkOtherCommand.getGame(discordSRV)) .then(LinkedCommand.getGame(discordSRV)) .then(ReloadCommand.get(discordSRV)) .then(ResyncCommand.getGame(discordSRV)) diff --git a/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/BroadcastCommand.java b/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/BroadcastCommand.java index b55c2b04..b6dca127 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/BroadcastCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/BroadcastCommand.java @@ -23,11 +23,11 @@ import com.discordsrv.api.discord.entity.channel.DiscordGuildMessageChannel; import com.discordsrv.api.discord.entity.channel.DiscordMessageChannel; import com.discordsrv.api.discord.entity.message.SendableDiscordMessage; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.command.game.abstraction.GameCommand; -import com.discordsrv.common.command.game.abstraction.GameCommandArguments; -import com.discordsrv.common.command.game.abstraction.GameCommandExecutor; -import com.discordsrv.common.command.game.abstraction.GameCommandSuggester; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommandArguments; +import com.discordsrv.common.command.game.abstraction.command.GameCommandExecutor; +import com.discordsrv.common.command.game.abstraction.command.GameCommandSuggester; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.IChannelConfig; import com.discordsrv.common.permission.game.Permission; diff --git a/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/LinkInitGameCommand.java b/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/LinkInitGameCommand.java new file mode 100644 index 00000000..7a5f3b5c --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/LinkInitGameCommand.java @@ -0,0 +1,107 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.discordsrv.common.command.game.commands.subcommand; + +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.abstraction.player.IPlayer; +import com.discordsrv.common.command.game.abstraction.command.GameCommandArguments; +import com.discordsrv.common.command.game.abstraction.command.GameCommandExecutor; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; +import com.discordsrv.common.config.messages.MessagesConfig; +import com.discordsrv.common.core.logging.Logger; +import com.discordsrv.common.core.logging.NamedLogger; +import com.discordsrv.common.feature.linking.LinkProvider; +import com.discordsrv.common.feature.linking.LinkStore; +import com.discordsrv.common.util.ComponentUtil; +import com.github.benmanes.caffeine.cache.Cache; + +import java.util.UUID; + +public class LinkInitGameCommand implements GameCommandExecutor { + + private static GameCommandExecutor INSTANCE; + + public static GameCommandExecutor getExecutor(DiscordSRV discordSRV) { + if (INSTANCE == null) { + INSTANCE = new LinkInitGameCommand(discordSRV); + } + + return INSTANCE; + } + + private final DiscordSRV discordSRV; + private final Logger logger; + private final Cache linkCheckRateLimit; + + private LinkInitGameCommand(DiscordSRV discordSRV) { + this.discordSRV = discordSRV; + this.logger = new NamedLogger(discordSRV, "LINK_INIT_COMMAND"); + this.linkCheckRateLimit = discordSRV.caffeineBuilder() + .expireAfterWrite(LinkStore.LINKING_CODE_RATE_LIMIT) + .build(); + } + + @Override + public void execute(ICommandSender sender, GameCommandArguments arguments, String label) { + if (!(sender instanceof IPlayer)) { + sender.sendMessage(discordSRV.messagesConfig(sender).pleaseSpecifyPlayerAndUserToLink.asComponent()); + return; + } + + IPlayer player = (IPlayer) sender; + MessagesConfig.Minecraft messages = discordSRV.messagesConfig(player); + + LinkProvider linkProvider = discordSRV.linkProvider(); + if (linkProvider.getCachedUserId(player.uniqueId()).isPresent()) { + // Check cache first + player.sendMessage(messages.alreadyLinked1st.asComponent()); + return; + } + + if (linkCheckRateLimit.getIfPresent(player.uniqueId()) != null) { + player.sendMessage(messages.pleaseWaitBeforeRunningThatCommandAgain.asComponent()); + return; + } + linkCheckRateLimit.put(player.uniqueId(), true); + + player.sendMessage(discordSRV.messagesConfig(player).checkingLinkStatus.asComponent()); + linkProvider.queryUserId(player.uniqueId(), true).whenComplete((userId, t1) -> { + if (t1 != null) { + logger.error("Failed to check linking status", t1); + player.sendMessage(messages.unableToLinkAtThisTime.asComponent()); + return; + } + if (userId.isPresent()) { + player.sendMessage(messages.nowLinked1st.asComponent()); + return; + } + + linkProvider.getLinkingInstructions(player, label).whenComplete((comp, t2) -> { + if (t2 != null) { + logger.error("Failed to link account", t2); + player.sendMessage(messages.unableToLinkAtThisTime.asComponent()); + return; + } + + player.sendMessage(ComponentUtil.fromAPI(comp)); + }); + }); + + } +} diff --git a/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/reload/ReloadCommand.java b/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/reload/ReloadCommand.java index 81041c21..7774917f 100644 --- a/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/reload/ReloadCommand.java +++ b/common/src/main/java/com/discordsrv/common/command/game/commands/subcommand/reload/ReloadCommand.java @@ -21,11 +21,11 @@ package com.discordsrv.common.command.game.commands.subcommand.reload; import com.discordsrv.api.DiscordSRVApi; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.abstraction.player.IPlayer; -import com.discordsrv.common.command.game.abstraction.GameCommand; -import com.discordsrv.common.command.game.abstraction.GameCommandArguments; -import com.discordsrv.common.command.game.abstraction.GameCommandExecutor; -import com.discordsrv.common.command.game.abstraction.GameCommandSuggester; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; +import com.discordsrv.common.command.game.abstraction.command.GameCommandArguments; +import com.discordsrv.common.command.game.abstraction.command.GameCommandExecutor; +import com.discordsrv.common.command.game.abstraction.command.GameCommandSuggester; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.common.permission.game.Permission; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; diff --git a/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/ConfigurateConfigManager.java b/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/ConfigurateConfigManager.java index 9a734787..a6eec74a 100644 --- a/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/ConfigurateConfigManager.java +++ b/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/ConfigurateConfigManager.java @@ -29,6 +29,9 @@ import com.discordsrv.common.config.configurate.fielddiscoverer.FieldValueDiscov import com.discordsrv.common.config.configurate.fielddiscoverer.OrderedFieldDiscovererProxy; import com.discordsrv.common.config.configurate.manager.loader.ConfigLoaderProvider; import com.discordsrv.common.config.configurate.serializer.*; +import com.discordsrv.common.config.configurate.serializer.helper.DiscordMessageSerializer; +import com.discordsrv.common.config.configurate.serializer.helper.MinecraftMessageSerializer; +import com.discordsrv.common.config.helper.DiscordMessage; import com.discordsrv.common.config.helper.MinecraftMessage; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.ChannelConfig; @@ -207,8 +210,9 @@ public abstract class ConfigurateConfigManager { diff --git a/common/src/main/java/com/discordsrv/common/config/configurate/serializer/SendableDiscordMessageSerializer.java b/common/src/main/java/com/discordsrv/common/config/configurate/serializer/SendableDiscordMessageSerializer.java index acd6d5b5..fde99869 100644 --- a/common/src/main/java/com/discordsrv/common/config/configurate/serializer/SendableDiscordMessageSerializer.java +++ b/common/src/main/java/com/discordsrv/common/config/configurate/serializer/SendableDiscordMessageSerializer.java @@ -35,9 +35,11 @@ import java.util.List; public class SendableDiscordMessageSerializer implements TypeSerializer { private final NamingScheme namingScheme; + private final boolean preferContentOnly; - public SendableDiscordMessageSerializer(NamingScheme namingScheme) { + public SendableDiscordMessageSerializer(NamingScheme namingScheme, boolean preferContentOnly) { this.namingScheme = namingScheme; + this.preferContentOnly = preferContentOnly; } private String map(String option) { @@ -96,6 +98,11 @@ public class SendableDiscordMessageSerializer implements TypeSerializer. + */ + +package com.discordsrv.common.config.configurate.serializer.helper; + +import com.discordsrv.common.config.configurate.serializer.SendableDiscordMessageSerializer; +import com.discordsrv.common.config.helper.DiscordMessage; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.serialize.TypeSerializer; +import org.spongepowered.configurate.util.NamingScheme; + +import java.lang.reflect.Type; + +public class DiscordMessageSerializer implements TypeSerializer { + + private final SendableDiscordMessageSerializer serializer; + + public DiscordMessageSerializer(NamingScheme namingScheme) { + this.serializer = new SendableDiscordMessageSerializer(namingScheme, true); + } + + @Override + public DiscordMessage deserialize(Type type, ConfigurationNode node) throws SerializationException { + return new DiscordMessage(serializer.deserialize(type, node)); + } + + @Override + public void serialize(Type type, @Nullable DiscordMessage obj, ConfigurationNode node) throws SerializationException { + serializer.serialize(type, obj != null ? obj.builder() : null, node); + } +} diff --git a/common/src/main/java/com/discordsrv/common/config/configurate/serializer/MinecraftMessageSerializer.java b/common/src/main/java/com/discordsrv/common/config/configurate/serializer/helper/MinecraftMessageSerializer.java similarity index 96% rename from common/src/main/java/com/discordsrv/common/config/configurate/serializer/MinecraftMessageSerializer.java rename to common/src/main/java/com/discordsrv/common/config/configurate/serializer/helper/MinecraftMessageSerializer.java index 8a7f4cd0..b40b206e 100644 --- a/common/src/main/java/com/discordsrv/common/config/configurate/serializer/MinecraftMessageSerializer.java +++ b/common/src/main/java/com/discordsrv/common/config/configurate/serializer/helper/MinecraftMessageSerializer.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.common.config.configurate.serializer; +package com.discordsrv.common.config.configurate.serializer.helper; import com.discordsrv.common.config.helper.MinecraftMessage; import org.jetbrains.annotations.Nullable; diff --git a/common/src/main/java/com/discordsrv/common/config/helper/DiscordMessage.java b/common/src/main/java/com/discordsrv/common/config/helper/DiscordMessage.java new file mode 100644 index 00000000..085c42ed --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/helper/DiscordMessage.java @@ -0,0 +1,42 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.discordsrv.common.config.helper; + +import com.discordsrv.api.discord.entity.message.SendableDiscordMessage; + +public class DiscordMessage { + + private final SendableDiscordMessage.Builder builder; + + public DiscordMessage(SendableDiscordMessage.Builder builder) { + this.builder = builder; + } + + public SendableDiscordMessage get() { + return builder.build(); + } + + public SendableDiscordMessage.Builder builder() { + return builder.clone(); + } + + public SendableDiscordMessage.Formatter format() { + return builder.toFormatter(); + } +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/PresenceUpdaterConfig.java b/common/src/main/java/com/discordsrv/common/config/main/PresenceUpdaterConfig.java index c796b133..2a443c33 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/PresenceUpdaterConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/PresenceUpdaterConfig.java @@ -67,8 +67,8 @@ public class PresenceUpdaterConfig { @Constants.Comment({"online, idle, do_not_disturb, invisible"}) public OnlineStatus status = OnlineStatus.ONLINE; - @Comment("This may be prefixed by one of the following to specify the activity type: %1\n" - + "You can prefix the value with %2 and a YouTube or Twitch link to use the Streaming activity type") + @Comment("This may be prefixed by one of the following and a space to specify the activity type: %1\n" + + "You can use streaming by setting the value to: %2, a YouTube or Twitch link and the text all seperated by a space") @Constants.Comment({ "\"playing\", \"listening\", \"watching\", \"competing in\"", "\"streaming\"" diff --git a/common/src/main/java/com/discordsrv/common/config/main/generic/GameCommandExecutionConditionConfig.java b/common/src/main/java/com/discordsrv/common/config/main/generic/GameCommandExecutionConditionConfig.java index 799ce340..130e6ec7 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/generic/GameCommandExecutionConditionConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/generic/GameCommandExecutionConditionConfig.java @@ -21,7 +21,7 @@ package com.discordsrv.common.config.main.generic; import com.discordsrv.api.discord.entity.DiscordUser; import com.discordsrv.api.discord.entity.guild.DiscordGuildMember; import com.discordsrv.api.discord.entity.guild.DiscordRole; -import com.discordsrv.common.command.game.GameCommandExecutionHelper; +import com.discordsrv.common.command.game.abstraction.GameCommandExecutionHelper; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; diff --git a/common/src/main/java/com/discordsrv/common/config/messages/MessagesConfig.java b/common/src/main/java/com/discordsrv/common/config/messages/MessagesConfig.java index a1fa861d..35411f00 100644 --- a/common/src/main/java/com/discordsrv/common/config/messages/MessagesConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/messages/MessagesConfig.java @@ -19,13 +19,14 @@ package com.discordsrv.common.config.messages; import com.discordsrv.api.discord.entity.DiscordUser; -import com.discordsrv.api.placeholder.provider.SinglePlaceholder; +import com.discordsrv.api.discord.entity.message.SendableDiscordMessage; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.abstraction.player.IOfflinePlayer; import com.discordsrv.common.command.combined.abstraction.CommandExecution; import com.discordsrv.common.config.Config; import com.discordsrv.common.config.configurate.annotation.Constants; import com.discordsrv.common.config.configurate.annotation.Untranslated; +import com.discordsrv.common.config.helper.DiscordMessage; import com.discordsrv.common.config.helper.MinecraftMessage; import com.discordsrv.common.util.CompletableFutureUtil; import org.spongepowered.configurate.objectmapping.ConfigSerializable; @@ -94,35 +95,35 @@ public class MessagesConfig implements Config { public void playerNotFound(CommandExecution execution) { execution.send( minecraft.playerNotFound.asComponent(), - discord.playerNotFound + discord.playerNotFound.get() ); } public void userNotFound(CommandExecution execution) { execution.send( minecraft.userNotFound.asComponent(), - discord.userNotFound + discord.userNotFound.get() ); } public void unableToCheckLinkingStatus(CommandExecution execution) { execution.send( minecraft.unableToCheckLinkingStatus.asComponent(), - discord.unableToCheckLinkingStatus + discord.unableToCheckLinkingStatus.get() ); } public void playerAlreadyLinked3rd(CommandExecution execution) { execution.send( minecraft.playerAlreadyLinked3rd.asComponent(), - discord.playerAlreadyLinked3rd + discord.playerAlreadyLinked3rd.get() ); } public void userAlreadyLinked3rd(CommandExecution execution) { execution.send( minecraft.userAlreadyLinked3rd.asComponent(), - discord.userAlreadyLinked3rd + discord.userAlreadyLinked3rd.get() ); } @@ -134,13 +135,12 @@ public class MessagesConfig implements Config { .addPlaceholder("user_id", userId) .addPlaceholder("player_uuid", playerUUID) .build(), - discordSRV.placeholderService().replacePlaceholders( - execution.messages().discord.nowLinked3rd, - user, - player, - new SinglePlaceholder("user_id", userId), - new SinglePlaceholder("player_uuid", playerUUID) - ) + execution.messages().discord.nowLinked3rd.format() + .addContext(user, player) + .addPlaceholder("user_id", userId) + .addPlaceholder("player_uuid", playerUUID) + .applyPlaceholderService() + .build() )); } @@ -158,13 +158,12 @@ public class MessagesConfig implements Config { .addPlaceholder("user_id", userId) .addPlaceholder("player_uuid", playerUUID) .build(), - discordSRV.placeholderService().replacePlaceholders( - discord.discordUserLinkedTo, - user, - player, - new SinglePlaceholder("user_id", userId), - new SinglePlaceholder("player_uuid", playerUUID) - ) + discord.discordUserLinkedTo.format() + .addContext(user, player) + .addPlaceholder("user_id", userId) + .addPlaceholder("player_uuid", playerUUID) + .applyPlaceholderService() + .build() )); } @@ -180,11 +179,11 @@ public class MessagesConfig implements Config { .addContext(user) .addPlaceholder("user_id", userId) .build(), - discordSRV.placeholderService().replacePlaceholders( - discord.discordUserUnlinked, - user, - new SinglePlaceholder("user_id", userId) - ) + discord.discordUserUnlinked.format() + .addContext(user) + .addPlaceholder("user_id", userId) + .applyPlaceholderService() + .build() )); } @@ -202,13 +201,12 @@ public class MessagesConfig implements Config { .addPlaceholder("player_uuid", playerUUID) .addPlaceholder("user_id", userId) .build(), - discordSRV.placeholderService().replacePlaceholders( - discord.minecraftPlayerLinkedTo, - player, - user, - new SinglePlaceholder("player_uuid", playerUUID), - new SinglePlaceholder("user_id", userId) - ) + discord.minecraftPlayerLinkedTo.format() + .addContext(player, user) + .addPlaceholder("player_uuid", playerUUID) + .addPlaceholder("user_id", userId) + .applyPlaceholderService() + .build() )); } @@ -224,18 +222,17 @@ public class MessagesConfig implements Config { .addContext(player) .addPlaceholder("player_uuid", playerUUID) .build(), - discordSRV.placeholderService().replacePlaceholders( - discord.minecraftPlayerUnlinked, - player, - new SinglePlaceholder("player_uuid", playerUUID) - ) + discord.minecraftPlayerUnlinked.format() + .addPlaceholder("player_uuid", playerUUID) + .applyPlaceholderService() + .build() )); } public void unlinked(CommandExecution execution) { execution.send( minecraft.unlinked.asComponent(), - discord.unlinked + discord.unlinked.get() ); } @@ -246,6 +243,7 @@ public class MessagesConfig implements Config { private static final String ERROR_COLOR = "&c"; private static final String SUCCESS_COLOR = "&a"; private static final String NEUTRAL_COLOR = "&b"; + private static final String BLURPLE_COLOR = "ᛩF2"; private MinecraftMessage make(String rawFormat) { return new MinecraftMessage(rawFormat); @@ -326,6 +324,12 @@ public class MessagesConfig implements Config { "&fMinecraftAuth" }) public MinecraftMessage minecraftAuthLinking = make("%1Please visit %2 to link your account through %3"); + @Constants({NEUTRAL_COLOR, BLURPLE_COLOR}) + public MinecraftMessage storageLinking = make( + "%1Join our %2Discord %1server at " + + "[click:open_url:%discord_invite%]%discord_invite_simple%[click]" + + " and link your account by running the " + + "&r[click:copy_to_clipboard:/ link %code%][hover:show_text:Click to copy]/ link %code%"); // TODO @Untranslated(Untranslated.Type.COMMENT) @Comment("/discord unlink") @@ -343,63 +347,75 @@ public class MessagesConfig implements Config { private static final String INPUT_ERROR_PREFIX = "\uD83D\uDDD2️ "; private static final String ERROR_PREFIX = "❌ "; + private DiscordMessage make(String rawFormat) { + return new DiscordMessage(SendableDiscordMessage.builder().setContent(rawFormat)); + } + @Comment("Generic") @Constants(INPUT_ERROR_PREFIX) - public String pleaseSpecifyPlayer = "%1Please specify the Minecraft player"; + public DiscordMessage pleaseSpecifyPlayer = make("%1Please specify the Minecraft player"); @Constants(INPUT_ERROR_PREFIX) - public String pleaseSpecifyUser = "%1Please specify the Discord user"; + public DiscordMessage pleaseSpecifyUser = make("%1Please specify the Discord user"); @Constants(INPUT_ERROR_PREFIX) - public String pleaseSpecifyPlayerOrUser = "%1Please specify the Minecraft player or Discord user"; + public DiscordMessage pleaseSpecifyPlayerOrUser = make("%1Please specify the Minecraft player or Discord user"); @Constants(ERROR_PREFIX) - public String playerNotFound = "%1Minecraft player not found"; + public DiscordMessage playerNotFound = make("%1Minecraft player not found"); @Constants(ERROR_PREFIX) - public String userNotFound = "%1Discord user not found"; + public DiscordMessage userNotFound = make("%1Discord user not found"); @Constants(ERROR_PREFIX) - public String unableToCheckLinkingStatus = "%1Unable to check linking status, please try again later"; + public DiscordMessage unableToCheckLinkingStatus = make("%1Unable to check linking status, please try again later"); @Constants({ SUCCESS_PREFIX, "**%user_name%** (<@%user_id%>)", "**%player_name%** (%player_uuid%)" }) - public String discordUserLinkedTo = "%1%2 is linked to %3"; + public DiscordMessage discordUserLinkedTo = make("%1%2 is linked to %3"); @Constants({ ERROR_PREFIX, "**%user_name%** (<@%user_id%>)" }) - public String discordUserUnlinked = "%1%2 is __unlinked__"; + public DiscordMessage discordUserUnlinked = make("%1%2 is __unlinked__"); @Constants({ SUCCESS_PREFIX, "**%player_name%** (%player_uuid%)", "**%user_name%** (<@%user_id%>)" }) - public String minecraftPlayerLinkedTo = "%1%2 is linked to %3"; + public DiscordMessage minecraftPlayerLinkedTo = make("%1%2 is linked to %3"); @Constants({ ERROR_PREFIX, "**%player_name%** (%player_uuid%)" }) - public String minecraftPlayerUnlinked = "%1%2 is __unlinked__"; + public DiscordMessage minecraftPlayerUnlinked = make("%1%2 is __unlinked__"); @Untranslated(Untranslated.Type.COMMENT) @Comment("/discord link") @Constants(ERROR_PREFIX) - public String playerAlreadyLinked3rd = "%1That Minecraft player is already linked"; + public DiscordMessage playerAlreadyLinked3rd = make("%1That Minecraft player is already linked"); @Constants(ERROR_PREFIX) - public String userAlreadyLinked3rd = "%1That Discord user is already linked"; + public DiscordMessage userAlreadyLinked3rd = make("%1That Discord user is already linked"); + @Constants(ERROR_PREFIX) + public DiscordMessage alreadyLinked1st = make("%1You are already linked"); @Constants({ SUCCESS_PREFIX, "**%player_name%** (%player_uuid%)", "**%user_name%** (<@%user_id%>)" }) - public String nowLinked3rd = "%1Link created successfully\n%2 and %3"; + public DiscordMessage nowLinked3rd = make("%1Link created successfully\n%2 and %3"); + @Constants(ERROR_PREFIX) + public DiscordMessage pleaseWaitBeforeRunningThatCommandAgain = make("%1Please wait before running that command again"); + @Constants(ERROR_PREFIX) + public DiscordMessage invalidLinkingCode = make("%1Invalid linking code"); + @Constants({SUCCESS_PREFIX, "**%player_name%**"}) + public DiscordMessage accountLinked = make("%1Account linked to %2 successfully"); @Untranslated(Untranslated.Type.COMMENT) @Comment("/discord unlink") @Constants({SUCCESS_PREFIX}) - public String unlinked = "%1Accounts unlinked"; + public DiscordMessage unlinked = make("%1Accounts unlinked"); } } diff --git a/common/src/main/java/com/discordsrv/common/core/storage/Storage.java b/common/src/main/java/com/discordsrv/common/core/storage/Storage.java index 98368df8..d31697e4 100644 --- a/common/src/main/java/com/discordsrv/common/core/storage/Storage.java +++ b/common/src/main/java/com/discordsrv/common/core/storage/Storage.java @@ -19,6 +19,7 @@ package com.discordsrv.common.core.storage; import com.discordsrv.common.feature.linking.LinkStore; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.Blocking; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,8 +44,8 @@ public interface Storage { /** * Inserts the given code for the given player, removing any existing code if any, with a {@link LinkStore#LINKING_CODE_EXPIRY_TIME} expiry. */ - void storeLinkingCode(@NotNull UUID player, String code); - UUID getLinkingCode(String code); + void storeLinkingCode(@NotNull UUID player, String username, String code); + Pair getLinkingCode(String code); void removeLinkingCode(@NotNull UUID player); int getLinkedAccountCount(); diff --git a/common/src/main/java/com/discordsrv/common/core/storage/impl/MemoryStorage.java b/common/src/main/java/com/discordsrv/common/core/storage/impl/MemoryStorage.java index b963a41e..c0fd1efb 100644 --- a/common/src/main/java/com/discordsrv/common/core/storage/impl/MemoryStorage.java +++ b/common/src/main/java/com/discordsrv/common/core/storage/impl/MemoryStorage.java @@ -21,17 +21,20 @@ package com.discordsrv.common.core.storage.impl; import com.discordsrv.common.core.storage.Storage; import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.DualHashBidiMap; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class MemoryStorage implements Storage { public static String IDENTIFIER = UUID.randomUUID().toString(); private final BidiMap linkedAccounts = new DualHashBidiMap<>(); - private final BidiMap linkingCodes = new DualHashBidiMap<>(); + private final Map> linkingCodes = new ConcurrentHashMap<>(); public MemoryStorage() {} @@ -64,22 +67,23 @@ public class MemoryStorage implements Storage { } @Override - public void storeLinkingCode(@NotNull UUID player, String code) { - linkingCodes.put(player, code); + public void storeLinkingCode(@NotNull UUID player, @NotNull String username, String code) { + linkingCodes.put(code, Pair.of(player, username)); } @Override - public UUID getLinkingCode(String code) { - return linkingCodes.getKey(code); + public Pair getLinkingCode(String code) { + return linkingCodes.get(code); } @Override public void removeLinkingCode(@NotNull UUID player) { - linkingCodes.remove(player); + linkingCodes.values().removeIf(code -> code.getKey() == player); } @Override public int getLinkedAccountCount() { return linkedAccounts.size(); } + } diff --git a/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/SQLStorage.java b/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/SQLStorage.java index 133ddab2..fa9bca67 100644 --- a/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/SQLStorage.java +++ b/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/SQLStorage.java @@ -24,6 +24,7 @@ import com.discordsrv.common.exception.StorageException; import com.discordsrv.common.feature.linking.LinkStore; import com.discordsrv.common.util.function.CheckedConsumer; import com.discordsrv.common.util.function.CheckedFunction; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -165,20 +166,16 @@ public abstract class SQLStorage implements Storage { } @Override - public UUID getLinkingCode(String code) { + public Pair getLinkingCode(String code) { return useConnection(connection -> { - // Clean expired codes - try (PreparedStatement statement = connection.prepareStatement("delete from " + tablePrefix() + LINKING_CODES_TABLE_NAME + " where EXPIRY < ?;")) { - statement.setLong(1, getTimeMS()); - statement.executeUpdate(); - } - // Get the uuid for the code - try (PreparedStatement statement = connection.prepareStatement("select PLAYERUUID from " + tablePrefix() + LINKING_CODES_TABLE_NAME + " where CODE = ? LIMIT 1;")) { + try (PreparedStatement statement = connection.prepareStatement("select PLAYERUUID, PLAYERUSERNAME from " + tablePrefix() + LINKING_CODES_TABLE_NAME + " where CODE = ? LIMIT 1;")) { statement.setString(1, code); try (ResultSet resultSet = statement.executeQuery()) { if (resultSet.next()) { - return UUID.fromString(resultSet.getString("PLAYERUUID")); + UUID uuid = UUID.fromString(resultSet.getString("PLAYERUUID")); + String username = resultSet.getString("PLAYERUSERNAME"); + return Pair.of(uuid, username); } } } @@ -197,7 +194,7 @@ public abstract class SQLStorage implements Storage { } @Override - public void storeLinkingCode(@NotNull UUID player, String code) { + public void storeLinkingCode(@NotNull UUID player, @NotNull String username, String code) { useConnection(connection -> { // Remove existing code try (PreparedStatement statement = connection.prepareStatement("delete from " + tablePrefix() + LINKING_CODES_TABLE_NAME + " where PLAYERUUID = ?;")) { @@ -206,10 +203,11 @@ public abstract class SQLStorage implements Storage { } // Insert new code - try (PreparedStatement statement = connection.prepareStatement("insert into " + tablePrefix() + LINKING_CODES_TABLE_NAME + " (PLAYERUUID, CODE, EXPIRY) VALUES (?, ?, ?);")) { + try (PreparedStatement statement = connection.prepareStatement("insert into " + tablePrefix() + LINKING_CODES_TABLE_NAME + " (PLAYERUUID, PLAYERUSERNAME, CODE, EXPIRY) VALUES (?, ?, ?, ?);")) { statement.setString(1, player.toString()); - statement.setString(2, code); - statement.setLong(3, getTimeMS() + LinkStore.LINKING_CODE_EXPIRY_TIME.toMillis()); + statement.setString(2, username); + statement.setString(3, code); + statement.setLong(4, getTimeMS() + LinkStore.LINKING_CODE_EXPIRY_TIME.toMillis()); exceptEffectedRows(statement.executeUpdate(), 1); } }); diff --git a/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/file/H2Storage.java b/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/file/H2Storage.java index 81438ae0..3e5011d9 100644 --- a/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/file/H2Storage.java +++ b/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/file/H2Storage.java @@ -102,21 +102,27 @@ public class H2Storage extends SQLStorage { public void createTables(Connection connection, String tablePrefix) throws SQLException { try (Statement statement = connection.createStatement()) { statement.execute( - "create table if not exists " + tablePrefix + LINKED_ACCOUNTS_TABLE_NAME + " " - + "(ID int not null auto_increment, " - + "PLAYER_UUID varchar(36), " - + "USER_ID bigint, " - + "constraint LINKED_ACCOUNTS_PK primary key (ID)" - + ")"); + "create table if not exists " + tablePrefix + LINKED_ACCOUNTS_TABLE_NAME + " (" + + "ID int not null auto_increment," + + "PLAYER_UUID varchar(36)," + + "USER_ID bigint," + + "constraint LINKED_ACCOUNTS_PK primary key (ID)," + + "constraint LINKED_ACCOUNTS_UQ unique (PLAYER_UUID, USER_ID)" + + ");"); } try (Statement statement = connection.createStatement()) { statement.execute( - "create table if not exists " + tablePrefix + LINKING_CODES_TABLE_NAME + " " - + "(PLAYERUUID varchar(36), " - + "CODE varchar(8), " - + "EXPIRY bigint, " - + "constraint LINKING_CODES_PK primary key (PLAYERUUID)" - + ")"); + "create table if not exists " + tablePrefix + LINKING_CODES_TABLE_NAME + " (" + + "PLAYERUUID varchar(36)," + + "PLAYERUSERNAME varchar(32)," + + "CODE varchar(8)," + + "EXPIRY bigint," + + "constraint LINKING_CODES_PK primary key (PLAYERUUID)," + + "constraint LINKING_CODES_UQ unique (CODE)" + + ");"); + } + try (Statement statement = connection.createStatement()) { + statement.execute("alter table " + tablePrefix + LINKING_CODES_TABLE_NAME + " add column if not exists PLAYERUSERNAME varchar(32);"); } } } diff --git a/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/hikari/MySQLStorage.java b/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/hikari/MySQLStorage.java index 5404fb1d..ad68cea0 100644 --- a/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/hikari/MySQLStorage.java +++ b/common/src/main/java/com/discordsrv/common/core/storage/impl/sql/hikari/MySQLStorage.java @@ -57,17 +57,23 @@ public class MySQLStorage extends HikariStorage { + "(ID int not null auto_increment, " + "PLAYER_UUID varchar(36), " + "USER_ID bigint, " - + "constraint LINKED_ACCOUNTS_PK primary key (ID)" - + ")"); + + "constraint LINKED_ACCOUNTS_PK primary key (ID)," + + "constraint LINKED_ACCOUNTS_UQ unique (PLAYER_UUID, USER_ID)" + + ");"); } try (Statement statement = connection.createStatement()) { statement.execute( - "create table if not exists " + tablePrefix + LINKING_CODES_TABLE_NAME + " " - + "(PLAYERUUID varchar(36)," + "create table if not exists " + tablePrefix + LINKING_CODES_TABLE_NAME + " (" + + "PLAYERUUID varchar(36)," + + "PLAYERUSERNAME varchar(32)," + "CODE varchar(8)," + "EXPIRY bigint," - + "constraint LINKING_CODES_PK primary key (PLAYERUUID)" - + ")"); + + "constraint LINKING_CODES_PK primary key (PLAYERUUID)," + + "constraint LINKING_CODES_UQ unique (CODE)" + + ");"); + } + try (Statement statement = connection.createStatement()) { + statement.execute("alter table " + tablePrefix + LINKING_CODES_TABLE_NAME + " add column if not exists PLAYERUSERNAME varchar(32);"); } } diff --git a/common/src/main/java/com/discordsrv/common/feature/DiscordInviteModule.java b/common/src/main/java/com/discordsrv/common/feature/DiscordInviteModule.java index be1c43d4..6a141815 100644 --- a/common/src/main/java/com/discordsrv/common/feature/DiscordInviteModule.java +++ b/common/src/main/java/com/discordsrv/common/feature/DiscordInviteModule.java @@ -199,4 +199,9 @@ public class DiscordInviteModule extends AbstractModule { public CharSequence getInvite() { return FormattedText.of(invite != null ? invite : UNKNOWN_INVITE); } + + @Placeholder("discord_invite_simple") + public CharSequence getInviteSimple() { + return FormattedText.of(invite != null ? invite.replace("https://", "") : UNKNOWN_INVITE); + } } diff --git a/common/src/main/java/com/discordsrv/common/feature/console/Console.java b/common/src/main/java/com/discordsrv/common/feature/console/Console.java index 6bc77d2e..7c8abc3b 100644 --- a/common/src/main/java/com/discordsrv/common/feature/console/Console.java +++ b/common/src/main/java/com/discordsrv/common/feature/console/Console.java @@ -18,8 +18,8 @@ package com.discordsrv.common.feature.console; -import com.discordsrv.common.command.game.executor.CommandExecutorProvider; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.executor.CommandExecutorProvider; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.common.core.logging.backend.LoggingBackend; public interface Console extends ICommandSender { diff --git a/common/src/main/java/com/discordsrv/common/feature/console/SingleConsoleHandler.java b/common/src/main/java/com/discordsrv/common/feature/console/SingleConsoleHandler.java index 3d6d9921..a7057998 100644 --- a/common/src/main/java/com/discordsrv/common/feature/console/SingleConsoleHandler.java +++ b/common/src/main/java/com/discordsrv/common/feature/console/SingleConsoleHandler.java @@ -31,7 +31,7 @@ import com.discordsrv.api.events.discord.message.DiscordMessageReceiveEvent; import com.discordsrv.api.placeholder.format.PlainPlaceholderFormat; import com.discordsrv.api.placeholder.provider.SinglePlaceholder; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.command.game.GameCommandExecutionHelper; +import com.discordsrv.common.command.game.abstraction.GameCommandExecutionHelper; import com.discordsrv.common.config.main.ConsoleConfig; import com.discordsrv.common.config.main.generic.DestinationConfig; import com.discordsrv.common.config.main.generic.GameCommandExecutionConditionConfig; diff --git a/common/src/main/java/com/discordsrv/common/feature/linking/LinkProvider.java b/common/src/main/java/com/discordsrv/common/feature/linking/LinkProvider.java index 24dcc0eb..a096afa9 100644 --- a/common/src/main/java/com/discordsrv/common/feature/linking/LinkProvider.java +++ b/common/src/main/java/com/discordsrv/common/feature/linking/LinkProvider.java @@ -74,6 +74,8 @@ public interface LinkProvider { String username, UUID playerUUID, @Nullable Locale locale, - @Nullable String requestReason + @Nullable String requestReason, + Object... additionalContext ); + boolean isValidCode(@NotNull String code); } diff --git a/common/src/main/java/com/discordsrv/common/feature/linking/LinkStore.java b/common/src/main/java/com/discordsrv/common/feature/linking/LinkStore.java index 90cc59c9..ef10416b 100644 --- a/common/src/main/java/com/discordsrv/common/feature/linking/LinkStore.java +++ b/common/src/main/java/com/discordsrv/common/feature/linking/LinkStore.java @@ -18,6 +18,7 @@ package com.discordsrv.common.feature.linking; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import java.time.Duration; @@ -32,8 +33,13 @@ public interface LinkStore extends LinkProvider { CompletableFuture createLink(@NotNull UUID playerUUID, long userId); CompletableFuture removeLink(@NotNull UUID playerUUID, long userId); - CompletableFuture getCodeLinking(long userId, @NotNull String code); - CompletableFuture removeLinkingCode(@NotNull String code); + /** + * Gets the linking code information for the given code. + * @param userId the Discord user id this request is for + * @param code the code + * @return a part with the Player's {@link UUID} and username + */ + CompletableFuture> getCodeLinking(long userId, @NotNull String code); CompletableFuture removeLinkingCode(@NotNull UUID playerUUID); CompletableFuture getLinkedAccountCount(); diff --git a/common/src/main/java/com/discordsrv/common/feature/linking/impl/MinecraftAuthenticationLinker.java b/common/src/main/java/com/discordsrv/common/feature/linking/impl/MinecraftAuthenticationLinker.java index b0492bb0..155b1e1e 100644 --- a/common/src/main/java/com/discordsrv/common/feature/linking/impl/MinecraftAuthenticationLinker.java +++ b/common/src/main/java/com/discordsrv/common/feature/linking/impl/MinecraftAuthenticationLinker.java @@ -20,7 +20,6 @@ package com.discordsrv.common.feature.linking.impl; import com.discordsrv.api.component.MinecraftComponent; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.abstraction.player.IPlayer; import com.discordsrv.common.core.logging.Logger; import com.discordsrv.common.core.logging.NamedLogger; import com.discordsrv.common.feature.linking.LinkStore; @@ -89,16 +88,28 @@ public class MinecraftAuthenticationLinker extends CachedLinkProvider { } @Override - public CompletableFuture getLinkingInstructions(@NotNull IPlayer player, @Nullable String requestReason) { - return getInstructions(player, requestReason); + public CompletableFuture getLinkingInstructions( + String username, + UUID playerUUID, + Locale locale, + @Nullable String requestReason, + Object... additionalContext + ) { + return getInstructions(username, playerUUID, locale, requestReason); } @Override - public CompletableFuture getLinkingInstructions(String username, UUID playerUUID, Locale locale, @Nullable String requestReason) { - return getInstructions(null, requestReason); + public boolean isValidCode(@NotNull String code) { + throw new IllegalStateException("Does not offer codes"); } - private CompletableFuture getInstructions(@Nullable IPlayer player, @Nullable String requestReason) { + private CompletableFuture getInstructions( + String playerName, + UUID playerUUID, + @Nullable Locale locale, + @Nullable String requestReason, + Object... additionalContext + ) { String method = null; if (requestReason != null) { requestReason = requestReason.toLowerCase(Locale.ROOT); @@ -121,10 +132,12 @@ public class MinecraftAuthenticationLinker extends CachedLinkProvider { String url = BASE_LINK_URL + (additionalParam.length() > 0 ? "/" + additionalParam : ""); String simple = url.substring(url.indexOf("://") + 3); // Remove protocol & don't include method query parameter - MinecraftComponent component = discordSRV.messagesConfig(player).minecraftAuthLinking.textBuilder() - .addContext(player) + MinecraftComponent component = discordSRV.messagesConfig(locale).minecraft.minecraftAuthLinking.textBuilder() + .addContext(additionalContext) .addPlaceholder("minecraftauth_link", url + (method != null ? "?command=" + method : null)) .addPlaceholder("minecraftauth_link_simple", simple) + .addPlaceholder("player_name", playerName) + .addPlaceholder("player_uuid", playerUUID) .applyPlaceholderService() .build(); return CompletableFuture.completedFuture(component); diff --git a/common/src/main/java/com/discordsrv/common/feature/linking/impl/StorageLinker.java b/common/src/main/java/com/discordsrv/common/feature/linking/impl/StorageLinker.java index 19fb0805..2627a44c 100644 --- a/common/src/main/java/com/discordsrv/common/feature/linking/impl/StorageLinker.java +++ b/common/src/main/java/com/discordsrv/common/feature/linking/impl/StorageLinker.java @@ -20,8 +20,7 @@ package com.discordsrv.common.feature.linking.impl; import com.discordsrv.api.component.MinecraftComponent; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.util.ComponentUtil; -import net.kyori.adventure.text.Component; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,18 +63,10 @@ public class StorageLinker extends CachedLinkProvider.Store { } @Override - public CompletableFuture getCodeLinking(long userId, @NotNull String code) { + public CompletableFuture> getCodeLinking(long userId, @NotNull String code) { return discordSRV.scheduler().supply(() -> discordSRV.storage().getLinkingCode(code)); } - @Override - public CompletableFuture removeLinkingCode(@NotNull String code) { - return discordSRV.scheduler().execute(() -> { - UUID player = discordSRV.storage().getLinkingCode(code); - discordSRV.storage().removeLinkingCode(player); - }); - } - @Override public CompletableFuture removeLinkingCode(@NotNull UUID playerUUID) { return discordSRV.scheduler().execute(() -> discordSRV.storage().removeLinkingCode(playerUUID)); @@ -89,7 +80,13 @@ public class StorageLinker extends CachedLinkProvider.Store { private final SecureRandom secureRandom = new SecureRandom(); @Override - public CompletableFuture getLinkingInstructions(String username, UUID playerUUID, @Nullable Locale locale, @Nullable String requestReason) { + public CompletableFuture getLinkingInstructions( + String username, + UUID playerUUID, + @Nullable Locale locale, + @Nullable String requestReason, + Object... additionalContext + ) { return discordSRV.scheduler().supply(() -> { String code = null; while (code == null || discordSRV.storage().getLinkingCode(code) != null) { @@ -99,8 +96,19 @@ public class StorageLinker extends CachedLinkProvider.Store { } } - discordSRV.storage().storeLinkingCode(playerUUID, code); - return ComponentUtil.toAPI(Component.text(code)); + discordSRV.storage().storeLinkingCode(playerUUID, username, code); + return discordSRV.messagesConfig(locale).minecraft.storageLinking.textBuilder() + .addContext(additionalContext) + .addPlaceholder("%code%", code) + .addPlaceholder("%player_name%", username) + .addPlaceholder("%player_uuid%", playerUUID) + .applyPlaceholderService() + .build(); }); } + + @Override + public boolean isValidCode(@NotNull String code) { + return code.matches("[0-9]{6}"); + } } diff --git a/common/src/main/java/com/discordsrv/common/util/CommandUtil.java b/common/src/main/java/com/discordsrv/common/util/CommandUtil.java index efef309d..88bab6af 100644 --- a/common/src/main/java/com/discordsrv/common/util/CommandUtil.java +++ b/common/src/main/java/com/discordsrv/common/util/CommandUtil.java @@ -23,7 +23,7 @@ import com.discordsrv.common.abstraction.player.IPlayer; import com.discordsrv.common.command.combined.abstraction.CommandExecution; import com.discordsrv.common.command.combined.abstraction.DiscordCommandExecution; import com.discordsrv.common.command.combined.abstraction.GameCommandExecution; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.core.logging.Logger; import com.discordsrv.common.permission.game.Permission; @@ -116,11 +116,11 @@ public final class CommandUtil { } else if (execution instanceof DiscordCommandExecution) { if (target == null) { if (selfPermitted && lookupUser) { - target = Long.toUnsignedString(((DiscordCommandExecution) execution).getUser().getIdLong()); + target = Long.toUnsignedString(((DiscordCommandExecution) execution).getUser().getId()); } else { execution.send( messages.minecraft.pleaseSpecifyUser.asComponent(), - messages.discord.pleaseSpecifyUser + messages.discord.pleaseSpecifyUser.get() ); return CompletableFuture.completedFuture(TargetLookupResult.INVALID); } @@ -142,7 +142,7 @@ public final class CommandUtil { } catch (IllegalArgumentException ignored) { execution.send( messages.minecraft.userNotFound.asComponent(), - messages.discord.userNotFound + messages.discord.userNotFound.get() ); return CompletableFuture.completedFuture(TargetLookupResult.INVALID); } @@ -176,7 +176,7 @@ public final class CommandUtil { } catch (IllegalArgumentException ignored) { execution.send( messages.minecraft.playerNotFound.asComponent(), - messages.discord.playerNotFound + messages.discord.playerNotFound.get() ); return CompletableFuture.completedFuture(TargetLookupResult.INVALID); } @@ -205,19 +205,19 @@ public final class CommandUtil { if (lookupPlayer && lookupUser) { execution.send( messages.minecraft.pleaseSpecifyPlayerOrUser.asComponent(), - messages.discord.pleaseSpecifyPlayerOrUser + messages.discord.pleaseSpecifyPlayerOrUser.get() ); return TargetLookupResult.INVALID; } else if (lookupPlayer) { execution.send( messages.minecraft.pleaseSpecifyPlayer.asComponent(), - messages.discord.pleaseSpecifyPlayer + messages.discord.pleaseSpecifyPlayer.get() ); return TargetLookupResult.INVALID; } else if (lookupUser) { execution.send( messages.minecraft.pleaseSpecifyUser.asComponent(), - messages.discord.pleaseSpecifyUser + messages.discord.pleaseSpecifyUser.get() ); return TargetLookupResult.INVALID; } else { diff --git a/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java b/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java index 5974327a..a0d4559e 100644 --- a/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java +++ b/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java @@ -24,8 +24,8 @@ import com.discordsrv.common.abstraction.bootstrap.LifecycleManager; import com.discordsrv.common.abstraction.player.IPlayer; import com.discordsrv.common.abstraction.player.provider.AbstractPlayerProvider; import com.discordsrv.common.abstraction.plugin.PluginManager; -import com.discordsrv.common.command.game.executor.CommandExecutorProvider; -import com.discordsrv.common.command.game.handler.ICommandHandler; +import com.discordsrv.common.command.game.abstraction.executor.CommandExecutorProvider; +import com.discordsrv.common.command.game.abstraction.handler.ICommandHandler; import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; import com.discordsrv.common.config.configurate.manager.MainConfigManager; import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; diff --git a/common/src/test/java/com/discordsrv/common/command/game/GameCommandFilterTest.java b/common/src/test/java/com/discordsrv/common/command/game/GameCommandFilterTest.java index a7d8f02b..ae2fa2a2 100644 --- a/common/src/test/java/com/discordsrv/common/command/game/GameCommandFilterTest.java +++ b/common/src/test/java/com/discordsrv/common/command/game/GameCommandFilterTest.java @@ -18,6 +18,7 @@ package com.discordsrv.common.command.game; +import com.discordsrv.common.command.game.abstraction.GameCommandExecutionHelper; import com.discordsrv.common.config.main.generic.GameCommandExecutionConditionConfig; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java b/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java index 59e9f3a5..c3623670 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java +++ b/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java @@ -20,7 +20,7 @@ package com.discordsrv.velocity; import com.discordsrv.common.AbstractDiscordSRV; import com.discordsrv.common.abstraction.plugin.PluginManager; -import com.discordsrv.common.command.game.handler.ICommandHandler; +import com.discordsrv.common.command.game.abstraction.handler.ICommandHandler; import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; import com.discordsrv.common.config.configurate.manager.MainConfigManager; import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; diff --git a/velocity/src/main/java/com/discordsrv/velocity/command/game/handler/VelocityCommandHandler.java b/velocity/src/main/java/com/discordsrv/velocity/command/game/handler/VelocityCommandHandler.java index 132c7c14..9d1324e9 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/command/game/handler/VelocityCommandHandler.java +++ b/velocity/src/main/java/com/discordsrv/velocity/command/game/handler/VelocityCommandHandler.java @@ -18,10 +18,10 @@ package com.discordsrv.velocity.command.game.handler; -import com.discordsrv.common.command.game.abstraction.GameCommand; -import com.discordsrv.common.command.game.handler.ICommandHandler; -import com.discordsrv.common.command.game.handler.util.BrigadierUtil; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.command.GameCommand; +import com.discordsrv.common.command.game.abstraction.handler.ICommandHandler; +import com.discordsrv.common.command.game.abstraction.handler.util.BrigadierUtil; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.velocity.VelocityDiscordSRV; import com.discordsrv.velocity.command.game.sender.VelocityCommandSender; import com.mojang.brigadier.tree.LiteralCommandNode; diff --git a/velocity/src/main/java/com/discordsrv/velocity/command/game/sender/VelocityCommandSender.java b/velocity/src/main/java/com/discordsrv/velocity/command/game/sender/VelocityCommandSender.java index 98427a56..da02427d 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/command/game/sender/VelocityCommandSender.java +++ b/velocity/src/main/java/com/discordsrv/velocity/command/game/sender/VelocityCommandSender.java @@ -18,7 +18,7 @@ package com.discordsrv.velocity.command.game.sender; -import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.command.game.abstraction.sender.ICommandSender; import com.discordsrv.velocity.VelocityDiscordSRV; import com.velocitypowered.api.command.CommandSource; import net.kyori.adventure.audience.Audience; diff --git a/velocity/src/main/java/com/discordsrv/velocity/console/VelocityConsole.java b/velocity/src/main/java/com/discordsrv/velocity/console/VelocityConsole.java index f7385b74..765d7836 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/console/VelocityConsole.java +++ b/velocity/src/main/java/com/discordsrv/velocity/console/VelocityConsole.java @@ -18,7 +18,7 @@ package com.discordsrv.velocity.console; -import com.discordsrv.common.command.game.executor.CommandExecutorProvider; +import com.discordsrv.common.command.game.abstraction.executor.CommandExecutorProvider; import com.discordsrv.common.core.logging.backend.LoggingBackend; import com.discordsrv.common.core.logging.backend.impl.Log4JLoggerImpl; import com.discordsrv.common.feature.console.Console; diff --git a/velocity/src/main/java/com/discordsrv/velocity/console/executor/VelocityCommandExecutor.java b/velocity/src/main/java/com/discordsrv/velocity/console/executor/VelocityCommandExecutor.java index a3d7eaff..5a23fe61 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/console/executor/VelocityCommandExecutor.java +++ b/velocity/src/main/java/com/discordsrv/velocity/console/executor/VelocityCommandExecutor.java @@ -18,8 +18,8 @@ package com.discordsrv.velocity.console.executor; -import com.discordsrv.common.command.game.executor.AdventureCommandExecutorProxy; -import com.discordsrv.common.command.game.executor.CommandExecutor; +import com.discordsrv.common.command.game.abstraction.executor.AdventureCommandExecutorProxy; +import com.discordsrv.common.command.game.abstraction.executor.CommandExecutor; import com.discordsrv.velocity.VelocityDiscordSRV; import com.velocitypowered.api.proxy.ConsoleCommandSource; import net.kyori.adventure.text.Component; diff --git a/velocity/src/main/java/com/discordsrv/velocity/console/executor/VelocityCommandExecutorProvider.java b/velocity/src/main/java/com/discordsrv/velocity/console/executor/VelocityCommandExecutorProvider.java index 09d3346c..ef2e22af 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/console/executor/VelocityCommandExecutorProvider.java +++ b/velocity/src/main/java/com/discordsrv/velocity/console/executor/VelocityCommandExecutorProvider.java @@ -18,8 +18,8 @@ package com.discordsrv.velocity.console.executor; -import com.discordsrv.common.command.game.executor.CommandExecutor; -import com.discordsrv.common.command.game.executor.CommandExecutorProvider; +import com.discordsrv.common.command.game.abstraction.executor.CommandExecutor; +import com.discordsrv.common.command.game.abstraction.executor.CommandExecutorProvider; import com.discordsrv.velocity.VelocityDiscordSRV; import net.kyori.adventure.text.Component;