def fstasis(var, wrapper, message): """Removes or views stasis penalties.""" data = re.split(" +", message) from src.context import lower as irc_lower if data[0]: m = users.complete_match(data[0]) if m: acc = m.get().account else: acc = data[0] cur = var.STASISED_ACCS[irc_lower(acc)] if len(data) == 1: if var.STASISED_ACCS[irc_lower(acc)] == cur and cur > 0: wrapper.reply(messages["account_in_stasis"].format( data[0], acc, cur)) else: wrapper.reply(messages["account_not_in_stasis"].format( data[0], acc)) else: try: amt = int(data[1]) except ValueError: wrapper.reply(messages["stasis_non_negative"]) return if amt < 0: wrapper.reply(messages["stasis_non_negative"]) return elif amt > cur and var.RESTRICT_FSTASIS: wrapper.reply(messages["stasis_cannot_increase"]) return elif cur == 0: wrapper.reply(messages["account_not_in_stasis"].format( data[0], acc)) return db.set_stasis(amt, acc) db.init_vars() if amt > 0: wrapper.reply(messages["fstasis_account_add"].format( data[0], acc, amt)) else: wrapper.reply(messages["fstasis_account_remove"].format( data[0], acc)) else: stasised = {} for acc in var.STASISED_ACCS: if var.STASISED_ACCS[acc] > 0: stasised[acc] = var.STASISED_ACCS[acc] if stasised: msg = messages["currently_stasised"].format(", ".join( "\u0002{0}\u0002 ({1})".format(usr, number) for usr, number in stasised.items())) wrapper.reply(msg) else: wrapper.reply(messages["noone_stasised"])
def decrement_stasis(user=None): if user is not None: # decrement account stasis even if accounts are disabled if user.account in var.STASISED_ACCS: db.decrement_stasis(acc=user.account) else: db.decrement_stasis() # Also expire any expired stasis and tempbans and update our tracking vars db.expire_stasis() db.init_vars()
def add_warning(target: Union[str, users.User], amount: int, actor: users.User, reason: str, notes: str = None, expires=None, sanctions=None): if isinstance(target, users.User): tacc = target.account if tacc is None: return False else: tacc = target reason = reason.format() sacc = actor.account # Turn expires into a datetime if we were passed a string; note that no error checking is performed here if not isinstance(expires, datetime): expires = _parse_expires(expires) # determine if we need to automatically add any sanctions if sanctions is None: sanctions = {} prev = db.get_warning_points(tacc) cur = prev + amount if amount > 0: _get_auto_sanctions(sanctions, prev, cur) sid = db.add_warning(tacc, sacc, amount, reason, notes, expires) if "stasis" in sanctions: db.add_warning_sanction(sid, "stasis", sanctions["stasis"]) if "deny" in sanctions: for cmd in sanctions["deny"]: db.add_warning_sanction(sid, "deny command", cmd) if "tempban" in sanctions: # this inserts into the bantrack table too (acclist, hmlist) = db.add_warning_sanction(sid, "tempban", sanctions["tempban"]) cmodes = [] for acc in acclist: cmodes.append(("+b", "{0}{1}".format(var.ACCOUNT_PREFIX, acc))) channels.Main.mode(*cmodes) for user in channels.Main.users: if user.account in acclist: channels.Main.kick( user, messages["tempban_kick"].format(nick=user, botnick=users.Bot.nick, reason=reason)) # Update any tracking vars that may have changed due to this db.init_vars() return sid
def decrement_stasis(user=None): if user is not None: # decrement account stasis even if accounts are disabled if user.account in var.STASISED_ACCS: db.decrement_stasis(acc=user.account) for hostmask in var.STASISED: if user.match_hostmask(hostmask): db.decrement_stasis(hostmask=hostmask) else: db.decrement_stasis() # Also expire any expired stasis and tempbans and update our tracking vars db.expire_stasis() db.init_vars()
def decrement_stasis(nick=None): if nick and nick in var.USERS: ident = irc_lower(var.USERS[nick]["ident"]) host = var.USERS[nick]["host"].lower() acc = irc_lower(var.USERS[nick]["account"]) # decrement account stasis even if accounts are disabled if acc in var.STASISED_ACCS: db.decrement_stasis(acc=acc) for hostmask in var.STASISED: if match_hostmask(hostmask, nick, ident, host): db.decrement_stasis(hostmask=hostmask) else: db.decrement_stasis() # Also expire any expired stasis and tempbans and update our tracking vars db.expire_stasis() db.init_vars()
def fwarn_del(var, wrapper, args): if args.help: wrapper.reply(messages["fwarn_del_syntax"]) return warning = db.get_warning(args.id) if not warning: wrapper.reply(messages["fwarn_invalid_warning"]) return warning["deleted_by"] = wrapper.source db.del_warning(args.id, wrapper.source.account) db.init_vars() wrapper.reply(messages["fwarn_done"]) if var.LOG_CHANNEL: msg = messages["fwarn_log_del"].format(**warning) channels.get(var.LOG_CHANNEL).send(msg, prefix=var.LOG_PREFIX)
def warn_ack(var, wrapper, args): if args.help: wrapper.reply(messages["warn_ack_syntax"]) return acc = wrapper.source.account if not acc: return warning = db.get_warning(args.id, acc) if not warning: wrapper.reply(messages["fwarn_invalid_warning"]) return # only add stasis if this is the first time this warning is being acknowledged if not warning["ack"] and warning["sanctions"].get("stasis", 0) > 0: db.set_stasis(warning["sanctions"]["stasis"], acc, relative=True) db.init_vars() db.acknowledge_warning(args.id) wrapper.reply(messages["fwarn_done"])
def warn(var, wrapper, message): """View and acknowledge your warnings.""" # !warn list [-all] [page] - lists all active warnings, or all warnings if all passed # !warn view <id> - views details on warning id # !warn ack <id> - acknowledges warning id # Default if only !warn is given is to do !warn list. params = re.split(" +", message) try: command = params.pop(0) if command == "": command = "list" except IndexError: command = "list" if command not in ("list", "view", "ack", "help"): wrapper.reply(messages["warn_usage"]) return if command == "help": try: subcommand = params.pop(0) except IndexError: wrapper.reply(messages["warn_help_syntax"]) return if subcommand not in ("list", "view", "ack", "help"): wrapper.reply(messages["warn_usage"]) return wrapper.reply(messages["warn_{0}_syntax".format(subcommand)]) return if command == "list": list_all = False page = 1 try: list_all = params.pop(0) target = params.pop(0) page = int(params.pop(0)) except IndexError: pass except ValueError: wrapper.reply(messages["fwarn_page_invalid"]) return try: if list_all and list_all != "-all": page = int(list_all) list_all = False elif list_all == "-all": list_all = True except ValueError: wrapper.reply(messages["fwarn_page_invalid"]) return acc, hm = parse_warning_target(wrapper.source.nick) warnings = db.list_warnings(acc, hm, expired=list_all, skip=(page - 1) * 10, show=11) points = db.get_warning_points(acc, hm) wrapper.pm(messages["warn_list_header"].format( points, "" if points == 1 else "s")) i = 0 for warn in warnings: i += 1 if (i == 11): parts = [] if list_all: parts.append("-all") parts.append(str(page + 1)) wrapper.pm(messages["warn_list_footer"].format( " ".join(parts))) break start = "" end = "" ack = "" if warn["expires"] is not None: if warn["expired"]: expires = messages["fwarn_list_expired"].format( warn["expires"]) else: expires = messages["fwarn_view_expires"].format( warn["expires"]) else: expires = messages["fwarn_never_expires"] if warn["expired"]: start = "\u000314" end = " [\u00037{0}\u000314]\u0003".format( messages["fwarn_expired"]) if not warn["ack"]: ack = "\u0002!\u0002 " wrapper.pm(messages["warn_list"].format( start, ack, warn["id"], warn["issued"], warn["reason"], warn["amount"], "" if warn["amount"] == 1 else "s", expires, end)) if i == 0: wrapper.pm(messages["fwarn_list_empty"]) return if command == "view": try: warn_id = params.pop(0) if warn_id[0] == "#": warn_id = warn_id[1:] warn_id = int(warn_id) except (IndexError, ValueError): wrapper.reply(messages["warn_view_syntax"]) return acc, hm = parse_warning_target(wrapper.source.nick) warning = db.get_warning(warn_id, acc, hm) if warning is None: wrapper.reply(messages["fwarn_invalid_warning"]) return if warning["expired"]: expires = messages["fwarn_view_expired"].format(warning["expires"]) elif warning["expires"] is None: expires = messages["fwarn_view_active"].format( messages["fwarn_never_expires"]) else: expires = messages["fwarn_view_active"].format( messages["fwarn_view_expires"].format(warning["expires"])) wrapper.pm(messages["warn_view_header"].format( warning["id"], warning["issued"], warning["amount"], "" if warning["amount"] == 1 else "s", expires)) wrapper.pm(warning["reason"]) sanctions = [] if not warning["ack"]: sanctions.append(messages["warn_view_ack"].format(warning["id"])) if warning["sanctions"]: sanctions.append(messages["fwarn_view_sanctions"]) if "stasis" in warning["sanctions"]: if warning["sanctions"]["stasis"] != 1: sanctions.append( messages["fwarn_view_stasis_plural"].format( warning["sanctions"]["stasis"])) else: sanctions.append(messages["fwarn_view_stasis_sing"]) if "deny" in warning["sanctions"]: sanctions.append(messages["fwarn_view_deny"].format(", ".join( warning["sanctions"]["deny"]))) if sanctions: wrapper.pm(" ".join(sanctions)) return if command == "ack": try: warn_id = params.pop(0) if warn_id[0] == "#": warn_id = warn_id[1:] warn_id = int(warn_id) except (IndexError, ValueError): wrapper.reply(messages["warn_ack_syntax"]) return acc, hm = parse_warning_target(wrapper.source.nick) warning = db.get_warning(warn_id, acc, hm) if warning is None: wrapper.reply(messages["fwarn_invalid_warning"]) return # only add stasis if this is the first time this warning is being acknowledged if not warning["ack"] and warning["sanctions"].get("stasis", 0) > 0: db.set_stasis(warning["sanctions"]["stasis"], acc, hm, relative=True) db.init_vars() db.acknowledge_warning(warn_id) wrapper.reply(messages["fwarn_done"]) return
def fstasis(var, wrapper, message): """Removes or views stasis penalties.""" data = message.split() msg = None if data: lusers = {k.lower(): v for k, v in var.USERS.items()} acc, hostmask = parse_warning_target(data[0], lower=True) cur = max(var.STASISED[hostmask], var.STASISED_ACCS[acc]) if len(data) == 1: if acc is not None and var.STASISED_ACCS[acc] == cur: plural = "" if cur == 1 else "s" wrapper.reply(messages["account_in_stasis"].format( data[0], acc, cur, plural)) elif hostmask is not None and var.STASISED[hostmask] == cur: plural = "" if cur == 1 else "s" wrapper.reply(messages["hostmask_in_stasis"].format( data[0], hostmask, cur, plural)) elif acc is not None: wrapper.reply(messages["account_not_in_stasis"].format( data[0], acc)) else: wrapper.reply(messages["hostmask_not_in_stasis"].format( data[0], hostmask)) else: try: amt = int(data[1]) except ValueError: wrapper.reply(messages["stasis_not_negative"]) return if amt < 0: wrapper.reply(messages["stasis_not_negative"]) return elif amt > cur and var.RESTRICT_FSTASIS: wrapper.reply(messages["stasis_cannot_increase"]) return elif cur == 0: if acc is not None: wrapper.reply(messages["account_not_in_stasis"].format( data[0], acc)) return else: wrapper.reply(messages["hostmask_not_in_stasis"].format( data[0], hostmask)) return db.set_stasis(amt, acc, hostmask) db.init_vars() if amt > 0: plural = "" if amt == 1 else "s" if acc is not None: wrapper.reply(messages["fstasis_account_add"].format( data[0], acc, amt, plural)) else: wrapper.reply(messages["fstasis_hostmask_add"].format( data[0], hostmask, amt, plural)) elif acc is not None: wrapper.reply(messages["fstasis_account_remove"].format( data[0], acc)) else: wrapper.reply(messages["fstasis_hostmask_remove"].format( data[0], hostmask)) elif var.STASISED or var.STASISED_ACCS: stasised = {} for hostmask in var.STASISED: stasised[hostmask + " (Host)"] = var.STASISED[hostmask] for acc in var.STASISED_ACCS: stasised[acc + " (Account)"] = var.STASISED_ACCS[acc] msg = messages["currently_stasised"].format(", ".join( "\u0002{0}\u0002 ({1})".format(usr, number) for usr, number in stasised.items())) wrapper.reply(msg) else: wrapper.reply(messages["noone_stasised"])
def add_warning(cli, target, amount, actor, reason, notes=None, expires=None, sanctions=None): tacc, thm = parse_warning_target(target) if tacc is None and thm is None: return False if actor not in var.USERS and actor != users.Bot.nick: return False sacc = None shm = None if actor in var.USERS: sacc = var.USERS[actor]["account"] shm = actor + "!" + var.USERS[actor]["ident"] + "@" + var.USERS[actor][ "host"] # Turn expires into a datetime if we were passed a string; note that no error checking is performed here if isinstance(expires, str): exp_suffix = expires[-1] exp_amount = int(expires[:-1]) if exp_suffix == "d": expires = datetime.utcnow() + timedelta(days=exp_amount) elif exp_suffix == "h": expires = datetime.utcnow() + timedelta(hours=exp_amount) elif exp_suffix == "m": expires = datetime.utcnow() + timedelta(minutes=exp_amount) else: raise ValueError("Invalid expiration string") elif isinstance(expires, int): expires = datetime.utcnow() + timedelta(days=expires) # Round expires to the nearest minute (30s rounds up) if isinstance(expires, datetime): round_add = 0 if expires.second >= 30: round_add = 1 expires -= timedelta(seconds=expires.second, microseconds=expires.microsecond) expires += timedelta(minutes=round_add) # determine if we need to automatically add any sanctions if sanctions is None: sanctions = {} prev = db.get_warning_points(tacc, thm) cur = prev + amount if amount > 0: _get_auto_sanctions(sanctions, prev, cur) sid = db.add_warning(tacc, thm, sacc, shm, amount, reason, notes, expires) if "stasis" in sanctions: db.add_warning_sanction(sid, "stasis", sanctions["stasis"]) if "deny" in sanctions: for cmd in sanctions["deny"]: db.add_warning_sanction(sid, "deny command", cmd) if "tempban" in sanctions: # this inserts into the bantrack table too (acclist, hmlist) = db.add_warning_sanction(sid, "tempban", sanctions["tempban"]) cmodes = [] for acc in acclist: cmodes.append(("+b", "{0}{1}".format(var.ACCOUNT_PREFIX, acc))) for hm in hmlist: cmodes.append(("+b", "*!*@{0}".format(hm.split("@")[1]))) channels.Main.mode(*cmodes) for user in channels.Main.users: if user.account in acclist: channels.Main.kick( user, messages["tempban_kick"].format(nick=user, botnick=users.Bot.nick, reason=reason)) elif user.host in hmlist: channels.Main.kick( user, messages["tempban_kick"].format(nick=user, botnick=users.Bot.nick, reason=reason)) # Update any tracking vars that may have changed due to this db.init_vars() return sid
def warn(var, wrapper, message): """View and acknowledge your warnings.""" # !warn list [-all] [page] - lists all active warnings, or all warnings if all passed # !warn view <id> - views details on warning id # !warn ack <id> - acknowledges warning id # Default if only !warn is given is to do !warn list. params = re.split(" +", message) try: command = params.pop(0) if command == "": command = "list" except IndexError: command = "list" if command not in ("list", "view", "ack", "help"): wrapper.reply(messages["warn_usage"]) return if command == "help": try: subcommand = params.pop(0) except IndexError: wrapper.reply(messages["warn_help_syntax"]) return if subcommand not in ("list", "view", "ack", "help"): wrapper.reply(messages["warn_usage"]) return wrapper.reply(messages["warn_{0}_syntax".format(subcommand)]) return if command == "list": list_all = False page = 1 try: list_all = params.pop(0) target = params.pop(0) page = int(params.pop(0)) except IndexError: pass except ValueError: wrapper.reply(messages["fwarn_page_invalid"]) return try: if list_all and list_all != "-all": page = int(list_all) list_all = False elif list_all == "-all": list_all = True except ValueError: wrapper.reply(messages["fwarn_page_invalid"]) return acc, hm = parse_warning_target(wrapper.source.nick) warnings = db.list_warnings(acc, hm, expired=list_all, skip=(page-1)*10, show=11) points = db.get_warning_points(acc, hm) wrapper.pm(messages["warn_list_header"].format(points, "" if points == 1 else "s")) i = 0 for warn in warnings: i += 1 if (i == 11): parts = [] if list_all: parts.append("-all") parts.append(str(page + 1)) wrapper.pm(messages["warn_list_footer"].format(" ".join(parts))) break start = "" end = "" ack = "" if warn["expires"] is not None: if warn["expired"]: expires = messages["fwarn_list_expired"].format(warn["expires"]) else: expires = messages["fwarn_view_expires"].format(warn["expires"]) else: expires = messages["fwarn_never_expires"] if warn["expired"]: start = "\u000314" end = " [\u00037{0}\u000314]\u0003".format(messages["fwarn_expired"]) if not warn["ack"]: ack = "\u0002!\u0002 " wrapper.pm(messages["warn_list"].format( start, ack, warn["id"], warn["issued"], warn["reason"], warn["amount"], "" if warn["amount"] == 1 else "s", expires, end)) if i == 0: wrapper.pm(messages["fwarn_list_empty"]) return if command == "view": try: warn_id = params.pop(0) if warn_id[0] == "#": warn_id = warn_id[1:] warn_id = int(warn_id) except (IndexError, ValueError): wrapper.reply(messages["warn_view_syntax"]) return acc, hm = parse_warning_target(wrapper.source.nick) warning = db.get_warning(warn_id, acc, hm) if warning is None: wrapper.reply(messages["fwarn_invalid_warning"]) return if warning["expired"]: expires = messages["fwarn_view_expired"].format(warning["expires"]) elif warning["expires"] is None: expires = messages["fwarn_view_active"].format(messages["fwarn_never_expires"]) else: expires = messages["fwarn_view_active"].format(messages["fwarn_view_expires"].format(warning["expires"])) wrapper.pm(messages["warn_view_header"].format( warning["id"], warning["issued"], warning["amount"], "" if warning["amount"] == 1 else "s", expires)) wrapper.pm(warning["reason"]) sanctions = [] if not warning["ack"]: sanctions.append(messages["warn_view_ack"].format(warning["id"])) if warning["sanctions"]: sanctions.append(messages["fwarn_view_sanctions"]) if "stasis" in warning["sanctions"]: if warning["sanctions"]["stasis"] != 1: sanctions.append(messages["fwarn_view_stasis_plural"].format(warning["sanctions"]["stasis"])) else: sanctions.append(messages["fwarn_view_stasis_sing"]) if "deny" in warning["sanctions"]: sanctions.append(messages["fwarn_view_deny"].format(", ".join(warning["sanctions"]["deny"]))) if sanctions: wrapper.pm(" ".join(sanctions)) return if command == "ack": try: warn_id = params.pop(0) if warn_id[0] == "#": warn_id = warn_id[1:] warn_id = int(warn_id) except (IndexError, ValueError): wrapper.reply(messages["warn_ack_syntax"]) return acc, hm = parse_warning_target(wrapper.source.nick) warning = db.get_warning(warn_id, acc, hm) if warning is None: wrapper.reply(messages["fwarn_invalid_warning"]) return # only add stasis if this is the first time this warning is being acknowledged if not warning["ack"] and warning["sanctions"].get("stasis", 0) > 0: db.set_stasis(warning["sanctions"]["stasis"], acc, hm, relative=True) db.init_vars() db.acknowledge_warning(warn_id) wrapper.reply(messages["fwarn_done"]) return
def fstasis(var, wrapper, message): """Removes or views stasis penalties.""" data = message.split() msg = None if data: lusers = {k.lower(): v for k, v in var.USERS.items()} acc, hostmask = parse_warning_target(data[0], lower=True) cur = max(var.STASISED[hostmask], var.STASISED_ACCS[acc]) if len(data) == 1: if acc is not None and var.STASISED_ACCS[acc] == cur: plural = "" if cur == 1 else "s" wrapper.reply(messages["account_in_stasis"].format(data[0], acc, cur, plural)) elif hostmask is not None and var.STASISED[hostmask] == cur: plural = "" if cur == 1 else "s" wrapper.reply(messages["hostmask_in_stasis"].format(data[0], hostmask, cur, plural)) elif acc is not None: wrapper.reply(messages["account_not_in_stasis"].format(data[0], acc)) else: wrapper.reply(messages["hostmask_not_in_stasis"].format(data[0], hostmask)) else: try: amt = int(data[1]) except ValueError: wrapper.reply(messages["stasis_not_negative"]) return if amt < 0: wrapper.reply(messages["stasis_not_negative"]) return elif amt > cur and var.RESTRICT_FSTASIS: wrapper.reply(messages["stasis_cannot_increase"]) return elif cur == 0: if acc is not None: wrapper.reply(messages["account_not_in_stasis"].format(data[0], acc)) return else: wrapper.reply(messages["hostmask_not_in_stasis"].format(data[0], hostmask)) return db.set_stasis(amt, acc, hostmask) db.init_vars() if amt > 0: plural = "" if amt == 1 else "s" if acc is not None: wrapper.reply(messages["fstasis_account_add"].format(data[0], acc, amt, plural)) else: wrapper.reply(messages["fstasis_hostmask_add"].format(data[0], hostmask, amt, plural)) elif acc is not None: wrapper.reply(messages["fstasis_account_remove"].format(data[0], acc)) else: wrapper.reply(messages["fstasis_hostmask_remove"].format(data[0], hostmask)) elif var.STASISED or var.STASISED_ACCS: stasised = {} for hostmask in var.STASISED: stasised[hostmask+" (Host)"] = var.STASISED[hostmask] for acc in var.STASISED_ACCS: stasised[acc+" (Account)"] = var.STASISED_ACCS[acc] msg = messages["currently_stasised"].format(", ".join( "\u0002{0}\u0002 ({1})".format(usr, number) for usr, number in stasised.items())) wrapper.reply(msg) else: wrapper.reply(messages["noone_stasised"])
def add_warning(cli, target, amount, actor, reason, notes=None, expires=None, sanctions=None): tacc, thm = parse_warning_target(target) if tacc is None and thm is None: return False if actor not in var.USERS and actor != users.Bot.nick: return False sacc = None shm = None if actor in var.USERS: sacc = var.USERS[actor]["account"] shm = actor + "!" + var.USERS[actor]["ident"] + "@" + var.USERS[actor]["host"] # Turn expires into a datetime if we were passed a string; note that no error checking is performed here if isinstance(expires, str): exp_suffix = expires[-1] exp_amount = int(expires[:-1]) if exp_suffix == "d": expires = datetime.utcnow() + timedelta(days=exp_amount) elif exp_suffix == "h": expires = datetime.utcnow() + timedelta(hours=exp_amount) elif exp_suffix == "m": expires = datetime.utcnow() + timedelta(minutes=exp_amount) else: raise ValueError("Invalid expiration string") elif isinstance(expires, int): expires = datetime.utcnow() + timedelta(days=expires) # Round expires to the nearest minute (30s rounds up) if isinstance(expires, datetime): round_add = 0 if expires.second >= 30: round_add = 1 expires -= timedelta(seconds=expires.second, microseconds=expires.microsecond) expires += timedelta(minutes=round_add) # determine if we need to automatically add any sanctions if sanctions is None: sanctions = {} prev = db.get_warning_points(tacc, thm) cur = prev + amount if amount > 0: _get_auto_sanctions(sanctions, prev, cur) sid = db.add_warning(tacc, thm, sacc, shm, amount, reason, notes, expires) if "stasis" in sanctions: db.add_warning_sanction(sid, "stasis", sanctions["stasis"]) if "deny" in sanctions: for cmd in sanctions["deny"]: db.add_warning_sanction(sid, "deny command", cmd) if "tempban" in sanctions: # this inserts into the bantrack table too (acclist, hmlist) = db.add_warning_sanction(sid, "tempban", sanctions["tempban"]) cmodes = [] for acc in acclist: cmodes.append(("+b", "{0}{1}".format(var.ACCOUNT_PREFIX, acc))) for hm in hmlist: cmodes.append(("+b", "*!*@{0}".format(hm.split("@")[1]))) channels.Main.mode(*cmodes) for user in channels.Main.users: if user.account in acclist: channels.Main.kick(user, messages["tempban_kick"].format(nick=user, botnick=users.Bot.nick, reason=reason)) elif user.host in hmlist: channels.Main.kick(user, messages["tempban_kick"].format(nick=user, botnick=users.Bot.nick, reason=reason)) # Update any tracking vars that may have changed due to this db.init_vars() return sid
def add_warning(cli, target, amount, actor, reason, notes=None, expires=None, sanctions=None): # make 0-point warnings no-op successfully, otherwise we add warnings when things like PART_PENALTY is 0 if amount == 0: return False tacc, thm = parse_warning_target(target) if tacc is None and thm is None: return False if actor not in var.USERS and actor != botconfig.NICK: return False sacc = None shm = None if actor in var.USERS: sacc = var.USERS[actor]["account"] shm = actor + "!" + var.USERS[actor]["ident"] + "@" + var.USERS[actor]["host"] # Turn expires into a datetime if we were passed a string; note that no error checking is performed here if isinstance(expires, str): exp_suffix = expires[-1] exp_amount = int(expires[:-1]) if exp_suffix == "d": expires = datetime.utcnow() + timedelta(days=exp_amount) elif exp_suffix == "h": expires = datetime.utcnow() + timedelta(hours=exp_amount) elif exp_suffix == "m": expires = datetime.utcnow() + timedelta(minutes=exp_amount) else: raise ValueError("Invalid expiration string") elif isinstance(expires, int): expires = datetime.utcnow() + timedelta(days=expires) # Round expires to the nearest minute (30s rounds up) if isinstance(expires, datetime): round_add = 0 if expires.second >= 30: round_add = 1 expires -= timedelta(seconds=expires.second, microseconds=expires.microsecond) expires += timedelta(minutes=round_add) # determine if we need to automatically add any sanctions if sanctions is None: sanctions = {} prev = db.get_warning_points(tacc, thm) cur = prev + amount for (mn, mx, sanc) in var.AUTO_SANCTION: if (prev < mn and cur >= mn) or (prev >= mn and prev <= mx and cur <= mx): if "stasis" in sanc: if "stasis" not in sanctions: sanctions["stasis"] = sanc["stasis"] else: sanctions["stasis"] = max(sanctions["stasis"], sanc["stasis"]) if "scalestasis" in sanc: (a, b, c) = sanc["scalestasis"] amt = (a * cur * cur) + (b * cur) + c if "stasis" not in sanctions: sanctions["stasis"] = amt else: sanctions["stasis"] = max(sanctions["stasis"], amt) if "deny" in sanc: if "deny" not in sanctions: sanctions["deny"] = set(sanc["deny"]) else: sanctions["deny"].update(sanc["deny"]) if "tempban" in sanc: # tempban's param can either be a fixed expiry time or a number # which indicates the warning point threshold that the ban will be lifted at # if two are set at once, the threshold takes precedence over set times # within each category, a larger set time or a lower threshold takes precedence exp = None ths = None if isinstance(sanc["tempban"], str) and sanc["tempban"][-1] in ("d", "h", "m"): amt = int(sanc["tempban"][:-1]) dur = sanc["tempban"][-1] if dur == "d": exp = datetime.utcnow() + timedelta(days=amt) elif dur == "h": exp = datetime.utcnow() + timedelta(hours=amt) elif dur == "m": exp = datetime.utcnow() + timedelta(minutes=amt) else: ths = int(sanc["tempban"]) if "tempban" in sanctions: if isinstance(sanctions["tempban"], datetime): if ths is not None: sanctions["tempban"] = ths else: sanctions["tempban"] = max(sanctions["tempban"], exp) elif ths is not None: sanctions["tempban"] = min(sanctions["tempban"], ths) elif ths is not None: sanctions["tempban"] = ths else: sanctions["tempban"] = exp sid = db.add_warning(tacc, thm, sacc, shm, amount, reason, notes, expires) if "stasis" in sanctions: db.add_warning_sanction(sid, "stasis", sanctions["stasis"]) if "deny" in sanctions: for cmd in sanctions["deny"]: db.add_warning_sanction(sid, "deny command", cmd) if "tempban" in sanctions: # this inserts into the bantrack table too (acclist, hmlist) = db.add_warning_sanction(sid, "tempban", sanctions["tempban"]) cmodes = [] for acc in acclist: cmodes.append(("+b", "{0}{1}".format(var.ACCOUNT_PREFIX, acc))) for hm in hmlist: cmodes.append(("+b", "*!*@{0}".format(hm))) mass_mode(cli, cmodes, []) for (nick, user) in var.USERS.items(): if user["account"] in acclist: cli.kick(botconfig.CHANNEL, nick, messages["tempban_kick"].format(nick=nick, botnick=botconfig.NICK, reason=reason)) elif user["host"] in hmlist: cli.kick(botconfig.CHANNEL, nick, messages["tempban_kick"].format(nick=nick, botnick=botconfig.NICK, reason=reason)) # Update any tracking vars that may have changed due to this db.init_vars() return sid
def add_warning(cli, target, amount, actor, reason, notes=None, expires=None, sanctions=None): # make 0-point warnings no-op successfully, otherwise we add warnings when things like PART_PENALTY is 0 if amount == 0: return False tacc, thm = parse_warning_target(target) if tacc is None and thm is None: return False if actor not in var.USERS and actor != botconfig.NICK: return False sacc = None shm = None if actor in var.USERS: sacc = var.USERS[actor]["account"] shm = actor + "!" + var.USERS[actor]["ident"] + "@" + var.USERS[actor]["host"] # Turn expires into a datetime if we were passed a string; note that no error checking is performed here if isinstance(expires, str): exp_suffix = expires[-1] exp_amount = int(expires[:-1]) if exp_suffix == "d": expires = datetime.utcnow() + timedelta(days=exp_amount) elif exp_suffix == "h": expires = datetime.utcnow() + timedelta(hours=exp_amount) elif exp_suffix == "m": expires = datetime.utcnow() + timedelta(minutes=exp_amount) else: raise ValueError("Invalid expiration string") elif isinstance(expires, int): expires = datetime.utcnow() + timedelta(days=expires) # Round expires to the nearest minute (30s rounds up) if isinstance(expires, datetime): round_add = 0 if expires.second >= 30: round_add = 1 expires -= timedelta(seconds=expires.second, microseconds=expires.microsecond) expires += timedelta(minutes=round_add) # determine if we need to automatically add any sanctions if sanctions is None: sanctions = {} prev = db.get_warning_points(tacc, thm) cur = prev + amount for (mn, mx, sanc) in var.AUTO_SANCTION: if (prev < mn and cur >= mn) or (prev >= mn and prev <= mx and cur <= mx): if "stasis" in sanc: if "stasis" not in sanctions: sanctions["stasis"] = sanc["stasis"] else: sanctions["stasis"] = max(sanctions["stasis"], sanc["stasis"]) if "scalestasis" in sanc: (a, b, c) = sanc["scalestasis"] amt = (a * cur * cur) + (b * cur) + c if "stasis" not in sanctions: sanctions["stasis"] = amt else: sanctions["stasis"] = max(sanctions["stasis"], amt) if "deny" in sanc: if "deny" not in sanctions: sanctions["deny"] = set(sanc["deny"]) else: sanctions["deny"].update(sanc["deny"]) if "tempban" in sanc: # tempban's param can either be a fixed expiry time or a number # which indicates the warning point threshold that the ban will be lifted at # if two are set at once, the threshold takes precedence over set times # within each category, a larger set time or a lower threshold takes precedence exp = None ths = None if sanc["tempban"][-1] in ("d", "h", "m"): amt = int(sanc["tempban"][:-1]) dur = sanc["tempban"][-1] if dur == "d": exp = datetime.utcnow() + timedelta(days=amt) elif dur == "h": exp = datetime.utcnow() + timedelta(hours=amt) elif dur == "m": exp = datetime.utcnow() + timedelta(minutes=amt) else: ths = int(sanc["tempban"]) if "tempban" in sanctions: if isinstance(sanctions["tempban"], datetime): if ths is not None: sanctions["tempban"] = ths else: sanctions["tempban"] = max(sanctions["tempban"], exp) elif ths is not None: sanctions["tempban"] = min(sanctions["tempban"], ths) elif ths is not None: sanctions["tempban"] = ths else: sanctions["tempban"] = exp sid = db.add_warning(tacc, thm, sacc, shm, amount, reason, notes, expires) if "stasis" in sanctions: db.add_warning_sanction(sid, "stasis", sanctions["stasis"]) if "deny" in sanctions: for cmd in sanctions["deny"]: db.add_warning_sanction(sid, "deny command", cmd) if "tempban" in sanctions: # this inserts into the bantrack table too (acclist, hmlist) = db.add_warning_sanction(sid, "tempban", sanctions["tempban"]) cmodes = [] for acc in acclist: cmodes.append(("+b", "{0}{1}".format(var.ACCOUNT_PREFIX, acc))) for hm in hmlist: cmodes.append(("+b", "*!*@{0}".format(hm))) mass_mode(cli, cmodes, []) for (nick, user) in var.USERS.items(): if user["account"] in acclist: cli.kick(botconfig.CHANNEL, nick, messages["tempban_kick"].format(nick=nick, botnick=botconfig.NICK, reason=reason)) elif user["host"] in hmlist: cli.kick(botconfig.CHANNEL, nick, messages["tempban_kick"].format(nick=nick, botnick=botconfig.NICK, reason=reason)) # Update any tracking vars that may have changed due to this db.init_vars() return sid