Fix for #176 improve invalid role errors

This commit is contained in:
Fudster 2017-02-02 02:31:51 +00:00 committed by jacob1
parent 4c67a5b438
commit 0a6c6200ab
2 changed files with 66 additions and 42 deletions

View File

@ -15,7 +15,7 @@ __all__ = ["pm", "is_fake_nick", "mass_mode", "mass_privmsg", "reply",
"is_owner", "is_admin", "plural", "singular", "list_players", "is_owner", "is_admin", "plural", "singular", "list_players",
"list_players_and_roles", "list_participants", "get_role", "get_roles", "list_players_and_roles", "list_participants", "get_role", "get_roles",
"get_reveal_role", "get_templates", "role_order", "break_long_message", "get_reveal_role", "get_templates", "role_order", "break_long_message",
"complete_match", "get_victim", "get_nick", "InvalidModeException"] "complete_match","complete_one_match", "get_victim", "get_nick", "InvalidModeException"]
# message either privmsg or notice, depending on user settings # message either privmsg or notice, depending on user settings
def pm(cli, target, message): def pm(cli, target, message):
if is_fake_nick(target) and botconfig.DEBUG_MODE: if is_fake_nick(target) and botconfig.DEBUG_MODE:
@ -418,18 +418,19 @@ def break_long_message(phrases, joinstr = " "):
#completes a partial nickname or string from a list #completes a partial nickname or string from a list
def complete_match(string, matches): def complete_match(string, matches):
num_matches = 0 possible_matches = set()
bestmatch = string
for possible in matches: for possible in matches:
if string == possible: if string == possible:
return string, 1 return [string]
if possible.startswith(string) or possible.lstrip("[{\\^_`|}]").startswith(string): if possible.startswith(string) or possible.lstrip("[{\\^_`|}]").startswith(string):
bestmatch = possible possible_matches.add(possible)
num_matches += 1 return sorted(possible_matches)
if num_matches != 1:
return None, num_matches def complete_one_match(string, matches):
else: matches = complete_match(string,matches)
return bestmatch, 1 if len(matches) == 1:
return matches.pop()
return None
#wrapper around complete_match() used for roles #wrapper around complete_match() used for roles
def get_victim(cli, nick, victim, in_chan, self_in_list=False, bot_in_list=False): def get_victim(cli, nick, victim, in_chan, self_in_list=False, bot_in_list=False):
@ -444,20 +445,20 @@ def get_victim(cli, nick, victim, in_chan, self_in_list=False, bot_in_list=False
pl.append(botconfig.NICK) pl.append(botconfig.NICK)
pll.append(botconfig.NICK.lower()) pll.append(botconfig.NICK.lower())
tempvictim, num_matches = complete_match(victim.lower(), pll) tempvictims = complete_match(victim.lower(), pll)
if not tempvictim: if len(tempvictims) != 1:
#ensure messages about not being able to act on yourself work #ensure messages about not being able to act on yourself work
if num_matches == 0 and nick.lower().startswith(victim.lower()): if len(tempvictims) == 0 and nick.lower().startswith(victim.lower()):
return nick return nick
reply(cli, nick, chan, messages["not_playing"].format(victim), private=True) reply(cli, nick, chan, messages["not_playing"].format(victim), private=True)
return return
return pl[pll.index(tempvictim)] #convert back to normal casing return pl[pll.index(tempvictims.pop())] #convert back to normal casing
# wrapper around complete_match() used for any nick on the channel # wrapper around complete_match() used for any nick on the channel
def get_nick(cli, nick): def get_nick(cli, nick):
ul = [x for x in var.USERS] ul = [x for x in var.USERS]
ull = [x.lower() for x in var.USERS] ull = [x.lower() for x in var.USERS]
lnick, num_matches = complete_match(nick.lower(), ull) lnick = complete_match(nick.lower(), ull)
if not lnick: if not lnick:
return None return None
return ul[ull.index(lnick)] return ul[ull.index(lnick)]

View File

@ -2920,7 +2920,7 @@ def goat(cli, nick, chan, rest):
if not rest: if not rest:
cli.notice(nick, messages["not_enough_parameters"]) cli.notice(nick, messages["not_enough_parameters"])
victim, _ = complete_match(rest.lower(), ull) victim = complete_one_match(rest.lower(), ull)
if not victim: if not victim:
cli.notice(nick, messages["goat_target_not_in_channel"].format(rest)) cli.notice(nick, messages["goat_target_not_in_channel"].format(rest))
return return
@ -4450,7 +4450,7 @@ def consecrate(cli, nick, chan, rest):
dead = [x.nick for x in var.ALL_PLAYERS if x.nick not in alive] dead = [x.nick for x in var.ALL_PLAYERS if x.nick not in alive]
deadl = [x.lower() for x in dead] deadl = [x.lower() for x in dead]
tempvictim, num_matches = complete_match(victim.lower(), deadl) tempvictim = complete_one_match(victim.lower(), deadl)
if not tempvictim: if not tempvictim:
pm(cli, nick, messages["consecrate_fail"].format(victim)) pm(cli, nick, messages["consecrate_fail"].format(victim))
return return
@ -4539,7 +4539,7 @@ def pray(cli, nick, chan, rest):
pm(cli, nick, messages["not_enough_parameters"]) pm(cli, nick, messages["not_enough_parameters"])
return return
# complete this as a match with other roles (so "cursed" can match "cursed villager" for instance) # complete this as a match with other roles (so "cursed" can match "cursed villager" for instance)
role, _ = complete_match(what.lower(), var.ROLE_GUIDE.keys()) role = complete_one_match(what.lower(), var.ROLE_GUIDE.keys())
if role is None: if role is None:
# typo, let them fix it # typo, let them fix it
pm(cli, nick, messages["specific_invalid_role"].format(what)) pm(cli, nick, messages["specific_invalid_role"].format(what))
@ -4780,7 +4780,7 @@ def change_sides(cli, nick, chan, rest, sendmsg=True):
return return
team = re.split(" +", rest)[0] team = re.split(" +", rest)[0]
team, _ = complete_match(team, ("villagers", "wolves")) team = complete_one_match(team, ("villagers", "wolves"))
if not team: if not team:
pm(cli, nick, messages["turncoat_error"]) pm(cli, nick, messages["turncoat_error"])
return return
@ -6526,7 +6526,20 @@ def listroles(cli, nick, chan, rest):
elif rest[0] and not rest[0].isdigit(): elif rest[0] and not rest[0].isdigit():
gamemode = rest[0] gamemode = rest[0]
if gamemode not in var.GAME_MODES.keys(): if gamemode not in var.GAME_MODES.keys():
gamemode, _ = complete_match(rest[0], var.GAME_MODES.keys() - ["roles", "villagergame"] - var.DISABLED_GAMEMODES) matches = complete_match(rest[0], var.GAME_MODES.keys() - {"roles", "villagergame"} - var.DISABLED_GAMEMODES)
if len(matches) > 1:
reply(cli, nick, chan, nick + " " + messages["invalid_mode"].format(rest[0], ", ".join(matches)))
rest = []
roleindex = {}
return
if len(matches) == 0:
reply(cli, nick, chan, nick + " " + messages["invalid_mode_no_list"].format(rest[0], ", ".join(matches)))
rest = []
roleindex = {}
return
else:
gamemode = matches[0]
validMode = gamemode in var.GAME_MODES.keys() and gamemode != "roles" and gamemode != "villagergame" and gamemode not in var.DISABLED_GAMEMODES validMode = gamemode in var.GAME_MODES.keys() and gamemode != "roles" and gamemode != "villagergame" and gamemode not in var.DISABLED_GAMEMODES
if validMode and hasattr(var.GAME_MODES[gamemode][0](), "ROLE_GUIDE"): if validMode and hasattr(var.GAME_MODES[gamemode][0](), "ROLE_GUIDE"):
mode = var.GAME_MODES[gamemode][0]() mode = var.GAME_MODES[gamemode][0]()
@ -6536,7 +6549,6 @@ def listroles(cli, nick, chan, rest):
elif gamemode == "default" and "ROLE_INDEX" in var.ORIGINAL_SETTINGS and "ROLE_GUIDE" in var.ORIGINAL_SETTINGS: elif gamemode == "default" and "ROLE_INDEX" in var.ORIGINAL_SETTINGS and "ROLE_GUIDE" in var.ORIGINAL_SETTINGS:
roleindex = var.ORIGINAL_SETTINGS["ROLE_INDEX"] roleindex = var.ORIGINAL_SETTINGS["ROLE_INDEX"]
roleguide = var.ORIGINAL_SETTINGS["ROLE_GUIDE"] roleguide = var.ORIGINAL_SETTINGS["ROLE_GUIDE"]
rest.pop(0)
else: else:
if validMode and not hasattr(var.GAME_MODES[gamemode][0](), "ROLE_GUIDE"): if validMode and not hasattr(var.GAME_MODES[gamemode][0](), "ROLE_GUIDE"):
msg.append("{0}: {1}roles is disabled for the {2} game mode.".format(nick, botconfig.CMD_CHAR, gamemode)) msg.append("{0}: {1}roles is disabled for the {2} game mode.".format(nick, botconfig.CMD_CHAR, gamemode))
@ -6721,10 +6733,15 @@ def game_stats(cli, nick, chan, rest):
if len(rest) and not rest[0].isdigit(): if len(rest) and not rest[0].isdigit():
gamemode = rest[0] gamemode = rest[0]
if gamemode != "all" and gamemode not in var.GAME_MODES.keys(): if gamemode != "all" and gamemode not in var.GAME_MODES.keys():
gamemode, _ = complete_match(gamemode, var.GAME_MODES.keys()) matches = complete_match(gamemode, var.GAME_MODES.keys())
if not gamemode: if len(matches) == 1:
gamemode = matches[0]
if not matches:
cli.notice(nick, messages["invalid_mode_no_list"].format(rest[0])) cli.notice(nick, messages["invalid_mode_no_list"].format(rest[0]))
return return
if len(matches) > 1:
cli.notice(nick, messages["invalid_mode"].format(rest[0], ", ".join(matches)))
return
rest.pop(0) rest.pop(0)
# Check for invalid input # Check for invalid input
if len(rest) and rest[0].isdigit(): if len(rest) and rest[0].isdigit():
@ -6791,11 +6808,14 @@ def player_stats(cli, nick, chan, rest):
else: else:
role = " ".join(params[1:]) role = " ".join(params[1:])
if role not in var.ROLE_GUIDE.keys(): if role not in var.ROLE_GUIDE.keys():
match, _ = complete_match(role, var.ROLE_GUIDE.keys() | ["lover"]) matches = complete_match(role, var.ROLE_GUIDE.keys() | {"lover"})
if not match: if not matches:
reply(cli, nick, chan, messages["no_such_role"].format(role)) reply(cli, nick, chan, messages["no_such_role"].format(role))
return return
role = match if len(matches) > 1:
reply(cli, nick, chan,nick, messages["invalid_mode"].format(role, ", ".join(matches)))
return
role = matches
# Attempt to find the player's stats # Attempt to find the player's stats
reply(cli, nick, chan, db.get_player_stats(acc, hostmask, role)) reply(cli, nick, chan, db.get_player_stats(acc, hostmask, role))
@ -6813,12 +6833,15 @@ def vote_gamemode(var, wrapper, gamemode, doreply):
return return
if gamemode not in var.GAME_MODES.keys(): if gamemode not in var.GAME_MODES.keys():
match, _ = complete_match(gamemode, var.GAME_MODES.keys() - ["roles", "villagergame"] - var.DISABLED_GAMEMODES) matches = complete_match(gamemode, var.GAME_MODES.keys() - {"roles", "villagergame"} - var.DISABLED_GAMEMODES)
if not match: if not matches:
if doreply:
wrapper.pm(messages["invalid_mode_no_list"].format(gamemode)) wrapper.pm(messages["invalid_mode_no_list"].format(gamemode))
return return
gamemode = match if len(matches) > 1:
wrapper.pm(messages["invalid_mode"].format(gamemode, ", ".join(matches)))
return
if len(matches) == 1:
gamemode = matches[0]
if gamemode != "roles" and gamemode != "villagergame" and gamemode not in var.DISABLED_GAMEMODES: if gamemode != "roles" and gamemode != "villagergame" and gamemode not in var.DISABLED_GAMEMODES:
if var.GAMEMODE_VOTES.get(wrapper.source.nick) == gamemode: if var.GAMEMODE_VOTES.get(wrapper.source.nick) == gamemode:
@ -7167,9 +7190,9 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
if gamemode not in var.GAME_MODES.keys() - var.DISABLED_GAMEMODES: if gamemode not in var.GAME_MODES.keys() - var.DISABLED_GAMEMODES:
gamemode = gamemode.split()[0] gamemode = gamemode.split()[0]
gamemode, _ = complete_match(gamemode, var.GAME_MODES.keys() - var.DISABLED_GAMEMODES) gamemode = complete_one_match(gamemode, var.GAME_MODES.keys() - var.DISABLED_GAMEMODES)
if not gamemode: if not gamemode:
cli.notice(nick, messages["invalid_mode_no_list"].format(rest)) cli.notice(nick, messages["invalid_mode_no_list"].format(rest.split()[0]))
return return
parts[0] = gamemode parts[0] = gamemode