Finish warning system
- fwarn/warn commands to view and manipulate warnings - fstasis can now only decrease stasis, not add to it - refreshdb command can sync bot game state with what is in the db (including expiring any unexpired stasis or warnings) - stasis now expires - tempban is still not implemented and will not be implemented as part of the PR (it will come later, if ever) - sanctions can be automatically applied after warnings cross a certain threshold; some defaults are configured
This commit is contained in:
parent
bba5ab745e
commit
a6ea55a8fe
@ -574,6 +574,7 @@
|
|||||||
"account_not_in_stasis": "\u0002{0}\u0002 (Account: {1}) is not in stasis.",
|
"account_not_in_stasis": "\u0002{0}\u0002 (Account: {1}) is not in stasis.",
|
||||||
"currently_stasised": "Currently stasised: {0}",
|
"currently_stasised": "Currently stasised: {0}",
|
||||||
"noone_stasised": "Nobody is currently stasised.",
|
"noone_stasised": "Nobody is currently stasised.",
|
||||||
|
"stasis_cannot_increase": "Cannot increase stasis using fstasis; use fwarn instead.",
|
||||||
"no_command_specified": "Error: No command specified. Did you mean \u0002-cmds\u0002?",
|
"no_command_specified": "Error: No command specified. Did you mean \u0002-cmds\u0002?",
|
||||||
"invalid_option": "Invalid option: {0}",
|
"invalid_option": "Invalid option: {0}",
|
||||||
"command_does_not_exist": "That command does not exist.",
|
"command_does_not_exist": "That command does not exist.",
|
||||||
@ -797,14 +798,20 @@
|
|||||||
"villagergame_nope": "Game over! The villagers decided incorrectly that there are actually no wolves, allowing the wolves to slaughter the remainder of them in their sleep with impunity.",
|
"villagergame_nope": "Game over! The villagers decided incorrectly that there are actually no wolves, allowing the wolves to slaughter the remainder of them in their sleep with impunity.",
|
||||||
"stop_bot_ingame_safeguard": "Warning: A game is currently running. If you want to {what} the bot anyway, use \"{prefix}{cmd} -force\".",
|
"stop_bot_ingame_safeguard": "Warning: A game is currently running. If you want to {what} the bot anyway, use \"{prefix}{cmd} -force\".",
|
||||||
"fwarn_usage": "Usage: fwarn list|view|add|del|set|help. See fwarn help <subcommand> for more details.",
|
"fwarn_usage": "Usage: fwarn list|view|add|del|set|help. See fwarn help <subcommand> for more details.",
|
||||||
|
"warn_usage": "Usage: warn list|view|ack|help. See warn help <subcommand> for more details.",
|
||||||
"fwarn_list_syntax": "Usage: fwarn list [-all] [nick[!user@host]|=account] [page]",
|
"fwarn_list_syntax": "Usage: fwarn list [-all] [nick[!user@host]|=account] [page]",
|
||||||
"fwarn_view_syntax": "Usage: fwarn view <id>",
|
"fwarn_view_syntax": "Usage: fwarn view <id>",
|
||||||
"fwarn_del_syntax": "Usage: fwarn del <id>",
|
"fwarn_del_syntax": "Usage: fwarn del <id>",
|
||||||
"fwarn_set_syntax": "Usage: fwarn set <id> <reason> [| notes]",
|
"fwarn_set_syntax": "Usage: fwarn set <id> <reason> [| notes]",
|
||||||
"fwarn_help_syntax": "Usage: fwarn help <subcommand>",
|
"fwarn_help_syntax": "Usage: fwarn help <subcommand>",
|
||||||
|
"warn_list_syntax": "Usage: warn list [-all] [page]",
|
||||||
|
"warn_view_syntax": "Usage: warn view <id>",
|
||||||
|
"warn_ack_syntax": "Usage: warn ack <id>",
|
||||||
|
"warn_help_syntax": "Uwage: warn help <subcommand>",
|
||||||
"fwarn_add_syntax": "Usage: fwarn add <nick[!user@host]|=account> [@]<points> [~expiry] [sanctions] <:reason> [| notes]",
|
"fwarn_add_syntax": "Usage: fwarn add <nick[!user@host]|=account> [@]<points> [~expiry] [sanctions] <:reason> [| notes]",
|
||||||
"fwarn_page_invalid": "Invalid page, must be a number 1 or greater.",
|
"fwarn_page_invalid": "Invalid page, must be a number 1 or greater.",
|
||||||
"fwarn_points_invalid": "Invalid points, must be a number above 0.",
|
"fwarn_points_invalid": "Invalid points, must be a number above 0.",
|
||||||
|
"fwarn_expiry_invalid": "Invalid expiration amount, must be a number above 0.",
|
||||||
"fwarn_expiry_invalid_suffix": "Invalid expiration suffix, must use either d, h, or m.",
|
"fwarn_expiry_invalid_suffix": "Invalid expiration suffix, must use either d, h, or m.",
|
||||||
"fwarn_cannot_add": "Cannot add warning, double-check your parameters (the nick might be wrong or you are not joined to the channel).",
|
"fwarn_cannot_add": "Cannot add warning, double-check your parameters (the nick might be wrong or you are not joined to the channel).",
|
||||||
"fwarn_added": "Added warning {0}.",
|
"fwarn_added": "Added warning {0}.",
|
||||||
@ -813,24 +820,32 @@
|
|||||||
"fwarn_stasis_invalid": "Invalid stasis amount, specify sanction as stasis=number.",
|
"fwarn_stasis_invalid": "Invalid stasis amount, specify sanction as stasis=number.",
|
||||||
"fwarn_deny_invalid": "Invalid denied commands, specify sanction as deny=command,command,command without spaces.",
|
"fwarn_deny_invalid": "Invalid denied commands, specify sanction as deny=command,command,command without spaces.",
|
||||||
"fwarn_deny_invalid_command": "Invalid command \"{0}\", specify sanction as deny=command,command,command without spaces.",
|
"fwarn_deny_invalid_command": "Invalid command \"{0}\", specify sanction as deny=command,command,command without spaces.",
|
||||||
"fwarn_list_header": "{0} has {1} active warning points.",
|
"fwarn_list_header": "{0} has {1} active warning points. Warnings prefixed with \u0002!\u0002 are unacknowledged.",
|
||||||
|
"warn_list_header": "You have {0} active warning points. You must acknowledge all warnings prefixed with \u0002!\u0002 by using \"warn ack <id>\" before you can join games.",
|
||||||
"fwarn_list": "{0}{1}[#{2} {3}] to {4} by {5} - {6} ({7} points, {8}){9}",
|
"fwarn_list": "{0}{1}[#{2} {3}] to {4} by {5} - {6} ({7} points, {8}){9}",
|
||||||
|
"warn_list": "{0}{1}[#{2} {3}] {4} ({5} points, {6}){7}",
|
||||||
"fwarn_deleted": "deleted",
|
"fwarn_deleted": "deleted",
|
||||||
"fwarn_expired": "expired",
|
"fwarn_expired": "expired",
|
||||||
|
"fwarn_list_expired": "expired on {0}",
|
||||||
"fwarn_never_expires": "never expires",
|
"fwarn_never_expires": "never expires",
|
||||||
"fwarn_list_footer": "More results are available, use fwarn list {0} to view them.",
|
"fwarn_list_footer": "More results are available, use fwarn list {0} to view them.",
|
||||||
|
"warn_list_footer": "More results are available, use warn list {0} to view them.",
|
||||||
"fwarn_list_empty": "No results.",
|
"fwarn_list_empty": "No results.",
|
||||||
"fwarn_invalid_warning": "The specified warning id does not exist or you do not have permission to view it.",
|
"fwarn_invalid_warning": "The specified warning id does not exist or you do not have permission to view it.",
|
||||||
"fwarn_view_header": "Warning #{0}, given to {1} on {2} by {3}. {4} points. {5}.",
|
"fwarn_view_header": "Warning #{0}, given to {1} on {2} by {3}. {4} points. {5}.",
|
||||||
|
"warn_view_header": "Warning #{0}, given on {1}. {2} points. {3}.",
|
||||||
"fwarn_view_active": "Currently active, {0}",
|
"fwarn_view_active": "Currently active, {0}",
|
||||||
"fwarn_view_expires": "expires on {0}",
|
"fwarn_view_expires": "expires on {0}",
|
||||||
"fwarn_view_expired": "Expired on {0}",
|
"fwarn_view_expired": "Expired on {0}",
|
||||||
"fwarn_view_deleted": "Deleted on {0} by {1}",
|
"fwarn_view_deleted": "Deleted on {0} by {1}",
|
||||||
"fwarn_view_ack": "Warning has not yet been acknowledged.",
|
"fwarn_view_ack": "Warning has not yet been acknowledged.",
|
||||||
|
"warn_view_ack": "You have not yet acknowledge this warning. You must acknowledge this warning by using \"warn ack {0}\" before you can join games.",
|
||||||
"fwarn_view_sanctions": "Sanctions:",
|
"fwarn_view_sanctions": "Sanctions:",
|
||||||
"fwarn_view_stasis": "{0} games of stasis.",
|
"fwarn_view_stasis_sing": "1 game of stasis.",
|
||||||
|
"fwarn_view_stasis_plural": "{0} games of stasis.",
|
||||||
"fwarn_view_deny": "denied {0}.",
|
"fwarn_view_deny": "denied {0}.",
|
||||||
"fwarn_reason_required": "A public warning reason is required.",
|
"fwarn_reason_required": "A public warning reason is required.",
|
||||||
|
"warn_unacked": "You have unacknowledged warnings and cannot join at this time. Use \"warn list\" to view them.",
|
||||||
|
|
||||||
"_": " vim: set sw=4 expandtab:"
|
"_": " vim: set sw=4 expandtab:"
|
||||||
}
|
}
|
||||||
|
@ -84,10 +84,6 @@ if args.normal: normal = True
|
|||||||
botconfig.DEBUG_MODE = debug_mode if not normal else False
|
botconfig.DEBUG_MODE = debug_mode if not normal else False
|
||||||
botconfig.VERBOSE_MODE = verbose if not normal else False
|
botconfig.VERBOSE_MODE = verbose if not normal else False
|
||||||
|
|
||||||
# Initialize Database
|
|
||||||
|
|
||||||
db.init()
|
|
||||||
|
|
||||||
# Logger
|
# Logger
|
||||||
|
|
||||||
# replace characters that can't be encoded with '?'
|
# replace characters that can't be encoded with '?'
|
||||||
|
236
src/db.py
236
src/db.py
@ -3,34 +3,37 @@ import src.settings as var
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
# increment this whenever making a schema change so that the schema upgrade functions run on start
|
# increment this whenever making a schema change so that the schema upgrade functions run on start
|
||||||
# they do not run by default for performance reasons
|
# they do not run by default for performance reasons
|
||||||
SCHEMA_VERSION = 1
|
SCHEMA_VERSION = 1
|
||||||
|
|
||||||
conn = None
|
need_install = not os.path.isfile("data.sqlite3")
|
||||||
|
conn = sqlite3.connect("data.sqlite3")
|
||||||
|
with conn:
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("PRAGMA foreign_keys = ON")
|
||||||
|
if need_install:
|
||||||
|
_install()
|
||||||
|
c.execute("PRAGMA user_version")
|
||||||
|
row = c.fetchone()
|
||||||
|
if row[0] == 0:
|
||||||
|
# new schema does not exist yet, migrate from old schema
|
||||||
|
# NOTE: game stats are NOT migrated to the new schema; the old gamestats table
|
||||||
|
# will continue to exist to allow queries against it, however given how horribly
|
||||||
|
# inaccurate the stats on it are, it would be a disservice to copy those inaccurate
|
||||||
|
# statistics over to the new schema which has the capability of actually being accurate.
|
||||||
|
_migrate()
|
||||||
|
elif row[0] < SCHEMA_VERSION:
|
||||||
|
_upgrade()
|
||||||
|
c.close()
|
||||||
|
|
||||||
def init():
|
del need_install, c
|
||||||
global conn
|
|
||||||
need_install = not os.path.isfile("data.sqlite3")
|
def init_vars():
|
||||||
conn = sqlite3.connect("data.sqlite3")
|
with var.GRAVEYARD_LOCK:
|
||||||
with conn:
|
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute("PRAGMA foreign_keys = ON")
|
|
||||||
if need_install:
|
|
||||||
_install()
|
|
||||||
c.execute("PRAGMA user_version")
|
|
||||||
row = c.fetchone()
|
|
||||||
if row[0] == 0:
|
|
||||||
# new schema does not exist yet, migrate from old schema
|
|
||||||
# NOTE: game stats are NOT migrated to the new schema; the old gamestats table
|
|
||||||
# will continue to exist to allow queries against it, however given how horribly
|
|
||||||
# inaccurate the stats on it are, it would be a disservice to copy those inaccurate
|
|
||||||
# statistics over to the new schema which has the capability of actually being accurate.
|
|
||||||
_migrate()
|
|
||||||
elif row[0] < SCHEMA_VERSION:
|
|
||||||
_upgrade()
|
|
||||||
|
|
||||||
c.execute("""SELECT
|
c.execute("""SELECT
|
||||||
pl.account,
|
pl.account,
|
||||||
pl.hostmask,
|
pl.hostmask,
|
||||||
@ -39,14 +42,37 @@ def init():
|
|||||||
pe.deadchat,
|
pe.deadchat,
|
||||||
pe.pingif,
|
pe.pingif,
|
||||||
pe.stasis_amount,
|
pe.stasis_amount,
|
||||||
pe.stasis_expires
|
pe.stasis_expires,
|
||||||
|
COALESCE(at.flags, a.flags)
|
||||||
FROM person pe
|
FROM person pe
|
||||||
JOIN person_player pp
|
JOIN person_player pp
|
||||||
ON pp.person = pe.id
|
ON pp.person = pe.id
|
||||||
JOIN player pl
|
JOIN player pl
|
||||||
ON pl.id = pp.player
|
ON pl.id = pp.player
|
||||||
|
LEFT JOIN access a
|
||||||
|
ON a.person = pe.id
|
||||||
|
LEFT JOIN access_template at
|
||||||
|
ON at.id = a.template
|
||||||
WHERE pl.active = 1""")
|
WHERE pl.active = 1""")
|
||||||
for (acc, host, notice, simple, dc, pi, stasis, stasisexp) in c:
|
|
||||||
|
var.SIMPLE_NOTIFY = set() # cloaks of people who !simple, who don't want detailed instructions
|
||||||
|
var.SIMPLE_NOTIFY_ACCS = set() # same as above, except accounts. takes precedence
|
||||||
|
var.PREFER_NOTICE = set() # cloaks of people who !notice, who want everything /notice'd
|
||||||
|
var.PREFER_NOTICE_ACCS = set() # Same as above, except accounts. takes precedence
|
||||||
|
var.STASISED = defaultdict(int)
|
||||||
|
var.STASISED_ACCS = defaultdict(int)
|
||||||
|
var.PING_IF_PREFS = {}
|
||||||
|
var.PING_IF_PREFS_ACCS = {}
|
||||||
|
var.PING_IF_NUMS = defaultdict(set)
|
||||||
|
var.PING_IF_NUMS_ACCS = defaultdict(set)
|
||||||
|
var.DEADCHAT_PREFS = set()
|
||||||
|
var.DEADCHAT_PREFS_ACCS = set()
|
||||||
|
var.FLAGS = defaultdict(str)
|
||||||
|
var.FLAGS_ACCS = defaultdict(str)
|
||||||
|
var.DENY = defaultdict(set)
|
||||||
|
var.DENY_ACCS = defaultdict(set)
|
||||||
|
|
||||||
|
for acc, host, notice, simple, dc, pi, stasis, stasisexp, flags in c:
|
||||||
if acc is not None:
|
if acc is not None:
|
||||||
if simple == 1:
|
if simple == 1:
|
||||||
var.SIMPLE_NOTIFY_ACCS.add(acc)
|
var.SIMPLE_NOTIFY_ACCS.add(acc)
|
||||||
@ -59,6 +85,8 @@ def init():
|
|||||||
var.PING_IF_NUMS_ACCS[pi].add(acc)
|
var.PING_IF_NUMS_ACCS[pi].add(acc)
|
||||||
if dc == 1:
|
if dc == 1:
|
||||||
var.DEADCHAT_PREFS_ACCS.add(acc)
|
var.DEADCHAT_PREFS_ACCS.add(acc)
|
||||||
|
if flags:
|
||||||
|
var.FLAGS_ACCS[acc] = flags
|
||||||
elif host is not None:
|
elif host is not None:
|
||||||
if simple == 1:
|
if simple == 1:
|
||||||
var.SIMPLE_NOTIFY.add(host)
|
var.SIMPLE_NOTIFY.add(host)
|
||||||
@ -71,6 +99,74 @@ def init():
|
|||||||
var.PING_IF_NUMS[pi].add(host)
|
var.PING_IF_NUMS[pi].add(host)
|
||||||
if dc == 1:
|
if dc == 1:
|
||||||
var.DEADCHAT_PREFS.add(host)
|
var.DEADCHAT_PREFS.add(host)
|
||||||
|
if flags:
|
||||||
|
var.FLAGS[host] = flags
|
||||||
|
|
||||||
|
c.execute("""SELECT
|
||||||
|
pl.account,
|
||||||
|
pl.hostmask,
|
||||||
|
ws.data
|
||||||
|
FROM warning w
|
||||||
|
JOIN warning_sanction ws
|
||||||
|
ON ws.warning = w.id
|
||||||
|
JOIN person pe
|
||||||
|
ON pe.id = w.target
|
||||||
|
JOIN person_player pp
|
||||||
|
ON pp.person = pe.id
|
||||||
|
JOIN player pl
|
||||||
|
ON pl.id = pp.player
|
||||||
|
WHERE
|
||||||
|
ws.sanction = 'deny command'
|
||||||
|
AND w.deleted = 0
|
||||||
|
AND (
|
||||||
|
w.expires IS NULL
|
||||||
|
OR w.expires > datetime('now')
|
||||||
|
)""")
|
||||||
|
for acc, host, command in c:
|
||||||
|
if acc is not None:
|
||||||
|
var.DENY_ACCS[acc].add(command)
|
||||||
|
if host is not None:
|
||||||
|
var.DENY[host].add(command)
|
||||||
|
|
||||||
|
init_vars()
|
||||||
|
|
||||||
|
def decrement_stasis(acc=None, hostmask=None):
|
||||||
|
peid, plid = _get_ids(acc, hostmask)
|
||||||
|
if (acc is not None or hostmask is not None) and peid is None:
|
||||||
|
return
|
||||||
|
sql = "UPDATE person SET stasis_amount = MAX(0, stasis_amount - 1)"
|
||||||
|
params = ()
|
||||||
|
if peid is not None:
|
||||||
|
sql += " WHERE id = ?"
|
||||||
|
params = (peid,)
|
||||||
|
|
||||||
|
with conn:
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute(sql, params)
|
||||||
|
|
||||||
|
def decrease_stasis(newamt, acc=None, hostmask=None):
|
||||||
|
peid, plid = _get_ids(acc, hostmask)
|
||||||
|
if peid is None:
|
||||||
|
return
|
||||||
|
if newamt < 0:
|
||||||
|
newamt = 0
|
||||||
|
|
||||||
|
with conn:
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("""UPDATE person
|
||||||
|
SET stasis_amount = MIN(stasis_amount, ?)
|
||||||
|
WHERE id = ?""", (newamt, peid))
|
||||||
|
|
||||||
|
def expire_stasis():
|
||||||
|
with conn:
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("""UPDATE person
|
||||||
|
SET
|
||||||
|
stasis_amount = 0,
|
||||||
|
stasis_expires = NULL
|
||||||
|
WHERE
|
||||||
|
stasis_expires IS NOT NULL
|
||||||
|
AND stasis_expires <= datetime('now')""")
|
||||||
|
|
||||||
def toggle_simple(acc, hostmask):
|
def toggle_simple(acc, hostmask):
|
||||||
_toggle_thing("simple", acc, hostmask)
|
_toggle_thing("simple", acc, hostmask)
|
||||||
@ -84,9 +180,6 @@ def toggle_deadchat(acc, hostmask):
|
|||||||
def set_pingif(val, acc, hostmask):
|
def set_pingif(val, acc, hostmask):
|
||||||
_set_thing("pingif", val, acc, hostmask, raw=False)
|
_set_thing("pingif", val, acc, hostmask, raw=False)
|
||||||
|
|
||||||
def set_stasis(val, acc, hostmask):
|
|
||||||
_set_thing("stasis_amount", val, acc, hostmask, raw=False)
|
|
||||||
|
|
||||||
def add_game(mode, size, started, finished, winner, players, options):
|
def add_game(mode, size, started, finished, winner, players, options):
|
||||||
""" Adds a game record to the database.
|
""" Adds a game record to the database.
|
||||||
|
|
||||||
@ -257,39 +350,6 @@ def get_game_totals(mode):
|
|||||||
totals.append("\u0002{0}p\u0002: {1}".format(*row))
|
totals.append("\u0002{0}p\u0002: {1}".format(*row))
|
||||||
return "Total games ({0}) | {1}".format(total_games, ", ".join(totals))
|
return "Total games ({0}) | {1}".format(total_games, ", ".join(totals))
|
||||||
|
|
||||||
def get_flags(acc, hostmask):
|
|
||||||
peid, plid = _get_ids(acc, hostmask)
|
|
||||||
c = conn.cursor()
|
|
||||||
c.execute("""SELECT COALESCE(at.flags, a.flags)
|
|
||||||
FROM access a
|
|
||||||
LEFT JOIN access_template at
|
|
||||||
ON at.id = a.template
|
|
||||||
WHERE a.person = ?""", (peid,))
|
|
||||||
row = c.fetchone()
|
|
||||||
if row is None:
|
|
||||||
return ""
|
|
||||||
return row[0]
|
|
||||||
|
|
||||||
def get_denied_commands(acc, hostmask):
|
|
||||||
peid, plid = _get_ids(acc, hostmask)
|
|
||||||
c = conn.cursor()
|
|
||||||
c.execute("""SELECT ws.data
|
|
||||||
FROM warning w
|
|
||||||
JOIN warning_sanction ws
|
|
||||||
ON ws.warning = w.id
|
|
||||||
WHERE
|
|
||||||
ws.sanction = 'deny command'
|
|
||||||
AND w.target = ?
|
|
||||||
AND w.deleted = 0
|
|
||||||
AND (
|
|
||||||
w.expires IS NULL
|
|
||||||
OR w.expires > datetime('now')
|
|
||||||
)""", (peid,))
|
|
||||||
cmds = set()
|
|
||||||
for row in c:
|
|
||||||
cmds.add(row[0])
|
|
||||||
return cmds
|
|
||||||
|
|
||||||
def get_warning_points(acc, hostmask):
|
def get_warning_points(acc, hostmask):
|
||||||
peid, plid = _get_ids(acc, hostmask)
|
peid, plid = _get_ids(acc, hostmask)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
@ -305,6 +365,23 @@ def get_warning_points(acc, hostmask):
|
|||||||
row = c.fetchone()
|
row = c.fetchone()
|
||||||
return row[0]
|
return row[0]
|
||||||
|
|
||||||
|
def has_unacknowledged_warnings(acc, hostmask):
|
||||||
|
peid, plid = _get_ids(acc, hostmask)
|
||||||
|
if peid is None:
|
||||||
|
return False
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("""SELECT MIN(acknowledged)
|
||||||
|
FROM warning
|
||||||
|
WHERE
|
||||||
|
target = ?
|
||||||
|
AND deleted = 0
|
||||||
|
AND (
|
||||||
|
expires IS NULL
|
||||||
|
OR expires > datetime('now')
|
||||||
|
)""", (peid,))
|
||||||
|
row = c.fetchone()
|
||||||
|
return not bool(row[0])
|
||||||
|
|
||||||
def list_all_warnings(list_all=False, skip=0, show=0):
|
def list_all_warnings(list_all=False, skip=0, show=0):
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
sql = """SELECT
|
sql = """SELECT
|
||||||
@ -356,7 +433,7 @@ def list_all_warnings(list_all=False, skip=0, show=0):
|
|||||||
"reason": row[9]})
|
"reason": row[9]})
|
||||||
return warnings
|
return warnings
|
||||||
|
|
||||||
def list_warnings(acc, hostmask, list_all=False, skip=0, show=0):
|
def list_warnings(acc, hostmask, expired=False, deleted=False, skip=0, show=0):
|
||||||
peid, plid = _get_ids(acc, hostmask)
|
peid, plid = _get_ids(acc, hostmask)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
sql = """SELECT
|
sql = """SELECT
|
||||||
@ -383,16 +460,16 @@ def list_warnings(acc, hostmask, list_all=False, skip=0, show=0):
|
|||||||
WHERE
|
WHERE
|
||||||
warning.target = ?
|
warning.target = ?
|
||||||
"""
|
"""
|
||||||
if not list_all:
|
if not deleted:
|
||||||
sql += """ AND deleted = 0
|
sql += " AND deleted = 0"
|
||||||
AND (
|
if not expired:
|
||||||
|
sql += """ AND (
|
||||||
expires IS NULL
|
expires IS NULL
|
||||||
OR expires > datetime('now')
|
OR expires > datetime('now')
|
||||||
)
|
)"""
|
||||||
"""
|
sql += " ORDER BY warning.issued DESC"
|
||||||
sql += "ORDER BY warning.issued DESC\n"
|
|
||||||
if show > 0:
|
if show > 0:
|
||||||
sql += "LIMIT {0} OFFSET {1}".format(show, skip)
|
sql += " LIMIT {0} OFFSET {1}".format(show, skip)
|
||||||
|
|
||||||
c.execute(sql, (botconfig.NICK, peid))
|
c.execute(sql, (botconfig.NICK, peid))
|
||||||
warnings = []
|
warnings = []
|
||||||
@ -410,7 +487,7 @@ def list_warnings(acc, hostmask, list_all=False, skip=0, show=0):
|
|||||||
return warnings
|
return warnings
|
||||||
|
|
||||||
def get_warning(warn_id, acc=None, hm=None):
|
def get_warning(warn_id, acc=None, hm=None):
|
||||||
pe, pl = _get_ids(acc, hm)
|
peid, plid = _get_ids(acc, hm)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
sql = """SELECT
|
sql = """SELECT
|
||||||
warning.id,
|
warning.id,
|
||||||
@ -486,13 +563,14 @@ def get_warning_sanctions(warn_id):
|
|||||||
def add_warning(tacc, thm, sacc, shm, amount, reason, notes, expires, need_ack):
|
def add_warning(tacc, thm, sacc, shm, amount, reason, notes, expires, need_ack):
|
||||||
teid, tlid = _get_ids(tacc, thm)
|
teid, tlid = _get_ids(tacc, thm)
|
||||||
seid, slid = _get_ids(sacc, shm)
|
seid, slid = _get_ids(sacc, shm)
|
||||||
|
ack = 0 if need_ack else 1
|
||||||
with conn:
|
with conn:
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute("""INSERT INTO warning
|
c.execute("""INSERT INTO warning
|
||||||
(
|
(
|
||||||
target, sender, amount,
|
target, sender, amount,
|
||||||
issued, expires,
|
issued, expires,
|
||||||
reasons, notes,
|
reason, notes,
|
||||||
acknowledged
|
acknowledged
|
||||||
)
|
)
|
||||||
VALUES
|
VALUES
|
||||||
@ -501,7 +579,7 @@ def add_warning(tacc, thm, sacc, shm, amount, reason, notes, expires, need_ack):
|
|||||||
datetime('now'), ?,
|
datetime('now'), ?,
|
||||||
?, ?,
|
?, ?,
|
||||||
?
|
?
|
||||||
)""", (teid, seid, amount, expires, reasons, notes, not need_ack))
|
)""", (teid, seid, amount, expires, reason, notes, ack))
|
||||||
return c.lastrowid
|
return c.lastrowid
|
||||||
|
|
||||||
def add_warning_sanction(warning, sanction, data):
|
def add_warning_sanction(warning, sanction, data):
|
||||||
@ -512,6 +590,19 @@ def add_warning_sanction(warning, sanction, data):
|
|||||||
VALUES
|
VALUES
|
||||||
(?, ?, ?)""", (warning, sanction, data))
|
(?, ?, ?)""", (warning, sanction, data))
|
||||||
|
|
||||||
|
if sanction == "stasis":
|
||||||
|
c.execute("SELECT target FROM warning WHERE id = ?", (warning,))
|
||||||
|
peid = c.fetchone()[0]
|
||||||
|
c.execute("""UPDATE person
|
||||||
|
SET
|
||||||
|
stasis_amount = stasis_amount + ?,
|
||||||
|
stasis_expires = datetime(CASE WHEN stasis_expires IS NULL
|
||||||
|
OR stasis_expires <= datetime('now')
|
||||||
|
THEN 'now'
|
||||||
|
ELSE stasis_expires END,
|
||||||
|
'+{0} hours')
|
||||||
|
WHERE id = ?""".format(int(data)), (data, peid))
|
||||||
|
|
||||||
def del_warning(warning, acc, hm):
|
def del_warning(warning, acc, hm):
|
||||||
peid, plid = _get_ids(acc, hm)
|
peid, plid = _get_ids(acc, hm)
|
||||||
with conn:
|
with conn:
|
||||||
@ -533,6 +624,11 @@ def set_warning(warning, reason, notes):
|
|||||||
SET reason = ?, notes = ?
|
SET reason = ?, notes = ?
|
||||||
WHERE id = ?""", (reason, notes, warning))
|
WHERE id = ?""", (reason, notes, warning))
|
||||||
|
|
||||||
|
def acknowledge_warning(warning):
|
||||||
|
with conn:
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("UPDATE warning SET acknowledged = 1 WHERE id = ?", (warning,))
|
||||||
|
|
||||||
def _upgrade():
|
def _upgrade():
|
||||||
# no upgrades yet, once there are some, add methods like _add_table(), _add_column(), etc.
|
# no upgrades yet, once there are some, add methods like _add_table(), _add_column(), etc.
|
||||||
# that check for the existence of that table/column/whatever and adds/drops/whatevers them
|
# that check for the existence of that table/column/whatever and adds/drops/whatevers them
|
||||||
|
@ -188,15 +188,13 @@ class cmd:
|
|||||||
cli.notice(nick, messages["not_owner"])
|
cli.notice(nick, messages["not_owner"])
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: cache flags and cmds (below) on init, possibly store in var.USERS
|
flags = var.FLAGS[hostmask] + var.FLAGS_ACCS[acc]
|
||||||
# that would greatly reduce our db calls
|
|
||||||
flags = db.get_flags(acc, hostmask)
|
|
||||||
is_full_admin = "F" in flags
|
is_full_admin = "F" in flags
|
||||||
if self.flag and (is_full_admin or is_owner):
|
if self.flag and (is_full_admin or is_owner):
|
||||||
adminlog(chan, rawnick, self.name, rest)
|
adminlog(chan, rawnick, self.name, rest)
|
||||||
return self.func(*largs)
|
return self.func(*largs)
|
||||||
|
|
||||||
denied_cmds = db.get_denied_commands(acc, hostmask)
|
denied_cmds = var.DENY[hostmask] | var.DENY_ACCS[acc]
|
||||||
for command in self.cmds:
|
for command in self.cmds:
|
||||||
if command in denied_cmds:
|
if command in denied_cmds:
|
||||||
if chan == nick:
|
if chan == nick:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import fnmatch
|
import fnmatch
|
||||||
import re
|
import re
|
||||||
|
import threading
|
||||||
from collections import defaultdict, OrderedDict
|
from collections import defaultdict, OrderedDict
|
||||||
|
|
||||||
import botconfig
|
import botconfig
|
||||||
@ -195,10 +196,6 @@ TOTEM_CHANCES = { "death": ( 1 , 1 , 0
|
|||||||
|
|
||||||
GAME_MODES = {}
|
GAME_MODES = {}
|
||||||
GAME_PHASES = ("night", "day") # all phases that constitute "in game", game modes can extend this with custom phases
|
GAME_PHASES = ("night", "day") # all phases that constitute "in game", game modes can extend this with custom phases
|
||||||
SIMPLE_NOTIFY = set() # cloaks of people who !simple, who don't want detailed instructions
|
|
||||||
SIMPLE_NOTIFY_ACCS = set() # same as above, except accounts. takes precedence
|
|
||||||
PREFER_NOTICE = set() # cloaks of people who !notice, who want everything /notice'd
|
|
||||||
PREFER_NOTICE_ACCS = set() # Same as above, except accounts. takes precedence
|
|
||||||
|
|
||||||
ACCOUNTS_ONLY = False # If True, will use only accounts for everything
|
ACCOUNTS_ONLY = False # If True, will use only accounts for everything
|
||||||
DISABLE_ACCOUNTS = False # If True, all account-related features are disabled. Automatically set if we discover we do not have proper ircd support for accounts
|
DISABLE_ACCOUNTS = False # If True, all account-related features are disabled. Automatically set if we discover we do not have proper ircd support for accounts
|
||||||
@ -212,9 +209,6 @@ NICKSERV_REGAIN_COMMAND = "REGAIN {nick}"
|
|||||||
CHANSERV = "ChanServ"
|
CHANSERV = "ChanServ"
|
||||||
CHANSERV_OP_COMMAND = "OP {channel}"
|
CHANSERV_OP_COMMAND = "OP {channel}"
|
||||||
|
|
||||||
STASISED = defaultdict(int)
|
|
||||||
STASISED_ACCS = defaultdict(int)
|
|
||||||
|
|
||||||
# TODO: move this to a game mode called "fixed" once we implement a way to randomize roles (and have that game mode be called "random")
|
# TODO: move this to a game mode called "fixed" once we implement a way to randomize roles (and have that game mode be called "random")
|
||||||
DEFAULT_ROLE = "villager"
|
DEFAULT_ROLE = "villager"
|
||||||
ROLE_INDEX = ( 4 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 15 , 16 , 18 , 20 , 21 , 23 , 24 )
|
ROLE_INDEX = ( 4 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 15 , 16 , 18 , 20 , 21 , 23 , 24 )
|
||||||
@ -328,16 +322,9 @@ FORTUNE_CHANCE = 1/25
|
|||||||
|
|
||||||
RULES = (botconfig.CHANNEL + " channel rules: http://wolf.xnrand.com/rules")
|
RULES = (botconfig.CHANNEL + " channel rules: http://wolf.xnrand.com/rules")
|
||||||
|
|
||||||
# pingif-related mappings
|
GRAVEYARD_LOCK = threading.RLock()
|
||||||
|
WARNING_LOCK = threading.RLock()
|
||||||
PING_IF_PREFS = {}
|
WAIT_TB_LOCK = threading.RLock()
|
||||||
PING_IF_PREFS_ACCS = {}
|
|
||||||
|
|
||||||
PING_IF_NUMS = defaultdict(set)
|
|
||||||
PING_IF_NUMS_ACCS = defaultdict(set)
|
|
||||||
|
|
||||||
DEADCHAT_PREFS = set()
|
|
||||||
DEADCHAT_PREFS_ACCS = set()
|
|
||||||
|
|
||||||
#TODO: move all of these to util.py or other files, as they are certainly NOT settings!
|
#TODO: move all of these to util.py or other files, as they are certainly NOT settings!
|
||||||
|
|
||||||
@ -386,7 +373,7 @@ def is_admin(nick, ident=None, host=None, acc=None):
|
|||||||
if not acc:
|
if not acc:
|
||||||
acc = USERS[nick]["account"]
|
acc = USERS[nick]["account"]
|
||||||
hostmask = nick + "!" + ident + "@" + host
|
hostmask = nick + "!" + ident + "@" + host
|
||||||
flags = db.get_flags(acc, hostmask)
|
flags = var.FLAGS[hostmask] + var.FLAGS_ACCS[acc]
|
||||||
return "F" in flags
|
return "F" in flags
|
||||||
|
|
||||||
def irc_lower(nick):
|
def irc_lower(nick):
|
||||||
|
342
src/wolfgame.py
342
src/wolfgame.py
@ -89,9 +89,6 @@ var.LAST_SAID_TIME = {}
|
|||||||
|
|
||||||
var.GAME_START_TIME = datetime.now() # for idle checker only
|
var.GAME_START_TIME = datetime.now() # for idle checker only
|
||||||
var.CAN_START_TIME = 0
|
var.CAN_START_TIME = 0
|
||||||
var.GRAVEYARD_LOCK = threading.RLock()
|
|
||||||
var.WARNING_LOCK = threading.RLock()
|
|
||||||
var.WAIT_TB_LOCK = threading.RLock()
|
|
||||||
var.STARTED_DAY_PLAYERS = 0
|
var.STARTED_DAY_PLAYERS = 0
|
||||||
|
|
||||||
var.DISCONNECTED = {} # players who got disconnected
|
var.DISCONNECTED = {} # players who got disconnected
|
||||||
@ -361,6 +358,15 @@ def get_victim(cli, nick, victim, in_chan, self_in_list=False, bot_in_list=False
|
|||||||
return
|
return
|
||||||
return pl[pll.index(tempvictim)] #convert back to normal casing
|
return pl[pll.index(tempvictim)] #convert back to normal casing
|
||||||
|
|
||||||
|
# wrapper around complete_match() used for any nick on the channel
|
||||||
|
def get_nick(cli, nick):
|
||||||
|
ul = [x for x in var.USERS]
|
||||||
|
ull = [x.lower() for x in var.USERS]
|
||||||
|
lnick, num_matches = complete_match(nick.lower(), ull)
|
||||||
|
if not lnick:
|
||||||
|
return None
|
||||||
|
return ul[ull.index(lnick)]
|
||||||
|
|
||||||
def get_roles(*roles):
|
def get_roles(*roles):
|
||||||
all_roles = []
|
all_roles = []
|
||||||
for role in roles:
|
for role in roles:
|
||||||
@ -449,6 +455,10 @@ def sync_modes(cli):
|
|||||||
|
|
||||||
mass_mode(cli, voices, other)
|
mass_mode(cli, voices, other)
|
||||||
|
|
||||||
|
@cmd("refreshdb", flag="m", pm=True)
|
||||||
|
def refreshdb(cli, nick, chan, rest):
|
||||||
|
"""Updates our tracking vars to the current db state."""
|
||||||
|
db.init_vars()
|
||||||
|
|
||||||
@cmd("fdie", "fbye", flag="D", pm=True)
|
@cmd("fdie", "fbye", flag="D", pm=True)
|
||||||
def forced_exit(cli, nick, chan, rest):
|
def forced_exit(cli, nick, chan, rest):
|
||||||
@ -1162,11 +1172,13 @@ def join_player(cli, player, chan, who=None, forced=False, *, sanity=True):
|
|||||||
ident = var.USERS[player]["ident"]
|
ident = var.USERS[player]["ident"]
|
||||||
host = var.USERS[player]["host"]
|
host = var.USERS[player]["host"]
|
||||||
acc = var.USERS[player]["account"]
|
acc = var.USERS[player]["account"]
|
||||||
|
hostmask = player + "!" + ident + "@" + host
|
||||||
elif is_fake_nick(player) and botconfig.DEBUG_MODE:
|
elif is_fake_nick(player) and botconfig.DEBUG_MODE:
|
||||||
# fakenick
|
# fakenick
|
||||||
ident = None
|
ident = None
|
||||||
host = None
|
host = None
|
||||||
acc = None
|
acc = None
|
||||||
|
hostmask = None
|
||||||
else:
|
else:
|
||||||
return False # Not normal
|
return False # Not normal
|
||||||
if not acc or acc == "*" or var.DISABLE_ACCOUNTS:
|
if not acc or acc == "*" or var.DISABLE_ACCOUNTS:
|
||||||
@ -1183,6 +1195,11 @@ def join_player(cli, player, chan, who=None, forced=False, *, sanity=True):
|
|||||||
"s" if stasis != 1 else ""))
|
"s" if stasis != 1 else ""))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# don't check unacked warnings on fjoin
|
||||||
|
if who == player and db.has_unacknowledged_warnings(acc, hostmask):
|
||||||
|
cli.notice(player, messages["warn_unacked"])
|
||||||
|
return False
|
||||||
|
|
||||||
cmodes = [("+v", player)]
|
cmodes = [("+v", player)]
|
||||||
if var.PHASE == "none":
|
if var.PHASE == "none":
|
||||||
if var.AUTO_TOGGLE_MODES and player in var.USERS and var.USERS[player]["modes"]:
|
if var.AUTO_TOGGLE_MODES and player in var.USERS and var.USERS[player]["modes"]:
|
||||||
@ -1297,6 +1314,9 @@ def kill_join(cli, chan):
|
|||||||
reset()
|
reset()
|
||||||
cli.msg(chan, msg)
|
cli.msg(chan, msg)
|
||||||
cli.msg(chan, messages["game_idle_cancel"])
|
cli.msg(chan, messages["game_idle_cancel"])
|
||||||
|
# use this opportunity to expire pending stasis
|
||||||
|
db.expire_stasis()
|
||||||
|
db.init_vars()
|
||||||
if var.AFTER_FLASTGAME is not None:
|
if var.AFTER_FLASTGAME is not None:
|
||||||
var.AFTER_FLASTGAME()
|
var.AFTER_FLASTGAME()
|
||||||
var.AFTER_FLASTGAME = None
|
var.AFTER_FLASTGAME = None
|
||||||
@ -7907,19 +7927,15 @@ def decrement_stasis(nick=None):
|
|||||||
acc = var.USERS[nick]["account"]
|
acc = var.USERS[nick]["account"]
|
||||||
# decrement account stasis even if accounts are disabled
|
# decrement account stasis even if accounts are disabled
|
||||||
if acc in var.STASISED_ACCS:
|
if acc in var.STASISED_ACCS:
|
||||||
var.STASISED_ACCS[acc] = max(0, var.STASISED_ACCS[acc] - 1)
|
db.decrement_stasis(acc=acc)
|
||||||
db.set_stasis(var.STASISED_ACCS[acc], acc, None)
|
|
||||||
for hostmask in var.STASISED:
|
for hostmask in var.STASISED:
|
||||||
if var.match_hostmask(hostmask, nick, ident, host):
|
if var.match_hostmask(hostmask, nick, ident, host):
|
||||||
var.STASISED[hostmask] = max(0, var.STASISED[hostmask] - 1)
|
db.decrement_stasis(hostmask=hostmask)
|
||||||
db.set_stasis(var.STASISED[hostmask], None, hostmask)
|
|
||||||
else:
|
else:
|
||||||
for acc in var.STASISED_ACCS:
|
db.decrement_stasis()
|
||||||
var.STASISED_ACCS[acc] = max(0, var.STASISED_ACCS[acc] - 1)
|
# Also expire any expired stasis and update our tracking vars
|
||||||
db.set_stasis(var.STASISED_ACCS[acc], acc, None)
|
db.expire_stasis()
|
||||||
for hostmask in var.STASISED:
|
db.init_vars()
|
||||||
var.STASISED[hostmask] = max(0, var.STASISED[hostmask] - 1)
|
|
||||||
db.set_stasis(var.STASISED[hostmask], None, hostmask)
|
|
||||||
|
|
||||||
def parse_warning_target(target):
|
def parse_warning_target(target):
|
||||||
if target[0] == "=":
|
if target[0] == "=":
|
||||||
@ -7988,6 +8004,9 @@ def add_warning(target, amount, actor, reason, notes=None, expires=None, need_ac
|
|||||||
for cmd in sanctions["deny"]:
|
for cmd in sanctions["deny"]:
|
||||||
db.add_warning_sanction(sid, "deny command", cmd)
|
db.add_warning_sanction(sid, "deny command", cmd)
|
||||||
|
|
||||||
|
# Update any tracking vars that may have changed due to this
|
||||||
|
db.init_vars()
|
||||||
|
|
||||||
return sid
|
return sid
|
||||||
|
|
||||||
@cmd("stasis", chan=True, pm=True)
|
@cmd("stasis", chan=True, pm=True)
|
||||||
@ -8000,14 +8019,226 @@ def stasis(cli, nick, chan, rest):
|
|||||||
|
|
||||||
reply(cli, nick, chan, msg, prefix_nick=True)
|
reply(cli, nick, chan, msg, prefix_nick=True)
|
||||||
|
|
||||||
|
@cmd("fstasis", flag="A", chan=True, pm=True)
|
||||||
|
def fstasis(cli, nick, chan, rest):
|
||||||
|
"""Removes or views stasis penalties."""
|
||||||
|
|
||||||
|
data = rest.split()
|
||||||
|
msg = None
|
||||||
|
|
||||||
|
if data:
|
||||||
|
lusers = {k.lower(): v for k, v in var.USERS.items()}
|
||||||
|
acc, hostmask = parse_warning_target(data[0])
|
||||||
|
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"
|
||||||
|
reply(cli, nick, chan, 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"
|
||||||
|
reply(cli, nick, chan, messages["hostmask_in_stasis"].format(data[0], hostmask, cur, plural))
|
||||||
|
elif acc is not None:
|
||||||
|
reply(cli, nick, chan, messages["account_not_in_stasis"].format(data[0], acc))
|
||||||
|
else:
|
||||||
|
reply(cli, nick, chan, messages["hostmask_not_in_stasis"].format(data[0], hostmask))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
amt = int(data[1])
|
||||||
|
except ValueError:
|
||||||
|
reply(cli, nick, chan, messages["stasis_not_negative"])
|
||||||
|
return
|
||||||
|
|
||||||
|
if amt < 0:
|
||||||
|
reply(cli, nick, chan, messages["stasis_not_negative"])
|
||||||
|
return
|
||||||
|
elif amt > cur:
|
||||||
|
reply(cli, nick, chan, messages["stasis_cannot_increase"])
|
||||||
|
return
|
||||||
|
elif cur == 0:
|
||||||
|
if acc is not None:
|
||||||
|
reply(cli, nick, chan, messages["account_not_in_stasis"].format(data[0], acc))
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
reply(cli, nick, chan, messages["hostmask_not_in_stasis"].format(data[0], hostmask))
|
||||||
|
return
|
||||||
|
|
||||||
|
db.decrease_stasis(amt, acc, hostmask)
|
||||||
|
db.init_vars()
|
||||||
|
if amt > 0:
|
||||||
|
plural = "" if amt == 1 else "s"
|
||||||
|
if acc is not None:
|
||||||
|
reply(cli, nick, chan, messages["fstasis_account_add"].format(data[0], acc, amt, plural))
|
||||||
|
else:
|
||||||
|
reply(cli, nick, chan, messages["fstasis_hostmask_add"].format(data[0], hostmask, amt, plural))
|
||||||
|
elif acc is not None:
|
||||||
|
reply(cli, nick, chan, messages["fstasis_account_remove"].format(data[0], acc))
|
||||||
|
else:
|
||||||
|
reply(cli, nick, chan, messages["fstasis_hostmask_remove"].format(data[0], hostmask))
|
||||||
|
elif var.STASISED or var.STASISED_ACCS:
|
||||||
|
stasised = {}
|
||||||
|
for hostmask in var.STASISED:
|
||||||
|
if var.DISABLE_ACCOUNTS:
|
||||||
|
stasised[hostmask] = var.STASISED[hostmask]
|
||||||
|
else:
|
||||||
|
stasised[hostmask+" (Host)"] = var.STASISED[hostmask]
|
||||||
|
if not var.DISABLE_ACCOUNTS:
|
||||||
|
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()))
|
||||||
|
reply(cli, nick, chan, msg)
|
||||||
|
else:
|
||||||
|
reply(cli, nick, chan, messages["noone_stasised"])
|
||||||
|
|
||||||
@cmd("warn", pm=True)
|
@cmd("warn", pm=True)
|
||||||
def warn(cli, nick, chan, rest):
|
def warn(cli, nick, chan, rest):
|
||||||
"""View and acknowledge your warnings."""
|
"""View and acknowledge your warnings."""
|
||||||
# !warn list [all] - lists all active warnings, or all warnings if all passed
|
# !warn list [-all] [page] - lists all active warnings, or all warnings if all passed
|
||||||
# !warn view <id> - views details on warning id
|
# !warn view <id> - views details on warning id
|
||||||
# !warn ack <id> - acknowledges warning id
|
# !warn ack <id> - acknowledges warning id
|
||||||
# Default if only !warn is given is to do !warn list.
|
# Default if only !warn is given is to do !warn list.
|
||||||
pass
|
params = re.split(" +", rest)
|
||||||
|
|
||||||
|
try:
|
||||||
|
command = params.pop(0)
|
||||||
|
if command == "":
|
||||||
|
command = "list"
|
||||||
|
except IndexError:
|
||||||
|
command = "list"
|
||||||
|
|
||||||
|
if command not in ("list", "view", "ack", "help"):
|
||||||
|
reply(cli, nick, chan, messages["warn_usage"])
|
||||||
|
return
|
||||||
|
|
||||||
|
if command == "help":
|
||||||
|
try:
|
||||||
|
subcommand = params.pop(0)
|
||||||
|
except IndexError:
|
||||||
|
reply(cli, nick, chan, messages["warn_help_syntax"])
|
||||||
|
return
|
||||||
|
if subcommand not in ("list", "view", "ack", "help"):
|
||||||
|
reply(cli, nick, chan, messages["warn_usage"])
|
||||||
|
return
|
||||||
|
reply(cli, nick, chan, 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:
|
||||||
|
reply(cli, nick, chan, 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:
|
||||||
|
reply(cli, nick, chan, messages["fwarn_page_invalid"])
|
||||||
|
return
|
||||||
|
|
||||||
|
acc, hm = parse_warning_target(nick)
|
||||||
|
warnings = db.list_warnings(acc, hm, expired=list_all, skip=(page-1)*10, show=11)
|
||||||
|
points = db.get_warning_points(acc, hm)
|
||||||
|
cli.notice(nick, messages["warn_list_header"].format(points))
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for warn in warnings:
|
||||||
|
i += 1
|
||||||
|
if (i == 11):
|
||||||
|
parts = []
|
||||||
|
if list_all:
|
||||||
|
parts.append("-all")
|
||||||
|
parts.append(str(page + 1))
|
||||||
|
cli.notice(nick, 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 "
|
||||||
|
cli.notice(nick, messages["warn_list"].format(
|
||||||
|
start, ack, warn["id"], warn["issued"], warn["reason"], warn["amount"], expires, end))
|
||||||
|
if i == 0:
|
||||||
|
cli.notice(nick, messages["fwarn_list_empty"])
|
||||||
|
return
|
||||||
|
|
||||||
|
if command == "view":
|
||||||
|
try:
|
||||||
|
warn_id = int(params.pop(0))
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
reply(cli, nick, chan, messages["warn_view_syntax"])
|
||||||
|
return
|
||||||
|
|
||||||
|
acc, hm = parse_warning_target(nick)
|
||||||
|
warning = db.get_warning(warn_id, acc, hm)
|
||||||
|
if warning is None:
|
||||||
|
reply(cli, nick, chan, 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"]))
|
||||||
|
|
||||||
|
cli.notice(nick, messages["warn_view_header"].format(
|
||||||
|
warning["id"], warning["issued"], warning["amount"], expires))
|
||||||
|
cli.notice(nick, 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:
|
||||||
|
cli.notice(nick, " ".join(sanctions))
|
||||||
|
return
|
||||||
|
|
||||||
|
if command == "ack":
|
||||||
|
try:
|
||||||
|
warn_id = int(params.pop(0))
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
reply(cli, nick, chan, messages["warn_ack_syntax"])
|
||||||
|
return
|
||||||
|
|
||||||
|
acc, hm = parse_warning_target(nick)
|
||||||
|
warning = db.get_warning(warn_id, acc, hm)
|
||||||
|
if warning is None:
|
||||||
|
reply(cli, nick, chan, messages["fwarn_invalid_warning"])
|
||||||
|
return
|
||||||
|
|
||||||
|
db.acknowledge_warning(warn_id)
|
||||||
|
reply(cli, nick, chan, messages["fwarn_done"])
|
||||||
|
return
|
||||||
|
|
||||||
@cmd("fwarn", flag="A", pm=True)
|
@cmd("fwarn", flag="A", pm=True)
|
||||||
def fwarn(cli, nick, chan, rest):
|
def fwarn(cli, nick, chan, rest):
|
||||||
@ -8039,7 +8270,7 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
target = None
|
target = None
|
||||||
points = None
|
points = None
|
||||||
need_ack = False
|
need_ack = False
|
||||||
expiry = None
|
expires = None
|
||||||
sanctions = {}
|
sanctions = {}
|
||||||
reason = None
|
reason = None
|
||||||
notes = None
|
notes = None
|
||||||
@ -8050,6 +8281,10 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
reply(cli, nick, chan, messages["fwarn_usage"])
|
reply(cli, nick, chan, messages["fwarn_usage"])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if command not in ("list", "view", "add", "del", "set", "help"):
|
||||||
|
reply(cli, nick, chan, messages["fwarn_usage"])
|
||||||
|
return
|
||||||
|
|
||||||
if command == "help":
|
if command == "help":
|
||||||
try:
|
try:
|
||||||
subcommand = params.pop(0)
|
subcommand = params.pop(0)
|
||||||
@ -8069,18 +8304,30 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
list_all = params.pop(0)
|
list_all = params.pop(0)
|
||||||
target = params.pop(0)
|
target = params.pop(0)
|
||||||
page = int(params.pop(0))
|
page = int(params.pop(0))
|
||||||
if list_all and list_all != "-all":
|
|
||||||
if target is not None:
|
|
||||||
page = int(target)
|
|
||||||
target = list_all
|
|
||||||
list_all = False
|
|
||||||
elif show_all == "-all":
|
|
||||||
list_all = True
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
except ValueError:
|
except ValueError:
|
||||||
reply(cli, nick, chan, messages["fwarn_page_invalid"])
|
reply(cli, nick, chan, messages["fwarn_page_invalid"])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
if list_all and list_all != "-all":
|
||||||
|
if target is not None:
|
||||||
|
page = int(target)
|
||||||
|
target = list_all
|
||||||
|
list_all = False
|
||||||
|
elif list_all == "-all":
|
||||||
|
list_all = True
|
||||||
|
except ValueError:
|
||||||
|
reply(cli, nick, chan, messages["fwarn_page_invalid"])
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
page = int(target)
|
||||||
|
target = None
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
if target is not None:
|
if target is not None:
|
||||||
acc, hm = parse_warning_target(target)
|
acc, hm = parse_warning_target(target)
|
||||||
if acc is None and hm is None:
|
if acc is None and hm is None:
|
||||||
@ -8088,7 +8335,7 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
return
|
return
|
||||||
warnings = db.list_warnings(acc, hm, list_all=list_all, skip=(page-1)*10, show=11)
|
warnings = db.list_warnings(acc, hm, list_all=list_all, skip=(page-1)*10, show=11)
|
||||||
points = db.get_warning_points(acc, hm)
|
points = db.get_warning_points(acc, hm)
|
||||||
reply(cli, nick, chan, messages["fwarn_list_header"].format(target, points))
|
cli.notice(nick, messages["fwarn_list_header"].format(target, points))
|
||||||
else:
|
else:
|
||||||
warnings = db.list_all_warnings(list_all=list_all, skip=(page-1)*10, show=11)
|
warnings = db.list_all_warnings(list_all=list_all, skip=(page-1)*10, show=11)
|
||||||
|
|
||||||
@ -8102,12 +8349,18 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
if target is not None:
|
if target is not None:
|
||||||
parts.append(target)
|
parts.append(target)
|
||||||
parts.append(str(page + 1))
|
parts.append(str(page + 1))
|
||||||
reply(cli, nick, chan, messages["fwarn_list_footer"].format(" ".join(parts)))
|
cli.notice(nick, messages["fwarn_list_footer"].format(" ".join(parts)))
|
||||||
break
|
break
|
||||||
start = ""
|
start = ""
|
||||||
end = ""
|
end = ""
|
||||||
ack = ""
|
ack = ""
|
||||||
expires = warn["expires"] if warn["expires"] is not None else messages["fwarn_never_expires"]
|
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["deleted"]:
|
if warn["deleted"]:
|
||||||
start = "\u000314"
|
start = "\u000314"
|
||||||
end = " [\u00034{0}\u000314]\u0003".format(messages["fwarn_deleted"])
|
end = " [\u00034{0}\u000314]\u0003".format(messages["fwarn_deleted"])
|
||||||
@ -8116,11 +8369,11 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
end = " [\u00037{0}\u000314]\u0003".format(messages["fwarn_expired"])
|
end = " [\u00037{0}\u000314]\u0003".format(messages["fwarn_expired"])
|
||||||
if not warn["ack"]:
|
if not warn["ack"]:
|
||||||
ack = "\u0002!\u0002 "
|
ack = "\u0002!\u0002 "
|
||||||
reply(cli, nick, chan, messages["fwarn_list"].format(
|
cli.notice(nick, messages["fwarn_list"].format(
|
||||||
start, ack, warn["id"], warn["issued"], warn["target"],
|
start, ack, warn["id"], warn["issued"], warn["target"],
|
||||||
warn["sender"], warn["reason"], warn["amount"], expires, end))
|
warn["sender"], warn["reason"], warn["amount"], expires, end))
|
||||||
if i == 0:
|
if i == 0:
|
||||||
reply(cli, nick, chan, messages["fwarn_list_empty"])
|
cli.notice(nick, messages["fwarn_list_empty"])
|
||||||
return
|
return
|
||||||
|
|
||||||
if command == "view":
|
if command == "view":
|
||||||
@ -8144,14 +8397,14 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
else:
|
else:
|
||||||
expires = messages["fwarn_view_active"].format(messages["fwarn_view_expires"].format(warning["expires"]))
|
expires = messages["fwarn_view_active"].format(messages["fwarn_view_expires"].format(warning["expires"]))
|
||||||
|
|
||||||
reply(cli, nick, chan, messages["fwarn_view_header"].format(
|
cli.notice(nick, messages["fwarn_view_header"].format(
|
||||||
warning["id"], warning["target"], warning["issued"], warning["sender"],
|
warning["id"], warning["target"], warning["issued"], warning["sender"],
|
||||||
warning["amount"], expires))
|
warning["amount"], expires))
|
||||||
|
|
||||||
reason = [warning["reason"]]
|
reason = [warning["reason"]]
|
||||||
if warning["notes"] is not None:
|
if warning["notes"] is not None:
|
||||||
reason.append(warning["notes"])
|
reason.append(warning["notes"])
|
||||||
reply(cli, nick, chan, " | ".join(reason))
|
cli.notice(nick, " | ".join(reason))
|
||||||
|
|
||||||
sanctions = []
|
sanctions = []
|
||||||
if not warning["ack"]:
|
if not warning["ack"]:
|
||||||
@ -8159,11 +8412,14 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
if warning["sanctions"]:
|
if warning["sanctions"]:
|
||||||
sanctions.append(messages["fwarn_view_sanctions"])
|
sanctions.append(messages["fwarn_view_sanctions"])
|
||||||
if "stasis" in warning["sanctions"]:
|
if "stasis" in warning["sanctions"]:
|
||||||
sanctions.append(messages["fwarn_view_stasis"].format(warning["sanctions"]["stasis"]))
|
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"]:
|
if "deny" in warning["sanctions"]:
|
||||||
sanctions.append(messages["fwarn_view_deny"].format(", ".join(warning["sanctions"]["deny"])))
|
sanctions.append(messages["fwarn_view_deny"].format(", ".join(warning["sanctions"]["deny"])))
|
||||||
if sanctions:
|
if sanctions:
|
||||||
reply(cli, nick, chan, " ".join(sanctions))
|
cli.notice(nick, " ".join(sanctions))
|
||||||
return
|
return
|
||||||
|
|
||||||
if command == "del":
|
if command == "del":
|
||||||
@ -8217,10 +8473,6 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
reply(cli, nick, chan, messages["fwarn_done"])
|
reply(cli, nick, chan, messages["fwarn_done"])
|
||||||
return
|
return
|
||||||
|
|
||||||
if command != "add":
|
|
||||||
reply(cli, nick, chan, messages["fwarn_usage"])
|
|
||||||
return
|
|
||||||
|
|
||||||
# command == "add"
|
# command == "add"
|
||||||
while params:
|
while params:
|
||||||
p = params.pop(0)
|
p = params.pop(0)
|
||||||
@ -8256,7 +8508,7 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
if p == "~":
|
if p == "~":
|
||||||
reply(cli, nick, chan, messages["fwarn_syntax"])
|
reply(cli, nick, chan, messages["fwarn_syntax"])
|
||||||
return
|
return
|
||||||
expiry = p[1:]
|
expires = p[1:]
|
||||||
else:
|
else:
|
||||||
# sanctions are the only thing left here
|
# sanctions are the only thing left here
|
||||||
sanc = p.split("=", 1)
|
sanc = p.split("=", 1)
|
||||||
@ -8303,12 +8555,22 @@ def fwarn(cli, nick, chan, rest):
|
|||||||
# convert expires into a proper datetime
|
# convert expires into a proper datetime
|
||||||
if expires is not None:
|
if expires is not None:
|
||||||
suffix = expires[-1]
|
suffix = expires[-1]
|
||||||
|
try:
|
||||||
|
amount = int(expires[:-1])
|
||||||
|
except ValueError:
|
||||||
|
reply(cli, nick, chan, messages["fwarn_expiry_invalid"])
|
||||||
|
return
|
||||||
|
|
||||||
|
if amount <= 0:
|
||||||
|
reply(cli, nick, chan, messages["fwarn_expiry_invalid"])
|
||||||
|
return
|
||||||
|
|
||||||
if suffix == "d":
|
if suffix == "d":
|
||||||
expires = datetime.now() + timedelta(days=expires[:-1])
|
expires = datetime.now() + timedelta(days=amount)
|
||||||
elif suffix == "h":
|
elif suffix == "h":
|
||||||
expires = datetime.now() + timedelta(hours=expires[:-1])
|
expires = datetime.now() + timedelta(hours=amount)
|
||||||
elif suffix == "m":
|
elif suffix == "m":
|
||||||
expires = datetime.now() + timedelta(minutes=expires[:-1])
|
expires = datetime.now() + timedelta(minutes=amount)
|
||||||
else:
|
else:
|
||||||
reply(cli, nick, chan, messages["fwarn_expiry_invalid_suffix"])
|
reply(cli, nick, chan, messages["fwarn_expiry_invalid_suffix"])
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user