Add !fspectate command

Admin-only command (can be !fallowed) to spectate deadchat or wolfchat.
The person spectating is not revealed to anyone in the chat, however
they can see everyone in that chat.

If used outside of debug mode, it is restricted a la !revealroles where
it cannot be used by an alive player or an active vengeful ghost.
This commit is contained in:
skizzerz 2015-11-14 21:04:43 -06:00
parent 468b67d069
commit d3676948c3
3 changed files with 108 additions and 35 deletions

View File

@ -745,5 +745,10 @@
"available_modes": "Available game modes: \u0002",
"process_exited": "Process %s exited with %s %d",
"admin_fleave_deadchat": "You have forced {0} to leave the deadchat.",
"available_mode_setters_help": "Votes to make a specific game mode more likely. Available game mode setters: "
"available_mode_setters_help": "Votes to make a specific game mode more likely. Available game mode setters: ",
"fspectate_help": "Usage: fspectate <wolfchat|deadchat> [on|off]",
"fspectate_restricted": "You may not spectate while playing.",
"fspectate_deadchat_disabled": "Deadchat is disabled and may not be spectated.",
"fspectate_on": "You are now spectating {0}.",
"fspectate_off": "You are no longer spectating {0}."
}

View File

@ -23,6 +23,8 @@ def mass_mode(cli, md_param, md_plain):
cli.mode(botconfig.CHANNEL, "".join(md_plain))
def mass_privmsg(cli, targets, msg, notice=False, privmsg=False):
if not targets:
return
if not notice and not privmsg:
msg_targs = []
not_targs = []
@ -151,5 +153,7 @@ def relay_wolfchat_command(cli, nick, message, roles, is_wolf_command=False, is_
wcwolves = var.list_players(wcroles)
wcwolves.remove(nick)
if wcwolves:
mass_privmsg(cli, wcwolves, message)
mass_privmsg(cli, wcwolves, message)
mass_privmsg(cli, var.SPECTATING_WOLFCHAT, "[wolfchat] " + message)
# vim: set expandtab:sw=4:ts=4:

View File

@ -424,6 +424,8 @@ def reset():
var.PLAYERS.clear()
var.DCED_PLAYERS.clear()
var.DISCONNECTED.clear()
var.SPECTATING_WOLFCHAT = set()
var.SPECTATING_DEADCHAT = set()
reset()
@ -1052,12 +1054,14 @@ def join_deadchat(cli, *all_nicks):
else:
msg = messages["multiple_joined_deadchat"].format("\u0002, \u0002".join(nicks[:-1]), nicks[-1])
mass_privmsg(cli, var.DEADCHAT_PLAYERS, msg)
mass_privmsg(cli, var.SPECTATING_DEADCHAT, "[deadchat] " + msg)
mass_privmsg(cli, nicks, messages["joined_deadchat"])
people = var.DEADCHAT_PLAYERS | set(nicks)
mass_privmsg(cli, nicks, messages["list_deadchat"].format(", ".join(people)))
var.DEADCHAT_PLAYERS.update(nicks)
var.SPECTATING_DEADCHAT.difference_update(nicks)
def leave_deadchat(cli, nick, force=""):
if not var.ENABLE_DEADCHAT:
@ -1067,12 +1071,15 @@ def leave_deadchat(cli, nick, force=""):
return
var.DEADCHAT_PLAYERS.remove(nick)
msg = ""
if force:
pm(cli, nick, messages["force_leave_deadchat"].format(force))
mass_privmsg(cli, var.DEADCHAT_PLAYERS, messages["player_force_leave_deadchat"].format(nick, force))
msg = messages["player_force_leave_deadchat"].format(nick, force)
else:
pm(cli, nick, messages["leave_deadchat"])
mass_privmsg(cli, var.DEADCHAT_PLAYERS, messages["player_left_deadchat"].format(nick))
msg = messages["player_left_deadchat"].format(nick)
mass_privmsg(cli, var.DEADCHAT_PLAYERS, msg)
mass_privmsg(cli, var.SPECTATING_DEADCHAT, "[deadchat] " + msg)
@cmd("deadchat", pm=True)
def deadchat_pref(cli, nick, chan, rest):
@ -3403,6 +3410,16 @@ def rename_player(cli, prefix, nick):
var.ENTRANCED.remove(prefix)
var.ENTRANCED.add(nick)
if prefix in var.DEADCHAT_PLAYERS:
var.DEADCHAT_PLAYERS.remove(prefix)
var.DEADCHAT_PLAYERS.add(nick)
if prefix in var.SPECTATING_DEADCHAT:
var.SPECTATING_DEADCHAT.remove(prefix)
var.SPECTATING_DEADCHAT.add(nick)
if prefix in var.SPECTATING_WOLFCHAT:
var.SPECTATING_WOLFCHAT.remove(prefix)
var.SPECTATING_WOLFCHAT.add(nick)
event = Event("rename_player", {})
event.dispatch(cli, var, prefix, nick)
@ -3672,6 +3689,9 @@ def leave(cli, what, nick, why=""):
msg = (messages["leave_death_no_reveal"] + "{1}").format(nick, population)
make_stasis(nick, var.LEAVE_STASIS_PENALTY)
cli.msg(botconfig.CHANNEL, msg)
var.SPECTATING_WOLFCHAT.discard(nick)
var.SPECTATING_DEADCHAT.discard(nick)
leave_deadchat(cli, nick)
if what not in ("badnick", "account") and nick in var.USERS:
var.USERS[nick]["modes"] = set()
var.USERS[nick]["moded"] = set()
@ -6421,13 +6441,14 @@ def relay(cli, nick, chan, rest):
if nick not in pl:
if var.ENABLE_DEADCHAT and nick in var.DEADCHAT_PLAYERS:
to_msg = var.DEADCHAT_PLAYERS - {nick}
if rest.startswith("\u0001ACTION"):
rest = rest[7:-1]
mass_privmsg(cli, [x for x in var.DEADCHAT_PLAYERS if x != nick],
"* \u0002{0}\u0002{1}".format(nick, rest))
mass_privmsg(cli, to_msg, "* \u0002{0}\u0002{1}".format(nick, rest))
mass_privmsg(cli, var.SPECTATING_DEADCHAT, "* [deadchat] \u0002{0}\u0002{1}".format(nick, rest))
else:
mass_privmsg(cli, [x for x in var.DEADCHAT_PLAYERS if x != nick],
"\u0002{0}\u0002 says: {1}".format(nick, rest))
mass_privmsg(cli, to_msg, "\u0002{0}\u0002 says: {1}".format(nick, rest))
mass_privmsg(cli, var.SPECTATING_DEADCHAT, "[deadchat] \u0002{0}\u0002 says: {1}".format(nick, rest))
elif nick in badguys and len(badguys) > 1:
# handle wolfchat toggles
@ -6443,13 +6464,14 @@ def relay(cli, nick, chan, rest):
return
badguys.remove(nick)
to_msg = set(badguys) & var.PLAYERS.keys()
if rest.startswith("\u0001ACTION"):
rest = rest[7:-1]
mass_privmsg(cli, [x for x in badguys if x in var.PLAYERS],
"* \u0002{0}\u0002{1}".format(nick, rest))
mass_privmsg(cli, to_msg, "* \u0002{0}\u0002{1}".format(nick, rest))
mass_privmsg(cli, var.SPECTATING_WOLFCHAT, "* [wolfchat] \u0002{0}\u0002{1}".format(nick, rest))
else:
mass_privmsg(cli, [x for x in badguys if x in var.PLAYERS],
"\u0002{0}\u0002 says: {1}".format(nick, rest))
mass_privmsg(cli, to_msg, "\u0002{0}\u0002 says: {1}".format(nick, rest))
mass_privmsg(cli, var.SPECTATING_WOLFCHAT, "[wolfchat] \u0002{0}\u0002 says: {1}".format(nick, rest))
@handle_error
def transition_night(cli):
@ -7396,6 +7418,8 @@ def start(cli, nick, chan, forced = False, restart = ""):
var.DULLAHAN_TARGETS = {}
var.DEADCHAT_PLAYERS = set()
var.SPECTATING_WOLFCHAT = set()
var.SPECTATING_DEADCHAT = set()
for role, count in addroles.items():
if role in var.TEMPLATE_RESTRICTIONS.keys():
@ -8801,6 +8825,67 @@ def fact(cli, raw_nick, chan, rest):
"""Act through the bot as an action."""
_say(cli, raw_nick, rest, "fact", action=True)
def can_run_restricted_cmd(nick):
# if allowed in normal games, restrict it so that it can only be used by dead players and
# non-players (don't allow active vengeful ghosts either).
# also don't allow in-channel (e.g. make it pm only)
if botconfig.DEBUG_MODE:
return True
pl = var.list_players() + [vg for (vg, against) in var.VENGEFUL_GHOSTS.items() if not against.startswith("!")]
if nick in pl:
return False
if nick in var.USERS and var.USERS[nick]["account"] in [var.USERS[player]["account"] for player in pl if player in var.USERS]:
return False
hostmask = var.USERS[nick]["ident"] + "@" + var.USERS[nick]["host"]
if nick in var.USERS and hostmask in [var.USERS[player]["ident"] + "@" + var.USERS[player]["host"] for player in pl if player in var.USERS]:
return False
return True
@cmd("fspectate", admin_only=True, pm=True, phases=("day", "night"))
def fspectate(cli, nick, chan, rest):
"""Spectate wolfchat or deadchat."""
if not can_run_restricted_cmd(nick):
pm(cli, nick, messages["fspectate_restricted"])
return
params = rest.split(" ")
on = "on"
if not len(params):
pm(cli, nick, messages["fspectate_help"])
return
elif len(params) > 1:
on = params[1].lower()
what = params[0].lower()
if what not in ("wolfchat", "deadchat") or on not in ("on", "off"):
pm(cli, nick, messages["fspectate_help"])
return
if on == "off":
if what == "wolfchat":
var.SPECTATING_WOLFCHAT.discard(nick)
else:
var.SPECTATING_DEADCHAT.discard(nick)
pm(cli, nick, messages["fspectate_off"].format(what))
else:
players = []
if what == "wolfchat":
var.SPECTATING_WOLFCHAT.add(nick)
players = (p for p in var.list_players() if in_wolflist(p, p))
elif var.ENABLE_DEADCHAT:
var.SPECTATING_DEADCHAT.add(nick)
players = var.DEADCHAT_PLAYERS
else:
pm(cli, nick, messages["fspectate_deadchat_disabled"])
return
pm(cli, nick, messages["fspectate_on"].format(what))
pm(cli, nick, "People in {0}: {1}".format(what, ", ".join(players)))
before_debug_mode_commands = list(COMMANDS.keys())
if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
@ -8828,29 +8913,8 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
@cmd("revealroles", admin_only=True, pm=True, phases=("day", "night"))
def revealroles(cli, nick, chan, rest):
"""Reveal role information."""
def is_authorized():
# if allowed in normal games, restrict it so that it can only be used by dead players and
# non-players (don't allow active vengeful ghosts either).
# also don't allow in-channel (e.g. make it pm only)
if botconfig.DEBUG_MODE:
return True
pl = var.list_players() + [vg for (vg, against) in var.VENGEFUL_GHOSTS.items() if not against.startswith("!")]
if nick in pl:
return False
if nick in var.USERS and var.USERS[nick]["account"] in [var.USERS[player]["account"] for player in pl if player in var.USERS]:
return False
hostmask = var.USERS[nick]["ident"] + "@" + var.USERS[nick]["host"]
if nick in var.USERS and hostmask in [var.USERS[player]["ident"] + "@" + var.USERS[player]["host"] for player in pl if player in var.USERS]:
return False
return True
if not is_authorized():
if not can_run_restricted_cmd(nick):
if chan == nick:
pm(cli, nick, messages["temp_invalid_perms"])
else: