Merge pull request #274 from lykoss/cmd-old-api
Add a backwards-compatibility handler for commands
This commit is contained in:
commit
9f4b1a243d
@ -596,7 +596,6 @@
|
|||||||
"admin_forced_game": "A game mode has already been forced by an admin.",
|
"admin_forced_game": "A game mode has already been forced by an admin.",
|
||||||
"vote_game_fail": "You can't vote for that game mode.",
|
"vote_game_fail": "You can't vote for that game mode.",
|
||||||
"fsend_usage": "Usage: {0}{1} <target> <message>",
|
"fsend_usage": "Usage: {0}{1} <target> <message>",
|
||||||
"wrong_channel": "You have to be in {0} to use this command.",
|
|
||||||
"invalid_fsend_permissions": "You do not have permission to message this user or channel.",
|
"invalid_fsend_permissions": "You do not have permission to message this user or channel.",
|
||||||
"temp_invalid_perms": "You are not allowed to use that command right now.",
|
"temp_invalid_perms": "You are not allowed to use that command right now.",
|
||||||
"fgame_success": "\u0002{0}\u0002 has changed the game settings successfully.",
|
"fgame_success": "\u0002{0}\u0002 has changed the game settings successfully.",
|
||||||
|
@ -27,7 +27,13 @@ class _States(Enum):
|
|||||||
def predicate(name):
|
def predicate(name):
|
||||||
return not name.startswith(tuple(Features["CHANTYPES"]))
|
return not name.startswith(tuple(Features["CHANTYPES"]))
|
||||||
|
|
||||||
get = _channels.__getitem__
|
def get(name, *, allow_none=False):
|
||||||
|
try:
|
||||||
|
return _channels[name]
|
||||||
|
except KeyError:
|
||||||
|
if allow_none:
|
||||||
|
return None
|
||||||
|
raise
|
||||||
|
|
||||||
def add(name, cli, key=""):
|
def add(name, cli, key=""):
|
||||||
"""Add and return a new channel, or an existing one if it exists."""
|
"""Add and return a new channel, or an existing one if it exists."""
|
||||||
|
@ -14,9 +14,10 @@ from oyoyo.parse import parse_nick
|
|||||||
|
|
||||||
import botconfig
|
import botconfig
|
||||||
import src.settings as var
|
import src.settings as var
|
||||||
|
from src.dispatcher import MessageDispatcher
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import channels, users, logger, errlog, events
|
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
|
from src import channels, users, logger, errlog, events
|
||||||
|
|
||||||
adminlog = logger.logger("audit.log")
|
adminlog = logger.logger("audit.log")
|
||||||
|
|
||||||
@ -181,6 +182,121 @@ class handle_error:
|
|||||||
with print_traceback():
|
with print_traceback():
|
||||||
return self.func(*args, **kwargs)
|
return self.func(*args, **kwargs)
|
||||||
|
|
||||||
|
class command:
|
||||||
|
def __init__(self, *commands, flag=None, owner_only=False, chan=True, pm=False,
|
||||||
|
playing=False, silenced=False, phases=(), roles=(), users=None):
|
||||||
|
|
||||||
|
self.commands = frozenset(commands)
|
||||||
|
self.flag = flag
|
||||||
|
self.owner_only = owner_only
|
||||||
|
self.chan = chan
|
||||||
|
self.pm = pm
|
||||||
|
self.playing = playing
|
||||||
|
self.silenced = silenced
|
||||||
|
self.phases = phases
|
||||||
|
self.roles = roles
|
||||||
|
self.users = users # iterable of users that can use the command at any time (should be a mutable object)
|
||||||
|
self.func = None
|
||||||
|
self.aftergame = False
|
||||||
|
self.name = commands[0]
|
||||||
|
self.alt_allowed = bool(flag or owner_only)
|
||||||
|
|
||||||
|
alias = False
|
||||||
|
self.aliases = []
|
||||||
|
for name in commands:
|
||||||
|
for func in COMMANDS[name]:
|
||||||
|
if func.owner_only != owner_only or func.flag != flag:
|
||||||
|
raise ValueError("unmatching access levels for {0}".format(func.name))
|
||||||
|
|
||||||
|
COMMANDS[name].append(self)
|
||||||
|
if name in botconfig.ALLOWED_ALT_CHANNELS_COMMANDS:
|
||||||
|
self.alt_allowed = True
|
||||||
|
if name in getattr(botconfig, "OWNERS_ONLY_COMMANDS", ()):
|
||||||
|
self.owner_only = True
|
||||||
|
if alias:
|
||||||
|
self.aliases.append(name)
|
||||||
|
alias = True
|
||||||
|
|
||||||
|
def __call__(self, func):
|
||||||
|
if isinstance(func, command):
|
||||||
|
func = func.func
|
||||||
|
self.func = func
|
||||||
|
self.__doc__ = func.__doc__
|
||||||
|
return self
|
||||||
|
|
||||||
|
@handle_error
|
||||||
|
def caller(self, cli, rawnick, chan, rest):
|
||||||
|
user = users._add(cli, nick=rawnick) # FIXME
|
||||||
|
|
||||||
|
if users.equals(chan, users.Bot.nick): # PM
|
||||||
|
target = users.Bot
|
||||||
|
else:
|
||||||
|
target = channels.add(chan, cli)
|
||||||
|
|
||||||
|
dispatcher = MessageDispatcher(user, target)
|
||||||
|
|
||||||
|
if (not self.pm and dispatcher.private) or (not self.chan and dispatcher.public):
|
||||||
|
return # channel or PM command that we don't allow
|
||||||
|
|
||||||
|
if dispatcher.public and target is not channels.Main and not (self.flag or self.owner_only):
|
||||||
|
if "" in self.commands or not self.alt_allowed:
|
||||||
|
return # commands not allowed in alt channels
|
||||||
|
|
||||||
|
if "" in self.commands:
|
||||||
|
return self.func(var, dispatcher, rest)
|
||||||
|
|
||||||
|
if self.phases and var.PHASE not in self.phases:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.playing and (user.nick not in list_players() or user.nick in var.DISCONNECTED): # FIXME: Need to change this once list_players() / var.DISCONNECTED use User instances
|
||||||
|
return
|
||||||
|
|
||||||
|
for role in self.roles:
|
||||||
|
if user.nick in var.ROLES[role]: # FIXME: Need to change this once var.ROLES[role] holds User instances
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if (self.users is not None and user not in self.users) or self.roles:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.silenced and user.nick in var.SILENCED: # FIXME: Need to change this once var.SILENCED holds User instances
|
||||||
|
dispatcher.pm(messages["silenced"])
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.roles or (self.users is not None and user in self.users):
|
||||||
|
return self.func(var, dispatcher, rest) # don't check restrictions for role commands
|
||||||
|
|
||||||
|
if self.owner_only:
|
||||||
|
if user.is_owner():
|
||||||
|
adminlog(chan, rawnick, self.name, rest)
|
||||||
|
return self.func(var, dispatcher, rest)
|
||||||
|
|
||||||
|
dispatcher.pm(messages["not_owner"])
|
||||||
|
return
|
||||||
|
|
||||||
|
temp = user.lower()
|
||||||
|
|
||||||
|
flags = var.FLAGS[temp.rawnick] + var.FLAGS_ACCS[temp.account] # TODO: add flags handling to User
|
||||||
|
|
||||||
|
if self.flag and (user.is_admin() or user.is_owner()):
|
||||||
|
adminlog(chan, rawnick, self.name, rest)
|
||||||
|
return self.func(var, dispatcher, rest)
|
||||||
|
|
||||||
|
denied_commands = var.DENY[temp.rawnick] | var.DENY_ACCS[temp.account] # TODO: add denied commands handling to User
|
||||||
|
|
||||||
|
if self.commands & denied_commands:
|
||||||
|
dispatcher.pm(messages["invalid_permissions"])
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.flag:
|
||||||
|
if self.flag in flags:
|
||||||
|
adminlog(chan, rawnick, self.name, rest)
|
||||||
|
return self.func(var, dispatcher, rest)
|
||||||
|
|
||||||
|
dispatcher.pm(messages["not_an_admin"])
|
||||||
|
return
|
||||||
|
|
||||||
|
return self.func(var, dispatcher, rest)
|
||||||
|
|
||||||
class cmd:
|
class cmd:
|
||||||
def __init__(self, *cmds, raw_nick=False, flag=None, owner_only=False,
|
def __init__(self, *cmds, raw_nick=False, flag=None, owner_only=False,
|
||||||
chan=True, pm=False, playing=False, silenced=False,
|
chan=True, pm=False, playing=False, silenced=False,
|
||||||
@ -222,8 +338,11 @@ class cmd:
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
@handle_error
|
@handle_error
|
||||||
def caller(self, *args):
|
def caller(self, cli, rawnick, chan, rest):
|
||||||
largs = list(args)
|
if users.equals(chan, users.Bot.nick):
|
||||||
|
chan = users.parse_rawnick_as_dict(rawnick)["nick"]
|
||||||
|
|
||||||
|
largs = [cli, rawnick, chan, rest]
|
||||||
|
|
||||||
cli, rawnick, chan, rest = largs
|
cli, rawnick, chan, rest = largs
|
||||||
nick, mode, ident, host = parse_nick(rawnick)
|
nick, mode, ident, host = parse_nick(rawnick)
|
||||||
|
47
src/dispatcher.py
Normal file
47
src/dispatcher.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
from src import channels, users
|
||||||
|
from src import settings as var
|
||||||
|
|
||||||
|
from src.utilities import list_players
|
||||||
|
|
||||||
|
class MessageDispatcher:
|
||||||
|
"""Dispatcher class for raw IRC messages."""
|
||||||
|
|
||||||
|
def __init__(self, source, target):
|
||||||
|
self.source = source
|
||||||
|
self.target = target
|
||||||
|
|
||||||
|
@property
|
||||||
|
def private(self):
|
||||||
|
return self.target is users.Bot
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public(self):
|
||||||
|
return self.target is not users.Bot
|
||||||
|
|
||||||
|
def pm(self, *messages, **kwargs):
|
||||||
|
"""Send a private message or notice to the sender."""
|
||||||
|
kwargs.setdefault("notice", self.public)
|
||||||
|
self.source.send(*messages, **kwargs)
|
||||||
|
|
||||||
|
def send(self, *messages, **kwargs):
|
||||||
|
"""Send a message to the channel or a private message."""
|
||||||
|
if self.private:
|
||||||
|
self.pm(*messages, **kwargs)
|
||||||
|
else:
|
||||||
|
self.target.send(*messages, **kwargs)
|
||||||
|
|
||||||
|
def reply(self, *messages, prefix_nick=False, **kwargs):
|
||||||
|
"""Reply to the user, either in channel or privately."""
|
||||||
|
first = ""
|
||||||
|
if prefix_nick:
|
||||||
|
first = "{0}: ".format(self.source.nick)
|
||||||
|
if self.private:
|
||||||
|
self.source.send(*messages, **kwargs)
|
||||||
|
elif (self.target is channels.Main and
|
||||||
|
((self.source.nick not in list_players() and var.PHASE in var.GAME_PHASES) or
|
||||||
|
(var.DEVOICE_DURING_NIGHT and var.PHASE == "night"))): # FIXME
|
||||||
|
kwargs.setdefault("notice", True)
|
||||||
|
self.source.send(*messages, **kwargs)
|
||||||
|
else:
|
||||||
|
kwargs.setdefault("first", first)
|
||||||
|
self.target.send(*messages, **kwargs)
|
@ -10,7 +10,7 @@ import src.settings as var
|
|||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.decorators import handle_error
|
from src.decorators import handle_error
|
||||||
from src import events
|
from src import events, channels, users
|
||||||
|
|
||||||
def game_mode(name, minp, maxp, likelihood = 0):
|
def game_mode(name, minp, maxp, likelihood = 0):
|
||||||
def decor(c):
|
def decor(c):
|
||||||
@ -1202,23 +1202,24 @@ class MaelstromMode(GameMode):
|
|||||||
if not var.ACCOUNTS_ONLY:
|
if not var.ACCOUNTS_ONLY:
|
||||||
self.DEAD_HOSTS.add(var.USERS[nick]["host"].lower())
|
self.DEAD_HOSTS.add(var.USERS[nick]["host"].lower())
|
||||||
|
|
||||||
def on_join(self, evt, cli, var, nick, chan, rest, forced=False):
|
def on_join(self, evt, var, wrapper, message, forced=False):
|
||||||
if var.PHASE != "day" or (nick != chan and chan != botconfig.CHANNEL):
|
if var.PHASE != "day" or (wrapper.public and wrapper.target is not channels.Main):
|
||||||
return
|
return
|
||||||
if (irc_lower(nick) in (irc_lower(x) for x in var.ALL_PLAYERS) or
|
temp = wrapper.source.lower()
|
||||||
irc_lower(var.USERS[nick]["account"]) in self.DEAD_ACCOUNTS or
|
if (temp.nick in (irc_lower(x) for x in var.ALL_PLAYERS) or # FIXME
|
||||||
var.USERS[nick]["host"].lower() in self.DEAD_HOSTS):
|
temp.account in self.DEAD_ACCOUNTS or
|
||||||
cli.notice(nick, messages["maelstrom_dead"])
|
temp.host in self.DEAD_HOSTS):
|
||||||
|
wrapper.pm(messages["maelstrom_dead"])
|
||||||
return
|
return
|
||||||
if not forced and evt.data["join_player"](cli, nick, botconfig.CHANNEL, sanity=False):
|
if not forced and evt.data["join_player"](var, type(wrapper)(wrapper.source, channels.Main), sanity=False):
|
||||||
self._on_join(cli, var, nick, chan)
|
self._on_join(var, wrapper)
|
||||||
evt.prevent_default = True
|
evt.prevent_default = True
|
||||||
elif forced:
|
elif forced:
|
||||||
# in fjoin, handle this differently
|
# in fjoin, handle this differently
|
||||||
jp = evt.data["join_player"]
|
jp = evt.data["join_player"]
|
||||||
evt.data["join_player"] = lambda cli, nick, chan, who=None, forced=False: jp(cli, nick, chan, who=who, forced=forced, sanity=False) and self._on_join(cli, var, nick, chan)
|
evt.data["join_player"] = lambda var, wrapper, who=None, forced=False: jp(var, wrapper, who=who, forced=forced, sanity=False) and self._on_join(var, wrapper)
|
||||||
|
|
||||||
def _on_join(self, cli, var, nick, chan):
|
def _on_join(self, var, wrapper):
|
||||||
role = random.choice(self.roles)
|
role = random.choice(self.roles)
|
||||||
|
|
||||||
lpl = len(list_players()) + 1
|
lpl = len(list_players()) + 1
|
||||||
@ -1248,31 +1249,30 @@ class MaelstromMode(GameMode):
|
|||||||
elif role == "succubus":
|
elif role == "succubus":
|
||||||
lsuccubi += 1
|
lsuccubi += 1
|
||||||
|
|
||||||
if self.chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, lsuccubi, 0, cli, end_game=False):
|
if self.chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, lsuccubi, 0, wrapper.client, end_game=False):
|
||||||
return self._on_join(cli, var, nick, chan)
|
return self._on_join(var, wrapper)
|
||||||
|
|
||||||
var.ROLES[role].add(nick)
|
var.ROLES[role].add(wrapper.source.nick)
|
||||||
var.ORIGINAL_ROLES[role].add(nick)
|
var.ORIGINAL_ROLES[role].add(wrapper.source.nick)
|
||||||
var.FINAL_ROLES[nick] = role
|
var.FINAL_ROLES[wrapper.source.nick] = role
|
||||||
var.LAST_SAID_TIME[nick] = datetime.now()
|
var.LAST_SAID_TIME[wrapper.source.nick] = datetime.now()
|
||||||
if nick in var.USERS:
|
if wrapper.source.nick in var.USERS:
|
||||||
var.PLAYERS[nick] = var.USERS[nick]
|
var.PLAYERS[wrapper.source.nick] = var.USERS[wrapper.source.nick]
|
||||||
|
|
||||||
if role == "doctor":
|
if role == "doctor":
|
||||||
lpl = len(list_players())
|
lpl = len(list_players())
|
||||||
var.DOCTORS[nick] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * lpl)
|
var.DOCTORS[wrapper.source.nick] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * lpl)
|
||||||
# let them know their role
|
# let them know their role
|
||||||
# FIXME: this is fugly
|
|
||||||
from src.decorators import COMMANDS
|
from src.decorators import COMMANDS
|
||||||
COMMANDS["myrole"][0].caller(cli, nick, chan, "")
|
COMMANDS["myrole"][0].caller(wrapper.source.client, wrapper.source.nick, wrapper.target.name, "") # FIXME: New/old API
|
||||||
# if they're a wolfchat role, alert the other wolves
|
# if they're a wolfchat role, alert the other wolves
|
||||||
if role in var.WOLFCHAT_ROLES:
|
if role in var.WOLFCHAT_ROLES:
|
||||||
relay_wolfchat_command(cli, nick, messages["wolfchat_new_member"].format(nick, role), var.WOLFCHAT_ROLES, is_wolf_command=True, is_kill_command=True)
|
relay_wolfchat_command(wrapper.source.client, wrapper.source.nick, messages["wolfchat_new_member"].format(wrapper.source.nick, role), var.WOLFCHAT_ROLES, is_wolf_command=True, is_kill_command=True)
|
||||||
# TODO: make this part of !myrole instead, no reason we can't give out wofllist in that
|
# TODO: make this part of !myrole instead, no reason we can't give out wofllist in that
|
||||||
wolves = list_players(var.WOLFCHAT_ROLES)
|
wolves = list_players(var.WOLFCHAT_ROLES)
|
||||||
pl = list_players()
|
pl = list_players()
|
||||||
random.shuffle(pl)
|
random.shuffle(pl)
|
||||||
pl.remove(nick)
|
pl.remove(wrapper.source.nick)
|
||||||
for i, player in enumerate(pl):
|
for i, player in enumerate(pl):
|
||||||
prole = get_role(player)
|
prole = get_role(player)
|
||||||
if prole in var.WOLFCHAT_ROLES:
|
if prole in var.WOLFCHAT_ROLES:
|
||||||
@ -1282,7 +1282,7 @@ class MaelstromMode(GameMode):
|
|||||||
pl[i] = "\u0002{0}\u0002 ({1}{2})".format(player, cursed, prole)
|
pl[i] = "\u0002{0}\u0002 ({1}{2})".format(player, cursed, prole)
|
||||||
elif player in var.ROLES["cursed villager"]:
|
elif player in var.ROLES["cursed villager"]:
|
||||||
pl[i] = player + " (cursed)"
|
pl[i] = player + " (cursed)"
|
||||||
pm(cli, nick, "Players: " + ", ".join(pl))
|
wrapper.pm("Players: " + ", ".join(pl))
|
||||||
|
|
||||||
def role_attribution(self, evt, cli, var, chk_win_conditions, villagers):
|
def role_attribution(self, evt, cli, var, chk_win_conditions, villagers):
|
||||||
self.chk_win_conditions = chk_win_conditions
|
self.chk_win_conditions = chk_win_conditions
|
||||||
|
@ -15,22 +15,19 @@ def on_privmsg(cli, rawnick, chan, msg, *, notice=False):
|
|||||||
if notice and "!" not in rawnick or not rawnick: # server notice; we don't care about those
|
if notice and "!" not in rawnick or not rawnick: # server notice; we don't care about those
|
||||||
return
|
return
|
||||||
|
|
||||||
if not users.equals(chan, botconfig.NICK) and botconfig.IGNORE_HIDDEN_COMMANDS and not chan.startswith(tuple(hooks.Features["CHANTYPES"])):
|
if not users.equals(chan, users.Bot.nick) and botconfig.IGNORE_HIDDEN_COMMANDS and not chan.startswith(tuple(hooks.Features["CHANTYPES"])):
|
||||||
return
|
return
|
||||||
|
|
||||||
if (notice and ((not users.equals(chan, botconfig.NICK) and not botconfig.ALLOW_NOTICE_COMMANDS) or
|
if (notice and ((not users.equals(chan, users.Bot.nick) and not botconfig.ALLOW_NOTICE_COMMANDS) or
|
||||||
(users.equals(chan, botconfig.NICK) and not botconfig.ALLOW_PRIVATE_NOTICE_COMMANDS))):
|
(users.equals(chan, users.Bot.nick) and not botconfig.ALLOW_PRIVATE_NOTICE_COMMANDS))):
|
||||||
return # not allowed in settings
|
return # not allowed in settings
|
||||||
|
|
||||||
if users.equals(chan, botconfig.NICK):
|
|
||||||
chan = users.parse_rawnick_as_dict(rawnick)["nick"]
|
|
||||||
|
|
||||||
for fn in decorators.COMMANDS[""]:
|
for fn in decorators.COMMANDS[""]:
|
||||||
fn.caller(cli, rawnick, chan, msg)
|
fn.caller(cli, rawnick, chan, msg)
|
||||||
|
|
||||||
phase = var.PHASE
|
phase = var.PHASE
|
||||||
for x in list(decorators.COMMANDS.keys()):
|
for x in list(decorators.COMMANDS.keys()):
|
||||||
if chan != users.parse_rawnick_as_dict(rawnick)["nick"] and not msg.lower().startswith(botconfig.CMD_CHAR):
|
if not users.equals(chan, users.Bot.nick) and not msg.lower().startswith(botconfig.CMD_CHAR):
|
||||||
break # channel message but no prefix; ignore
|
break # channel message but no prefix; ignore
|
||||||
if msg.lower().startswith(botconfig.CMD_CHAR+x):
|
if msg.lower().startswith(botconfig.CMD_CHAR+x):
|
||||||
h = msg[len(x)+len(botconfig.CMD_CHAR):]
|
h = msg[len(x)+len(botconfig.CMD_CHAR):]
|
||||||
|
@ -55,13 +55,13 @@ def dullahan_retract(cli, nick, chan, rest):
|
|||||||
pm(cli, nick, messages["retracted_kill"])
|
pm(cli, nick, messages["retracted_kill"])
|
||||||
|
|
||||||
@event_listener("player_win")
|
@event_listener("player_win")
|
||||||
def on_player_win(evt, cli, var, nick, role, winner, survived):
|
def on_player_win(evt, var, user, role, winner, survived):
|
||||||
if role != "dullahan":
|
if role != "dullahan":
|
||||||
return
|
return
|
||||||
alive = set(list_players())
|
alive = set(list_players())
|
||||||
if nick in var.ENTRANCED:
|
if user.nick in var.ENTRANCED:
|
||||||
alive -= var.ROLES["succubus"]
|
alive -= var.ROLES["succubus"]
|
||||||
if not TARGETS[nick] & alive:
|
if not TARGETS[user.nick] & alive:
|
||||||
evt.data["iwon"] = True
|
evt.data["iwon"] = True
|
||||||
|
|
||||||
@event_listener("del_player")
|
@event_listener("del_player")
|
||||||
@ -222,7 +222,7 @@ def on_myrole(evt, cli, var, nick):
|
|||||||
evt.data["messages"].append(messages["dullahan_targets_dead"])
|
evt.data["messages"].append(messages["dullahan_targets_dead"])
|
||||||
|
|
||||||
@event_listener("revealroles_role")
|
@event_listener("revealroles_role")
|
||||||
def on_revealroles_role(evt, cli, var, nickname, role):
|
def on_revealroles_role(evt, var, wrapper, nickname, role):
|
||||||
if role == "dullahan" and nickname in TARGETS:
|
if role == "dullahan" and nickname in TARGETS:
|
||||||
targets = TARGETS[nickname] - var.DEAD
|
targets = TARGETS[nickname] - var.DEAD
|
||||||
if targets:
|
if targets:
|
||||||
|
@ -53,7 +53,7 @@ brokentotem = set() # type: Set[str]
|
|||||||
|
|
||||||
@cmd("give", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=var.TOTEM_ORDER)
|
@cmd("give", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=var.TOTEM_ORDER)
|
||||||
@cmd("totem", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=var.TOTEM_ORDER)
|
@cmd("totem", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=var.TOTEM_ORDER)
|
||||||
def totem(cli, nick, chan, rest, prefix="You"):
|
def totem(cli, nick, chan, rest, prefix="You"): # XXX: The transition_day_begin event needs updating alongside this
|
||||||
"""Give a totem to a player."""
|
"""Give a totem to a player."""
|
||||||
victim = get_victim(cli, nick, re.split(" +",rest)[0], False, True)
|
victim = get_victim(cli, nick, re.split(" +",rest)[0], False, True)
|
||||||
if not victim:
|
if not victim:
|
||||||
@ -299,7 +299,7 @@ def on_chk_decision_lynch5(evt, cli, var, voters):
|
|||||||
evt.params.del_player(cli, target, True, end_game=False, killer_role="shaman", deadlist=evt.data["deadlist"], original=target, ismain=False)
|
evt.params.del_player(cli, target, True, end_game=False, killer_role="shaman", deadlist=evt.data["deadlist"], original=target, ismain=False)
|
||||||
|
|
||||||
@event_listener("player_win")
|
@event_listener("player_win")
|
||||||
def on_player_win(evt, cli, var, splr, rol, winner, survived):
|
def on_player_win(evt, var, user, rol, winner, survived):
|
||||||
if rol == "crazed shaman" and survived and not winner.startswith("@") and singular(winner) not in var.WIN_STEALER_ROLES:
|
if rol == "crazed shaman" and survived and not winner.startswith("@") and singular(winner) not in var.WIN_STEALER_ROLES:
|
||||||
evt.data["iwon"] = True
|
evt.data["iwon"] = True
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ def on_transition_day_begin(evt, cli, var):
|
|||||||
ps.remove(succubus)
|
ps.remove(succubus)
|
||||||
if ps:
|
if ps:
|
||||||
target = random.choice(ps)
|
target = random.choice(ps)
|
||||||
totem.func(cli, shaman, shaman, target, messages["random_totem_prefix"])
|
totem.func(cli, shaman, shaman, target, messages["random_totem_prefix"]) # XXX: Old API
|
||||||
else:
|
else:
|
||||||
LASTGIVEN[shaman] = None
|
LASTGIVEN[shaman] = None
|
||||||
elif shaman not in SHAMANS:
|
elif shaman not in SHAMANS:
|
||||||
@ -594,7 +594,7 @@ def on_myrole(evt, cli, var, nick):
|
|||||||
evt.data["messages"].append(messages["totem_simple"].format(TOTEMS[nick]))
|
evt.data["messages"].append(messages["totem_simple"].format(TOTEMS[nick]))
|
||||||
|
|
||||||
@event_listener("revealroles_role")
|
@event_listener("revealroles_role")
|
||||||
def on_revealroles(evt, cli, var, nickname, role):
|
def on_revealroles(evt, var, wrapper, nickname, role):
|
||||||
if role in var.TOTEM_ORDER and nickname in TOTEMS:
|
if role in var.TOTEM_ORDER and nickname in TOTEMS:
|
||||||
if nickname in SHAMANS:
|
if nickname in SHAMANS:
|
||||||
evt.data["special_case"].append("giving {0} totem to {1}".format(TOTEMS[nickname], SHAMANS[nickname][0]))
|
evt.data["special_case"].append("giving {0} totem to {1}".format(TOTEMS[nickname], SHAMANS[nickname][0]))
|
||||||
|
@ -7,8 +7,8 @@ from collections import defaultdict
|
|||||||
import botconfig
|
import botconfig
|
||||||
import src.settings as var
|
import src.settings as var
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import command, event_listener
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
|
@ -4,79 +4,79 @@ from collections import defaultdict
|
|||||||
|
|
||||||
import src.settings as var
|
import src.settings as var
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import command, event_listener
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
KILLS = {} # type: Dict[str, str]
|
KILLS = {} # type: Dict[str, str]
|
||||||
GHOSTS = {} # type: Dict[str, str]
|
GHOSTS = {} # type: Dict[users.User, str]
|
||||||
|
|
||||||
# temporary holding variable, only non-empty during transition_day
|
# temporary holding variable, only non-empty during transition_day
|
||||||
# as such, no need to track nick changes, etc. with it
|
# as such, no need to track nick changes, etc. with it
|
||||||
drivenoff = {} # type: Dict[str, str]
|
drivenoff = {} # type: Dict[str, str]
|
||||||
|
|
||||||
@cmd("kill", chan=False, pm=True, playing=False, silenced=True, phases=("night",), nicks=GHOSTS)
|
@command("kill", chan=False, pm=True, playing=False, silenced=True, phases=("night",), users=GHOSTS)
|
||||||
def vg_kill(cli, nick, chan, rest):
|
def vg_kill(var, wrapper, message):
|
||||||
"""Take revenge on someone each night after you die."""
|
"""Take revenge on someone each night after you die."""
|
||||||
if GHOSTS[nick][0] == "!":
|
if GHOSTS[wrapper.source][0] == "!":
|
||||||
return
|
return
|
||||||
|
|
||||||
victim = get_victim(cli, nick, re.split(" +",rest)[0], False)
|
victim = get_victim(wrapper.source.client, wrapper.source.nick, re.split(" +", message)[0], False)
|
||||||
if not victim:
|
if not victim:
|
||||||
return
|
return
|
||||||
|
|
||||||
if victim == nick:
|
if victim == wrapper.source.nick:
|
||||||
pm(cli, nick, messages["player_dead"])
|
wrapper.pm(messages["player_dead"])
|
||||||
return
|
return
|
||||||
|
|
||||||
wolves = list_players(var.WOLFTEAM_ROLES)
|
wolves = list_players(var.WOLFTEAM_ROLES)
|
||||||
if GHOSTS[nick] == "wolves" and victim not in wolves:
|
if GHOSTS[wrapper.source] == "wolves" and victim not in wolves:
|
||||||
pm(cli, nick, messages["vengeful_ghost_wolf"])
|
wrapper.pm(messages["vengeful_ghost_wolf"])
|
||||||
return
|
return
|
||||||
elif GHOSTS[nick] == "villagers" and victim in wolves:
|
elif GHOSTS[wrapper.source] == "villagers" and victim in wolves:
|
||||||
pm(cli, nick, messages["vengeful_ghost_villager"])
|
wrapper.pm(messages["vengeful_ghost_villager"])
|
||||||
return
|
return
|
||||||
|
|
||||||
orig = victim
|
orig = victim
|
||||||
evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": False})
|
evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": False})
|
||||||
evt.dispatch(cli, var, "kill", nick, victim, frozenset({"detrimental"}))
|
evt.dispatch(wrapper.source.client, var, "kill", wrapper.source.nick, victim, frozenset({"detrimental"}))
|
||||||
if evt.prevent_default:
|
if evt.prevent_default:
|
||||||
return
|
return
|
||||||
victim = evt.data["target"]
|
victim = evt.data["target"]
|
||||||
|
|
||||||
KILLS[nick] = victim
|
KILLS[wrapper.source.nick] = victim
|
||||||
|
|
||||||
msg = messages["wolf_target"].format(orig)
|
msg = messages["wolf_target"].format(orig)
|
||||||
pm(cli, nick, messages["player"].format(msg))
|
wrapper.pm(messages["player"].format(msg))
|
||||||
|
|
||||||
debuglog("{0} ({1}) KILL: {2} ({3})".format(nick, get_role(nick), victim, get_role(victim)))
|
debuglog("{0} ({1}) KILL: {2} ({3})".format(wrapper.source.nick, get_role(wrapper.source.nick), victim, get_role(victim)))
|
||||||
chk_nightdone(cli)
|
chk_nightdone(wrapper.source.client)
|
||||||
|
|
||||||
@cmd("retract", "r", chan=False, pm=True, playing=False, phases=("night",))
|
@command("retract", "r", chan=False, pm=True, playing=False, phases=("night",))
|
||||||
def vg_retract(cli, nick, chan, rest):
|
def vg_retract(var, wrapper, message):
|
||||||
"""Removes a vengeful ghost's kill selection."""
|
"""Removes a vengeful ghost's kill selection."""
|
||||||
if nick not in GHOSTS:
|
if wrapper.source not in GHOSTS:
|
||||||
return
|
return
|
||||||
if nick in KILLS:
|
if wrapper.source.nick in KILLS:
|
||||||
del KILLS[nick]
|
del KILLS[wrapper.source.nick]
|
||||||
pm(cli, nick, messages["retracted_kill"])
|
wrapper.pm(messages["retracted_kill"])
|
||||||
|
|
||||||
@event_listener("list_participants")
|
@event_listener("list_participants")
|
||||||
def on_list_participants(evt, var):
|
def on_list_participants(evt, var):
|
||||||
evt.data["pl"].extend([p for p in GHOSTS if GHOSTS[p][0] != "!"])
|
evt.data["pl"].extend([p.nick for p in GHOSTS if GHOSTS[p][0] != "!"])
|
||||||
evt.data["pl"].extend([p for p in drivenoff])
|
evt.data["pl"].extend([p for p in drivenoff])
|
||||||
|
|
||||||
@event_listener("player_win", priority=1)
|
@event_listener("player_win", priority=1)
|
||||||
def on_player_win(evt, cli, var, nick, role, winner, survived):
|
def on_player_win(evt, var, user, role, winner, survived):
|
||||||
# alive VG winning is handled in villager.py
|
# alive VG winning is handled in villager.py
|
||||||
# extending VG to work with new teams can be done by registering
|
# extending VG to work with new teams can be done by registering
|
||||||
# a listener at priority > 1, importing src.roles.vengefulghost,
|
# a listener at priority > 1, importing src.roles.vengefulghost,
|
||||||
# and checking if the nick is in GHOSTS.
|
# and checking if the user is in GHOSTS.
|
||||||
if nick in GHOSTS:
|
if user in GHOSTS:
|
||||||
evt.data["special"].append("vg activated")
|
evt.data["special"].append("vg activated")
|
||||||
against = GHOSTS[nick]
|
against = GHOSTS[user]
|
||||||
if GHOSTS[nick][0] == "!":
|
if against[0] == "!":
|
||||||
evt.data["special"].append("vg driven off")
|
evt.data["special"].append("vg driven off")
|
||||||
against = against[1:]
|
against = against[1:]
|
||||||
if against == "villagers" and winner == "wolves":
|
if against == "villagers" and winner == "wolves":
|
||||||
@ -97,14 +97,15 @@ def on_del_player(evt, cli, var, nick, nickrole, nicktpls, death_triggers):
|
|||||||
del KILLS[h]
|
del KILLS[h]
|
||||||
# extending VG to work with new teams can be done by registering a listener
|
# extending VG to work with new teams can be done by registering a listener
|
||||||
# at priority < 6, importing src.roles.vengefulghost, and setting
|
# at priority < 6, importing src.roles.vengefulghost, and setting
|
||||||
# GHOSTS[nick] to something; if that is done then this logic is not run.
|
# GHOSTS[user] to something; if that is done then this logic is not run.
|
||||||
if death_triggers and nickrole == "vengeful ghost" and nick not in GHOSTS:
|
user = users._get(nick) # FIXME
|
||||||
|
if death_triggers and nickrole == "vengeful ghost" and user not in GHOSTS:
|
||||||
if evt.params.killer_role in var.WOLFTEAM_ROLES:
|
if evt.params.killer_role in var.WOLFTEAM_ROLES:
|
||||||
GHOSTS[nick] = "wolves"
|
GHOSTS[user] = "wolves"
|
||||||
else:
|
else:
|
||||||
GHOSTS[nick] = "villagers"
|
GHOSTS[user] = "villagers"
|
||||||
pm(cli, nick, messages["vengeful_turn"].format(GHOSTS[nick]))
|
user.send(messages["vengeful_turn"].format(GHOSTS[user]))
|
||||||
debuglog(nick, "(vengeful ghost) TRIGGER", GHOSTS[nick])
|
debuglog(nick, "(vengeful ghost) TRIGGER", GHOSTS[user])
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename(evt, cli, var, prefix, nick):
|
def on_rename(evt, cli, var, prefix, nick):
|
||||||
@ -118,8 +119,6 @@ def on_rename(evt, cli, var, prefix, nick):
|
|||||||
KILLS.update(kvp)
|
KILLS.update(kvp)
|
||||||
if prefix in KILLS:
|
if prefix in KILLS:
|
||||||
del KILLS[prefix]
|
del KILLS[prefix]
|
||||||
if prefix in GHOSTS:
|
|
||||||
GHOSTS[nick] = GHOSTS.pop(prefix)
|
|
||||||
|
|
||||||
@event_listener("night_acted")
|
@event_listener("night_acted")
|
||||||
def on_acted(evt, cli, var, nick, sender):
|
def on_acted(evt, cli, var, nick, sender):
|
||||||
@ -132,22 +131,22 @@ def on_transition_day_begin(evt, cli, var):
|
|||||||
wolves = set(list_players(var.WOLFTEAM_ROLES))
|
wolves = set(list_players(var.WOLFTEAM_ROLES))
|
||||||
villagers = set(list_players()) - wolves
|
villagers = set(list_players()) - wolves
|
||||||
for ghost, target in GHOSTS.items():
|
for ghost, target in GHOSTS.items():
|
||||||
if target[0] == "!" or ghost in var.SILENCED:
|
if target[0] == "!" or ghost.nick in var.SILENCED:
|
||||||
continue
|
continue
|
||||||
if ghost not in KILLS:
|
if ghost.nick not in KILLS:
|
||||||
choice = set()
|
choice = set()
|
||||||
if target == "wolves":
|
if target == "wolves":
|
||||||
choice = wolves.copy()
|
choice = wolves.copy()
|
||||||
elif target == "villagers":
|
elif target == "villagers":
|
||||||
choice = villagers.copy()
|
choice = villagers.copy()
|
||||||
evt = Event("vg_kill", {"pl": choice})
|
evt = Event("vg_kill", {"pl": choice})
|
||||||
evt.dispatch(cli, var, ghost, target)
|
evt.dispatch(var, ghost, target)
|
||||||
choice = evt.data["pl"]
|
choice = evt.data["pl"]
|
||||||
# roll this into the above event once succubus is split off
|
# roll this into the above event once succubus is split off
|
||||||
if ghost in var.ENTRANCED:
|
if ghost.nick in var.ENTRANCED:
|
||||||
choice -= var.ROLES["succubus"]
|
choice -= var.ROLES["succubus"]
|
||||||
if choice:
|
if choice:
|
||||||
KILLS[ghost] = random.choice(list(choice))
|
KILLS[ghost.nick] = random.choice(list(choice))
|
||||||
|
|
||||||
@event_listener("transition_day", priority=2)
|
@event_listener("transition_day", priority=2)
|
||||||
def on_transition_day(evt, cli, var):
|
def on_transition_day(evt, cli, var):
|
||||||
@ -159,35 +158,35 @@ def on_transition_day(evt, cli, var):
|
|||||||
@event_listener("transition_day", priority=3.01)
|
@event_listener("transition_day", priority=3.01)
|
||||||
def on_transition_day3(evt, cli, var):
|
def on_transition_day3(evt, cli, var):
|
||||||
for k, d in list(KILLS.items()):
|
for k, d in list(KILLS.items()):
|
||||||
if GHOSTS[k] == "villagers":
|
if GHOSTS[users._get(k)] == "villagers":
|
||||||
evt.data["killers"][d].remove(k)
|
evt.data["killers"][d].remove(k)
|
||||||
evt.data["killers"][d].insert(0, k)
|
evt.data["killers"][d].insert(0, k)
|
||||||
|
|
||||||
@event_listener("transition_day", priority=6.01)
|
@event_listener("transition_day", priority=6.01)
|
||||||
def on_transition_day6(evt, cli, var):
|
def on_transition_day6(evt, cli, var):
|
||||||
for k, d in list(KILLS.items()):
|
for k, d in list(KILLS.items()):
|
||||||
if GHOSTS[k] == "villagers" and k in evt.data["killers"][d]:
|
if GHOSTS[users._get(k)] == "villagers" and k in evt.data["killers"][d]:
|
||||||
evt.data["killers"][d].remove(k)
|
evt.data["killers"][d].remove(k)
|
||||||
evt.data["killers"][d].insert(0, k)
|
evt.data["killers"][d].insert(0, k)
|
||||||
# important, otherwise our del_player listener messages the vg
|
# important, otherwise our del_player listener messages the vg
|
||||||
del KILLS[k]
|
del KILLS[k]
|
||||||
|
|
||||||
@event_listener("retribution_kill")
|
@event_listener("retribution_kill") # FIXME: This function, and all of the event
|
||||||
def on_retribution_kill(evt, cli, var, victim, orig_target):
|
def on_retribution_kill(evt, cli, var, victim, orig_target):
|
||||||
t = evt.data["target"]
|
t = evt.data["target"]
|
||||||
if t in GHOSTS:
|
if users._get(t) in GHOSTS:
|
||||||
drivenoff[t] = GHOSTS[t]
|
drivenoff[t] = GHOSTS[users._get(t)]
|
||||||
GHOSTS[t] = "!" + GHOSTS[t]
|
GHOSTS[users._get(t)] = "!" + GHOSTS[users._get(t)]
|
||||||
evt.data["message"].append(messages["totem_banish"].format(victim, t))
|
evt.data["message"].append(messages["totem_banish"].format(victim, t))
|
||||||
evt.data["target"] = None
|
evt.data["target"] = None
|
||||||
|
|
||||||
@event_listener("get_participant_role")
|
@event_listener("get_participant_role")
|
||||||
def on_get_participant_role(evt, var, nick):
|
def on_get_participant_role(evt, var, nick):
|
||||||
if nick in GHOSTS:
|
if users._get(nick) in GHOSTS: # FIXME
|
||||||
if nick in drivenoff:
|
if nick in drivenoff:
|
||||||
against = drivenoff[nick]
|
against = drivenoff[nick]
|
||||||
else:
|
else:
|
||||||
against = GHOSTS[nick]
|
against = GHOSTS[users._get(nick)]
|
||||||
if against == "villagers":
|
if against == "villagers":
|
||||||
evt.data["role"] = "wolf"
|
evt.data["role"] = "wolf"
|
||||||
elif against == "wolves":
|
elif against == "wolves":
|
||||||
@ -196,7 +195,7 @@ def on_get_participant_role(evt, var, nick):
|
|||||||
@event_listener("chk_nightdone")
|
@event_listener("chk_nightdone")
|
||||||
def on_chk_nightdone(evt, cli, var):
|
def on_chk_nightdone(evt, cli, var):
|
||||||
evt.data["actedcount"] += len(KILLS)
|
evt.data["actedcount"] += len(KILLS)
|
||||||
evt.data["nightroles"].extend([p for p in GHOSTS if GHOSTS[p][0] != "!"])
|
evt.data["nightroles"].extend([p.nick for p in GHOSTS if GHOSTS[p][0] != "!"])
|
||||||
|
|
||||||
@event_listener("transition_night_end", priority=2)
|
@event_listener("transition_night_end", priority=2)
|
||||||
def on_transition_night_end(evt, cli, var):
|
def on_transition_night_end(evt, cli, var):
|
||||||
@ -215,27 +214,28 @@ def on_transition_night_end(evt, cli, var):
|
|||||||
|
|
||||||
random.shuffle(pl)
|
random.shuffle(pl)
|
||||||
|
|
||||||
if v_ghost in var.PLAYERS and not is_user_simple(v_ghost):
|
if not v_ghost.prefers_simple():
|
||||||
pm(cli, v_ghost, messages["vengeful_ghost_notify"].format(who))
|
v_ghost.send(messages["vengeful_ghost_notify"].format(who))
|
||||||
else:
|
else:
|
||||||
pm(cli, v_ghost, messages["vengeful_ghost_simple"])
|
v_ghost.send(messages["vengeful_ghost_simple"])
|
||||||
pm(cli, v_ghost, who.capitalize() + ": " + ", ".join(pl))
|
v_ghost.send(who.capitalize() + ": " + ", ".join(pl))
|
||||||
debuglog("GHOST: {0} (target: {1}) - players: {2}".format(v_ghost, who, ", ".join(pl)))
|
debuglog("GHOST: {0} (target: {1}) - players: {2}".format(v_ghost.nick, who, ", ".join(pl)))
|
||||||
|
|
||||||
@event_listener("myrole")
|
@event_listener("myrole")
|
||||||
def on_myrole(evt, cli, var, nick):
|
def on_myrole(evt, cli, var, nick):
|
||||||
if nick in GHOSTS:
|
user = users._get(nick)
|
||||||
|
if user in GHOSTS:
|
||||||
evt.prevent_default = True
|
evt.prevent_default = True
|
||||||
if GHOSTS[nick][0] != "!":
|
if GHOSTS[user][0] != "!":
|
||||||
pm(cli, nick, messages["vengeful_role"].format(GHOSTS[nick]))
|
user.send(messages["vengeful_role"].format(GHOSTS[user]))
|
||||||
|
|
||||||
@event_listener("revealroles")
|
@event_listener("revealroles")
|
||||||
def on_revealroles(evt, cli, var):
|
def on_revealroles(evt, var, wrapper):
|
||||||
if GHOSTS:
|
if GHOSTS:
|
||||||
glist = []
|
glist = []
|
||||||
for ghost, team in GHOSTS.items():
|
for ghost, team in GHOSTS.items():
|
||||||
dead = "driven away, " if team[0] == "!" else ""
|
dead = "driven away, " if team[0] == "!" else ""
|
||||||
glist.append("{0} ({1}against {2})".format(ghost, dead, team.lstrip("!")))
|
glist.append("{0} ({1}against {2})".format(ghost.nick, dead, team.lstrip("!")))
|
||||||
evt.data["output"].append("\u0002dead vengeful ghost\u0002: {0}".format(", ".join(glist)))
|
evt.data["output"].append("\u0002dead vengeful ghost\u0002: {0}".format(", ".join(glist)))
|
||||||
|
|
||||||
@event_listener("begin_day")
|
@event_listener("begin_day")
|
||||||
|
@ -33,7 +33,7 @@ def on_transition_night_end(evt, cli, var):
|
|||||||
# No listeners should register before this one
|
# No listeners should register before this one
|
||||||
# This sets up the initial state, based on village/wolfteam/neutral affiliation
|
# This sets up the initial state, based on village/wolfteam/neutral affiliation
|
||||||
@event_listener("player_win", priority=0)
|
@event_listener("player_win", priority=0)
|
||||||
def on_player_win(evt, cli, var, nick, role, winner, survived):
|
def on_player_win(evt, var, user, role, winner, survived):
|
||||||
# init won/iwon to False
|
# init won/iwon to False
|
||||||
evt.data["won"] = False
|
evt.data["won"] = False
|
||||||
evt.data["iwon"] = False
|
evt.data["iwon"] = False
|
||||||
|
@ -145,7 +145,7 @@ def on_transition_night_end(evt, cli, var):
|
|||||||
pm(cli, child, messages["child_simple"])
|
pm(cli, child, messages["child_simple"])
|
||||||
|
|
||||||
@event_listener("revealroles_role")
|
@event_listener("revealroles_role")
|
||||||
def on_revealroles_role(evt, cli, var, nick, role):
|
def on_revealroles_role(evt, var, wrapper, nick, role):
|
||||||
if role == "wild child":
|
if role == "wild child":
|
||||||
if nick in IDOLS:
|
if nick in IDOLS:
|
||||||
evt.data["special_case"].append("picked {0} as idol".format(IDOLS[nick]))
|
evt.data["special_case"].append("picked {0} as idol".format(IDOLS[nick]))
|
||||||
|
14
src/users.py
14
src/users.py
@ -105,8 +105,14 @@ def _add(cli, *, nick, ident=None, host=None, realname=None, account=None):
|
|||||||
|
|
||||||
new = cls(cli, nick, ident, host, realname, account)
|
new = cls(cli, nick, ident, host, realname, account)
|
||||||
|
|
||||||
if new is not Bot and new.ident is not None and new.host is not None:
|
if new is not Bot:
|
||||||
_users.add(new)
|
try:
|
||||||
|
hash(new)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
_users.add(new)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def add(nick, **blah): # backwards-compatible API
|
def add(nick, **blah): # backwards-compatible API
|
||||||
@ -292,7 +298,7 @@ class User(IRCContext):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
for hostmask in hosts:
|
for hostmask in hosts:
|
||||||
if match_hostmask(hostmask, self.nick, self.ident, self.host):
|
if self.match_hostmask(hostmask):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
@ -314,7 +320,7 @@ class User(IRCContext):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
for hostmask in hosts:
|
for hostmask in hosts:
|
||||||
if match_hostmask(hostmask, self.nick, self.ident, self.host):
|
if self.match_hostmask(hostmask):
|
||||||
return True
|
return True
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
438
src/wolfgame.py
438
src/wolfgame.py
@ -46,10 +46,11 @@ import botconfig
|
|||||||
import src
|
import src
|
||||||
import src.settings as var
|
import src.settings as var
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import db, decorators, events, channels, users, hooks, logger, proxy, debuglog, errlog, plog
|
from src import db, events, channels, users, hooks, logger, proxy, debuglog, errlog, plog
|
||||||
from src.decorators import cmd, hook, handle_error, event_listener, COMMANDS
|
from src.decorators import command, cmd, hook, handle_error, event_listener, COMMANDS
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.warnings import *
|
from src.warnings import *
|
||||||
|
from src.context import IRCContext
|
||||||
|
|
||||||
# done this way so that events is accessible in !eval (useful for debugging)
|
# done this way so that events is accessible in !eval (useful for debugging)
|
||||||
Event = events.Event
|
Event = events.Event
|
||||||
@ -135,12 +136,12 @@ def connect_callback():
|
|||||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||||
|
|
||||||
if signum in (signal.SIGINT, signal.SIGTERM):
|
if signum in (signal.SIGINT, signal.SIGTERM):
|
||||||
forced_exit.func(cli, "<console>", botconfig.CHANNEL, "")
|
forced_exit.func(cli, "<console>", botconfig.CHANNEL, "") # XXX: Old API
|
||||||
elif signum == SIGUSR1:
|
elif signum == SIGUSR1:
|
||||||
restart_program.func(cli, "<console>", botconfig.CHANNEL, "")
|
restart_program.func(cli, "<console>", botconfig.CHANNEL, "") # XXX: Old API
|
||||||
elif signum == SIGUSR2:
|
elif signum == SIGUSR2:
|
||||||
plog("Scheduling aftergame restart")
|
plog("Scheduling aftergame restart")
|
||||||
aftergame.func(cli, "<console>", botconfig.CHANNEL, "frestart")
|
aftergame.func(cli, "<console>", botconfig.CHANNEL, "frestart") # XXX: Old API
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, sighandler)
|
signal.signal(signal.SIGINT, sighandler)
|
||||||
signal.signal(signal.SIGTERM, sighandler)
|
signal.signal(signal.SIGTERM, sighandler)
|
||||||
@ -360,7 +361,7 @@ def refreshdb(cli, nick, chan, rest):
|
|||||||
reply(cli, nick, chan, "Done.")
|
reply(cli, nick, chan, "Done.")
|
||||||
|
|
||||||
@cmd("die", "bye", "fdie", "fbye", flag="D", pm=True)
|
@cmd("die", "bye", "fdie", "fbye", flag="D", pm=True)
|
||||||
def forced_exit(cli, nick, chan, rest):
|
def forced_exit(cli, nick, chan, rest): # XXX: sighandler (top of file) also needs updating alongside this one
|
||||||
"""Forces the bot to close."""
|
"""Forces the bot to close."""
|
||||||
|
|
||||||
args = rest.split()
|
args = rest.split()
|
||||||
@ -413,7 +414,7 @@ def _restart_program(cli, mode=None):
|
|||||||
|
|
||||||
|
|
||||||
@cmd("restart", "frestart", flag="D", pm=True)
|
@cmd("restart", "frestart", flag="D", pm=True)
|
||||||
def restart_program(cli, nick, chan, rest):
|
def restart_program(cli, nick, chan, rest): # XXX: sighandler (top of file) also needs updating alongside this one
|
||||||
"""Restarts the bot."""
|
"""Restarts the bot."""
|
||||||
|
|
||||||
args = rest.split()
|
args = rest.split()
|
||||||
@ -791,7 +792,7 @@ def toggle_altpinged_status(nick, value, old=None):
|
|||||||
var.PING_IF_NUMS[old].discard(hostmask)
|
var.PING_IF_NUMS[old].discard(hostmask)
|
||||||
|
|
||||||
@handle_error
|
@handle_error
|
||||||
def join_timer_handler(cli):
|
def join_timer_handler():
|
||||||
with var.WARNING_LOCK:
|
with var.WARNING_LOCK:
|
||||||
var.PINGING_IFS = True
|
var.PINGING_IFS = True
|
||||||
to_ping = []
|
to_ping = []
|
||||||
@ -830,7 +831,7 @@ def join_timer_handler(cli):
|
|||||||
var.PINGING_IFS = False
|
var.PINGING_IFS = False
|
||||||
return
|
return
|
||||||
|
|
||||||
@hook("whoreply", hookid=387)
|
@hook("whoreply", hookid=387) # FIXME: Use events
|
||||||
def ping_altpingers_noacc(cli, bot_server, bot_nick, chan, ident, host, server, nick, status, hopcount_gecos):
|
def ping_altpingers_noacc(cli, bot_server, bot_nick, chan, ident, host, server, nick, status, hopcount_gecos):
|
||||||
if ("G" in status or is_user_stasised(nick) or not var.PINGING_IFS or
|
if ("G" in status or is_user_stasised(nick) or not var.PINGING_IFS or
|
||||||
nick == bot_nick or nick in pl):
|
nick == bot_nick or nick in pl):
|
||||||
@ -865,7 +866,7 @@ def join_timer_handler(cli):
|
|||||||
var.PINGED_ALREADY.add(hostmask)
|
var.PINGED_ALREADY.add(hostmask)
|
||||||
|
|
||||||
@hook("endofwho", hookid=387)
|
@hook("endofwho", hookid=387)
|
||||||
def fetch_altpingers(*stuff):
|
def fetch_altpingers(cli, *stuff):
|
||||||
# fun fact: if someone joined 10 seconds after someone else, the bot would break.
|
# fun fact: if someone joined 10 seconds after someone else, the bot would break.
|
||||||
# effectively, the join would delete join_pinger from var.TIMERS and this function
|
# effectively, the join would delete join_pinger from var.TIMERS and this function
|
||||||
# here would be reached before it was created again, thus erroring and crashing.
|
# here would be reached before it was created again, thus erroring and crashing.
|
||||||
@ -882,11 +883,7 @@ def join_timer_handler(cli):
|
|||||||
|
|
||||||
cli.msg(botconfig.CHANNEL, msg)
|
cli.msg(botconfig.CHANNEL, msg)
|
||||||
|
|
||||||
# FIXME
|
channels.Main.who()
|
||||||
if not var.DISABLE_ACCOUNTS:
|
|
||||||
cli.who(botconfig.CHANNEL, "%tcuihsnfdlar,")
|
|
||||||
else:
|
|
||||||
cli.who(botconfig.CHANNEL)
|
|
||||||
|
|
||||||
def get_deadchat_pref(nick):
|
def get_deadchat_pref(nick):
|
||||||
if users.exists(nick):
|
if users.exists(nick):
|
||||||
@ -991,8 +988,8 @@ def deadchat_pref(cli, nick, chan, rest):
|
|||||||
|
|
||||||
reply(cli, nick, chan, msg, private=True)
|
reply(cli, nick, chan, msg, private=True)
|
||||||
|
|
||||||
@cmd("join", "j", pm=True)
|
@command("join", "j", pm=True)
|
||||||
def join(cli, nick, chan, rest):
|
def join(var, wrapper, message):
|
||||||
"""Either starts a new game of Werewolf or joins an existing game that has not started yet."""
|
"""Either starts a new game of Werewolf or joins an existing game that has not started yet."""
|
||||||
# keep this and the event in fjoin() in sync
|
# keep this and the event in fjoin() in sync
|
||||||
evt = Event("join", {
|
evt = Event("join", {
|
||||||
@ -1000,72 +997,57 @@ def join(cli, nick, chan, rest):
|
|||||||
"join_deadchat": join_deadchat,
|
"join_deadchat": join_deadchat,
|
||||||
"vote_gamemode": vote_gamemode
|
"vote_gamemode": vote_gamemode
|
||||||
})
|
})
|
||||||
if not evt.dispatch(cli, var, nick, chan, rest, forced=False):
|
if not evt.dispatch(var, wrapper, message, forced=False):
|
||||||
return
|
return
|
||||||
if var.PHASE in ("none", "join"):
|
if var.PHASE in ("none", "join"):
|
||||||
if chan == nick:
|
if wrapper.private:
|
||||||
return
|
return
|
||||||
if var.ACCOUNTS_ONLY:
|
if var.ACCOUNTS_ONLY:
|
||||||
if users.exists(nick) and (not users.get(nick).account or users.get(nick).account == "*"):
|
if users._get(nick).account is None: # FIXME
|
||||||
cli.notice(nick, messages["not_logged_in"])
|
wrapper.pm(messages["not_logged_in"])
|
||||||
return
|
return
|
||||||
if evt.data["join_player"](cli, nick, chan) and rest:
|
if evt.data["join_player"](var, wrapper) and message:
|
||||||
evt.data["vote_gamemode"](cli, nick, chan, rest.lower().split()[0], False)
|
evt.data["vote_gamemode"](var, wrapper, message.lower().split()[0], doreply=False)
|
||||||
|
|
||||||
else: # join deadchat
|
else: # join deadchat
|
||||||
if chan == nick and nick != botconfig.NICK:
|
if wrapper.private and wrapper.source is not wrapper.target:
|
||||||
evt.data["join_deadchat"](cli, nick)
|
evt.data["join_deadchat"](var, wrapper)
|
||||||
|
|
||||||
def join_player(cli, player, chan, who=None, forced=False, *, sanity=True):
|
def join_player(var, wrapper, who=None, forced=False, *, sanity=True):
|
||||||
if who is None:
|
if who is None:
|
||||||
who = player
|
who = wrapper.source
|
||||||
|
|
||||||
pl = list_players()
|
pl = list_players()
|
||||||
if chan != botconfig.CHANNEL:
|
if wrapper.target is not channels.Main:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if users.exists(player):
|
stasis = wrapper.source.stasis_count()
|
||||||
ident = irc_lower(users.get(player).ident)
|
|
||||||
host = users.get(player).host.lower()
|
|
||||||
acc = irc_lower(users.get(player).account)
|
|
||||||
hostmask = player + "!" + ident + "@" + host
|
|
||||||
elif is_fake_nick(player) and botconfig.DEBUG_MODE:
|
|
||||||
# fakenick
|
|
||||||
ident = None
|
|
||||||
host = None
|
|
||||||
acc = None
|
|
||||||
hostmask = None
|
|
||||||
else:
|
|
||||||
return False # Not normal
|
|
||||||
if not acc or acc == "*" or var.DISABLE_ACCOUNTS:
|
|
||||||
acc = None
|
|
||||||
|
|
||||||
stasis = is_user_stasised(player)
|
|
||||||
|
|
||||||
if stasis > 0:
|
if stasis > 0:
|
||||||
if forced and stasis == 1:
|
if forced and stasis == 1:
|
||||||
decrement_stasis(player)
|
decrement_stasis(wrapper.source.nick)
|
||||||
else:
|
else:
|
||||||
cli.notice(who, messages["stasis"].format(
|
who.send(messages["stasis"].format(
|
||||||
"you are" if player == who else player + " is", stasis,
|
"you are" if wrapper.source is who else wrapper.source.nick + " is", stasis,
|
||||||
"s" if stasis != 1 else ""))
|
"s" if stasis != 1 else ""), notice=True)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
temp = wrapper.source.lower()
|
||||||
|
|
||||||
# don't check unacked warnings on fjoin
|
# don't check unacked warnings on fjoin
|
||||||
if who == player and db.has_unacknowledged_warnings(acc, hostmask):
|
if wrapper.source is who and db.has_unacknowledged_warnings(temp.account, temp.rawnick):
|
||||||
cli.notice(player, messages["warn_unacked"])
|
wrapper.pm(messages["warn_unacked"])
|
||||||
return False
|
return False
|
||||||
|
|
||||||
cmodes = [("+v", player)]
|
cmodes = [("+v", wrapper.source.nick)]
|
||||||
if var.PHASE == "none":
|
if var.PHASE == "none":
|
||||||
if var.AUTO_TOGGLE_MODES and users.exists(player) and users.get(player).modes:
|
if var.AUTO_TOGGLE_MODES and users.get(player).modes: # FIXME: Need to properly handle mode changes (whole block)
|
||||||
for mode in users.get(player).modes:
|
for mode in users.get(wrapper.source.nick).modes:
|
||||||
cmodes.append(("-"+mode, player))
|
cmodes.append(("-"+mode, wrapper.source.nick))
|
||||||
users.get(player).moded.update(users.get(player).modes)
|
users.get(wrapper.source.nick).moded.update(users.get(wrapper.source.nick).modes)
|
||||||
users.get(player).modes = set()
|
users.get(wrapper.source.nick).modes.clear()
|
||||||
mass_mode(cli, cmodes, [])
|
var.ROLES["person"].add(wrapper.source.nick) # FIXME: Need to store Users, not nicks
|
||||||
var.ROLES["person"].add(player)
|
var.ALL_PLAYERS.append(wrapper.source.nick)
|
||||||
var.ALL_PLAYERS.append(player)
|
|
||||||
var.PHASE = "join"
|
var.PHASE = "join"
|
||||||
with var.WAIT_TB_LOCK:
|
with var.WAIT_TB_LOCK:
|
||||||
var.WAIT_TB_TOKENS = var.WAIT_TB_INIT
|
var.WAIT_TB_TOKENS = var.WAIT_TB_INIT
|
||||||
@ -1073,12 +1055,12 @@ def join_player(cli, player, chan, who=None, forced=False, *, sanity=True):
|
|||||||
var.GAME_ID = time.time()
|
var.GAME_ID = time.time()
|
||||||
var.PINGED_ALREADY_ACCS = set()
|
var.PINGED_ALREADY_ACCS = set()
|
||||||
var.PINGED_ALREADY = set()
|
var.PINGED_ALREADY = set()
|
||||||
if host:
|
if wrapper.source.userhost:
|
||||||
var.JOINED_THIS_GAME.add(ident + "@" + host)
|
var.JOINED_THIS_GAME.add(wrapper.source.userhost)
|
||||||
if acc:
|
if wrapper.source.account:
|
||||||
var.JOINED_THIS_GAME_ACCS.add(acc)
|
var.JOINED_THIS_GAME_ACCS.add(wrapper.source.account)
|
||||||
var.CAN_START_TIME = datetime.now() + timedelta(seconds=var.MINIMUM_WAIT)
|
var.CAN_START_TIME = datetime.now() + timedelta(seconds=var.MINIMUM_WAIT)
|
||||||
cli.msg(chan, messages["new_game"].format(player, botconfig.CMD_CHAR))
|
wrapper.send(messages["new_game"].format(wrapper.source.nick, botconfig.CMD_CHAR))
|
||||||
|
|
||||||
# Set join timer
|
# Set join timer
|
||||||
if var.JOIN_TIME_LIMIT > 0:
|
if var.JOIN_TIME_LIMIT > 0:
|
||||||
@ -1087,52 +1069,50 @@ def join_player(cli, player, chan, who=None, forced=False, *, sanity=True):
|
|||||||
t.daemon = True
|
t.daemon = True
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
elif player in pl:
|
elif wrapper.source.nick in pl: # FIXME: To fix when everything returns Users
|
||||||
cli.notice(who, messages["already_playing"].format("You" if who == player else "They"))
|
who.send(messages["already_playing"].format("You" if who is wrapper.source else "They"), notice=True)
|
||||||
# if we're not doing insane stuff, return True so that one can use !join to vote for a game mode
|
# if we're not doing insane stuff, return True so that one can use !join to vote for a game mode
|
||||||
# even if they are already joined. If we ARE doing insane stuff, return False to indicate that
|
# even if they are already joined. If we ARE doing insane stuff, return False to indicate that
|
||||||
# the player was not successfully joined by this call.
|
# the player was not successfully joined by this call.
|
||||||
return sanity
|
return sanity
|
||||||
elif len(pl) >= var.MAX_PLAYERS:
|
elif len(pl) >= var.MAX_PLAYERS:
|
||||||
cli.notice(who, messages["too_many_players"])
|
who.send(messages["too_many_players"], notice=True)
|
||||||
return False
|
return False
|
||||||
elif sanity and var.PHASE != "join":
|
elif sanity and var.PHASE != "join":
|
||||||
cli.notice(who, messages["game_already_running"])
|
who.send(messages["game_already_running"], notice=True)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if acc is not None and not botconfig.DEBUG_MODE:
|
if not botconfig.DEBUG_MODE:
|
||||||
for user in pl:
|
for nick in pl:
|
||||||
if irc_lower(users.get(user).account) == acc:
|
if users._get(nick).lower().account == temp.account: # FIXME
|
||||||
msg = messages["account_already_joined"]
|
msg = messages["account_already_joined"]
|
||||||
if who == player:
|
if who is wrapper.source:
|
||||||
cli.notice(who, msg.format(user, "your", messages["join_swap_instead"].format(botconfig.CMD_CHAR)))
|
who.send(msg.format(user, "your", messages["join_swap_instead"].format(botconfig.CMD_CHAR)), notice=True)
|
||||||
else:
|
else:
|
||||||
cli.notice(who, msg.format(user, "their", ""))
|
who.send(msg.format(user, "their", ""), notice=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
var.ALL_PLAYERS.append(player)
|
var.ALL_PLAYERS.append(wrapper.source.nick)
|
||||||
if not is_fake_nick(player) or not botconfig.DEBUG_MODE:
|
if not wrapper.source.is_fake or not botconfig.DEBUG_MODE:
|
||||||
if var.AUTO_TOGGLE_MODES and users.get(player).modes:
|
if var.AUTO_TOGGLE_MODES and users.get(wrapper.source.nick).modes:
|
||||||
for mode in var.USERS[player]["modes"]:
|
for mode in users.get(wrapper.source.nick).modes:
|
||||||
cmodes.append(("-"+mode, player))
|
cmodes.append(("-"+mode, wrapper.source.nick))
|
||||||
users.get(player).moded.update(users.get(player).modes)
|
users.get(wrapper.source.nick).moded.update(users.get(wrapper.source.nick).modes)
|
||||||
users.get(player).modes = set()
|
users.get(wrapper.source.nick).modes.clear()
|
||||||
mass_mode(cli, cmodes, [])
|
wrapper.send(messages["player_joined"].format(wrapper.source.nick, len(pl) + 1))
|
||||||
cli.msg(chan, messages["player_joined"].format(player, len(pl) + 1))
|
|
||||||
if not sanity:
|
if not sanity:
|
||||||
# Abandon Hope All Ye Who Enter Here
|
# Abandon Hope All Ye Who Enter Here
|
||||||
leave_deadchat(cli, player)
|
leave_deadchat(wrapper.source.client, wrapper.source.nick)
|
||||||
var.SPECTATING_DEADCHAT.discard(player)
|
var.SPECTATING_DEADCHAT.discard(wrapper.source.nick)
|
||||||
var.SPECTATING_WOLFCHAT.discard(player)
|
var.SPECTATING_WOLFCHAT.discard(wrapper.source.nick)
|
||||||
return True
|
return True
|
||||||
var.ROLES["person"].add(player)
|
var.ROLES["person"].add(wrapper.source.nick)
|
||||||
if not is_fake_nick(player):
|
if not wrapper.source.is_fake:
|
||||||
hostmask = ident + "@" + host
|
if wrapper.source.userhost not in var.JOINED_THIS_GAME and wrapper.source.account not in var.JOINED_THIS_GAME_ACCS:
|
||||||
if hostmask not in var.JOINED_THIS_GAME and (not acc or acc not in var.JOINED_THIS_GAME_ACCS):
|
|
||||||
# make sure this only happens once
|
# make sure this only happens once
|
||||||
var.JOINED_THIS_GAME.add(hostmask)
|
var.JOINED_THIS_GAME.add(wrapper.source.userhost)
|
||||||
if acc:
|
if wrapper.source.account:
|
||||||
var.JOINED_THIS_GAME_ACCS.add(acc)
|
var.JOINED_THIS_GAME_ACCS.add(wrapper.source.account)
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
|
|
||||||
# add var.EXTRA_WAIT_JOIN to wait time
|
# add var.EXTRA_WAIT_JOIN to wait time
|
||||||
@ -1154,11 +1134,13 @@ def join_player(cli, player, chan, who=None, forced=False, *, sanity=True):
|
|||||||
if "join_pinger" in var.TIMERS:
|
if "join_pinger" in var.TIMERS:
|
||||||
var.TIMERS["join_pinger"][0].cancel()
|
var.TIMERS["join_pinger"][0].cancel()
|
||||||
|
|
||||||
t = threading.Timer(10, join_timer_handler, (cli,))
|
t = threading.Timer(10, join_timer_handler)
|
||||||
var.TIMERS["join_pinger"] = (t, time.time(), 10)
|
var.TIMERS["join_pinger"] = (t, time.time(), 10)
|
||||||
t.daemon = True
|
t.daemon = True
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
|
channels.Main.mode(*cmodes)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@handle_error
|
@handle_error
|
||||||
@ -1179,8 +1161,8 @@ def kill_join(cli, chan):
|
|||||||
var.AFTER_FLASTGAME = None
|
var.AFTER_FLASTGAME = None
|
||||||
|
|
||||||
|
|
||||||
@cmd("fjoin", flag="A")
|
@command("fjoin", flag="A")
|
||||||
def fjoin(cli, nick, chan, rest):
|
def fjoin(var, wrapper, message):
|
||||||
"""Forces someone to join a game."""
|
"""Forces someone to join a game."""
|
||||||
# keep this and the event in def join() in sync
|
# keep this and the event in def join() in sync
|
||||||
evt = Event("join", {
|
evt = Event("join", {
|
||||||
@ -1188,24 +1170,26 @@ def fjoin(cli, nick, chan, rest):
|
|||||||
"join_deadchat": join_deadchat,
|
"join_deadchat": join_deadchat,
|
||||||
"vote_gamemode": vote_gamemode
|
"vote_gamemode": vote_gamemode
|
||||||
})
|
})
|
||||||
if not evt.dispatch(cli, var, nick, chan, rest, forced=True):
|
if not evt.dispatch(var, wrapper, message, forced=True):
|
||||||
return
|
return
|
||||||
noticed = False
|
noticed = False
|
||||||
fake = False
|
fake = False
|
||||||
if not rest.strip():
|
if not message.strip():
|
||||||
evt.data["join_player"](cli, nick, chan, forced=True)
|
evt.data["join_player"](var, wrapper, forced=True)
|
||||||
|
|
||||||
for tojoin in re.split(" +",rest):
|
for tojoin in re.split(" +", message):
|
||||||
tojoin = tojoin.strip()
|
tojoin = tojoin.strip()
|
||||||
if "-" in tojoin:
|
if "-" in tojoin:
|
||||||
first, hyphen, last = tojoin.partition("-")
|
first, hyphen, last = tojoin.partition("-")
|
||||||
if first.isdigit() and last.isdigit():
|
if first.isdigit() and last.isdigit():
|
||||||
if int(last)+1 - int(first) > var.MAX_PLAYERS - len(list_players()):
|
if int(last)+1 - int(first) > var.MAX_PLAYERS - len(list_players()):
|
||||||
cli.msg(chan, messages["too_many_players_to_join"].format(nick))
|
wrapper.send(messages["too_many_players_to_join"].format(wrapper.source.nick))
|
||||||
break
|
break
|
||||||
fake = True
|
fake = True
|
||||||
for i in range(int(first), int(last)+1):
|
for i in range(int(first), int(last)+1):
|
||||||
evt.data["join_player"](cli, str(i), chan, forced=True, who=nick)
|
user = users._add(wrapper.source.client, nick=str(i)) # FIXME
|
||||||
|
channels.Dummy.users.add(user) # keep a strong reference to fake users (this will be removed eventually)
|
||||||
|
evt.data["join_player"](var, type(wrapper)(user, wrapper.target), forced=True, who=wrapper.source)
|
||||||
continue
|
continue
|
||||||
if not tojoin:
|
if not tojoin:
|
||||||
continue
|
continue
|
||||||
@ -1214,23 +1198,23 @@ def fjoin(cli, nick, chan, rest):
|
|||||||
if tojoin.lower() not in ull or not var.USERS[ul[ull.index(tojoin.lower())]]["inchan"]:
|
if tojoin.lower() not in ull or not var.USERS[ul[ull.index(tojoin.lower())]]["inchan"]:
|
||||||
if not is_fake_nick(tojoin) or not botconfig.DEBUG_MODE:
|
if not is_fake_nick(tojoin) or not botconfig.DEBUG_MODE:
|
||||||
if not noticed: # important
|
if not noticed: # important
|
||||||
cli.msg(chan, nick+messages["fjoin_in_chan"])
|
wrapper.send(wrapper.source.nick+messages["fjoin_in_chan"])
|
||||||
noticed = True
|
noticed = True
|
||||||
continue
|
continue
|
||||||
if not is_fake_nick(tojoin):
|
if not is_fake_nick(tojoin):
|
||||||
tojoin = ul[ull.index(tojoin.lower())].strip()
|
tojoin = ul[ull.index(tojoin.lower())].strip()
|
||||||
if not botconfig.DEBUG_MODE and var.ACCOUNTS_ONLY:
|
if not botconfig.DEBUG_MODE and var.ACCOUNTS_ONLY:
|
||||||
if not users.get(tojoin).account or users.get(tojoin).account == "*":
|
if not users.get(tojoin).account or users.get(tojoin).account == "*":
|
||||||
cli.notice(nick, messages["account_not_logged_in"].format(tojoin))
|
wrapper.pm(messages["account_not_logged_in"].format(tojoin))
|
||||||
return
|
return
|
||||||
elif botconfig.DEBUG_MODE:
|
elif botconfig.DEBUG_MODE:
|
||||||
fake = True
|
fake = True
|
||||||
if tojoin != botconfig.NICK:
|
if tojoin != users.Bot.nick:
|
||||||
evt.data["join_player"](cli, tojoin, chan, forced=True, who=nick)
|
evt.data["join_player"](var, type(wrapper)(users._add(wrapper.source.client, nick=tojoin), wrapper.target), forced=True, who=wrapper.source)
|
||||||
else:
|
else:
|
||||||
cli.notice(nick, messages["not_allowed"])
|
wrapper.pm(messages["not_allowed"])
|
||||||
if fake:
|
if fake:
|
||||||
cli.msg(chan, messages["fjoin_success"].format(nick, len(list_players())))
|
wrapper.send(messages["fjoin_success"].format(wrapper.source.nick, len(list_players())))
|
||||||
|
|
||||||
@cmd("fleave", "fquit", flag="A", pm=True, phases=("join", "day", "night"))
|
@cmd("fleave", "fquit", flag="A", pm=True, phases=("join", "day", "night"))
|
||||||
def fleave(cli, nick, chan, rest):
|
def fleave(cli, nick, chan, rest):
|
||||||
@ -2381,7 +2365,7 @@ def stop_game(cli, winner="", abort=False, additional_winners=None, log=True):
|
|||||||
survived = list_players()
|
survived = list_players()
|
||||||
if not pentry["dced"]:
|
if not pentry["dced"]:
|
||||||
evt = Event("player_win", {"won": won, "iwon": iwon, "special": pentry["special"]})
|
evt = Event("player_win", {"won": won, "iwon": iwon, "special": pentry["special"]})
|
||||||
evt.dispatch(cli, var, splr, rol, winner, splr in survived)
|
evt.dispatch(var, users._get(splr), rol, winner, splr in survived) # FIXME
|
||||||
won = evt.data["won"]
|
won = evt.data["won"]
|
||||||
iwon = evt.data["iwon"]
|
iwon = evt.data["iwon"]
|
||||||
# ensure that it is a) a list, and b) a copy (so it can't be mutated out from under us later)
|
# ensure that it is a) a list, and b) a copy (so it can't be mutated out from under us later)
|
||||||
@ -3760,7 +3744,7 @@ def transition_day(cli, gameid=0):
|
|||||||
for mm in var.ROLES["matchmaker"]:
|
for mm in var.ROLES["matchmaker"]:
|
||||||
if mm not in var.MATCHMAKERS:
|
if mm not in var.MATCHMAKERS:
|
||||||
lovers = random.sample(pl, 2)
|
lovers = random.sample(pl, 2)
|
||||||
choose.func(cli, mm, mm, lovers[0] + " " + lovers[1], sendmsg=False)
|
choose.func(cli, mm, mm, lovers[0] + " " + lovers[1], sendmsg=False) # XXX: Old API
|
||||||
pm(cli, mm, messages["random_matchmaker"])
|
pm(cli, mm, messages["random_matchmaker"])
|
||||||
|
|
||||||
# Reset daytime variables
|
# Reset daytime variables
|
||||||
@ -4656,35 +4640,34 @@ def retract(cli, nick, chan, rest):
|
|||||||
else:
|
else:
|
||||||
cli.notice(nick, messages["pending_vote"])
|
cli.notice(nick, messages["pending_vote"])
|
||||||
|
|
||||||
@cmd("shoot", playing=True, silenced=True, phases=("day",))
|
@command("shoot", playing=True, silenced=True, phases=("day",))
|
||||||
def shoot(cli, nick, chan, rest):
|
def shoot(var, wrapper, message):
|
||||||
"""Use this to fire off a bullet at someone in the day if you have bullets."""
|
"""Use this to fire off a bullet at someone in the day if you have bullets."""
|
||||||
|
if wrapper.target is not channels.Main:
|
||||||
if chan != botconfig.CHANNEL:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if nick not in var.GUNNERS.keys():
|
if wrapper.source.nick not in var.GUNNERS.keys():
|
||||||
cli.notice(nick, messages["no_gun"])
|
wrapper.pm(messages["no_gun"])
|
||||||
return
|
return
|
||||||
elif not var.GUNNERS.get(nick):
|
elif not var.GUNNERS.get(wrapper.source.nick):
|
||||||
cli.notice(nick, messages["no_bullets"])
|
wrapper.pm(messages["no_bullets"])
|
||||||
return
|
return
|
||||||
victim = get_victim(cli, nick, re.split(" +",rest)[0], True)
|
victim = get_victim(wrapper.source.client, wrapper.source.nick, re.split(" +", message)[0], True)
|
||||||
if not victim:
|
if not victim:
|
||||||
return
|
return
|
||||||
if victim == nick:
|
if victim == wrapper.source.nick:
|
||||||
cli.notice(nick, messages["gunner_target_self"])
|
wrapper.pm(messages["gunner_target_self"])
|
||||||
return
|
return
|
||||||
# get actual victim
|
# get actual victim
|
||||||
victim = choose_target(nick, victim)
|
victim = choose_target(wrapper.source.nick, victim)
|
||||||
|
|
||||||
wolfshooter = nick in list_players(var.WOLFCHAT_ROLES)
|
wolfshooter = wrapper.source.nick in list_players(var.WOLFCHAT_ROLES)
|
||||||
var.GUNNERS[nick] -= 1
|
var.GUNNERS[wrapper.source.nick] -= 1
|
||||||
|
|
||||||
rand = random.random()
|
rand = random.random()
|
||||||
if nick in var.ROLES["village drunk"]:
|
if wrapper.source.nick in var.ROLES["village drunk"]:
|
||||||
chances = var.DRUNK_GUN_CHANCES
|
chances = var.DRUNK_GUN_CHANCES
|
||||||
elif nick in var.ROLES["sharpshooter"]:
|
elif wrapper.source.nick in var.ROLES["sharpshooter"]:
|
||||||
chances = var.SHARPSHOOTER_GUN_CHANCES
|
chances = var.SHARPSHOOTER_GUN_CHANCES
|
||||||
else:
|
else:
|
||||||
chances = var.GUN_CHANCES
|
chances = var.GUN_CHANCES
|
||||||
@ -4701,26 +4684,26 @@ def shoot(cli, nick, chan, rest):
|
|||||||
if rand <= chances[0] and not (wolfshooter and wolfvictim) and not alwaysmiss:
|
if rand <= chances[0] and not (wolfshooter and wolfvictim) and not alwaysmiss:
|
||||||
# didn't miss or suicide and it's not a wolf shooting another wolf
|
# didn't miss or suicide and it's not a wolf shooting another wolf
|
||||||
|
|
||||||
cli.msg(chan, messages["shoot_success"].format(nick, victim))
|
wrapper.send(messages["shoot_success"].format(wrapper.source.nick, victim))
|
||||||
an = "n" if victimrole.startswith(("a", "e", "i", "o", "u")) else ""
|
an = "n" if victimrole.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
if realrole in var.WOLF_ROLES:
|
if realrole in var.WOLF_ROLES:
|
||||||
if var.ROLE_REVEAL == "on":
|
if var.ROLE_REVEAL == "on":
|
||||||
cli.msg(chan, messages["gunner_victim_wolf_death"].format(victim,an, victimrole))
|
wrapper.send(messages["gunner_victim_wolf_death"].format(victim,an, victimrole))
|
||||||
else: # off and team
|
else: # off and team
|
||||||
cli.msg(chan, messages["gunner_victim_wolf_death_no_reveal"].format(victim))
|
wrapper.send(messages["gunner_victim_wolf_death_no_reveal"].format(victim))
|
||||||
if not del_player(cli, victim, killer_role = get_role(nick)):
|
if not del_player(wrapper.source.client, victim, killer_role=get_role(wrapper.source.nick)):
|
||||||
return
|
return
|
||||||
elif random.random() <= chances[3]:
|
elif random.random() <= chances[3]:
|
||||||
accident = "accidentally "
|
accident = "accidentally "
|
||||||
if nick in var.ROLES["sharpshooter"]:
|
if wrapper.source.nick in var.ROLES["sharpshooter"]:
|
||||||
accident = "" # it's an accident if the sharpshooter DOESN'T headshot :P
|
accident = "" # it's an accident if the sharpshooter DOESN'T headshot :P
|
||||||
cli.msg(chan, messages["gunner_victim_villager_death"].format(victim, accident))
|
wrapper.send(messages["gunner_victim_villager_death"].format(victim, accident))
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
cli.msg(chan, messages["gunner_victim_role"].format(an, victimrole))
|
wrapper.send(messages["gunner_victim_role"].format(an, victimrole))
|
||||||
if not del_player(cli, victim, killer_role = get_role(nick)):
|
if not del_player(wrapper.source.client, victim, killer_role=get_role(wrapper.source.nick)):
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
cli.msg(chan, messages["gunner_victim_injured"].format(victim))
|
wrapper.send(messages["gunner_victim_injured"].format(victim))
|
||||||
var.WOUNDED.add(victim)
|
var.WOUNDED.add(victim)
|
||||||
lcandidates = list(var.VOTES.keys())
|
lcandidates = list(var.VOTES.keys())
|
||||||
for cand in lcandidates: # remove previous vote
|
for cand in lcandidates: # remove previous vote
|
||||||
@ -4729,16 +4712,16 @@ def shoot(cli, nick, chan, rest):
|
|||||||
if not var.VOTES.get(cand):
|
if not var.VOTES.get(cand):
|
||||||
del var.VOTES[cand]
|
del var.VOTES[cand]
|
||||||
break
|
break
|
||||||
chk_decision(cli)
|
chk_decision(wrapper.source.client)
|
||||||
chk_win(cli)
|
chk_win(wrapper.source.client)
|
||||||
elif rand <= chances[0] + chances[1]:
|
elif rand <= chances[0] + chances[1]:
|
||||||
cli.msg(chan, messages["gunner_miss"].format(nick))
|
wrapper.send(messages["gunner_miss"].format(wrapper.source.nick))
|
||||||
else:
|
else:
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
cli.msg(chan, messages["gunner_suicide"].format(nick, get_reveal_role(nick)))
|
wrapper.send(messages["gunner_suicide"].format(wrapper.source.nick, get_reveal_role(wrapper.source.nick)))
|
||||||
else:
|
else:
|
||||||
cli.msg(chan, messages["gunner_suicide_no_reveal"].format(nick))
|
wrapper.send(messages["gunner_suicide_no_reveal"].format(wrapper.source.nick))
|
||||||
if not del_player(cli, nick, killer_role = "villager"): # blame explosion on villager's shoddy gun construction or something
|
if not del_player(wrapper.source.client, wrapper.source.nick, killer_role="villager"): # blame explosion on villager's shoddy gun construction or something
|
||||||
return # Someone won.
|
return # Someone won.
|
||||||
|
|
||||||
def is_safe(nick, victim): # helper function
|
def is_safe(nick, victim): # helper function
|
||||||
@ -4791,7 +4774,7 @@ def consecrate(cli, nick, chan, rest):
|
|||||||
# (for example, if there was a role that could raise corpses as undead somethings, this would prevent that from working)
|
# (for example, if there was a role that could raise corpses as undead somethings, this would prevent that from working)
|
||||||
# regardless if this has any actual effect or not, it still removes the priest from being able to vote
|
# regardless if this has any actual effect or not, it still removes the priest from being able to vote
|
||||||
from src.roles import vengefulghost
|
from src.roles import vengefulghost
|
||||||
if victim in vengefulghost.GHOSTS:
|
if users._get(victim) in vengefulghost.GHOSTS:
|
||||||
var.SILENCED.add(victim)
|
var.SILENCED.add(victim)
|
||||||
|
|
||||||
var.CONSECRATING.add(nick)
|
var.CONSECRATING.add(nick)
|
||||||
@ -4970,7 +4953,7 @@ def hvisit(cli, nick, chan, rest):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if nick == victim: # Staying home (same as calling pass, so call pass)
|
if nick == victim: # Staying home (same as calling pass, so call pass)
|
||||||
pass_cmd.func(cli, nick, chan, "")
|
pass_cmd.func(cli, nick, chan, "") # XXX: Old API
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
victim = choose_target(nick, victim)
|
victim = choose_target(nick, victim)
|
||||||
@ -5111,7 +5094,7 @@ def bite_cmd(cli, nick, chan, rest):
|
|||||||
|
|
||||||
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",),
|
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",),
|
||||||
roles=("harlot", "turncoat", "warlock", "succubus"))
|
roles=("harlot", "turncoat", "warlock", "succubus"))
|
||||||
def pass_cmd(cli, nick, chan, rest):
|
def pass_cmd(cli, nick, chan, rest): # XXX: hvisit (3 functions above this one) also needs updating alongside this
|
||||||
"""Decline to use your special power for that night."""
|
"""Decline to use your special power for that night."""
|
||||||
nickrole = get_role(nick)
|
nickrole = get_role(nick)
|
||||||
|
|
||||||
@ -5177,7 +5160,7 @@ def change_sides(cli, nick, chan, rest, sendmsg=True):
|
|||||||
|
|
||||||
@cmd("choose", chan=False, pm=True, playing=True, phases=("night",), roles=("matchmaker",))
|
@cmd("choose", chan=False, pm=True, playing=True, phases=("night",), roles=("matchmaker",))
|
||||||
@cmd("match", chan=False, pm=True, playing=True, phases=("night",), roles=("matchmaker",))
|
@cmd("match", chan=False, pm=True, playing=True, phases=("night",), roles=("matchmaker",))
|
||||||
def choose(cli, nick, chan, rest, sendmsg=True):
|
def choose(cli, nick, chan, rest, sendmsg=True): # XXX: transition_day also needs updating alongside this one
|
||||||
"""Select two players to fall in love. You may select yourself as one of the lovers."""
|
"""Select two players to fall in love. You may select yourself as one of the lovers."""
|
||||||
if not var.FIRST_NIGHT:
|
if not var.FIRST_NIGHT:
|
||||||
return
|
return
|
||||||
@ -7053,7 +7036,7 @@ def myrole(cli, nick, chan, rest):
|
|||||||
pm(cli, nick, message)
|
pm(cli, nick, message)
|
||||||
|
|
||||||
@cmd("aftergame", "faftergame", flag="D", raw_nick=True, pm=True)
|
@cmd("aftergame", "faftergame", flag="D", raw_nick=True, pm=True)
|
||||||
def aftergame(cli, rawnick, chan, rest):
|
def aftergame(cli, rawnick, chan, rest): # XXX: lastgame (just below this one) and sighandler (top of file) also need updating alongside this one
|
||||||
"""Schedule a command to be run after the current game."""
|
"""Schedule a command to be run after the current game."""
|
||||||
nick = parse_nick(rawnick)[0]
|
nick = parse_nick(rawnick)[0]
|
||||||
if not rest.strip():
|
if not rest.strip():
|
||||||
@ -7100,7 +7083,7 @@ def flastgame(cli, rawnick, chan, rest):
|
|||||||
var.ADMIN_TO_PING = nick
|
var.ADMIN_TO_PING = nick
|
||||||
|
|
||||||
if rest.strip():
|
if rest.strip():
|
||||||
aftergame.func(cli, rawnick, botconfig.CHANNEL, rest)
|
aftergame.func(cli, rawnick, botconfig.CHANNEL, rest) # XXX: Old API
|
||||||
|
|
||||||
@cmd("gamestats", "gstats", pm=True)
|
@cmd("gamestats", "gstats", pm=True)
|
||||||
def game_stats(cli, nick, chan, rest):
|
def game_stats(cli, nick, chan, rest):
|
||||||
@ -7143,7 +7126,7 @@ def game_stats(cli, nick, chan, rest):
|
|||||||
# Attempt to find game stats for the given game size
|
# Attempt to find game stats for the given game size
|
||||||
reply(cli, nick, chan, db.get_game_stats(gamemode, gamesize))
|
reply(cli, nick, chan, db.get_game_stats(gamemode, gamesize))
|
||||||
|
|
||||||
@cmd("playerstats", "pstats", "player", "p", pm=True)
|
@cmd("playerstats", "pstats", "player", "p", pm=True) # XXX: mystats (just after this) needs updating along this one
|
||||||
def player_stats(cli, nick, chan, rest):
|
def player_stats(cli, nick, chan, rest):
|
||||||
"""Gets the stats for the given player and role or a list of role totals if no role is given."""
|
"""Gets the stats for the given player and role or a list of role totals if no role is given."""
|
||||||
if (chan != nick and var.LAST_PSTATS and var.PSTATS_RATE_LIMIT and
|
if (chan != nick and var.LAST_PSTATS and var.PSTATS_RATE_LIMIT and
|
||||||
@ -7209,49 +7192,48 @@ def my_stats(cli, nick, chan, rest):
|
|||||||
player_stats.func(cli, nick, chan, " ".join([nick] + rest))
|
player_stats.func(cli, nick, chan, " ".join([nick] + rest))
|
||||||
|
|
||||||
# Called from !game and !join, used to vote for a game mode
|
# Called from !game and !join, used to vote for a game mode
|
||||||
def vote_gamemode(cli, nick, chan, gamemode, doreply):
|
def vote_gamemode(var, wrapper, gamemode, doreply):
|
||||||
if var.FGAMED:
|
if var.FGAMED:
|
||||||
if doreply:
|
if doreply:
|
||||||
cli.notice(nick, messages["admin_forced_game"])
|
wrapper.pm(messages["admin_forced_game"])
|
||||||
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)
|
match, _ = complete_match(gamemode, var.GAME_MODES.keys() - ["roles", "villagergame"] - var.DISABLED_GAMEMODES)
|
||||||
if not match:
|
if not match:
|
||||||
if doreply:
|
if doreply:
|
||||||
cli.notice(nick, messages["invalid_mode_no_list"].format(gamemode))
|
wrapper.pm(messages["invalid_mode_no_list"].format(gamemode))
|
||||||
return
|
return
|
||||||
gamemode = match
|
gamemode = match
|
||||||
|
|
||||||
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(nick) == gamemode:
|
if var.GAMEMODE_VOTES.get(wrapper.source.nick) == gamemode:
|
||||||
cli.notice(nick, messages["already_voted_game"].format(gamemode))
|
wrapper.pm(messages["already_voted_game"].format(gamemode))
|
||||||
else:
|
else:
|
||||||
var.GAMEMODE_VOTES[nick] = gamemode
|
var.GAMEMODE_VOTES[wrapper.source.nick] = gamemode
|
||||||
cli.msg(chan, messages["vote_game_mode"].format(nick, gamemode))
|
wrapper.send(messages["vote_game_mode"].format(wrapper.source.nick, gamemode))
|
||||||
else:
|
else:
|
||||||
if doreply:
|
if doreply:
|
||||||
cli.notice(nick, messages["vote_game_fail"])
|
wrapper.pm(messages["vote_game_fail"])
|
||||||
|
|
||||||
@cmd("game", playing=True, phases=("join",))
|
@command("game", playing=True, phases=("join",))
|
||||||
def game(cli, nick, chan, rest):
|
def game(var, wrapper, message):
|
||||||
"""Vote for a game mode to be picked."""
|
"""Vote for a game mode to be picked."""
|
||||||
if rest:
|
if message:
|
||||||
vote_gamemode(cli, nick, chan, rest.lower().split()[0], True)
|
vote_gamemode(var, wrapper, message.lower().split()[0], doreply=True)
|
||||||
else:
|
else:
|
||||||
gamemodes = ", ".join("\u0002{0}\u0002".format(gamemode) if len(list_players()) in range(var.GAME_MODES[gamemode][1],
|
gamemodes = ", ".join("\u0002{0}\u0002".format(gamemode) if len(list_players()) in range(var.GAME_MODES[gamemode][1],
|
||||||
var.GAME_MODES[gamemode][2]+1) else gamemode for gamemode in var.GAME_MODES.keys() if gamemode != "roles" and
|
var.GAME_MODES[gamemode][2]+1) else gamemode for gamemode in var.GAME_MODES.keys() if gamemode != "roles" and
|
||||||
gamemode != "villagergame" and gamemode not in var.DISABLED_GAMEMODES)
|
gamemode != "villagergame" and gamemode not in var.DISABLED_GAMEMODES)
|
||||||
cli.notice(nick, messages["no_mode_specified"] + gamemodes)
|
wrapper.pm(messages["no_mode_specified"] + gamemodes)
|
||||||
return
|
return
|
||||||
|
|
||||||
@cmd("games", "modes", pm=True)
|
@command("games", "modes", pm=True)
|
||||||
def show_modes(cli, nick, chan, rest):
|
def show_modes(var, wrapper, message):
|
||||||
"""Show the available game modes."""
|
"""Show the available game modes."""
|
||||||
msg = messages["available_modes"]
|
|
||||||
modes = "\u0002, \u0002".join(sorted(var.GAME_MODES.keys() - {"roles", "villagergame"} - var.DISABLED_GAMEMODES))
|
modes = "\u0002, \u0002".join(sorted(var.GAME_MODES.keys() - {"roles", "villagergame"} - var.DISABLED_GAMEMODES))
|
||||||
|
|
||||||
reply(cli, nick, chan, msg + modes + "\u0002", private=True)
|
wrapper.pm("{0}{1}\u0002".format(messages["available_modes"], modes))
|
||||||
|
|
||||||
def game_help(args=""):
|
def game_help(args=""):
|
||||||
return (messages["available_mode_setters_help"] +
|
return (messages["available_mode_setters_help"] +
|
||||||
@ -7343,52 +7325,53 @@ def update(cli, nick, chan, rest):
|
|||||||
if ret:
|
if ret:
|
||||||
restart_program.caller(cli, nick, chan, "Updating bot")
|
restart_program.caller(cli, nick, chan, "Updating bot")
|
||||||
|
|
||||||
@cmd("send", "fsend", flag="F", pm=True)
|
@command("send", "fsend", flag="F", pm=True)
|
||||||
def fsend(cli, nick, chan, rest):
|
def fsend(var, wrapper, message):
|
||||||
"""Forcibly send raw IRC commands to the server."""
|
"""Forcibly send raw IRC commands to the server."""
|
||||||
cli.send(rest)
|
wrapper.source.client.send(message)
|
||||||
|
|
||||||
def _say(cli, raw_nick, rest, command, action=False):
|
def _say(wrapper, rest, cmd, action=False):
|
||||||
(nick, _, ident, host) = parse_nick(raw_nick)
|
|
||||||
rest = rest.split(" ", 1)
|
rest = rest.split(" ", 1)
|
||||||
|
|
||||||
if len(rest) < 2:
|
if len(rest) < 2:
|
||||||
pm(cli, nick, messages["fsend_usage"].format(
|
wrapper.pm(messages["fsend_usage"].format(botconfig.CMD_CHAR, cmd))
|
||||||
botconfig.CMD_CHAR, command))
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
(target, message) = rest
|
target, message = rest
|
||||||
|
|
||||||
if not is_admin(nick, ident, host):
|
if target.startswith(tuple(hooks.Features["CHANTYPES"])):
|
||||||
if not users.exists(nick):
|
targ = channels.get(target, allow_none=True)
|
||||||
pm(cli, nick, messages["wrong_channel"].format(
|
else:
|
||||||
botconfig.CHANNEL))
|
targ = users._get(target, allow_multiple=True) # FIXME
|
||||||
|
if len(targ) == 1:
|
||||||
|
targ = targ[0]
|
||||||
|
else:
|
||||||
|
targ = None
|
||||||
|
|
||||||
return
|
if targ is None:
|
||||||
|
targ = IRCClient(target, wrapper.source.client)
|
||||||
if rest[0] != botconfig.CHANNEL:
|
|
||||||
pm(cli, nick, messages["invalid_fsend_permissions"])
|
|
||||||
|
|
||||||
|
if not wrapper.source.is_admin():
|
||||||
|
if targ is not channels.Main:
|
||||||
|
wrapper.pm(messages["invalid_fsend_permissions"])
|
||||||
return
|
return
|
||||||
|
|
||||||
if action:
|
if action:
|
||||||
message = "\u0001ACTION {0}\u0001".format(message)
|
message = "\u0001ACTION {0}\u0001".format(message)
|
||||||
|
|
||||||
cli.send("PRIVMSG {0} :{1}".format(target, message))
|
targ.send(message, privmsg=True)
|
||||||
|
|
||||||
|
@command("say", "fsay", flag="s", pm=True)
|
||||||
@cmd("say", "fsay", flag="s", raw_nick=True, pm=True)
|
def fsay(var, wrapper, message):
|
||||||
def fsay(cli, raw_nick, chan, rest):
|
|
||||||
"""Talk through the bot as a normal message."""
|
"""Talk through the bot as a normal message."""
|
||||||
_say(cli, raw_nick, rest, "say")
|
_say(wrapper, message, "say")
|
||||||
|
|
||||||
@cmd("act", "do", "me", "fact", "fdo", "fme", flag="s", raw_nick=True, pm=True)
|
@command("act", "do", "me", "fact", "fdo", "fme", flag="s", pm=True)
|
||||||
def fact(cli, raw_nick, chan, rest):
|
def fact(var, wrapper, message):
|
||||||
"""Act through the bot as an action."""
|
"""Act through the bot as an action."""
|
||||||
_say(cli, raw_nick, rest, "act", action=True)
|
_say(wrapper, message, "act", action=True)
|
||||||
|
|
||||||
def can_run_restricted_cmd(nick):
|
def can_run_restricted_cmd(user):
|
||||||
# if allowed in normal games, restrict it so that it can only be used by dead players and
|
# 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).
|
# non-players (don't allow active vengeful ghosts either).
|
||||||
# also don't allow in-channel (e.g. make it pm only)
|
# also don't allow in-channel (e.g. make it pm only)
|
||||||
@ -7398,35 +7381,34 @@ def can_run_restricted_cmd(nick):
|
|||||||
|
|
||||||
pl = list_participants()
|
pl = list_participants()
|
||||||
|
|
||||||
if nick in pl:
|
if user.nick in pl: # FIXME: Need to update this once list_participants() holds User instances
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if users.exists(nick) and users.get(nick).account in [users.get(player).account for player in pl if users.exists(player)]:
|
if user.account in [users._get(player).account for player in pl]: # FIXME
|
||||||
return False
|
return False
|
||||||
|
|
||||||
hostmask = users.get(nick).ident + "@" + users.get(nick).host
|
if user.userhost in [users._get(player).userhost for player in pl]: # FIXME
|
||||||
if users.exists(nick) and hostmask in [users.get(player).ident + "@" + users.get(player).host for player in pl if users.exists(player)]:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@cmd("spectate", "fspectate", flag="A", pm=True, phases=("day", "night"))
|
@command("spectate", "fspectate", flag="A", pm=True, phases=("day", "night"))
|
||||||
def fspectate(cli, nick, chan, rest):
|
def fspectate(var, wrapper, message):
|
||||||
"""Spectate wolfchat or deadchat."""
|
"""Spectate wolfchat or deadchat."""
|
||||||
if not can_run_restricted_cmd(nick):
|
if not can_run_restricted_cmd(wrapper.source):
|
||||||
pm(cli, nick, messages["fspectate_restricted"])
|
pm(cli, nick, messages["fspectate_restricted"])
|
||||||
return
|
return
|
||||||
|
|
||||||
params = rest.split(" ")
|
params = message.split(" ")
|
||||||
on = "on"
|
on = "on"
|
||||||
if not len(params):
|
if not len(params):
|
||||||
pm(cli, nick, messages["fspectate_help"])
|
wrapper.pm(messages["fspectate_help"])
|
||||||
return
|
return
|
||||||
elif len(params) > 1:
|
elif len(params) > 1:
|
||||||
on = params[1].lower()
|
on = params[1].lower()
|
||||||
what = params[0].lower()
|
what = params[0].lower()
|
||||||
if what not in ("wolfchat", "deadchat") or on not in ("on", "off"):
|
if what not in ("wolfchat", "deadchat") or on not in ("on", "off"):
|
||||||
pm(cli, nick, messages["fspectate_help"])
|
wrapper.pm(messages["fspectate_help"])
|
||||||
return
|
return
|
||||||
|
|
||||||
if on == "off":
|
if on == "off":
|
||||||
@ -7434,54 +7416,50 @@ def fspectate(cli, nick, chan, rest):
|
|||||||
var.SPECTATING_WOLFCHAT.discard(nick)
|
var.SPECTATING_WOLFCHAT.discard(nick)
|
||||||
else:
|
else:
|
||||||
var.SPECTATING_DEADCHAT.discard(nick)
|
var.SPECTATING_DEADCHAT.discard(nick)
|
||||||
pm(cli, nick, messages["fspectate_off"].format(what))
|
wrapper.pm(messages["fspectate_off"].format(what))
|
||||||
else:
|
else:
|
||||||
players = []
|
players = []
|
||||||
if what == "wolfchat":
|
if what == "wolfchat":
|
||||||
var.SPECTATING_WOLFCHAT.add(nick)
|
var.SPECTATING_WOLFCHAT.add(nick)
|
||||||
players = (p for p in list_players() if in_wolflist(p, p))
|
players = (p for p in list_players() if in_wolflist(p, p))
|
||||||
elif var.ENABLE_DEADCHAT:
|
elif var.ENABLE_DEADCHAT:
|
||||||
if nick in var.DEADCHAT_PLAYERS:
|
if wrapper.source.nick in var.DEADCHAT_PLAYERS: # FIXME
|
||||||
pm(cli, nick, messages["fspectate_in_deadchat"])
|
wrapper.pm(messages["fspectate_in_deadchat"])
|
||||||
return
|
return
|
||||||
var.SPECTATING_DEADCHAT.add(nick)
|
var.SPECTATING_DEADCHAT.add(nick)
|
||||||
players = var.DEADCHAT_PLAYERS
|
players = var.DEADCHAT_PLAYERS
|
||||||
else:
|
else:
|
||||||
pm(cli, nick, messages["fspectate_deadchat_disabled"])
|
wrapper.pm(messages["fspectate_deadchat_disabled"])
|
||||||
return
|
return
|
||||||
pm(cli, nick, messages["fspectate_on"].format(what))
|
wrapper.pm(messages["fspectate_on"].format(what))
|
||||||
pm(cli, nick, "People in {0}: {1}".format(what, ", ".join(players)))
|
wrapper.pm("People in {0}: {1}".format(what, ", ".join(players)))
|
||||||
|
|
||||||
before_debug_mode_commands = list(COMMANDS.keys())
|
before_debug_mode_commands = list(COMMANDS.keys())
|
||||||
|
|
||||||
if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
||||||
|
|
||||||
@cmd("eval", owner_only=True, pm=True)
|
@command("eval", owner_only=True, pm=True)
|
||||||
def pyeval(cli, nick, chan, rest):
|
def pyeval(var, wrapper, message):
|
||||||
"""Evaluate a Python expression."""
|
"""Evaluate a Python expression."""
|
||||||
try:
|
try:
|
||||||
a = str(eval(rest))
|
wrapper.send(str(eval(message))[:500])
|
||||||
if len(a) < 500:
|
|
||||||
cli.msg(chan, a)
|
|
||||||
else:
|
|
||||||
cli.msg(chan, a[:500])
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
cli.msg(chan, "{e.__class__.__name__}: {e}".format(e=e))
|
wrapper.send("{e.__class__.__name__}: {e}".format(e=e))
|
||||||
|
|
||||||
@cmd("exec", owner_only=True, pm=True)
|
@command("exec", owner_only=True, pm=True)
|
||||||
def py(cli, nick, chan, rest):
|
def py(var, wrapper, message):
|
||||||
"""Execute arbitrary Python code."""
|
"""Execute arbitrary Python code."""
|
||||||
try:
|
try:
|
||||||
exec(rest)
|
exec(message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
cli.msg(chan, "{e.__class__.__name__}: {e}".format(e=e))
|
wrapper.send("{e.__class__.__name__}: {e}".format(e=e))
|
||||||
|
|
||||||
@cmd("revealroles", flag="a", pm=True, phases=("day", "night"))
|
@command("revealroles", flag="a", pm=True, phases=("day", "night"))
|
||||||
def revealroles(cli, nick, chan, rest):
|
def revealroles(var, wrapper, message):
|
||||||
"""Reveal role information."""
|
"""Reveal role information."""
|
||||||
|
|
||||||
if not can_run_restricted_cmd(nick):
|
if not can_run_restricted_cmd(wrapper.source):
|
||||||
reply(cli, nick, chan, messages["temp_invalid_perms"], private=True)
|
wrapper.pm(messages["temp_invalid_perms"])
|
||||||
return
|
return
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
@ -7507,7 +7485,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
|||||||
if var.TURNCOATS[nickname][0] != "none" else "not currently on any side")
|
if var.TURNCOATS[nickname][0] != "none" else "not currently on any side")
|
||||||
|
|
||||||
evt = Event("revealroles_role", {"special_case": special_case})
|
evt = Event("revealroles_role", {"special_case": special_case})
|
||||||
evt.dispatch(cli, var, nickname, role)
|
evt.dispatch(var, wrapper, nickname, role)
|
||||||
special_case = evt.data["special_case"]
|
special_case = evt.data["special_case"]
|
||||||
|
|
||||||
if not evt.prevent_default and nickname not in var.ORIGINAL_ROLES[role] and role not in var.TEMPLATE_RESTRICTIONS:
|
if not evt.prevent_default and nickname not in var.ORIGINAL_ROLES[role] and role not in var.TEMPLATE_RESTRICTIONS:
|
||||||
@ -7552,12 +7530,12 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
|||||||
output.append("\u0002charmed players\u0002: {0}".format(", ".join(var.CHARMED | var.TOBECHARMED)))
|
output.append("\u0002charmed players\u0002: {0}".format(", ".join(var.CHARMED | var.TOBECHARMED)))
|
||||||
|
|
||||||
evt = Event("revealroles", {"output": output})
|
evt = Event("revealroles", {"output": output})
|
||||||
evt.dispatch(cli, var)
|
evt.dispatch(var, wrapper)
|
||||||
|
|
||||||
if botconfig.DEBUG_MODE:
|
if botconfig.DEBUG_MODE:
|
||||||
cli.msg(chan, break_long_message(output, " | "))
|
wrapper.send(*output, sep=" | ")
|
||||||
else:
|
else:
|
||||||
reply(cli, nick, chan, break_long_message(output, " | "), private=True)
|
wrapper.pm(*output, sep=" | ")
|
||||||
|
|
||||||
|
|
||||||
@cmd("fgame", flag="d", raw_nick=True, phases=("join",))
|
@cmd("fgame", flag="d", raw_nick=True, phases=("join",))
|
||||||
@ -7645,7 +7623,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
|||||||
if fn.chan:
|
if fn.chan:
|
||||||
fn.caller(cli, user, chan, " ".join(rst))
|
fn.caller(cli, user, chan, " ".join(rst))
|
||||||
else:
|
else:
|
||||||
fn.caller(cli, user, user, " ".join(rst))
|
fn.caller(cli, user, users.Bot.nick, " ".join(rst))
|
||||||
cli.msg(chan, messages["operation_successful"])
|
cli.msg(chan, messages["operation_successful"])
|
||||||
else:
|
else:
|
||||||
cli.msg(chan, messages["command_not_found"])
|
cli.msg(chan, messages["command_not_found"])
|
||||||
@ -7685,7 +7663,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
|||||||
if fn.chan:
|
if fn.chan:
|
||||||
fn.caller(cli, user, chan, " ".join(rst))
|
fn.caller(cli, user, chan, " ".join(rst))
|
||||||
else:
|
else:
|
||||||
fn.caller(cli, user, user, " ".join(rst))
|
fn.caller(cli, user, users.Bot.nick, " ".join(rst))
|
||||||
cli.msg(chan, messages["operation_successful"])
|
cli.msg(chan, messages["operation_successful"])
|
||||||
else:
|
else:
|
||||||
cli.msg(chan, messages["command_not_found"])
|
cli.msg(chan, messages["command_not_found"])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user