Merge pull request #101 from lykoss/decorators-overhaul

Huge overhaul to the decorators (+ a lot of small changes).
This commit is contained in:
Ryan Schmidt 2015-01-02 23:58:53 -06:00
commit 6714f66e54
4 changed files with 449 additions and 803 deletions

View File

@ -7,6 +7,7 @@ import tools.moduleloader as ld
import traceback import traceback
from settings import common as var from settings import common as var
from base64 import b64encode from base64 import b64encode
from oyoyo.parse import parse_nick
import imp import imp
def on_privmsg(cli, rawnick, chan, msg, notice = False): def on_privmsg(cli, rawnick, chan, msg, notice = False):
@ -19,47 +20,36 @@ def on_privmsg(cli, rawnick, chan, msg, notice = False):
(chan == botconfig.NICK and not botconfig.ALLOW_PRIVATE_NOTICE_COMMANDS))): (chan == botconfig.NICK and not botconfig.ALLOW_PRIVATE_NOTICE_COMMANDS))):
return # not allowed in settings return # not allowed in settings
if chan != botconfig.NICK: #not a PM if chan == botconfig.NICK:
chan = parse_nick(rawnick)[0]
if currmod and "" in currmod.COMMANDS.keys(): if currmod and "" in currmod.COMMANDS.keys():
for fn in currmod.COMMANDS[""]: for fn in currmod.COMMANDS[""]:
try: try:
fn(cli, rawnick, chan, msg) fn(cli, rawnick, chan, msg)
except Exception as e: except:
if botconfig.DEBUG_MODE: if botconfig.DEBUG_MODE:
raise e raise
else:
logging.error(traceback.format_exc())
cli.msg(chan, "An error has occurred and has been logged.")
# Now that is always called first.
for x in set(list(COMMANDS.keys()) + (list(currmod.COMMANDS.keys()) if currmod else list())):
if x and msg.lower().startswith(botconfig.CMD_CHAR+x):
h = msg[len(x)+len(botconfig.CMD_CHAR):]
if not h or h[0] == " " or not x:
for fn in COMMANDS.get(x,[])+(currmod.COMMANDS.get(x,[]) if currmod else []):
try:
fn(cli, rawnick, chan, h.lstrip())
except Exception as e:
if botconfig.DEBUG_MODE:
raise e
else: else:
logging.error(traceback.format_exc()) logging.error(traceback.format_exc())
cli.msg(chan, "An error has occurred and has been logged.") cli.msg(chan, "An error has occurred and has been logged.")
else: for x in set(list(COMMANDS.keys()) + (list(currmod.COMMANDS.keys()) if currmod else list())):
for x in set(list(PM_COMMANDS.keys()) + (list(currmod.PM_COMMANDS.keys()) if currmod else list())): if chan != parse_nick(rawnick)[0] and not msg.lower().startswith(botconfig.CMD_CHAR):
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):]
elif not x or msg.lower().startswith(x): elif not x or msg.lower().startswith(x):
h = msg[len(x):] h = msg[len(x):]
else: else:
continue continue
if not h or h[0] == " " or not x: if not h or h[0] == " ":
for fn in PM_COMMANDS.get(x, [])+(currmod.PM_COMMANDS.get(x,[]) if currmod else []): for fn in COMMANDS.get(x, []) + (currmod.COMMANDS.get(x, []) if currmod else []):
try: try:
fn(cli, rawnick, h.lstrip()) fn(cli, rawnick, chan, h.lstrip())
except Exception as e: except:
if botconfig.DEBUG_MODE: if botconfig.DEBUG_MODE:
raise e raise
else: else:
logging.error(traceback.format_exc()) logging.error(traceback.format_exc())
cli.msg(chan, "An error has occurred and has been logged.") cli.msg(chan, "An error has occurred and has been logged.")
@ -87,11 +77,9 @@ def __unhandled__(cli, prefix, cmd, *args):
COMMANDS = {} COMMANDS = {}
PM_COMMANDS = {}
HOOKS = {} HOOKS = {}
cmd = decorators.generate(COMMANDS) cmd = decorators.generate(COMMANDS)
pmcmd = decorators.generate(PM_COMMANDS)
hook = decorators.generate(HOOKS, raw_nick=True, permissions=False) hook = decorators.generate(HOOKS, raw_nick=True, permissions=False)
def connect_callback(cli): def connect_callback(cli):

File diff suppressed because it is too large Load Diff

View File

@ -66,6 +66,7 @@ START_WITH_DAY = False
WOLF_STEALS_GUN = True # at night, the wolf can steal steal the victim's bullets WOLF_STEALS_GUN = True # at night, the wolf can steal steal the victim's bullets
ROLE_REVEAL = True ROLE_REVEAL = True
LOVER_WINS_WITH_FOOL = False # if fool is lynched, does their lover win with them? LOVER_WINS_WITH_FOOL = False # if fool is lynched, does their lover win with them?
DEFAULT_SEEN_AS_VILL = True # non-wolves are seen as villager regardless of the default role
# Minimum number of players needed for mad scientist to skip over dead people when determining who is next to them # Minimum number of players needed for mad scientist to skip over dead people when determining who is next to them
# Set to 0 to always skip over dead players. Note this is number of players that !joined, NOT number of players currently alive # Set to 0 to always skip over dead players. Note this is number of players that !joined, NOT number of players currently alive
@ -180,13 +181,17 @@ ROLE_GUIDE = {# village roles
# If every wolf role dies, and there are no remaining traitors, the game ends and villagers win (monster may steal win) # If every wolf role dies, and there are no remaining traitors, the game ends and villagers win (monster may steal win)
WOLF_ROLES = ["wolf", "alpha wolf", "werecrow", "wolf cub"] WOLF_ROLES = ["wolf", "alpha wolf", "werecrow", "wolf cub"]
# Access to wolfchat, and counted towards the # of wolves vs villagers when determining if a side has won # Access to wolfchat, and counted towards the # of wolves vs villagers when determining if a side has won
WOLFCHAT_ROLES = ["wolf", "alpha wolf", "werecrow", "wolf cub", "traitor", "hag", "sorcerer"] WOLFCHAT_ROLES = WOLF_ROLES + ["traitor", "hag", "sorcerer"]
# Wins with the wolves, even if the roles are not necessarily wolves themselves # Wins with the wolves, even if the roles are not necessarily wolves themselves
WOLFTEAM_ROLES = ["wolf", "alpha wolf", "werecrow", "wolf cub", "traitor", "hag", "sorcerer", "minion", "cultist"] WOLFTEAM_ROLES = WOLFCHAT_ROLES + ["minion", "cultist"]
# These roles never win as a team, only ever individually (either instead of or in addition to the regular winners) # These roles never win as a team, only ever individually (either instead of or in addition to the regular winners)
TRUE_NEUTRAL_ROLES = ["crazed shaman", "fool", "jester", "monster", "clone"] TRUE_NEUTRAL_ROLES = ["crazed shaman", "fool", "jester", "monster", "clone"]
# These are the roles that will NOT be used for when amnesiac turns, everything else is fair game! (var.DEFAULT_ROLE is also appended if not in this list) # These are the roles that will NOT be used for when amnesiac turns, everything else is fair game! (var.DEFAULT_ROLE is also appended if not in this list)
AMNESIAC_BLACKLIST = ["monster", "amnesiac", "minion", "matchmaker", "clone", "doctor", "villager", "cultist"] AMNESIAC_BLACKLIST = ["monster", "amnesiac", "minion", "matchmaker", "clone", "doctor", "villager", "cultist"]
# These roles are seen as wolf by the seer/oracle
SEEN_WOLF = WOLF_ROLES + ["monster", "mad scientist"]
# These are seen as the default role (or villager) when seen by seer
SEEN_DEFAULT = ["traitor", "hag", "sorcerer", "village elder", "time lord", "villager", "cultist", "minion", "vengeful ghost", "lycan", "clone", "fool", "jester"]
# The roles in here are considered templates and will be applied on TOP of other roles. The restrictions are a list of roles that they CANNOT be applied to # The roles in here are considered templates and will be applied on TOP of other roles. The restrictions are a list of roles that they CANNOT be applied to
# NB: if you want a template to apply to everyone, list it here but make the restrictions an empty list. Templates not listed here are considered full roles instead # NB: if you want a template to apply to everyone, list it here but make the restrictions an empty list. Templates not listed here are considered full roles instead
@ -223,7 +228,7 @@ QUIT_MESSAGES_NO_REVEAL = ("\u0002{0}\u0002 suddenly falls over dead before the
"\u0002{0}\u0002 fell off the roof of their house and is now dead.", "\u0002{0}\u0002 fell off the roof of their house and is now dead.",
"\u0002{0}\u0002 is crushed to death by a falling tree. The villagers desperately try to save them, but it is too late.") "\u0002{0}\u0002 is crushed to death by a falling tree. The villagers desperately try to save them, but it is too late.")
import botconfig, fnmatch import botconfig, fnmatch, sys, time, re
RULES = (botconfig.CHANNEL + " channel rules: http://wolf.xnrand.com/rules") RULES = (botconfig.CHANNEL + " channel rules: http://wolf.xnrand.com/rules")
DENY = {} DENY = {}

View File

@ -15,7 +15,8 @@ import settings.wolfgame as var
def generate(fdict, permissions=True, **kwargs): def generate(fdict, permissions=True, **kwargs):
"""Generates a decorator generator. Always use this""" """Generates a decorator generator. Always use this"""
def cmd(*s, raw_nick=False, admin_only=False, owner_only=False, hookid=-1): def cmd(*s, raw_nick=False, admin_only=False, owner_only=False, chan=True, pm=False,
game=False, join=False, none=False, playing=False, roles=(), hookid=-1):
def dec(f): def dec(f):
def innerf(*args): def innerf(*args):
largs = list(args) largs = list(args)
@ -29,13 +30,15 @@ def generate(fdict, permissions=True, **kwargs):
else: else:
nick = "" nick = ""
cloak = "" cloak = ""
if len(largs) > 3 and largs[2] and largs[2][0] == "#":
chan = largs[2]
else:
chan = ""
if not raw_nick and len(largs) > 1 and largs[1]: if not raw_nick and len(largs) > 1 and largs[1]:
largs[1] = nick largs[1] = nick
if chan and not chan == botconfig.CHANNEL and not admin_only and not owner_only: if nick == "<console>":
return f(*largs) # special case; no questions
if not pm and largs[2] == nick: # PM command
return
if not chan and largs[2] != nick: # channel command
return
if largs[2].startswith("#") and largs[2] != botconfig.CHANNEL and not admin_only and not owner_only:
if "" in s: if "" in s:
return # Don't have empty commands triggering in other channels return # Don't have empty commands triggering in other channels
allowed = False allowed = False
@ -51,6 +54,29 @@ def generate(fdict, permissions=True, **kwargs):
acc = None acc = None
if "" in s: if "" in s:
return f(*largs) return f(*largs)
if game and var.PHASE not in ("day", "night") + (("join",) if join else ()):
largs[0].notice(nick, "No game is currently running.")
return
if ((join and none and var.PHASE not in ("join", "none"))
or (none and not join and var.PHASE != "none")):
largs[0].notice(nick, "Sorry, but the game is already running. Try again next time.")
return
if join and not none:
if var.PHASE == "none":
largs[0].notice(nick, "No game is currently running.")
return
if var.PHASE != "join" and not game:
largs[0].notice(nick, "Werewolf is already in play.")
return
if playing and nick not in var.list_players() or nick in var.DISCONNECTED.keys():
cli.notice(nick, "You're not currently playing.")
return
if roles:
for role in roles:
if nick in var.ROLES[role]:
break
else:
return
if acc: if acc:
for pattern in var.DENY_ACCOUNTS.keys(): for pattern in var.DENY_ACCOUNTS.keys():
if fnmatch.fnmatch(acc.lower(), pattern.lower()): if fnmatch.fnmatch(acc.lower(), pattern.lower()):
@ -105,6 +131,13 @@ def generate(fdict, permissions=True, **kwargs):
innerf.owner_only = owner_only innerf.owner_only = owner_only
innerf.raw_nick = raw_nick innerf.raw_nick = raw_nick
innerf.admin_only = admin_only innerf.admin_only = admin_only
innerf.chan = chan
innerf.pm = pm
innerf.none = none
innerf.join = join
innerf.game = game
innerf.playing = playing
innerf.roles = roles
innerf.hookid = hookid innerf.hookid = hookid
innerf.__doc__ = f.__doc__ innerf.__doc__ = f.__doc__
return innerf return innerf