Skip to content

Commit

Permalink
Resolve UUIDs given as arguments in more places
Browse files Browse the repository at this point in the history
* Lookup the player's address if only a UUID was specified.
* Also, improve tab completion by including usage, help, etc.
  • Loading branch information
A248 committed Jan 27, 2024
1 parent 2985be9 commit 21dce81
Show file tree
Hide file tree
Showing 15 changed files with 161 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,20 @@
import space.arim.libertybans.core.alts.WhichAlts;
import space.arim.libertybans.core.commands.extra.TabCompletion;
import space.arim.libertybans.core.env.CmdSender;
import space.arim.libertybans.core.uuid.UUIDManager;
import space.arim.omnibus.util.concurrent.ReactionStage;

import java.util.stream.Stream;

@Singleton
public final class AltCommands extends AbstractSubCommandGroup {

private final UUIDManager uuidManager;
private final AltDetection altDetection;
private final AltCheckFormatter altCheckFormatter;
private final TabCompletion tabCompletion;

@Inject
public AltCommands(Dependencies dependencies, UUIDManager uuidManager, AltDetection altDetection, AltCheckFormatter altCheckFormatter, TabCompletion tabCompletion) {
public AltCommands(Dependencies dependencies, AltDetection altDetection, AltCheckFormatter altCheckFormatter, TabCompletion tabCompletion) {
super(dependencies, "alts");
this.uuidManager = uuidManager;
this.altDetection = altDetection;
this.altCheckFormatter = altCheckFormatter;
this.tabCompletion = tabCompletion;
Expand Down Expand Up @@ -92,12 +89,11 @@ public ReactionStage<Void> execute() {
return null;
}
String target = command().next();
return uuidManager.lookupPlayer(target).thenCompose((userDetails) -> {
if (userDetails.isEmpty()) {
sender().sendMessage(messages().all().notFound().player().replaceText("%TARGET%", target));
return argumentParser().parsePlayer(sender(), target).thenCompose((userDetails) -> {
if (userDetails == null) {
return completedFuture(null);
}
return altDetection.detectAlts(userDetails.get(), WhichAlts.ALL_ALTS).thenAccept((detectedAlts) -> {
return altDetection.detectAlts(userDetails, WhichAlts.ALL_ALTS).thenAccept((detectedAlts) -> {
if (detectedAlts.isEmpty()) {
sender().sendMessage(altsConfig().command().noneFound());
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,18 @@ public void execute(CmdSender sender, CommandPackage command) {
*/

private List<String> subCommandCompletions(CmdSender sender, Predicate<String> filter) {
return subCommandGroups.stream()
.flatMap((subCommandGroup) -> {
Stream<String> combined = Stream.concat(
subCommandGroups.stream().flatMap((subCommandGroup) -> {
return subCommandGroup.matches()
.stream()
.filter((subCmd) -> subCommandGroup.hasTabCompletePermission(sender, subCmd));
})
}),
Stream.of("version", "about", "usage", "help")
);
return combined
.filter(filter)
.sorted()
.collect(Collectors.toUnmodifiableList());
.toList();
}

@Override
Expand Down Expand Up @@ -149,7 +152,7 @@ public List<String> suggest(CmdSender sender, String[] args) {
if (!lastArg.isEmpty()) {
completions = completions.filter((completion) -> completion.toLowerCase(Locale.ROOT).startsWith(lastArg));
}
return completions.sorted().collect(Collectors.toUnmodifiableList());
return completions.sorted().toList();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@

import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Supplier;

public class StandardArgumentParser implements ArgumentParser {

Expand Down Expand Up @@ -74,41 +76,48 @@ private MessagesConfig.All.NotFound notFound() {
return all().notFound();
}

@Override
public CentralisedFuture<@Nullable UUID> parseOrLookupUUID(CmdSender sender, String targetArg) {
private <R> CentralisedFuture<@Nullable R> parseUUIDIfPossible(CmdSender sender, String targetArg,
Function<UUID, CentralisedFuture<R>> ifUuid,
Supplier<CentralisedFuture<R>> otherwise) {
return switch (targetArg.length()) {
case 36 -> {
UUID uuid;
try {
uuid = UUID.fromString(targetArg);
} catch (IllegalArgumentException ex) {
sender.sendMessage(notFound().uuid().replaceText("%TARGET%", targetArg));
yield completedFuture(null);
}
yield completedFuture(uuid);
}
case 32 -> {
long mostSigBits;
long leastSigBits;
try {
mostSigBits = Long.parseUnsignedLong(targetArg.substring(0, 16), 16);
leastSigBits = Long.parseUnsignedLong(targetArg.substring(16, 32), 16);
} catch (NumberFormatException ex) {
sender.sendMessage(notFound().uuid().replaceText("%TARGET%", targetArg));
yield completedFuture(null);
case 36 -> {
UUID uuid;
try {
uuid = UUID.fromString(targetArg);
} catch (IllegalArgumentException ex) {
sender.sendMessage(notFound().uuid().replaceText("%TARGET%", targetArg));
yield completedFuture(null);
}
yield ifUuid.apply(uuid);
}
yield completedFuture(new UUID(mostSigBits, leastSigBits));
}
default -> uuidManager.lookupUUID(targetArg).thenApply((uuid) -> {
if (uuid.isEmpty()) {
sender.sendMessage(notFound().player().replaceText("%TARGET%", targetArg));
return null;
case 32 -> {
long mostSigBits;
long leastSigBits;
try {
mostSigBits = Long.parseUnsignedLong(targetArg.substring(0, 16), 16);
leastSigBits = Long.parseUnsignedLong(targetArg.substring(16, 32), 16);
} catch (NumberFormatException ex) {
sender.sendMessage(notFound().uuid().replaceText("%TARGET%", targetArg));
yield completedFuture(null);
}
yield ifUuid.apply(new UUID(mostSigBits, leastSigBits));
}
return uuid.get();
});
default -> otherwise.get();
};
}

@Override
public CentralisedFuture<@Nullable UUID> parseOrLookupUUID(CmdSender sender, String targetArg) {
return parseUUIDIfPossible(sender, targetArg, this::completedFuture,
() -> uuidManager.lookupUUID(targetArg).thenApply((uuid) -> {
if (uuid.isEmpty()) {
sender.sendMessage(notFound().player().replaceText("%TARGET%", targetArg));
return null;
}
return uuid.get();
}));
}

@Override
public CentralisedFuture<@Nullable Operator> parseOperator(CmdSender sender, String operatorArg) {
if (ContainsCI.containsIgnoreCase(configs.getMessagesConfig().formatting().consoleArguments(), operatorArg)) {
Expand Down Expand Up @@ -148,13 +157,21 @@ private MessagesConfig.All.NotFound notFound() {

@Override
public CentralisedFuture<@Nullable UUIDAndAddress> parsePlayer(CmdSender sender, String targetArg) {
return uuidManager.lookupPlayer(targetArg).thenApply((optUuidAndAddress) -> {
return parseUUIDIfPossible(sender, targetArg, (uuid) -> {
return uuidManager.lookupLastAddress(uuid).thenApply((optAddress) -> {
if (optAddress.isEmpty()) {
sender.sendMessage(notFound().player().replaceText("%TARGET%", targetArg));
return null;
}
return new UUIDAndAddress(uuid, optAddress.get());
});
}, () -> uuidManager.lookupPlayer(targetArg).thenApply((optUuidAndAddress) -> {
if (optUuidAndAddress.isEmpty()) {
sender.sendMessage(notFound().player().replaceText("%TARGET%", targetArg));
return null;
}
return optUuidAndAddress.get();
});
}));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ public interface EnvUserResolver {

CentralisedFuture<Optional<UUIDAndAddress>> lookupPlayer(String name);

CentralisedFuture<Optional<InetAddress>> lookupCurrentAddress(UUID uuid);

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public final CentralisedFuture<Optional<UUIDAndAddress>> lookupPlayer(String nam
return performLookup(() -> lookupPlayer0(name));
}

@Override
public final CentralisedFuture<Optional<InetAddress>> lookupCurrentAddress(UUID uuid) {
return performLookup(() -> lookupCurrentAddress0(uuid));
}

protected abstract Optional<UUID> lookupUUID0(String name);

protected abstract Optional<String> lookupName0(UUID uuid);
Expand All @@ -70,4 +75,6 @@ public final CentralisedFuture<Optional<UUIDAndAddress>> lookupPlayer(String nam

protected abstract Optional<UUIDAndAddress> lookupPlayer0(String name);

protected abstract Optional<InetAddress> lookupCurrentAddress0(UUID uuid);

}
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,14 @@ public CentralisedFuture<Optional<UUIDAndAddress>> lookupPlayer(String name) {
});
}

@Override
public CentralisedFuture<Optional<NetworkAddress>> lookupLastAddress(UUID uuid) {
return envResolver.lookupCurrentAddress(uuid).thenCompose((envResolve) -> {
if (envResolve.isPresent()) {
return completedFuture(envResolve.map(NetworkAddress::of));
}
return queryingImpl.resolveLastAddress(uuid).thenApply(Optional::ofNullable);
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,16 @@ CentralisedFuture<UUIDAndAddress> resolvePlayer(String name) {
}));
}

CentralisedFuture<NetworkAddress> resolveLastAddress(UUID uuid) {
return dbProvider.get().query(SQLFunction.readOnly((context) -> {
return context
.select(ADDRESSES.ADDRESS)
.from(ADDRESSES)
.where(ADDRESSES.UUID.eq(uuid))
.orderBy(ADDRESSES.UPDATED.desc())
.limit(1)
.fetchOne(ADDRESSES.ADDRESS);
}));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,13 @@ public interface UUIDManager extends UserResolver, Part {
* @return a future yielding the user details or an empty optional if not found
*/
CentralisedFuture<Optional<UUIDAndAddress>> lookupPlayer(String name);


/**
* Looks up player details from a UUID
*
* @param uuid the uuid of the player
* @return a future yielding the latest address or an empty optional if not found
*/
CentralisedFuture<Optional<NetworkAddress>> lookupLastAddress(UUID uuid);

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package space.arim.libertybans.core.alts;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -90,7 +91,7 @@ public void formatMessage() throws UnknownHostException {
}
assertEquals("Alt report for MainUser\n" +
"detection_kind: " + alt.detectionKind() + ", address: " + address + ", username: " + username +
", " + "user_id: " + userId + ", date_recorded: " + date,
", user_id: " + userId + ", date_recorded: " + date,
PlainComponentSerializer.plain().serialize(altCheckFormatter.formatMessage(header, "MainUser", List.of(alt))));
}

Expand Down Expand Up @@ -134,4 +135,33 @@ public void formatPunishedAltsWithDetectionKind() throws UnknownHostException {
kind: NORMAL, username: None(Saint)""",
PlainComponentSerializer.plain().serialize(formattedMessage));
}

@Test
public void replaceUsernameInCommandOfLayout() throws UnknownHostException {
ComponentText header = ComponentText.create(Component.text("Alt report for %TARGET%"));
String address = "207.144.101.102";
UUID userId = UUID.randomUUID();
String username = "AltUser";
Instant date = Instant.parse("2021-07-23T02:15:23.000000Z");
DetectedAlt alt = new DetectedAlt(
userId, username, NetworkAddress.of(InetAddress.getByName(address)), date, DetectionKind.NORMAL
);
{
when(conf.layout()).thenReturn(ComponentText.create(Component.text(
"address: %ADDRESS%, date_recorded: %DATE_RECORDED%")
.clickEvent(ClickEvent.runCommand("/msg %RELEVANT_USER% hello"))
));
when(conf.normal()).thenReturn(Component.text("NORMAL"));
var nameDisplay = mock(AltsSection.Formatting.NameDisplay.class);
when(nameDisplay.notPunished()).thenReturn(ComponentText.create(Component.text("%USERNAME%")));
when(conf.nameDisplay()).thenReturn(nameDisplay);
when(formatter.prefix(any())).thenAnswer((invocation) -> invocation.getArgument(0));
when(formatter.formatAbsoluteDate(date)).thenReturn(date.toString());
}
assertEquals(Component.text(
"Alt report for MainUser\n" +
"address: " + address + ", date_recorded: " + date)
.clickEvent(ClickEvent.runCommand("/msg " + username + " hello")),
altCheckFormatter.formatMessage(header, "MainUser", List.of(alt)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,9 @@ public Optional<UUIDAndAddress> lookupPlayer0(String name) {
.map((player) -> new UUIDAndAddress(player.getUniqueId(), player.getAddress()));
}

@Override
public Optional<InetAddress> lookupCurrentAddress0(UUID uuid) {
return platform.getPlayer(uuid).map(QuackPlayer::getAddress);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ public Optional<UUIDAndAddress> lookupPlayer0(String name) {
.map((player) -> new UUIDAndAddress(player.getUniqueId(), addressReporter.getAddress(player)));
}

@Override
public Optional<InetAddress> lookupCurrentAddress0(UUID uuid) {
return Optional.ofNullable(server.getPlayer(uuid)).map(addressReporter::getAddress);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,9 @@ public Optional<UUIDAndAddress> lookupPlayer0(String name) {
.map((player) -> new UUIDAndAddress(player.getUniqueId(), player.getAddress().getAddress()));
}

@Override
public Optional<InetAddress> lookupCurrentAddress0(UUID uuid) {
return Optional.ofNullable(server.getPlayer(uuid)).map((player) -> player.getAddress().getAddress());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,9 @@ public Optional<UUIDAndAddress> lookupPlayer0(String name) {
.map((player) -> new UUIDAndAddress(player.uniqueId(), player.connection().address().getAddress()));
}

@Override
public Optional<InetAddress> lookupCurrentAddress0(UUID uuid) {
return game.server().player(uuid).map((player) -> player.connection().address().getAddress());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ public Optional<UUIDAndAddress> lookupPlayer0(String name) {
return Optional.empty();
}

@Override
public Optional<InetAddress> lookupCurrentAddress0(UUID uuid) {
return Optional.empty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,9 @@ public Optional<UUIDAndAddress> lookupPlayer0(String name) {
.map((player) -> new UUIDAndAddress(player.getUniqueId(), player.getRemoteAddress().getAddress()));
}

@Override
public Optional<InetAddress> lookupCurrentAddress0(UUID uuid) {
return server.getPlayer(uuid).map((player) -> player.getRemoteAddress().getAddress());
}

}

0 comments on commit 21dce81

Please sign in to comment.