From 55070fd44b0f535edc62070d8ef59ca3419ce78e Mon Sep 17 00:00:00 2001 From: jacob1 Date: Fri, 30 Oct 2015 17:03:46 -0400 Subject: [PATCH] add utilities.py, which contains some functions possibly needed by gamemode events this also fixes it so priest death events finally happen --- src/__init__.py | 1 + src/decorators.py | 1 + src/gamemodes.py | 55 +++--------------- src/utilities.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++ src/wolfgame.py | 106 +-------------------------------- 5 files changed, 157 insertions(+), 151 deletions(-) create mode 100644 src/utilities.py diff --git a/src/__init__.py b/src/__init__.py index 81f1ccb..6e68ea1 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -110,6 +110,7 @@ def logger(file, write=True, display=True): return log stream_handler = logger(None) +debuglog = logger("debug.log", write=False, display=False) def stream(output, level="normal"): if botconfig.VERBOSE_MODE or botconfig.DEBUG_MODE: diff --git a/src/decorators.py b/src/decorators.py index e5795aa..bb3e35d 100644 --- a/src/decorators.py +++ b/src/decorators.py @@ -5,6 +5,7 @@ from oyoyo.parse import parse_nick import botconfig import src.settings as var +from src.utilities import * from src import logger adminlog = logger("audit.log") diff --git a/src/gamemodes.py b/src/gamemodes.py index 4fc899c..f48ef47 100644 --- a/src/gamemodes.py +++ b/src/gamemodes.py @@ -5,6 +5,7 @@ import math import threading import src.settings as var +from src.utilities import * import botconfig from src import events @@ -827,64 +828,24 @@ class SleepyMode(GameMode): "in sinister tones, managing to perform \u0002{0}\u0002 {1} before the building is struck repeatedly by lightning, " + "setting it alight in a raging inferno...").format(total, var.plural("toll", total))) for seer in seers: - var.ROLE["seer"].remove(seer) - var.ROLE["doomsayer"].add(seer) + var.ROLES["seer"].remove(seer) + var.ROLES["doomsayer"].add(seer) pm(cli, seer, ("You feel something rushing into you and taking control over your mind and body. It causes you to rapidly " + "start transforming into a werewolf, and you realize your vision powers can now be used to inflict malady " + "on the unwary. You are now a \u0002doomsayer\u0002.")) - self.relay_wolfchat_command(var, cli, seer, "\u0002{0}\u0002 is now a \u0002doomsayer\u0002.", var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True) + relay_wolfchat_command(cli, seer, "\u0002{0}\u0002 is now a \u0002doomsayer\u0002.", var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True) for harlot in harlots: - var.ROLE["harlot"].remove(harlot) - var.ROLE["succubus"].add(harlot) + var.ROLES["harlot"].remove(harlot) + var.ROLES["succubus"].add(harlot) pm(cli, harlot, ("You feel something rushing into you and taking control over your mind and body. You are now a " + "\u0002succubus\u0002. Your job is to entrance the village, bringing them all under your absolute " + "control.")) for cultist in cultists: - var.ROLE["cultist"].remove(cultist) - var.ROLE["demoniac"].add(cultist) + var.ROLES["cultist"].remove(cultist) + var.ROLES["demoniac"].add(cultist) pm(cli, cultist, ("You feel something rushing into you and taking control over your mind and body, showing you your new purpose in life. " + "There are far greater evils than the wolves lurking in the shadows, and by sacrificing all of the wolves, you can " + "unleash those evils upon the world. You are now a \u0002demoniac\u0002.")) # NOTE: chk_win is called by del_player, don't need to call it here even though this has a chance of ending game - # TODO: this are duplicated from wolfgame.py, should split both off into a utilities.py or something and call it from there - def in_wolflist(self, var, nick, who): - myrole = var.get_role(nick) - role = var.get_role(who) - wolves = var.WOLFCHAT_ROLES - if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: - if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: - wolves = var.WOLF_ROLES - else: - wolves = var.WOLF_ROLES | {"traitor"} - return myrole in wolves and role in wolves - - def relay_wolfchat_command(self, var, cli, nick, message, roles, is_wolf_command=False, is_kill_command=False): - if not is_wolf_command and var.RESTRICT_WOLFCHAT & var.RW_NO_INTERACTION: - return - if not is_kill_command and var.RESTRICT_WOLFCHAT & var.RW_ONLY_KILL_CMD: - if var.PHASE == "night" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_NIGHT: - return - if var.PHASE == "day" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: - return - if not self.in_wolflist(var, nick, nick): - return - - wcroles = var.WOLFCHAT_ROLES - if var.RESTRICT_WOLFCHAT & var.RW_ONLY_SAME_CMD: - if var.PHASE == "night" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_NIGHT: - wcroles = roles - if var.PHASE == "day" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: - wcroles = roles - elif var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: - if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: - wcroles = var.WOLF_ROLES - else: - wcroles = var.WOLF_ROLES | {"traitor"} - - wcwolves = var.list_players(wcroles) - wcwolves.remove(nick) - if wcwolves: - mass_privmsg(cli, wcwolves, message) - # vim: set expandtab:sw=4:ts=4: diff --git a/src/utilities.py b/src/utilities.py new file mode 100644 index 0000000..1fcbcb2 --- /dev/null +++ b/src/utilities.py @@ -0,0 +1,145 @@ +import src.settings as var +import botconfig +import re + +from src.__init__ import debuglog + +# Some miscellaneous helper functions + +def mass_mode(cli, md_param, md_plain): + """ Example: mass_mode(cli, [('+v', 'asdf'), ('-v','wobosd')], ['-m']) """ + lmd = len(md_param) # store how many mode changes to do + if md_param: + for start_i in range(0, lmd, var.MODELIMIT): # 4 mode-changes at a time + if start_i + var.MODELIMIT > lmd: # If this is a remainder (mode-changes < 4) + z = list(zip(*md_param[start_i:])) # zip this remainder + ei = lmd % var.MODELIMIT # len(z) + else: + z = list(zip(*md_param[start_i:start_i+var.MODELIMIT])) # zip four + ei = var.MODELIMIT # len(z) + # Now z equal something like [('+v', '-v'), ('asdf', 'wobosd')] + arg1 = "".join(md_plain) + "".join(z[0]) + arg2 = " ".join(z[1]) # + " " + " ".join([x+"!*@*" for x in z[1]]) + cli.mode(botconfig.CHANNEL, arg1, arg2) + else: + cli.mode(botconfig.CHANNEL, "".join(md_plain)) + +def mass_privmsg(cli, targets, msg, notice=False, privmsg=False): + if not notice and not privmsg: + msg_targs = [] + not_targs = [] + for target in targets: + if is_user_notice(target): + not_targs.append(target) + else: + msg_targs.append(target) + while msg_targs: + if len(msg_targs) <= var.MAX_PRIVMSG_TARGETS: + bgs = ",".join(msg_targs) + msg_targs = None + else: + bgs = ",".join(msg_targs[:var.MAX_PRIVMSG_TARGETS]) + msg_targs = msg_targs[var.MAX_PRIVMSG_TARGETS:] + cli.msg(bgs, msg) + while not_targs: + if len(not_targs) <= var.MAX_PRIVMSG_TARGETS: + bgs = ",".join(not_targs) + not_targs = None + else: + bgs = ",".join(not_targs[:var.MAX_PRIVMSG_TARGETS]) + not_targs = not_targs[var.MAX_PRIVMSG_TARGETS:] + cli.notice(bgs, msg) + else: + while targets: + if len(targets) <= var.MAX_PRIVMSG_TARGETS: + bgs = ",".join(targets) + targets = None + else: + bgs = ",".join(targets[:var.MAX_PRIVMSG_TARGETS]) + target = targets[var.MAX_PRIVMSG_TARGETS:] + if notice: + cli.notice(bgs, msg) + else: + cli.msg(bgs, msg) + +def pm(cli, target, message): # message either privmsg or notice, depending on user settings + if is_fake_nick(target) and botconfig.DEBUG_MODE: + debuglog("Would message fake nick {0}: {1!r}".format(target, message)) + return + + if is_user_notice(target): + cli.notice(target, message) + return + + cli.msg(target, message) + +def is_user_simple(nick): + if nick in var.USERS: + ident = var.USERS[nick]["ident"] + host = var.USERS[nick]["host"] + acc = var.USERS[nick]["account"] + else: + return False + if acc and acc != "*" and not var.DISABLE_ACCOUNTS: + if acc in var.SIMPLE_NOTIFY_ACCS: + return True + return False + elif not var.ACCOUNTS_ONLY: + for hostmask in var.SIMPLE_NOTIFY: + if var.match_hostmask(hostmask, nick, ident, host): + return True + return False + +def is_user_notice(nick): + if nick in var.USERS and var.USERS[nick]["account"] and var.USERS[nick]["account"] != "*" and not var.DISABLE_ACCOUNTS: + if var.USERS[nick]["account"] in var.PREFER_NOTICE_ACCS: + return True + if nick in var.USERS and not var.ACCOUNTS_ONLY: + ident = var.USERS[nick]["ident"] + host = var.USERS[nick]["host"] + for hostmask in var.PREFER_NOTICE: + if var.match_hostmask(hostmask, nick, ident, host): + return True + return False + +def is_fake_nick(who): + return re.search(r"^[0-9]+$", who) + +def in_wolflist(nick, who): + myrole = var.get_role(nick) + role = var.get_role(who) + wolves = var.WOLFCHAT_ROLES + if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: + if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: + wolves = var.WOLF_ROLES + else: + wolves = var.WOLF_ROLES | {"traitor"} + return myrole in wolves and role in wolves + +def relay_wolfchat_command(cli, nick, message, roles, is_wolf_command=False, is_kill_command=False): + if not is_wolf_command and var.RESTRICT_WOLFCHAT & var.RW_NO_INTERACTION: + return + if not is_kill_command and var.RESTRICT_WOLFCHAT & var.RW_ONLY_KILL_CMD: + if var.PHASE == "night" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_NIGHT: + return + if var.PHASE == "day" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: + return + if not in_wolflist(nick, nick): + return + + wcroles = var.WOLFCHAT_ROLES + if var.RESTRICT_WOLFCHAT & var.RW_ONLY_SAME_CMD: + if var.PHASE == "night" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_NIGHT: + wcroles = roles + if var.PHASE == "day" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: + wcroles = roles + elif var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: + if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: + wcroles = var.WOLF_ROLES + else: + wcroles = var.WOLF_ROLES | {"traitor"} + + wcwolves = var.list_players(wcroles) + wcwolves.remove(nick) + if wcwolves: + mass_privmsg(cli, wcwolves, message) diff --git a/src/wolfgame.py b/src/wolfgame.py index d5284d9..a7de52d 100644 --- a/src/wolfgame.py +++ b/src/wolfgame.py @@ -43,12 +43,12 @@ from oyoyo.parse import parse_nick import botconfig import src.settings as var -from src import decorators, events, logger +from src.utilities import * +from src import decorators, events, logger, debuglog # done this way so that events is accessible in !eval (useful for debugging) Event = events.Event -debuglog = logger("debug.log", write=False, display=False) # will be True if in debug mode errlog = logger("errors.log") plog = logger(None) #use this instead of print so that logs have timestamps @@ -362,37 +362,6 @@ def get_roles(*roles): all_roles.append(var.ROLES[role]) return list(itertools.chain(*all_roles)) -def mass_mode(cli, md_param, md_plain): - """ Example: mass_mode(cli, [('+v', 'asdf'), ('-v','wobosd')], ['-m']) """ - lmd = len(md_param) # store how many mode changes to do - if md_param: - for start_i in range(0, lmd, var.MODELIMIT): # 4 mode-changes at a time - if start_i + var.MODELIMIT > lmd: # If this is a remainder (mode-changes < 4) - z = list(zip(*md_param[start_i:])) # zip this remainder - ei = lmd % var.MODELIMIT # len(z) - else: - z = list(zip(*md_param[start_i:start_i+var.MODELIMIT])) # zip four - ei = var.MODELIMIT # len(z) - # Now z equal something like [('+v', '-v'), ('asdf', 'wobosd')] - arg1 = "".join(md_plain) + "".join(z[0]) - arg2 = " ".join(z[1]) # + " " + " ".join([x+"!*@*" for x in z[1]]) - cli.mode(botconfig.CHANNEL, arg1, arg2) - else: - cli.mode(botconfig.CHANNEL, "".join(md_plain)) - -def pm(cli, target, message): # message either privmsg or notice, depending on user settings - if is_fake_nick(target) and botconfig.DEBUG_MODE: - debuglog("Would message fake nick {0}: {1!r}".format(target, message)) - return - - if is_user_notice(target): - cli.notice(target, message) - return - - cli.msg(target, message) - -decorators.pm = pm - def reset_settings(): var.CURRENT_GAMEMODE.teardown() var.CURRENT_GAMEMODE = var.GAME_MODES["default"][0]() @@ -697,23 +666,6 @@ def mark_simple_notify(cli, nick, chan, rest): cli.notice(nick, "You now receive simple role instructions.") -def is_user_simple(nick): - if nick in var.USERS: - ident = var.USERS[nick]["ident"] - host = var.USERS[nick]["host"] - acc = var.USERS[nick]["account"] - else: - return False - if acc and acc != "*" and not var.DISABLE_ACCOUNTS: - if acc in var.SIMPLE_NOTIFY_ACCS: - return True - return False - elif not var.ACCOUNTS_ONLY: - for hostmask in var.SIMPLE_NOTIFY: - if var.match_hostmask(hostmask, nick, ident, host): - return True - return False - @cmd("notice", raw_nick=True, pm=True) def mark_prefer_notice(cli, nick, chan, rest): """Makes the bot NOTICE you for every interaction.""" @@ -769,18 +721,6 @@ def mark_prefer_notice(cli, nick, chan, rest): cli.notice(nick, "The bot will now always NOTICE you.") -def is_user_notice(nick): - if nick in var.USERS and var.USERS[nick]["account"] and var.USERS[nick]["account"] != "*" and not var.DISABLE_ACCOUNTS: - if var.USERS[nick]["account"] in var.PREFER_NOTICE_ACCS: - return True - if nick in var.USERS and not var.ACCOUNTS_ONLY: - ident = var.USERS[nick]["ident"] - host = var.USERS[nick]["host"] - for hostmask in var.PREFER_NOTICE: - if var.match_hostmask(hostmask, nick, ident, host): - return True - return False - @cmd("swap", "replace", pm=True, phases=("join", "day", "night")) def replace(cli, nick, chan, rest): """Swap out a player logged in to your account.""" @@ -5346,48 +5286,6 @@ def check_exchange(cli, actor, nick): return True return False -def is_fake_nick(who): - return re.search(r"^[0-9]+$", who) - -def in_wolflist(nick, who): - myrole = var.get_role(nick) - role = var.get_role(who) - wolves = var.WOLFCHAT_ROLES - if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: - if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: - wolves = var.WOLF_ROLES - else: - wolves = var.WOLF_ROLES | {"traitor"} - return myrole in wolves and role in wolves - -def relay_wolfchat_command(cli, nick, message, roles, is_wolf_command=False, is_kill_command=False): - if not is_wolf_command and var.RESTRICT_WOLFCHAT & var.RW_NO_INTERACTION: - return - if not is_kill_command and var.RESTRICT_WOLFCHAT & var.RW_ONLY_KILL_CMD: - if var.PHASE == "night" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_NIGHT: - return - if var.PHASE == "day" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: - return - if not in_wolflist(nick, nick): - return - - wcroles = var.WOLFCHAT_ROLES - if var.RESTRICT_WOLFCHAT & var.RW_ONLY_SAME_CMD: - if var.PHASE == "night" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_NIGHT: - wcroles = roles - if var.PHASE == "day" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: - wcroles = roles - elif var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: - if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: - wcroles = var.WOLF_ROLES - else: - wcroles = var.WOLF_ROLES | {"traitor"} - - wcwolves = var.list_players(wcroles) - wcwolves.remove(nick) - if wcwolves: - mass_privmsg(cli, wcwolves, message) - @cmd("retract", "r", pm=True, phases=("day", "night")) def retract(cli, nick, chan, rest): """Takes back your vote during the day (for whom to lynch)."""