Add unlink command, some fixes & cleanup to other linking commands

This commit is contained in:
Vankka 2024-03-29 20:10:28 +02:00
parent 46ac4be92b
commit d4c54a21d1
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
9 changed files with 462 additions and 234 deletions

View File

@ -1,5 +1,7 @@
package com.discordsrv.common.command.combined.abstraction;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.config.messages.MessagesConfig;
import net.kyori.adventure.text.Component;
@ -27,6 +29,10 @@ public interface CommandExecution {
void send(Collection<Text> texts, Collection<Text> extra);
default void send(MinecraftComponent minecraft, String discord) {
send(ComponentUtil.fromAPI(minecraft), discord);
}
void send(Component minecraft, String discord);
void runAsync(Runnable runnable);

View File

@ -1,10 +1,8 @@
package com.discordsrv.common.command.combined.commands;
import com.discordsrv.api.discord.entity.DiscordUser;
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.placeholder.provider.SinglePlaceholder;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.command.combined.abstraction.CombinedCommand;
import com.discordsrv.common.command.combined.abstraction.CommandExecution;
@ -15,35 +13,32 @@ import com.discordsrv.common.command.game.sender.ICommandSender;
import com.discordsrv.common.command.util.CommandUtil;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.config.messages.MessagesConfig;
import com.discordsrv.common.future.util.CompletableFutureUtil;
import com.discordsrv.common.linking.LinkProvider;
import com.discordsrv.common.linking.LinkStore;
import com.discordsrv.common.logging.Logger;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.permission.Permission;
import com.discordsrv.common.player.IOfflinePlayer;
import com.discordsrv.common.player.IPlayer;
import com.github.benmanes.caffeine.cache.Cache;
import net.kyori.adventure.text.format.NamedTextColor;
import org.apache.commons.lang3.StringUtils;
import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class LinkInitCommand extends CombinedCommand {
private static DebugCommand INSTANCE;
private static LinkInitCommand INSTANCE;
private static GameCommand GAME;
private static DiscordCommand DISCORD;
private static DebugCommand getInstance(DiscordSRV discordSRV) {
return INSTANCE != null ? INSTANCE : (INSTANCE = new DebugCommand(discordSRV));
private static LinkInitCommand getInstance(DiscordSRV discordSRV) {
return INSTANCE != null ? INSTANCE : (INSTANCE = new LinkInitCommand(discordSRV));
}
public static GameCommand getGame(DiscordSRV discordSRV) {
if (GAME == null) {
LinkInitCommand command = new LinkInitCommand(discordSRV);
LinkInitCommand command = getInstance(discordSRV);
GAME = GameCommand.literal("link")
.then(
GameCommand.stringWord("player")
@ -62,15 +57,15 @@ public class LinkInitCommand extends CombinedCommand {
public static DiscordCommand getDiscord(DiscordSRV discordSRV) {
if (DISCORD == null) {
DebugCommand command = getInstance(discordSRV);
LinkInitCommand command = getInstance(discordSRV);
DISCORD = DiscordCommand.chatInput(ComponentIdentifier.of("DiscordSRV", "link"), "link", "Link players")
.addOption(
CommandOption.builder(CommandOption.Type.STRING, "player", "The player to link")
CommandOption.builder(CommandOption.Type.USER, "user", "The user to link")
.setRequired(true)
.build()
)
.addOption(
CommandOption.builder(CommandOption.Type.USER, "user", "The user to link")
CommandOption.builder(CommandOption.Type.STRING, "player", "The player to link")
.setRequired(true)
.build()
)
@ -128,69 +123,39 @@ public class LinkInitCommand extends CombinedCommand {
playerUUIDFuture.whenComplete((playerUUID, __) -> userIdFuture.whenComplete((userId, ___) -> {
if (playerUUID == null) {
execution.send(
execution.messages().minecraft.playerNotFound.asComponent(),
execution.messages().discord.playerNotFound
);
execution.messages().playerNotFound(execution);
return;
}
if (userId == null) {
execution.send(
execution.messages().minecraft.userNotFound.asComponent(),
execution.messages().discord.userNotFound
);
execution.messages().userNotFound(execution);
return;
}
CompletableFuture<IOfflinePlayer> playerFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.playerProvider().lookupOfflinePlayer(playerUUID),
Duration.ofSeconds(5)
);
CompletableFuture<DiscordUser> userFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.discordAPI().retrieveUserById(userId),
Duration.ofSeconds(5)
);
linkProvider.queryUserId(playerUUID).whenComplete((linkedUser, t) -> {
if (t != null) {
logger.error("Failed to check linking status", t);
execution.send(
execution.messages().minecraft.unableToCheckLinkingStatus.asComponent(),
execution.messages().discord.unableToCheckLinkingStatus
);
execution.messages().unableToCheckLinkingStatus(execution);
return;
}
if (linkedUser.isPresent()) {
execution.send(
execution.messages().minecraft.playerAlreadyLinked3rd.asComponent(),
execution.messages().discord.playerAlreadyLinked3rd
);
execution.messages().playerAlreadyLinked3rd(execution);
return;
}
linkProvider.queryPlayerUUID(userId).whenComplete((linkedPlayer, t2) -> {
if (t2 != null) {
logger.error("Failed to check linking status", t2);
execution.send(
execution.messages().minecraft.unableToCheckLinkingStatus.asComponent(),
execution.messages().discord.unableToCheckLinkingStatus
);
execution.messages().unableToCheckLinkingStatus(execution);
return;
}
if (linkedPlayer.isPresent()) {
execution.send(
execution.messages().minecraft.userAlreadyLinked3rd.asComponent(),
execution.messages().discord.userAlreadyLinked3rd
);
execution.messages().userAlreadyLinked3rd(execution);
return;
}
((LinkStore) linkProvider).createLink(playerUUID, userId).whenComplete((v, t3) -> {
if (t3 != null) {
logger.error("Failed to check linking status", t3);
logger.error("Failed to create link", t3);
execution.send(
execution.messages().minecraft.unableToLinkAtThisTime.asComponent(),
execution.messages().discord.unableToCheckLinkingStatus
@ -198,23 +163,7 @@ public class LinkInitCommand extends CombinedCommand {
return;
}
userFuture.whenComplete((user, ____) -> playerFuture.whenComplete((player, _____) -> execution.send(
ComponentUtil.fromAPI(
execution.messages().minecraft.nowLinked3rd.textBuilder()
.applyPlaceholderService()
.addContext(user, player)
.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().nowLinked3rd(discordSRV, execution, playerUUID, userId);
});
});
});

View File

@ -1,25 +1,18 @@
package com.discordsrv.common.command.combined.commands;
import com.discordsrv.api.discord.entity.DiscordUser;
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.placeholder.provider.SinglePlaceholder;
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.util.CommandUtil;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.future.util.CompletableFutureUtil;
import com.discordsrv.common.logging.Logger;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.permission.Permission;
import com.discordsrv.common.player.IOfflinePlayer;
import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class LinkedCommand extends CombinedCommand {
@ -50,7 +43,7 @@ public class LinkedCommand extends CombinedCommand {
public static DiscordCommand getDiscord(DiscordSRV discordSRV) {
if (DISCORD == null) {
LinkedCommand command = getInstance(discordSRV);
DISCORD = DiscordCommand.chatInput(ComponentIdentifier.of("DiscordSRV", "linked"), "linked", "Get the linking status of a given user")
DISCORD = DiscordCommand.chatInput(ComponentIdentifier.of("DiscordSRV", "linked"), "linked", "Check the linking status of accounts")
.addOption(CommandOption.builder(
CommandOption.Type.USER,
"user",
@ -95,73 +88,23 @@ public class LinkedCommand extends CombinedCommand {
private void processResult(CommandUtil.TargetLookupResult result, CommandExecution execution) {
if (result.isPlayer()) {
UUID playerUUID = result.getPlayerUUID();
CompletableFuture<IOfflinePlayer> playerFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.playerProvider().lookupOfflinePlayer(playerUUID),
Duration.ofSeconds(5)
);
discordSRV.linkProvider().getUserId(playerUUID).whenComplete((optUserId, t) -> {
if (t != null) {
logger.error("Failed to check linking status during linked command", t);
execution.send(
execution.messages().minecraft.unableToCheckLinkingStatus.asComponent(),
execution.messages().discord.unableToCheckLinkingStatus
);
execution.messages().unableToCheckLinkingStatus(execution);
return;
}
if (!optUserId.isPresent()) {
playerFuture.whenComplete((player, ___) -> execution.send(
ComponentUtil.fromAPI(
execution.messages().minecraft.minecraftPlayerUnlinked
.textBuilder()
.applyPlaceholderService()
.addContext(player)
.addPlaceholder("player_uuid", playerUUID)
.build()
),
discordSRV.placeholderService().replacePlaceholders(
execution.messages().discord.minecraftPlayerUnlinked,
player,
new SinglePlaceholder("player_uuid", playerUUID)
)
));
execution.messages().minecraftPlayerUnlinked(discordSRV, execution, playerUUID);
return;
}
long userId = optUserId.get();
CompletableFuture<DiscordUser> userFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.discordAPI().retrieveUserById(userId),
Duration.ofSeconds(5)
);
playerFuture.whenComplete((player, __) -> userFuture.whenComplete((user, ___) -> execution.send(
ComponentUtil.fromAPI(
execution.messages().minecraft.minecraftPlayerLinkedTo
.textBuilder()
.applyPlaceholderService()
.addContext(player, user)
.addPlaceholder("player_uuid", playerUUID)
.addPlaceholder("user_id", userId)
.build()
),
discordSRV.placeholderService().replacePlaceholders(
execution.messages().discord.minecraftPlayerLinkedTo,
player,
user,
new SinglePlaceholder("player_uuid", playerUUID),
new SinglePlaceholder("user_id", userId)
)
)));
execution.messages().minecraftPlayerLinkedTo(discordSRV, execution, playerUUID, userId);
});
} else {
long userId = result.getUserId();
CompletableFuture<DiscordUser> userFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.discordAPI().retrieveUserById(userId),
Duration.ofSeconds(5)
);
discordSRV.linkProvider().getPlayerUUID(userId).whenComplete((optPlayerUUID, t) -> {
if (t != null) {
@ -173,49 +116,12 @@ public class LinkedCommand extends CombinedCommand {
return;
}
if (!optPlayerUUID.isPresent()) {
userFuture.whenComplete((user, ___) -> execution.send(
ComponentUtil.fromAPI(
execution.messages().minecraft.discordUserUnlinked
.textBuilder()
.applyPlaceholderService()
.addContext(user)
.addPlaceholder("user_id", userId)
.build()
),
discordSRV.placeholderService().replacePlaceholders(
execution.messages().discord.discordUserUnlinked,
user,
new SinglePlaceholder("user_id", userId)
)
));
execution.messages().discordUserUnlinked(discordSRV, execution, userId);
return;
}
UUID playerUUID = optPlayerUUID.get();
CompletableFuture<IOfflinePlayer> playerFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.playerProvider().lookupOfflinePlayer(playerUUID),
Duration.ofSeconds(5)
);
userFuture.whenComplete((user, __) -> playerFuture.whenComplete((player, ___) -> execution.send(
ComponentUtil.fromAPI(
execution.messages().minecraft.discordUserLinkedTo
.textBuilder()
.applyPlaceholderService()
.addContext(user, player)
.addPlaceholder("user_id", userId)
.addPlaceholder("player_uuid", playerUUID)
.build()
),
discordSRV.placeholderService().replacePlaceholders(
execution.messages().discord.discordUserLinkedTo,
user,
player,
new SinglePlaceholder("user_id", userId),
new SinglePlaceholder("player_uuid", playerUUID)
)
)));
execution.messages().discordUserLinkedTo(discordSRV, execution, playerUUID, userId);
});
}
}

View File

@ -0,0 +1,150 @@
package com.discordsrv.common.command.combined.commands;
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.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.util.CommandUtil;
import com.discordsrv.common.linking.LinkProvider;
import com.discordsrv.common.linking.LinkStore;
import com.discordsrv.common.logging.Logger;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.permission.Permission;
import net.kyori.adventure.text.format.NamedTextColor;
import java.util.UUID;
public class UnlinkCommand extends CombinedCommand {
private static UnlinkCommand INSTANCE;
private static GameCommand GAME;
private static DiscordCommand DISCORD;
private static UnlinkCommand getInstance(DiscordSRV discordSRV) {
return INSTANCE != null ? INSTANCE : (INSTANCE = new UnlinkCommand(discordSRV));
}
public static GameCommand getGame(DiscordSRV discordSRV) {
if (GAME == null) {
UnlinkCommand command = getInstance(discordSRV);
GAME = GameCommand.literal("unlink")
.then(
GameCommand.stringGreedy("target")
.requiredPermission(Permission.COMMAND_UNLINK_OTHER)
.executor(command)
)
.requiredPermission(Permission.COMMAND_UNLINK)
.executor(command);
}
return GAME;
}
public static DiscordCommand getDiscord(DiscordSRV discordSRV) {
if (DISCORD == null) {
UnlinkCommand command = getInstance(discordSRV);
DISCORD = DiscordCommand.chatInput(ComponentIdentifier.of("DiscordSRV", "unlink"), "unlink", "Unlink accounts")
.addOption(CommandOption.builder(
CommandOption.Type.USER,
"user",
"The Discord user to unlink"
).setRequired(false).build())
.addOption(CommandOption.builder(
CommandOption.Type.STRING,
"player",
"The Minecraft player username or UUID to unlink"
).setRequired(false).build())
.setEventHandler(command)
.build();
}
return DISCORD;
}
private final Logger logger;
public UnlinkCommand(DiscordSRV discordSRV) {
super(discordSRV);
this.logger = new NamedLogger(discordSRV, "UNLINK_COMMAND");
}
@Override
public void execute(CommandExecution execution) {
execution.setEphemeral(true);
LinkProvider linkProvider = discordSRV.linkProvider();
if (!(linkProvider instanceof LinkStore)) {
execution.send(new Text("Cannot remove links with this link provider").withGameColor(NamedTextColor.DARK_RED));
return;
}
execution.runAsync(() -> CommandUtil.lookupTarget(discordSRV, logger, execution, true, Permission.COMMAND_UNLINK_OTHER)
.whenComplete((result, t) -> {
if (t != null) {
logger.error("Failed to execute linked command", t);
return;
}
if (result.isValid()) {
processResult(result, execution, (LinkStore) linkProvider);
} else {
execution.send(new Text("Invalid target"));
}
})
);
}
private void processResult(CommandUtil.TargetLookupResult result, CommandExecution execution, LinkStore linkStore) {
if (result.isPlayer()) {
UUID playerUUID = result.getPlayerUUID();
discordSRV.linkProvider().queryUserId(playerUUID)
.whenComplete((user, t) -> {
if (t != null) {
logger.error("Failed to query user", t);
execution.messages().unableToCheckLinkingStatus(execution);
return;
}
if (!user.isPresent()) {
execution.messages().minecraftPlayerUnlinked(discordSRV, execution, playerUUID);
return;
}
handleUnlinkForPair(playerUUID, user.get(), execution, linkStore);
});
} else {
long userId = result.getUserId();
discordSRV.linkProvider().queryPlayerUUID(result.getUserId())
.whenComplete((player, t) -> {
if (t != null) {
logger.error("Failed to query player", t);
execution.messages().unableToCheckLinkingStatus(execution);
return;
}
if (!player.isPresent()) {
execution.messages().discordUserUnlinked(discordSRV, execution, userId);
return;
}
handleUnlinkForPair(player.get(), userId, execution, linkStore);
});
}
}
private void handleUnlinkForPair(UUID player, Long user, CommandExecution execution, LinkStore linkStore) {
linkStore.removeLink(player, user).whenComplete((v, t2) -> {
if (t2 != null) {
logger.error("Failed to remove link", t2);
execution.send(
execution.messages().minecraft.unableToLinkAtThisTime.asComponent(),
execution.messages().discord.unableToCheckLinkingStatus
);
return;
}
execution.messages().unlinked(execution);
});
}
}

View File

@ -28,7 +28,9 @@ public class DiscordSRVDiscordCommand {
builder = builder.addSubCommand(ExecuteCommand.get(discordSRV));
}
if (discordSRV.linkProvider() instanceof LinkStore) {
builder = builder.addSubCommand(LinkInitCommand.getDiscord(discordSRV));
builder = builder
.addSubCommand(LinkInitCommand.getDiscord(discordSRV))
.addSubCommand(UnlinkCommand.getDiscord(discordSRV));
}
INSTANCE = builder

View File

@ -28,6 +28,7 @@ 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.component.util.ComponentUtil;
import com.discordsrv.common.linking.LinkStore;
import com.discordsrv.common.permission.Permission;
import java.util.Map;
@ -42,20 +43,25 @@ public class DiscordSRVGameCommand implements GameCommandExecutor {
if (COMMAND == null) {
COMMAND = new DiscordSRVGameCommand(discordSRV);
}
return INSTANCES.computeIfAbsent(alias, key ->
GameCommand.literal(alias)
.requiredPermission(Permission.COMMAND_ROOT)
.executor(COMMAND)
.then(BroadcastCommand.discord(discordSRV))
.then(BroadcastCommand.minecraft(discordSRV))
.then(BroadcastCommand.json(discordSRV))
.then(DebugCommand.getGame(discordSRV))
.then(LinkInitCommand.getGame(discordSRV))
.then(LinkedCommand.getGame(discordSRV))
.then(ReloadCommand.get(discordSRV))
.then(ResyncCommand.getGame(discordSRV))
.then(VersionCommand.getGame(discordSRV))
);
return INSTANCES.computeIfAbsent(alias, key -> {
GameCommand command = GameCommand.literal(alias)
.requiredPermission(Permission.COMMAND_ROOT)
.executor(COMMAND)
.then(BroadcastCommand.discord(discordSRV))
.then(BroadcastCommand.minecraft(discordSRV))
.then(BroadcastCommand.json(discordSRV))
.then(DebugCommand.getGame(discordSRV))
.then(LinkInitCommand.getGame(discordSRV))
.then(LinkedCommand.getGame(discordSRV))
.then(ReloadCommand.get(discordSRV))
.then(ResyncCommand.getGame(discordSRV))
.then(VersionCommand.getGame(discordSRV));
if (discordSRV.linkProvider() instanceof LinkStore) {
command = command.then(UnlinkCommand.getGame(discordSRV));
}
return command;
});
}
private final DiscordSRV discordSRV;

View File

@ -1,12 +1,24 @@
package com.discordsrv.common.config.messages;
import com.discordsrv.api.discord.entity.DiscordUser;
import com.discordsrv.api.placeholder.provider.SinglePlaceholder;
import com.discordsrv.common.DiscordSRV;
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.MinecraftMessage;
import com.discordsrv.common.future.util.CompletableFutureUtil;
import com.discordsrv.common.player.IOfflinePlayer;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@ConfigSerializable
public class MessagesConfig implements Config {
@ -17,6 +29,198 @@ public class MessagesConfig implements Config {
return FILE_NAME;
}
// Helper methods
private void withPlayer(DiscordSRV discordSRV, UUID playerUUID, Consumer<IOfflinePlayer> playerConsumer) {
CompletableFuture<IOfflinePlayer> playerFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.playerProvider().lookupOfflinePlayer(playerUUID),
Duration.ofSeconds(5)
);
playerFuture.whenComplete((player, __) -> playerConsumer.accept(player));
}
private void withUser(DiscordSRV discordSRV, long userId, Consumer<DiscordUser> userConsumer) {
CompletableFuture<DiscordUser> userFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.discordAPI().retrieveUserById(userId),
Duration.ofSeconds(5)
);
userFuture.whenComplete((player, __) -> userConsumer.accept(player));
}
private void withPlayerAndUser(
DiscordSRV discordSRV,
UUID playerUUID,
long userId,
BiConsumer<IOfflinePlayer, DiscordUser> playerAndUserConsumer
) {
CompletableFuture<IOfflinePlayer> playerFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.playerProvider().lookupOfflinePlayer(playerUUID),
Duration.ofSeconds(5)
);
CompletableFuture<DiscordUser> userFuture = CompletableFutureUtil.timeout(
discordSRV,
discordSRV.discordAPI().retrieveUserById(userId),
Duration.ofSeconds(5)
);
playerFuture.whenComplete((player, __) -> userFuture.whenComplete((user, ___) -> playerAndUserConsumer.accept(player, user)));
}
// Methods for responding directly to CommandExecutions
public void playerNotFound(CommandExecution execution) {
execution.send(
minecraft.playerNotFound.asComponent(),
discord.playerNotFound
);
}
public void userNotFound(CommandExecution execution) {
execution.send(
minecraft.userNotFound.asComponent(),
discord.userNotFound
);
}
public void unableToCheckLinkingStatus(CommandExecution execution) {
execution.send(
minecraft.unableToCheckLinkingStatus.asComponent(),
discord.unableToCheckLinkingStatus
);
}
public void playerAlreadyLinked3rd(CommandExecution execution) {
execution.send(
minecraft.playerAlreadyLinked3rd.asComponent(),
discord.playerAlreadyLinked3rd
);
}
public void userAlreadyLinked3rd(CommandExecution execution) {
execution.send(
minecraft.userAlreadyLinked3rd.asComponent(),
discord.userAlreadyLinked3rd
);
}
public void nowLinked3rd(DiscordSRV discordSRV, CommandExecution execution, UUID playerUUID, long userId) {
withPlayerAndUser(discordSRV, playerUUID, userId, (player, user) -> execution.send(
minecraft.nowLinked3rd.textBuilder()
.applyPlaceholderService()
.addContext(user, player)
.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)
)
));
}
public void discordUserLinkedTo(
DiscordSRV discordSRV,
CommandExecution execution,
UUID playerUUID,
long userId
) {
withPlayerAndUser(discordSRV, playerUUID, userId, (player, user) -> execution.send(
minecraft.discordUserLinkedTo
.textBuilder()
.applyPlaceholderService()
.addContext(user, player)
.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)
)
));
}
public void discordUserUnlinked(
DiscordSRV discordSRV,
CommandExecution execution,
long userId
) {
withUser(discordSRV, userId, (user) -> execution.send(
minecraft.discordUserUnlinked
.textBuilder()
.applyPlaceholderService()
.addContext(user)
.addPlaceholder("user_id", userId)
.build(),
discordSRV.placeholderService().replacePlaceholders(
discord.discordUserUnlinked,
user,
new SinglePlaceholder("user_id", userId)
)
));
}
public void minecraftPlayerLinkedTo(
DiscordSRV discordSRV,
CommandExecution execution,
UUID playerUUID,
long userId
) {
withPlayerAndUser(discordSRV, playerUUID, userId, (player, user) -> execution.send(
minecraft.minecraftPlayerLinkedTo
.textBuilder()
.applyPlaceholderService()
.addContext(player, user)
.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)
)
));
}
public void minecraftPlayerUnlinked(
DiscordSRV discordSRV,
CommandExecution execution,
UUID playerUUID
) {
withPlayer(discordSRV, playerUUID, (player) -> execution.send(
minecraft.minecraftPlayerUnlinked
.textBuilder()
.applyPlaceholderService()
.addContext(player)
.addPlaceholder("player_uuid", playerUUID)
.build(),
discordSRV.placeholderService().replacePlaceholders(
discord.minecraftPlayerUnlinked,
player,
new SinglePlaceholder("player_uuid", playerUUID)
)
));
}
public void unlinked(CommandExecution execution) {
execution.send(
minecraft.unlinked.asComponent(),
discord.unlinked
);
}
public Minecraft minecraft = new Minecraft();
@ConfigSerializable
@ -45,6 +249,34 @@ public class MessagesConfig implements Config {
@Constants(ERROR_COLOR)
public MinecraftMessage unableToCheckLinkingStatus = make("%1Unable to check linking status, please try again later");
@Constants({
SUCCESS_COLOR + "[hover:show_text:%user_id%][click:copy_to_clipboard:%user_id%]@%user_name%[click][hover]",
NEUTRAL_COLOR,
SUCCESS_COLOR + "[hover:show_text:%player_uuid%][click:copy_to_clipboard:%player_uuid%]%player_name|text:'<Unknown>'%[click][hover]"
})
public MinecraftMessage discordUserLinkedTo = make("%1 %2is linked to %3");
@Constants({
SUCCESS_COLOR + "[hover:show_text:%user_id%][click:copy_to_clipboard:%user_id%]@%user_name%[click][hover]",
NEUTRAL_COLOR,
ERROR_COLOR
})
public MinecraftMessage discordUserUnlinked = make("%1 %2is %3unlinked");
@Constants({
SUCCESS_COLOR + "[hover:show_text:%player_uuid%][click:copy_to_clipboard:%player_uuid%]%player_name|text:'<Unknown>'%[click][hover]",
NEUTRAL_COLOR,
SUCCESS_COLOR + "[hover:show_text:%user_id%][click:copy_to_clipboard:%user_id%]@%user_name%[click][hover]"
})
public MinecraftMessage minecraftPlayerLinkedTo = make("%1 %2is linked to %3");
@Constants({
SUCCESS_COLOR + "[hover:show_text:%player_uuid%][click:copy_to_clipboard:%player_uuid%]%player_name|text:'<Unknown>'%[click][hover]",
NEUTRAL_COLOR,
ERROR_COLOR
})
public MinecraftMessage minecraftPlayerUnlinked = make("%1 %2is %3unlinked");
@Untranslated(Untranslated.Type.COMMENT)
@Comment("/discord link")
@Constants(ERROR_COLOR)
@ -78,36 +310,9 @@ public class MessagesConfig implements Config {
public MinecraftMessage minecraftAuthLinking = make("%1Please visit %2 to link your account through %4");
@Untranslated(Untranslated.Type.COMMENT)
@Comment("/discord linked")
@Constants({
SUCCESS_COLOR + "[hover:show_text:%user_id%][click:copy_to_clipboard:%user_id%]@%user_name%[click][hover]",
NEUTRAL_COLOR,
SUCCESS_COLOR + "[hover:show_text:%player_uuid%][click:copy_to_clipboard:%player_uuid%]%player_name|text:'<Unknown>'%[click][hover]"
})
public MinecraftMessage discordUserLinkedTo = make("%1 %2is linked to %3");
@Untranslated(Untranslated.Type.COMMENT)
@Comment("/discord linked")
@Constants({
SUCCESS_COLOR + "[hover:show_text:%user_id%][click:copy_to_clipboard:%user_id%]@%user_name%[click][hover]",
NEUTRAL_COLOR,
ERROR_COLOR
})
public MinecraftMessage discordUserUnlinked = make("%1 %2is %3unlinked");
@Constants({
SUCCESS_COLOR + "[hover:show_text:%player_uuid%][click:copy_to_clipboard:%player_uuid%]%player_name|text:'<Unknown>'%[click][hover]",
NEUTRAL_COLOR,
SUCCESS_COLOR + "[hover:show_text:%user_id%][click:copy_to_clipboard:%user_id%]@%user_name%[click][hover]"
})
public MinecraftMessage minecraftPlayerLinkedTo = make("%1 %2is linked to %3");
@Constants({
SUCCESS_COLOR + "[hover:show_text:%player_uuid%][click:copy_to_clipboard:%player_uuid%]%player_name|text:'<Unknown>'%[click][hover]",
NEUTRAL_COLOR,
ERROR_COLOR
})
public MinecraftMessage minecraftPlayerUnlinked = make("%1 %2is %3unlinked");
@Comment("/discord unlink")
@Constants({SUCCESS_COLOR})
public MinecraftMessage unlinked = make("%1Accounts unlinked");
}
@ -134,21 +339,6 @@ public class MessagesConfig implements Config {
@Constants(ERROR_PREFIX)
public String unableToCheckLinkingStatus = "%1Unable to check linking status, please try again later";
@Untranslated(Untranslated.Type.COMMENT)
@Comment("/discord link")
@Constants(ERROR_PREFIX)
public String playerAlreadyLinked3rd = "%1That Minecraft player is already linked";
@Constants(ERROR_PREFIX)
public String userAlreadyLinked3rd = "%1That Discord user is already linked";
@Constants({
SUCCESS_PREFIX,
"**%player_name%** (%player_uuid%)",
"**%user_name%** (%user_id%)"
})
public String nowLinked3rd = "%1Link created successfully\n%2 and %3";
@Untranslated(Untranslated.Type.COMMENT)
@Comment("/discord linked")
@Constants({
SUCCESS_PREFIX,
"**%user_name%** (<@%user_id%>)",
@ -156,11 +346,9 @@ public class MessagesConfig implements Config {
})
public String discordUserLinkedTo = "%1%2 is linked to %3";
@Untranslated(Untranslated.Type.COMMENT)
@Comment("/discord linked")
@Constants({
ERROR_PREFIX,
"**%user_name%** (%user_id%)"
"**%user_name%** (<@%user_id%>)"
})
public String discordUserUnlinked = "%1%2 is __unlinked__";
@ -176,5 +364,24 @@ public class MessagesConfig implements Config {
"**%player_name%** (%player_uuid%)"
})
public String minecraftPlayerUnlinked = "%1%2 is __unlinked__";
@Untranslated(Untranslated.Type.COMMENT)
@Comment("/discord link")
@Constants(ERROR_PREFIX)
public String playerAlreadyLinked3rd = "%1That Minecraft player is already linked";
@Constants(ERROR_PREFIX)
public String userAlreadyLinked3rd = "%1That Discord user is already linked";
@Constants({
SUCCESS_PREFIX,
"**%player_name%** (%player_uuid%)",
"**%user_name%** (<@%user_id%>)"
})
public String nowLinked3rd = "%1Link created successfully\n%2 and %3";
@Untranslated(Untranslated.Type.COMMENT)
@Comment("/discord unlink")
@Constants({SUCCESS_PREFIX})
public String unlinked = "%1Accounts unlinked";
}
}

View File

@ -11,10 +11,12 @@ public enum Permission {
COMMAND_VERSION("command.admin.version"),
COMMAND_LINK_OTHER("command.admin.link.other"),
COMMAND_LINKED_OTHER("command.admin.linked.other"),
COMMAND_UNLINK_OTHER("command.admin.linked.other"),
// Player
COMMAND_ROOT("command.player.root"),
COMMAND_LINK("command.player.link"),
COMMAND_LINKED("command.player.linked"),
COMMAND_UNLINK("command.player.unlink"),
// Mentions
MENTION_USER("mention.user.base"),

View File

@ -139,7 +139,7 @@ public abstract class SQLStorage implements Storage {
@Override
public void removeLink(@NotNull UUID player, long userId) {
useConnection(connection -> {
try (PreparedStatement statement = connection.prepareStatement("delete " + tablePrefix() + LINKED_ACCOUNTS_TABLE_NAME + " where PLAYER_UUID = ?;")) {
try (PreparedStatement statement = connection.prepareStatement("delete from " + tablePrefix() + LINKED_ACCOUNTS_TABLE_NAME + " where PLAYER_UUID = ?;")) {
statement.setString(1, player.toString());
exceptEffectedRows(statement.executeUpdate(), 1);
}
@ -168,7 +168,7 @@ public abstract class SQLStorage implements Storage {
public UUID getLinkingCode(String code) {
return useConnection(connection -> {
// Clean expired codes
try (PreparedStatement statement = connection.prepareStatement("DELETE FROM " + tablePrefix() + LINKING_CODES_TABLE_NAME + " where EXPIRY < ?;")) {
try (PreparedStatement statement = connection.prepareStatement("delete from " + tablePrefix() + LINKING_CODES_TABLE_NAME + " where EXPIRY < ?;")) {
statement.setLong(1, getTimeMS());
statement.executeUpdate();
}
@ -188,7 +188,7 @@ public abstract class SQLStorage implements Storage {
@Override
public void removeLinkingCode(@NotNull UUID player) {
useConnection(connection -> {
try (PreparedStatement statement = connection.prepareStatement("DELETE FROM " + tablePrefix() + LINKING_CODES_TABLE_NAME + " WHERE PLAYERUUID = ?")) {
try (PreparedStatement statement = connection.prepareStatement("delete from " + tablePrefix() + LINKING_CODES_TABLE_NAME + " WHERE PLAYERUUID = ?")) {
statement.setString(1, player.toString());
statement.executeUpdate();
}
@ -199,13 +199,13 @@ public abstract class SQLStorage implements Storage {
public void storeLinkingCode(@NotNull UUID player, String code) {
useConnection(connection -> {
// Remove existing code
try (PreparedStatement statement = connection.prepareStatement("DELETE FROM " + tablePrefix() + LINKING_CODES_TABLE_NAME + " where PLAYERUUID = ?")) {
try (PreparedStatement statement = connection.prepareStatement("delete from " + tablePrefix() + LINKING_CODES_TABLE_NAME + " where PLAYERUUID = ?")) {
statement.setString(1, player.toString());
statement.executeUpdate();
}
// Insert new code
try (PreparedStatement statement = connection.prepareStatement("INSERT INTO " + tablePrefix() + LINKING_CODES_TABLE_NAME + " (PLAYERUUID, CODE, EXPIRY)")) {
try (PreparedStatement statement = connection.prepareStatement("insert into " + tablePrefix() + LINKING_CODES_TABLE_NAME + " (PLAYERUUID, CODE, EXPIRY)")) {
statement.setString(1, player.toString());
statement.setString(2, code);
statement.setLong(3, getTimeMS() + LinkStore.LINKING_CODE_EXPIRY_TIME.toMillis());