Huge overhaul to the decorators + small changes.
- Merge channel and PM commands in a single decorator. - Add many parameters for the decorators, reducing commands cluster. - Added back the admin_only check for some commands; special-cased '<console>'. - Moved the checking for which roles are seen wolf in the settings; same for seen as default. - Added a variable to pick if one is seen as the default role or as a villager where applicable (default: True). - Fixed seer/oracle seeing through amnesiac. - Some fixes to the totem chances that I forgot to add in the previous commit. - Removed some useless module imports. - Moved some functions to settings. - Changed all single-quotes to double-quotes in commands for consistency. - Renamed 'cmd' variable in both force and rforce commands to avoid confusion. - Probably a bunch of other things. Don't consider this commit description to be 100% complete.
This commit is contained in:
parent
53cf4970ca
commit
df26d8d25e
@ -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):
|
||||||
@ -18,51 +19,40 @@ def on_privmsg(cli, rawnick, chan, msg, notice = False):
|
|||||||
if (notice and ((chan != botconfig.NICK and not botconfig.ALLOW_NOTICE_COMMANDS) or
|
if (notice and ((chan != botconfig.NICK and not botconfig.ALLOW_NOTICE_COMMANDS) or
|
||||||
(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:
|
||||||
if currmod and "" in currmod.COMMANDS.keys():
|
chan = parse_nick(rawnick)[0]
|
||||||
for fn in currmod.COMMANDS[""]:
|
|
||||||
|
if currmod and "" in currmod.COMMANDS.keys():
|
||||||
|
for fn in currmod.COMMANDS[""]:
|
||||||
|
try:
|
||||||
|
fn(cli, rawnick, chan, msg)
|
||||||
|
except:
|
||||||
|
if botconfig.DEBUG_MODE:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
logging.error(traceback.format_exc())
|
||||||
|
cli.msg(chan, "An error has occurred and has been logged.")
|
||||||
|
|
||||||
|
for x in set(list(COMMANDS.keys()) + (list(currmod.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):
|
||||||
|
h = msg[len(x)+len(botconfig.CMD_CHAR):]
|
||||||
|
elif not x or msg.lower().startswith(x):
|
||||||
|
h = msg[len(x):]
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if not h or h[0] == " ":
|
||||||
|
for fn in COMMANDS.get(x, []) + (currmod.COMMANDS.get(x, []) if currmod else []):
|
||||||
try:
|
try:
|
||||||
fn(cli, rawnick, chan, msg)
|
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.")
|
||||||
# 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:
|
|
||||||
logging.error(traceback.format_exc())
|
|
||||||
cli.msg(chan, "An error has occurred and has been logged.")
|
|
||||||
|
|
||||||
else:
|
|
||||||
for x in set(list(PM_COMMANDS.keys()) + (list(currmod.PM_COMMANDS.keys()) if currmod else list())):
|
|
||||||
if msg.lower().startswith(botconfig.CMD_CHAR+x):
|
|
||||||
h = msg[len(x)+len(botconfig.CMD_CHAR):]
|
|
||||||
elif not x or msg.lower().startswith(x):
|
|
||||||
h = msg[len(x):]
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
if not h or h[0] == " " or not x:
|
|
||||||
for fn in PM_COMMANDS.get(x, [])+(currmod.PM_COMMANDS.get(x,[]) if currmod else []):
|
|
||||||
try:
|
|
||||||
fn(cli, rawnick, h.lstrip())
|
|
||||||
except Exception as e:
|
|
||||||
if botconfig.DEBUG_MODE:
|
|
||||||
raise e
|
|
||||||
else:
|
|
||||||
logging.error(traceback.format_exc())
|
|
||||||
cli.msg(chan, "An error has occurred and has been logged.")
|
|
||||||
|
|
||||||
def __unhandled__(cli, prefix, cmd, *args):
|
def __unhandled__(cli, prefix, cmd, *args):
|
||||||
currmod = ld.MODULES[ld.CURRENT_MODULE]
|
currmod = ld.MODULES[ld.CURRENT_MODULE]
|
||||||
@ -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):
|
||||||
|
1097
modules/wolfgame.py
1097
modules/wolfgame.py
File diff suppressed because it is too large
Load Diff
@ -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 = {}
|
||||||
@ -240,6 +245,32 @@ PING_IN_ACCS = [] # accounts of people who have opted in for ping
|
|||||||
|
|
||||||
is_role = lambda plyr, rol: rol in ROLES and plyr in ROLES[rol]
|
is_role = lambda plyr, rol: rol in ROLES and plyr in ROLES[rol]
|
||||||
|
|
||||||
|
def pm(cli, target, message): # message either privmsg or notice, depending on user settings
|
||||||
|
if is_fake_nick(target) and botconfig.DEBUG_MODE:
|
||||||
|
print("[{0}] Would send message to fake nick {1}: {2}".format(
|
||||||
|
time.strftime("%d/%b/%Y %H:%M:%S"),
|
||||||
|
target,
|
||||||
|
message), file=sys.stderr)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
if is_user_notice(target):
|
||||||
|
cli.notice(target, message)
|
||||||
|
return
|
||||||
|
|
||||||
|
cli.msg(target, message)
|
||||||
|
|
||||||
|
def is_user_notice(nick):
|
||||||
|
if nick in USERS and USERS[nick]["account"] and USERS[nick]["account"] != "*":
|
||||||
|
if USERS[nick]["account"] in PREFER_NOTICE_ACCS:
|
||||||
|
return True
|
||||||
|
if nick in USERS and USERS[nick]["cloak"] in PREFER_NOTICE and not ACCOUNTS_ONLY:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_fake_nick(who):
|
||||||
|
return re.match("[0-9]+", who)
|
||||||
|
|
||||||
def is_admin(nick):
|
def is_admin(nick):
|
||||||
if nick not in USERS.keys():
|
if nick not in USERS.keys():
|
||||||
return False
|
return False
|
||||||
|
@ -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,33 @@ 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:
|
||||||
|
if len(roles) == 1:
|
||||||
|
var.pm(largs[0], nick, "Only a{0} {1} may use this command.".format("n" if roles[0][0] in "aeiou" else "", roles[0]))
|
||||||
|
else:
|
||||||
|
var.pm(largs[0], nick, "Only a{0} {1} or {2} may use this command.".format("n" if roles[0][0] in "aeiou" else "", ", ".join(roles[:-1]), roles[-1]))
|
||||||
|
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 +135,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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user