MultiServer: fix case sensitivity in server commands (#1156)
* fix case sensitivity in server commands * improve ambiguous match breakout * worried about accidentally swapping team and slot * Remove now unused import
This commit is contained in:
parent
ed23a426ec
commit
09d8c4b912
|
@ -1802,14 +1802,32 @@ class ServerCommandProcessor(CommonCommandProcessor):
|
|||
self.output(response)
|
||||
return False
|
||||
|
||||
def resolve_player(self, input_name: str) -> typing.Optional[typing.Tuple[int, int, str]]:
|
||||
""" returns (team, slot, player name) """
|
||||
# first match case
|
||||
for (team, slot), name in self.ctx.player_names.items():
|
||||
if name == input_name:
|
||||
return team, slot, name
|
||||
|
||||
# if no case-sensitive match, then match without case only if there's only 1 match
|
||||
input_lower = input_name.lower()
|
||||
match: typing.Optional[typing.Tuple[int, int, str]] = None
|
||||
for (team, slot), name in self.ctx.player_names.items():
|
||||
lowered = name.lower()
|
||||
if lowered == input_lower:
|
||||
if match:
|
||||
return None # ambiguous input_name
|
||||
match = (team, slot, name)
|
||||
return match
|
||||
|
||||
@mark_raw
|
||||
def _cmd_collect(self, player_name: str) -> bool:
|
||||
"""Send out the remaining items to player."""
|
||||
seeked_player = player_name.lower()
|
||||
for (team, slot), name in self.ctx.player_names.items():
|
||||
if name.lower() == seeked_player:
|
||||
collect_player(self.ctx, team, slot)
|
||||
return True
|
||||
player = self.resolve_player(player_name)
|
||||
if player:
|
||||
team, slot, _ = player
|
||||
collect_player(self.ctx, team, slot)
|
||||
return True
|
||||
|
||||
self.output(f"Could not find player {player_name} to collect")
|
||||
return False
|
||||
|
@ -1822,11 +1840,11 @@ class ServerCommandProcessor(CommonCommandProcessor):
|
|||
@mark_raw
|
||||
def _cmd_forfeit(self, player_name: str) -> bool:
|
||||
"""Send out the remaining items from a player to their intended recipients."""
|
||||
seeked_player = player_name.lower()
|
||||
for (team, slot), name in self.ctx.player_names.items():
|
||||
if name.lower() == seeked_player:
|
||||
forfeit_player(self.ctx, team, slot)
|
||||
return True
|
||||
player = self.resolve_player(player_name)
|
||||
if player:
|
||||
team, slot, _ = player
|
||||
forfeit_player(self.ctx, team, slot)
|
||||
return True
|
||||
|
||||
self.output(f"Could not find player {player_name} to release")
|
||||
return False
|
||||
|
@ -1834,12 +1852,12 @@ class ServerCommandProcessor(CommonCommandProcessor):
|
|||
@mark_raw
|
||||
def _cmd_allow_forfeit(self, player_name: str) -> bool:
|
||||
"""Allow the specified player to use the !release command."""
|
||||
seeked_player = player_name.lower()
|
||||
for (team, slot), name in self.ctx.player_names.items():
|
||||
if name.lower() == seeked_player:
|
||||
self.ctx.allow_forfeits[(team, slot)] = True
|
||||
self.output(f"Player {player_name} is now allowed to use the !release command at any time.")
|
||||
return True
|
||||
player = self.resolve_player(player_name)
|
||||
if player:
|
||||
team, slot, name = player
|
||||
self.ctx.allow_forfeits[(team, slot)] = True
|
||||
self.output(f"Player {name} is now allowed to use the !release command at any time.")
|
||||
return True
|
||||
|
||||
self.output(f"Could not find player {player_name} to allow the !release command for.")
|
||||
return False
|
||||
|
@ -1847,13 +1865,12 @@ class ServerCommandProcessor(CommonCommandProcessor):
|
|||
@mark_raw
|
||||
def _cmd_forbid_forfeit(self, player_name: str) -> bool:
|
||||
""""Disallow the specified player from using the !release command."""
|
||||
seeked_player = player_name.lower()
|
||||
for (team, slot), name in self.ctx.player_names.items():
|
||||
if name.lower() == seeked_player:
|
||||
self.ctx.allow_forfeits[(team, slot)] = False
|
||||
self.output(
|
||||
f"Player {player_name} has to follow the server restrictions on use of the !release command.")
|
||||
return True
|
||||
player = self.resolve_player(player_name)
|
||||
if player:
|
||||
team, slot, name = player
|
||||
self.ctx.allow_forfeits[(team, slot)] = False
|
||||
self.output(f"Player {name} has to follow the server restrictions on use of the !release command.")
|
||||
return True
|
||||
|
||||
self.output(f"Could not find player {player_name} to forbid the !release command for.")
|
||||
return False
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import unittest
|
||||
from MultiServer import Context, ServerCommandProcessor
|
||||
|
||||
|
||||
class TestResolvePlayerName(unittest.TestCase):
|
||||
def test_resolve(self) -> None:
|
||||
p = ServerCommandProcessor(Context("", 0, "", "", 0, 0, False))
|
||||
p.ctx.player_names = {
|
||||
(1, 1): "AAA",
|
||||
(1, 2): "aBc",
|
||||
(1, 3): "abC",
|
||||
}
|
||||
assert not p.resolve_player("abc"), "ambiguous name entry shouldn't resolve to player"
|
||||
assert not p.resolve_player("Abc"), "ambiguous name entry shouldn't resolve to player"
|
||||
assert p.resolve_player("aBc") == (1, 2, "aBc"), "matching case resolve"
|
||||
assert p.resolve_player("abC") == (1, 3, "abC"), "matching case resolve"
|
||||
assert not p.resolve_player("aB"), "partial name shouldn't resolve to player"
|
||||
assert not p.resolve_player("abCD"), "incorrect name shouldn't resolve to player"
|
||||
|
||||
p.ctx.player_names = {
|
||||
(1, 1): "aaa",
|
||||
(1, 2): "abc",
|
||||
(1, 3): "abC",
|
||||
}
|
||||
assert p.resolve_player("abc") == (1, 2, "abc"), "matching case resolve"
|
||||
assert not p.resolve_player("Abc"), "ambiguous name entry shouldn't resolve to player"
|
||||
assert not p.resolve_player("aBc"), "ambiguous name entry shouldn't resolve to player"
|
||||
assert p.resolve_player("abC") == (1, 3, "abC"), "matching case resolve"
|
||||
|
||||
p.ctx.player_names = {
|
||||
(1, 1): "AbcdE",
|
||||
(1, 2): "abc",
|
||||
(1, 3): "abCD",
|
||||
}
|
||||
assert p.resolve_player("abc") == (1, 2, "abc"), "matching case resolve"
|
||||
assert p.resolve_player("abC") == (1, 2, "abc"), "case insensitive resolves when 1 match"
|
||||
assert p.resolve_player("Abc") == (1, 2, "abc"), "case insensitive resolves when 1 match"
|
||||
assert p.resolve_player("ABC") == (1, 2, "abc"), "case insensitive resolves when 1 match"
|
||||
assert p.resolve_player("abcd") == (1, 3, "abCD"), "case insensitive resolves when 1 match"
|
||||
assert not p.resolve_player("aB"), "partial name shouldn't resolve to player"
|
Loading…
Reference in New Issue