Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.tfminecraft.tfmcweb.managers;

import java.util.List;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

Expand All @@ -17,7 +20,7 @@
/**
* /linkdiscord — start Discord account link (async HTTP).
*/
public final class LinkDiscordCommand implements CommandExecutor {
public final class LinkDiscordCommand implements CommandExecutor, TabCompleter {

private final JavaPlugin plugin;
private final LinkCache linkCache;
Expand All @@ -33,6 +36,11 @@ public LinkDiscordCommand(
this.gateService = gateService;
}

@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return List.of();
}

// Keep the existing legacy text representation, formatting, and exact-string comparisons.
@SuppressWarnings("deprecation")
@Override
Expand Down
11 changes: 4 additions & 7 deletions src/main/java/net/tfminecraft/tfmcweb/managers/TokenCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -376,20 +376,17 @@ public List<String> onTabComplete(
if (args.length == 2 && "create".equalsIgnoreCase(args[0])) {
String p = args[1].toLowerCase(Locale.ROOT);
List<String> out = new ArrayList<>();
if (((canCreate && Cache.isTokenScopeEnabled("skin"))
|| (canStaff && Cache.isTokenScopeEnabled("skin_staff"))) && "skin".startsWith(p)) {
out.add("skin");
}
if (canCreate) {
if (Cache.isTokenScopeEnabled("skin") && "skin".startsWith(p)) {
out.add("skin");
}
if (Cache.isTokenScopeEnabled("drink") && "drink".startsWith(p)) {
out.add("drink");
}
if (Cache.isTokenScopeEnabled("profile") && "profile".startsWith(p)) {
out.add("profile");
}
} else if (canStaff
&& Cache.isTokenScopeEnabled("skin_staff")
&& "skin".startsWith(p)) {
out.add("skin");
}
return out;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.tfminecraft.tfmcweb.managers;

import java.util.List;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

Expand All @@ -16,7 +19,7 @@
/**
* /unlinkdiscord — remove Discord link for this Minecraft UUID (async HTTP).
*/
public final class UnlinkDiscordCommand implements CommandExecutor {
public final class UnlinkDiscordCommand implements CommandExecutor, TabCompleter {

private final JavaPlugin plugin;
private final LinkCache linkCache;
Expand All @@ -32,6 +35,11 @@ public UnlinkDiscordCommand(
this.gateService = gateService;
}

@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return List.of();
}

// Keep the existing legacy text representation, formatting, and exact-string comparisons.
@SuppressWarnings("deprecation")
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package net.tfminecraft.tfmcweb.managers;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.stream.Collectors;

Expand All @@ -10,6 +12,7 @@
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

Expand All @@ -21,7 +24,7 @@
/**
* /warning &lt;player&gt; &lt;reason…&gt; — in-game chat + web store + Discord DM via bot.
*/
public final class WarningCommand implements CommandExecutor {
public final class WarningCommand implements CommandExecutor, TabCompleter {

private final JavaPlugin plugin;
private final LinkCache linkCache;
Expand All @@ -31,6 +34,14 @@ public WarningCommand(JavaPlugin plugin, LinkCache linkCache) {
this.linkCache = linkCache;
}

@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length != 1 || !sender.hasPermission("tfmcweb.warning")) return List.of();
String prefix = args[0].toLowerCase(Locale.ROOT);
return Bukkit.getOnlinePlayers().stream().map(Player::getName)
.filter(name -> name.toLowerCase(Locale.ROOT).startsWith(prefix)).toList();
}

// Keep the existing legacy text representation, formatting, and exact-string comparisons.
@SuppressWarnings("deprecation")
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,29 @@ class PlayerAndAdminCommandsTest {
@BeforeEach void setup() throws Exception {f=new CommandFixture();}
@AfterEach void cleanup() throws Exception {f.close();}
void run(CommandExecutor command,org.bukkit.command.CommandSender sender,String...args){assertTrue(command.onCommand(sender,null,"cmd",args));}
@Test void operandFreeDiscordCommandsNeverSuggestPlayerNames() {
var link=new LinkDiscordCommand(f.plugin,f.cache,f.gate);
var unlink=new UnlinkDiscordCommand(f.plugin,f.cache,f.gate);
for(var sender:List.of(f.player,f.console)) {
for(String[] args:List.of(new String[0],new String[]{""},new String[]{"A"},new String[]{"Ada",""})) {
assertTrue(link.onTabComplete(sender,null,"linkdiscord",args).isEmpty());
assertTrue(unlink.onTabComplete(sender,null,"unlinkdiscord",args).isEmpty());
}
}
}

@Test void warningOnlyCompletesTheAuthorizedTargetArgument() {
var warning=new WarningCommand(f.plugin,f.cache);
assertTrue(warning.onTabComplete(f.console,null,"warning",new String[]{""}).isEmpty());
f.permissions(f.console,true);
assertEquals(List.of("Ada"),warning.onTabComplete(f.console,null,"warning",new String[]{""}));
assertEquals(List.of("Ada"),warning.onTabComplete(f.console,null,"warning",new String[]{"aD"}));
assertTrue(warning.onTabComplete(f.console,null,"warning",new String[]{"zzz"}).isEmpty());
for(String[] args:List.of(new String[0],new String[]{"Ada",""},new String[]{"Ada","reason",""})) {
assertTrue(warning.onTabComplete(f.console,null,"warning",args).isEmpty());
}
}

@Test void linkShowsCodesFailuresOrExistingIdentityAndIgnoresOfflinePlayer() {
var cmd=new LinkDiscordCommand(f.plugin,f.cache,f.gate);run(cmd,f.console);assertTrue(f.contains("Players only"));
for(CodeResult result:List.of(CodeResult.fail(null),CodeResult.fail("backend"),CodeResult.alreadyLinked(" AdaDiscord "),CodeResult.alreadyLinked(" "),CodeResult.success("ABC",Instant.now().plusSeconds(4000).toString()),CodeResult.success("ABC",null))){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ class TokenCommandTest {
when(f.player.isOnline()).thenReturn(false);f.messages.clear();run(f.player,"resetcooldowns","Ada");assertTrue(f.messages.isEmpty());
f.api.when(()->ProvinceSystemClient.resetCosmeticMintCooldowns(f.id.toString(),f.id.toString())).thenReturn(SimpleResult.success());run(f.player,"resetcooldowns","Ada");assertTrue(f.messages.isEmpty());
}
@Test void ordinaryCreatePermissionDoesNotHideTheEnabledStaffSkinRoute() {
f.permissions(f.player,true);
Cache.tokenEnabledScopes=List.of("skin_staff");
when(f.player.hasPermission("tfmcweb.token.create")).thenReturn(false);
assertEquals(List.of("skin"),command.onTabComplete(f.player,null,"token",new String[]{"create",""}));
when(f.player.hasPermission("tfmcweb.token.create")).thenReturn(true);
assertEquals(List.of("skin"),command.onTabComplete(f.player,null,"token",new String[]{"create",""}));
assertEquals(List.of("skin"),command.onTabComplete(f.player,null,"token",new String[]{"CREATE","S"}));
assertEquals(List.of("staff"),command.onTabComplete(f.player,null,"token",new String[]{"create","skin",""}));
when(f.player.hasPermission("tfmcweb.token.create.staff")).thenReturn(false);
assertTrue(command.onTabComplete(f.player,null,"token",new String[]{"create",""}).isEmpty());
Cache.tokenEnabledScopes=List.of("skin","skin_staff");
when(f.player.hasPermission("tfmcweb.token.create.staff")).thenReturn(true);
assertEquals(List.of("skin"),command.onTabComplete(f.player,null,"token",new String[]{"create",""}));
}

@Test void completionsRespectPermissionsEnabledScopesAndPrefix() {
assertTrue(command.onTabComplete(f.player,null,"token",new String[]{""}).isEmpty());f.permissions(f.player,true);
assertEquals(List.of("create","resetcooldowns"),command.onTabComplete(f.player,null,"token",new String[]{""}));
Expand Down