Compare commits
5 Commits
0589939137
...
f78d407d4c
Author | SHA1 | Date |
---|---|---|
Brian S. Stephan | f78d407d4c | |
Brian S. Stephan | 8528152483 | |
Brian S. Stephan | f2fb0a26a4 | |
Brian S. Stephan | 0f88715ffd | |
Brian S. Stephan | 2f98a64cdd |
|
@ -1,7 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-02-23 02:25
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-02-24 01:06
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-02-24 01:12
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -1,36 +1,28 @@
|
|||
"""Roll dice when asked, intended for RPGs."""
|
||||
|
||||
# this breaks yacc, but ply might be happy in py3
|
||||
#from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import math
|
||||
import re
|
||||
import random
|
||||
|
||||
from irc.client import NickMask
|
||||
|
||||
import ply.lex as lex
|
||||
import ply.yacc as yacc
|
||||
|
||||
from dice.roller import DiceRoller
|
||||
from ircbot.lib import Plugin
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Dice(Plugin):
|
||||
|
||||
"""Roll simple or complex dice strings."""
|
||||
|
||||
def __init__(self):
|
||||
"""Set up the plugin."""
|
||||
super(Dice, self).__init__()
|
||||
self.roller = DiceRoller()
|
||||
|
||||
def start(self):
|
||||
"""Set up the handlers."""
|
||||
|
||||
self.roller = DiceRoller()
|
||||
|
||||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!roll\s+(.*)$',
|
||||
self.handle_roll, -20)
|
||||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!ctech\s+(.*)$',
|
||||
self.handle_ctech, -20)
|
||||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!random\s+(.*)$',
|
||||
self.handle_random, -20)
|
||||
|
||||
|
@ -38,9 +30,7 @@ class Dice(Plugin):
|
|||
|
||||
def stop(self):
|
||||
"""Tear down handlers."""
|
||||
|
||||
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_roll)
|
||||
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_ctech)
|
||||
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_random)
|
||||
|
||||
super(Dice, self).stop()
|
||||
|
@ -68,368 +58,17 @@ class Dice(Plugin):
|
|||
dicestr = match.group(1)
|
||||
|
||||
logger.debug(event.recursing)
|
||||
try:
|
||||
reply_str = self.roller.do_roll(dicestr)
|
||||
except AssertionError as aex:
|
||||
reply_str = f"Could not roll dice: {aex}"
|
||||
except ValueError:
|
||||
reply_str = "Unable to parse roll"
|
||||
|
||||
if event.recursing:
|
||||
reply = "{0:s}".format(self.roller.do_roll(dicestr))
|
||||
reply = "{0:s}".format(reply_str)
|
||||
else:
|
||||
reply = "{0:s}: {1:s}".format(nick, self.roller.do_roll(dicestr))
|
||||
reply = "{0:s}: {1:s}".format(nick, reply_str)
|
||||
return self.bot.reply(event, re.sub(r'(\d+)(.*?\s+)(\(.*?\))', r'\1\214\3', reply))
|
||||
|
||||
def handle_ctech(self, connection, event, match):
|
||||
"""Handle cthulhutech dice rolls."""
|
||||
|
||||
nick = NickMask(event.source).nick
|
||||
rollitrs = re.split(';\s*', match.group(1))
|
||||
reply = ""
|
||||
for count, roll in enumerate(rollitrs):
|
||||
pattern = '^(\d+)d(?:(\+|\-)(\d+))?(?:\s+(.*))?'
|
||||
regex = re.compile(pattern)
|
||||
matches = regex.search(roll)
|
||||
if matches is not None:
|
||||
dice = int(matches.group(1))
|
||||
modifier = 0
|
||||
|
||||
if matches.group(2) is not None and matches.group(3) is not None:
|
||||
if str(matches.group(2)) == '-':
|
||||
modifier = -1 * int(matches.group(3))
|
||||
else:
|
||||
modifier = int(matches.group(3))
|
||||
|
||||
result = roll + ': '
|
||||
|
||||
rolls = []
|
||||
for d in range(dice):
|
||||
rolls.append(random.randint(1, 10))
|
||||
rolls.sort()
|
||||
rolls.reverse()
|
||||
|
||||
# highest single die method
|
||||
method1 = rolls[0]
|
||||
|
||||
# highest set method
|
||||
method2 = 0
|
||||
rolling_sum = 0
|
||||
for i, r in enumerate(rolls):
|
||||
# if next roll is same as current, sum and continue, else see if sum is best so far
|
||||
if i+1 < len(rolls) and rolls[i+1] == r:
|
||||
if rolling_sum == 0:
|
||||
rolling_sum = r
|
||||
rolling_sum += r
|
||||
else:
|
||||
if rolling_sum > method2:
|
||||
method2 = rolling_sum
|
||||
rolling_sum = 0
|
||||
# check for set in progress (e.g. lots of 1s)
|
||||
if rolling_sum > method2:
|
||||
method2 = rolling_sum
|
||||
|
||||
# straight method
|
||||
method3 = 0
|
||||
rolling_sum = 0
|
||||
count = 0
|
||||
for i, r in enumerate(rolls):
|
||||
# if next roll is one less as current, sum and continue, else check len and see if sum is best so far
|
||||
if i+1 < len(rolls) and rolls[i+1] == r-1:
|
||||
if rolling_sum == 0:
|
||||
rolling_sum = r
|
||||
count += 1
|
||||
rolling_sum += r-1
|
||||
count += 1
|
||||
else:
|
||||
if count >= 3 and rolling_sum > method3:
|
||||
method3 = rolling_sum
|
||||
rolling_sum = 0
|
||||
# check for straight in progress (e.g. straight ending in 1)
|
||||
if count >= 3 and rolling_sum > method3:
|
||||
method3 = rolling_sum
|
||||
|
||||
# get best roll
|
||||
best = max([method1, method2, method3])
|
||||
|
||||
# check for critical failure
|
||||
botch = False
|
||||
ones = 0
|
||||
for r in rolls:
|
||||
if r == 1:
|
||||
ones += 1
|
||||
if ones >= math.ceil(float(len(rolls))/2):
|
||||
botch = True
|
||||
|
||||
if botch:
|
||||
result += 'BOTCH'
|
||||
else:
|
||||
result += str(best + modifier)
|
||||
rollres = ''
|
||||
for i,r in enumerate(rolls):
|
||||
rollres += str(r)
|
||||
if i is not len(rolls)-1:
|
||||
rollres += ','
|
||||
result += ' [' + rollres
|
||||
if modifier != 0:
|
||||
if modifier > 0:
|
||||
result += ' +' + str(modifier)
|
||||
else:
|
||||
result += ' -' + str(modifier * -1)
|
||||
result += ']'
|
||||
|
||||
reply += result
|
||||
if count is not len(rollitrs)-1:
|
||||
reply += "; "
|
||||
if reply is not "":
|
||||
msg = "{0:s}: {1:s}".format(nick, reply)
|
||||
return self.bot.reply(event, msg)
|
||||
|
||||
|
||||
class DiceRoller(object):
|
||||
|
||||
tokens = ['NUMBER', 'TEXT', 'ROLLSEP']
|
||||
literals = ['#', '/', '+', '-', 'd']
|
||||
|
||||
t_TEXT = r'\s+[^;]+'
|
||||
t_ROLLSEP = r';\s*'
|
||||
|
||||
def build(self):
|
||||
lex.lex(module=self)
|
||||
yacc.yacc(module=self)
|
||||
|
||||
def t_NUMBER(self, t):
|
||||
r'\d+'
|
||||
t.value = int(t.value)
|
||||
return t
|
||||
|
||||
def t_error(self, t):
|
||||
t.lexer.skip(1)
|
||||
|
||||
precedence = (
|
||||
('left', 'ROLLSEP'),
|
||||
('left', '+', '-'),
|
||||
('right', 'd'),
|
||||
('left', '#'),
|
||||
('left', '/')
|
||||
)
|
||||
|
||||
output = ""
|
||||
|
||||
def roll_dice(self, keep, dice, size):
|
||||
"""Takes the parsed dice string for a single roll (eg 3/4d20) and performs
|
||||
the actual roll. Returns a string representing the result.
|
||||
"""
|
||||
|
||||
a = list(range(dice))
|
||||
for i in range(dice):
|
||||
a[i] = random.randint(1, size)
|
||||
if keep != dice:
|
||||
b = sorted(a, reverse=True)
|
||||
b = b[0:keep]
|
||||
else:
|
||||
b = a
|
||||
total = sum(b)
|
||||
outstr = "[" + ",".join(str(i) for i in a) + "]"
|
||||
|
||||
return (total, outstr)
|
||||
|
||||
def process_roll(self, trials, mods, comment):
|
||||
"""Processes rolls coming from the parser.
|
||||
|
||||
This generates the inputs for the roll_dice() command, and returns
|
||||
the full string representing the whole current dice string (the part
|
||||
up to a semicolon or end of line).
|
||||
"""
|
||||
|
||||
output = ""
|
||||
repeat = 1
|
||||
if trials != None:
|
||||
repeat = trials
|
||||
for i in range(repeat):
|
||||
mode = 1
|
||||
total = 0
|
||||
curr_str = ""
|
||||
if i > 0:
|
||||
output += ", "
|
||||
for m in mods:
|
||||
keep = 0
|
||||
dice = 1
|
||||
res = 0
|
||||
# if m is a tuple, then it is a die roll
|
||||
# m[0] = (keep, num dice)
|
||||
# m[1] = num faces on the die
|
||||
if type(m) == tuple:
|
||||
if m[0] != None:
|
||||
if m[0][0] != None:
|
||||
keep = m[0][0]
|
||||
dice = m[0][1]
|
||||
size = m[1]
|
||||
if keep > dice or keep == 0:
|
||||
keep = dice
|
||||
if size < 1:
|
||||
output = "# of sides for die is incorrect: %d" % size
|
||||
return output
|
||||
if dice < 1:
|
||||
output = "# of dice is incorrect: %d" % dice
|
||||
return output
|
||||
res = self.roll_dice(keep, dice, size)
|
||||
curr_str += "%d%s" % (res[0], res[1])
|
||||
res = res[0]
|
||||
elif m == "+":
|
||||
mode = 1
|
||||
curr_str += "+"
|
||||
elif m == "-":
|
||||
mode = -1
|
||||
curr_str += "-"
|
||||
else:
|
||||
res = m
|
||||
curr_str += str(m)
|
||||
total += mode * res
|
||||
if repeat == 1:
|
||||
if comment != None:
|
||||
output = "%d %s (%s)" % (total, comment.strip(), curr_str)
|
||||
else:
|
||||
output = "%d (%s)" % (total, curr_str)
|
||||
else:
|
||||
output += "%d (%s)" % (total, curr_str)
|
||||
if i == repeat - 1:
|
||||
if comment != None:
|
||||
output += " (%s)" % (comment.strip())
|
||||
return output
|
||||
|
||||
def p_roll_r(self, p):
|
||||
# Chain rolls together.
|
||||
|
||||
# General idea I had when creating this grammar: A roll string is a chain
|
||||
# of modifiers, which may be repeated for a certain number of trials. It can
|
||||
# have a comment that describes the roll
|
||||
# Multiple roll strings can be chained with semicolon
|
||||
|
||||
'roll : roll ROLLSEP roll'
|
||||
global output
|
||||
p[0] = p[1] + "; " + p[3]
|
||||
output = p[0]
|
||||
|
||||
def p_roll(self, p):
|
||||
# Parse a basic roll string.
|
||||
|
||||
'roll : trial modifier comment'
|
||||
global output
|
||||
mods = []
|
||||
if type(p[2]) == list:
|
||||
mods = p[2]
|
||||
else:
|
||||
mods = [p[2]]
|
||||
p[0] = self.process_roll(p[1], mods, p[3])
|
||||
output = p[0]
|
||||
|
||||
def p_roll_no_trials(self, p):
|
||||
# Parse a roll string without trials.
|
||||
|
||||
'roll : modifier comment'
|
||||
global output
|
||||
mods = []
|
||||
if type(p[1]) == list:
|
||||
mods = p[1]
|
||||
else:
|
||||
mods = [p[1]]
|
||||
p[0] = self.process_roll(None, mods, p[2])
|
||||
output = p[0]
|
||||
|
||||
def p_comment(self, p):
|
||||
# Parse a comment.
|
||||
|
||||
'''comment : TEXT
|
||||
|'''
|
||||
if len(p) == 2:
|
||||
p[0] = p[1]
|
||||
else:
|
||||
p[0] = None
|
||||
|
||||
def p_modifier(self, p):
|
||||
# Parse a modifier on a roll string.
|
||||
|
||||
'''modifier : modifier "+" modifier
|
||||
| modifier "-" modifier'''
|
||||
# Use append to prevent nested lists (makes dealing with this easier)
|
||||
if type(p[1]) == list:
|
||||
p[1].append(p[2])
|
||||
p[1].append(p[3])
|
||||
p[0] = p[1]
|
||||
elif type(p[3]) == list:
|
||||
p[3].insert(0, p[2])
|
||||
p[3].insert(0, p[1])
|
||||
p[0] = p[3]
|
||||
else:
|
||||
p[0] = [p[1], p[2], p[3]]
|
||||
|
||||
def p_die(self, p):
|
||||
# Return the left side before the "d", and the number of faces.
|
||||
|
||||
'modifier : left NUMBER'
|
||||
p[0] = (p[1], p[2])
|
||||
|
||||
def p_die_num(self, p):
|
||||
'modifier : NUMBER'
|
||||
p[0] = p[1]
|
||||
|
||||
def p_left(self, p):
|
||||
# Parse the number of dice we are rolling, and how many we are keeping.
|
||||
'left : keep dice'
|
||||
if p[1] == None:
|
||||
p[0] = [None, p[2]]
|
||||
else:
|
||||
p[0] = [p[1], p[2]]
|
||||
|
||||
def p_left_all(self, p):
|
||||
'left : dice'
|
||||
p[0] = [None, p[1]]
|
||||
|
||||
def p_left_e(self, p):
|
||||
'left :'
|
||||
p[0] = None
|
||||
|
||||
def p_total(self, p):
|
||||
'trial : NUMBER "#"'
|
||||
if len(p) > 1:
|
||||
p[0] = p[1]
|
||||
else:
|
||||
p[0] = None
|
||||
|
||||
def p_keep(self, p):
|
||||
'keep : NUMBER "/"'
|
||||
if p[1] != None:
|
||||
p[0] = p[1]
|
||||
else:
|
||||
p[0] = None
|
||||
|
||||
def p_dice(self, p):
|
||||
'dice : NUMBER "d"'
|
||||
p[0] = p[1]
|
||||
|
||||
def p_dice_one(self, p):
|
||||
'dice : "d"'
|
||||
p[0] = 1
|
||||
|
||||
def p_error(self, p):
|
||||
# Provide the user with something (albeit not much) when the roll can't be parsed.
|
||||
global output
|
||||
output = "Unable to parse roll"
|
||||
|
||||
def get_result(self):
|
||||
global output
|
||||
return output
|
||||
|
||||
def do_roll(self, dicestr):
|
||||
"""
|
||||
Roll some dice and get the result (with broken out rolls).
|
||||
|
||||
Keyword arguments:
|
||||
dicestr - format:
|
||||
N#X/YdS+M label
|
||||
N#: do the following roll N times (optional)
|
||||
X/: take the top X rolls of the Y times rolled (optional)
|
||||
Y : roll the die specified Y times (optional, defaults to 1)
|
||||
dS: roll a S-sided die
|
||||
+M: add M to the result (-M for subtraction) (optional)
|
||||
"""
|
||||
self.build()
|
||||
yacc.parse(dicestr)
|
||||
return self.get_result()
|
||||
|
||||
|
||||
plugin = Dice
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
"""Dice rollers used by the views, bots, etc."""
|
||||
import logging
|
||||
import random
|
||||
|
||||
import ply.lex as lex
|
||||
import ply.yacc as yacc
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DiceRoller(object):
|
||||
|
||||
tokens = ['NUMBER', 'TEXT', 'ROLLSEP']
|
||||
literals = ['#', '/', '+', '-', 'd']
|
||||
|
||||
t_TEXT = r'\s+[^;]+'
|
||||
t_ROLLSEP = r';\s*'
|
||||
|
||||
def build(self):
|
||||
lex.lex(module=self)
|
||||
yacc.yacc(module=self)
|
||||
|
||||
def t_NUMBER(self, t):
|
||||
r'\d+'
|
||||
t.value = int(t.value)
|
||||
return t
|
||||
|
||||
def t_error(self, t):
|
||||
t.lexer.skip(1)
|
||||
|
||||
precedence = (
|
||||
('left', 'ROLLSEP'),
|
||||
('left', '+', '-'),
|
||||
('right', 'd'),
|
||||
('left', '#'),
|
||||
('left', '/')
|
||||
)
|
||||
|
||||
output = ""
|
||||
|
||||
def roll_dice(self, keep, dice, size):
|
||||
"""Takes the parsed dice string for a single roll (eg 3/4d20) and performs
|
||||
the actual roll. Returns a string representing the result.
|
||||
"""
|
||||
|
||||
a = list(range(dice))
|
||||
for i in range(dice):
|
||||
a[i] = random.randint(1, size)
|
||||
if keep != dice:
|
||||
b = sorted(a, reverse=True)
|
||||
b = b[0:keep]
|
||||
else:
|
||||
b = a
|
||||
total = sum(b)
|
||||
outstr = "[" + ",".join(str(i) for i in a) + "]"
|
||||
|
||||
return (total, outstr)
|
||||
|
||||
def process_roll(self, trials, mods, comment):
|
||||
"""Processes rolls coming from the parser.
|
||||
|
||||
This generates the inputs for the roll_dice() command, and returns
|
||||
the full string representing the whole current dice string (the part
|
||||
up to a semicolon or end of line).
|
||||
"""
|
||||
rolls = mods[0][0][1] if mods[0][0][1] else 1
|
||||
assert trials <= 10, "Too many rolls (max: 10)."
|
||||
assert rolls <= 50, "Too many dice (max: 50) in roll."
|
||||
|
||||
output = ""
|
||||
repeat = 1
|
||||
if trials != None:
|
||||
repeat = trials
|
||||
for i in range(repeat):
|
||||
mode = 1
|
||||
total = 0
|
||||
curr_str = ""
|
||||
if i > 0:
|
||||
output += ", "
|
||||
for m in mods:
|
||||
keep = 0
|
||||
dice = 1
|
||||
res = 0
|
||||
# if m is a tuple, then it is a die roll
|
||||
# m[0] = (keep, num dice)
|
||||
# m[1] = num faces on the die
|
||||
if type(m) == tuple:
|
||||
if m[0] != None:
|
||||
if m[0][0] != None:
|
||||
keep = m[0][0]
|
||||
dice = m[0][1]
|
||||
size = m[1]
|
||||
if keep > dice or keep == 0:
|
||||
keep = dice
|
||||
if size < 1:
|
||||
output = "# of sides for die is incorrect: %d" % size
|
||||
return output
|
||||
if dice < 1:
|
||||
output = "# of dice is incorrect: %d" % dice
|
||||
return output
|
||||
res = self.roll_dice(keep, dice, size)
|
||||
curr_str += "%d%s" % (res[0], res[1])
|
||||
res = res[0]
|
||||
elif m == "+":
|
||||
mode = 1
|
||||
curr_str += "+"
|
||||
elif m == "-":
|
||||
mode = -1
|
||||
curr_str += "-"
|
||||
else:
|
||||
res = m
|
||||
curr_str += str(m)
|
||||
total += mode * res
|
||||
if repeat == 1:
|
||||
if comment != None:
|
||||
output = "%d %s (%s)" % (total, comment.strip(), curr_str)
|
||||
else:
|
||||
output = "%d (%s)" % (total, curr_str)
|
||||
else:
|
||||
output += "%d (%s)" % (total, curr_str)
|
||||
if i == repeat - 1:
|
||||
if comment != None:
|
||||
output += " (%s)" % (comment.strip())
|
||||
return output
|
||||
|
||||
def p_roll_r(self, p):
|
||||
# Chain rolls together.
|
||||
|
||||
# General idea I had when creating this grammar: A roll string is a chain
|
||||
# of modifiers, which may be repeated for a certain number of trials. It can
|
||||
# have a comment that describes the roll
|
||||
# Multiple roll strings can be chained with semicolon
|
||||
|
||||
'roll : roll ROLLSEP roll'
|
||||
global output
|
||||
p[0] = p[1] + "; " + p[3]
|
||||
output = p[0]
|
||||
|
||||
def p_roll(self, p):
|
||||
# Parse a basic roll string.
|
||||
|
||||
'roll : trial modifier comment'
|
||||
global output
|
||||
mods = []
|
||||
if type(p[2]) == list:
|
||||
mods = p[2]
|
||||
else:
|
||||
mods = [p[2]]
|
||||
p[0] = self.process_roll(p[1], mods, p[3])
|
||||
output = p[0]
|
||||
|
||||
def p_roll_no_trials(self, p):
|
||||
# Parse a roll string without trials.
|
||||
|
||||
'roll : modifier comment'
|
||||
global output
|
||||
mods = []
|
||||
if type(p[1]) == list:
|
||||
mods = p[1]
|
||||
else:
|
||||
mods = [p[1]]
|
||||
p[0] = self.process_roll(None, mods, p[2])
|
||||
output = p[0]
|
||||
|
||||
def p_comment(self, p):
|
||||
# Parse a comment.
|
||||
|
||||
'''comment : TEXT
|
||||
|'''
|
||||
if len(p) == 2:
|
||||
p[0] = p[1]
|
||||
else:
|
||||
p[0] = None
|
||||
|
||||
def p_modifier(self, p):
|
||||
# Parse a modifier on a roll string.
|
||||
|
||||
'''modifier : modifier "+" modifier
|
||||
| modifier "-" modifier'''
|
||||
# Use append to prevent nested lists (makes dealing with this easier)
|
||||
if type(p[1]) == list:
|
||||
p[1].append(p[2])
|
||||
p[1].append(p[3])
|
||||
p[0] = p[1]
|
||||
elif type(p[3]) == list:
|
||||
p[3].insert(0, p[2])
|
||||
p[3].insert(0, p[1])
|
||||
p[0] = p[3]
|
||||
else:
|
||||
p[0] = [p[1], p[2], p[3]]
|
||||
|
||||
def p_die(self, p):
|
||||
# Return the left side before the "d", and the number of faces.
|
||||
|
||||
'modifier : left NUMBER'
|
||||
p[0] = (p[1], p[2])
|
||||
|
||||
def p_die_num(self, p):
|
||||
'modifier : NUMBER'
|
||||
p[0] = p[1]
|
||||
|
||||
def p_left(self, p):
|
||||
# Parse the number of dice we are rolling, and how many we are keeping.
|
||||
'left : keep dice'
|
||||
if p[1] == None:
|
||||
p[0] = [None, p[2]]
|
||||
else:
|
||||
p[0] = [p[1], p[2]]
|
||||
|
||||
def p_left_all(self, p):
|
||||
'left : dice'
|
||||
p[0] = [None, p[1]]
|
||||
|
||||
def p_left_e(self, p):
|
||||
'left :'
|
||||
p[0] = None
|
||||
|
||||
def p_total(self, p):
|
||||
'trial : NUMBER "#"'
|
||||
if len(p) > 1:
|
||||
p[0] = p[1]
|
||||
else:
|
||||
p[0] = None
|
||||
|
||||
def p_keep(self, p):
|
||||
'keep : NUMBER "/"'
|
||||
if p[1] != None:
|
||||
p[0] = p[1]
|
||||
else:
|
||||
p[0] = None
|
||||
|
||||
def p_dice(self, p):
|
||||
'dice : NUMBER "d"'
|
||||
p[0] = p[1]
|
||||
|
||||
def p_dice_one(self, p):
|
||||
'dice : "d"'
|
||||
p[0] = 1
|
||||
|
||||
def p_error(self, p):
|
||||
"""Raise ValueError on unparseable strings."""
|
||||
raise ValueError("Error occurred in parser")
|
||||
|
||||
def get_result(self):
|
||||
global output
|
||||
return output
|
||||
|
||||
def do_roll(self, dicestr):
|
||||
"""
|
||||
Roll some dice and get the result (with broken out rolls).
|
||||
|
||||
Keyword arguments:
|
||||
dicestr - format:
|
||||
N#X/YdS+M label
|
||||
N#: do the following roll N times (optional)
|
||||
X/: take the top X rolls of the Y times rolled (optional)
|
||||
Y : roll the die specified Y times (optional, defaults to 1)
|
||||
dS: roll a S-sided die
|
||||
+M: add M to the result (-M for subtraction) (optional)
|
||||
"""
|
||||
self.build()
|
||||
yacc.parse(dicestr)
|
||||
return self.get_result()
|
|
@ -29,6 +29,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='dispatcheraction',
|
||||
name='dispatcher',
|
||||
field=models.ForeignKey(to='dispatch.Dispatcher'),
|
||||
field=models.ForeignKey(to='dispatch.Dispatcher', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -17,6 +17,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='dispatcheraction',
|
||||
name='dispatcher',
|
||||
field=models.ForeignKey(related_name='actions', to='dispatch.Dispatcher'),
|
||||
field=models.ForeignKey(related_name='actions', to='dispatch.Dispatcher', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class DispatcherAction(models.Model):
|
|||
(FILE_TYPE, "Write to file"),
|
||||
)
|
||||
|
||||
dispatcher = models.ForeignKey('Dispatcher', related_name='actions')
|
||||
dispatcher = models.ForeignKey('Dispatcher', related_name='actions', on_delete=models.CASCADE)
|
||||
type = models.CharField(max_length=16, choices=TYPE_CHOICES)
|
||||
destination = models.CharField(max_length=200)
|
||||
include_key = models.BooleanField(default=False)
|
||||
|
|
|
@ -11,7 +11,7 @@ https://docs.djangoproject.com/en/1.6/ref/settings/
|
|||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
|
@ -57,12 +57,11 @@ INSTALLED_APPS = (
|
|||
'twitter',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
MIDDLEWARE = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
|
|
|
@ -20,5 +20,5 @@ urlpatterns = [
|
|||
url(r'^races/', include('races.urls')),
|
||||
|
||||
url(r'^accounts/', include('registration.backends.default.urls')),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^admin/', admin.site.urls),
|
||||
]
|
||||
|
|
|
@ -26,6 +26,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='fact',
|
||||
name='category',
|
||||
field=models.ForeignKey(to='facts.FactCategory'),
|
||||
field=models.ForeignKey(to='facts.FactCategory', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-02-11 15:00
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ class Fact(models.Model):
|
|||
"""Define facts."""
|
||||
|
||||
fact = models.TextField()
|
||||
category = models.ForeignKey(FactCategory)
|
||||
category = models.ForeignKey(FactCategory, on_delete=models.CASCADE)
|
||||
nickmask = models.CharField(max_length=200, default='', blank=True)
|
||||
time = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -27,7 +25,7 @@ class Migration(migrations.Migration):
|
|||
('code_reviews_necessary', models.PositiveSmallIntegerField(default=0)),
|
||||
('code_reviewers', models.TextField(blank=True, default='')),
|
||||
('code_review_final_merge_assignees', models.TextField(blank=True, default='')),
|
||||
('gitlab_config', models.ForeignKey(to='gitlab_bot.GitlabConfig', null=True)),
|
||||
('gitlab_config', models.ForeignKey(to='gitlab_bot.GitlabConfig', null=True, on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class GitlabProjectConfig(models.Model):
|
|||
|
||||
"""Maintain settings for a particular project in GitLab."""
|
||||
|
||||
gitlab_config = models.ForeignKey('GitlabConfig', null=True)
|
||||
gitlab_config = models.ForeignKey('GitlabConfig', null=True, on_delete=models.CASCADE)
|
||||
project_id = models.CharField(max_length=64, unique=True)
|
||||
|
||||
manage_merge_request_code_reviews = models.BooleanField(default=False)
|
||||
|
|
|
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='botadmin',
|
||||
name='user',
|
||||
field=models.ForeignKey(default=1, to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(default=1, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ class BotUser(models.Model):
|
|||
"""Configure bot users, which can do things through the bot and standard Django auth."""
|
||||
|
||||
nickmask = models.CharField(max_length=200, unique=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
permissions = (
|
||||
|
|
|
@ -23,7 +23,7 @@ class Migration(migrations.Migration):
|
|||
('delta', models.SmallIntegerField()),
|
||||
('nickmask', models.CharField(default='', max_length=200, blank=True)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('key', models.ForeignKey(to='karma.KarmaKey')),
|
||||
('key', models.ForeignKey(to='karma.KarmaKey', on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -115,7 +115,7 @@ class KarmaLogEntryManager(models.Manager):
|
|||
class KarmaLogEntry(models.Model):
|
||||
"""Track each karma increment/decrement."""
|
||||
|
||||
key = models.ForeignKey('KarmaKey')
|
||||
key = models.ForeignKey('KarmaKey', on_delete=models.CASCADE)
|
||||
delta = models.SmallIntegerField()
|
||||
nickmask = models.CharField(max_length=200, default='', blank=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
|
|
@ -27,7 +27,7 @@ class Migration(migrations.Migration):
|
|||
('k2', models.CharField(max_length=128)),
|
||||
('v', models.CharField(max_length=128)),
|
||||
('count', models.IntegerField(default=0)),
|
||||
('context', models.ForeignKey(to='markov.MarkovContext')),
|
||||
('context', models.ForeignKey(to='markov.MarkovContext', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'permissions': set([('teach_line', 'Can teach lines'), ('import_log_file', 'Can import states from a log file')]),
|
||||
|
@ -40,7 +40,7 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('name', models.CharField(unique=True, max_length=64)),
|
||||
('chatter_chance', models.IntegerField(default=0)),
|
||||
('context', models.ForeignKey(to='markov.MarkovContext')),
|
||||
('context', models.ForeignKey(to='markov.MarkovContext', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class MarkovTarget(models.Model):
|
|||
"""Define IRC targets that relate to a context, and can occasionally be talked to."""
|
||||
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
context = models.ForeignKey(MarkovContext)
|
||||
context = models.ForeignKey(MarkovContext, on_delete=models.CASCADE)
|
||||
|
||||
chatter_chance = models.IntegerField(default=0)
|
||||
|
||||
|
@ -51,7 +51,7 @@ class MarkovState(models.Model):
|
|||
v = models.CharField(max_length=128)
|
||||
|
||||
count = models.IntegerField(default=0)
|
||||
context = models.ForeignKey(MarkovContext)
|
||||
context = models.ForeignKey(MarkovContext, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
index_together = [
|
||||
|
|
|
@ -29,7 +29,7 @@ class Migration(migrations.Migration):
|
|||
('joined', models.BooleanField(default=False)),
|
||||
('started', models.BooleanField(default=False)),
|
||||
('finished', models.BooleanField(default=False)),
|
||||
('race', models.ForeignKey(to='races.Race')),
|
||||
('race', models.ForeignKey(to='races.Race', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
|
@ -41,8 +41,8 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('update', models.TextField()),
|
||||
('event_time', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('race', models.ForeignKey(to='races.Race')),
|
||||
('racer', models.ForeignKey(to='races.Racer')),
|
||||
('race', models.ForeignKey(to='races.Race', on_delete=models.CASCADE)),
|
||||
('racer', models.ForeignKey(to='races.Racer', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['event_time'],
|
||||
|
|
|
@ -28,7 +28,7 @@ class Racer(models.Model):
|
|||
"""Track a racer in a race."""
|
||||
|
||||
nick = models.CharField(max_length=64)
|
||||
race = models.ForeignKey(Race)
|
||||
race = models.ForeignKey(Race, on_delete=models.CASCADE)
|
||||
|
||||
joined = models.BooleanField(default=False)
|
||||
started = models.BooleanField(default=False)
|
||||
|
@ -47,8 +47,8 @@ class RaceUpdate(models.Model):
|
|||
|
||||
"""Periodic updates for a racer."""
|
||||
|
||||
race = models.ForeignKey(Race)
|
||||
racer = models.ForeignKey(Racer)
|
||||
race = models.ForeignKey(Race, on_delete=models.CASCADE)
|
||||
racer = models.ForeignKey(Racer, on_delete=models.CASCADE)
|
||||
update = models.TextField()
|
||||
event_time = models.DateTimeField(default=timezone.now)
|
||||
|
||||
|
|
|
@ -2,64 +2,68 @@
|
|||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --output-file requirements-dev.txt requirements-dev.in
|
||||
# pip-compile --output-file=requirements-dev.txt requirements-dev.in
|
||||
#
|
||||
appdirs==1.4.0 # via setuptools
|
||||
astroid==1.4.9 # via pylint, pylint-celery, pylint-flask, pylint-plugin-utils, requirements-detector
|
||||
click==6.7 # via pip-tools
|
||||
astroid==2.2.5 # via pylint, pylint-celery, pylint-flask, requirements-detector
|
||||
certifi==2019.6.16 # via requests
|
||||
chardet==3.0.4 # via requests
|
||||
click==7.0 # via pip-tools
|
||||
django-adminplus==0.5
|
||||
django-bootstrap3==8.1.0
|
||||
django-extensions==1.7.6
|
||||
django-registration-redux==1.4
|
||||
django==1.10.5
|
||||
djangorestframework==3.5.3
|
||||
django-bootstrap3==11.0.0
|
||||
django-extensions==2.1.9
|
||||
django-registration-redux==2.6
|
||||
django==2.2.2
|
||||
djangorestframework==3.9.4
|
||||
dodgy==0.1.9 # via prospector
|
||||
first==2.0.1 # via pip-tools
|
||||
future==0.16.0 # via parsedatetime
|
||||
inflect==0.2.5 # via jaraco.itertools
|
||||
irc==15.0.6
|
||||
isort==4.2.5 # via pylint
|
||||
jaraco.classes==1.4 # via jaraco.collections
|
||||
jaraco.collections==1.5 # via irc, jaraco.text
|
||||
jaraco.functools==1.15.1 # via irc, jaraco.text
|
||||
jaraco.itertools==2.0 # via irc
|
||||
jaraco.logging==1.5 # via irc
|
||||
jaraco.stream==1.1.1 # via irc
|
||||
jaraco.text==1.9 # via irc, jaraco.collections
|
||||
lazy-object-proxy==1.2.2 # via astroid
|
||||
logilab-common==1.3.0
|
||||
future==0.17.1 # via parsedatetime
|
||||
idna==2.8 # via requests
|
||||
importlib-metadata==0.18 # via irc
|
||||
inflect==2.1.0 # via jaraco.itertools
|
||||
irc==17.1
|
||||
isort==4.3.20 # via pylint
|
||||
jaraco.classes==2.0 # via jaraco.collections
|
||||
jaraco.collections==2.0 # via irc
|
||||
jaraco.functools==2.0 # via irc, jaraco.text, tempora
|
||||
jaraco.itertools==4.4.2 # via irc
|
||||
jaraco.logging==2.0 # via irc
|
||||
jaraco.stream==2.0 # via irc
|
||||
jaraco.text==3.0 # via irc, jaraco.collections
|
||||
lazy-object-proxy==1.4.1 # via astroid
|
||||
logilab-common==1.4.2
|
||||
mccabe==0.6.1 # via prospector, pylint
|
||||
more-itertools==2.5.0 # via irc, jaraco.functools, jaraco.itertools
|
||||
oauthlib==2.0.1 # via requests-oauthlib
|
||||
packaging==16.8 # via setuptools
|
||||
parsedatetime==2.2
|
||||
more-itertools==7.0.0 # via irc, jaraco.functools, jaraco.itertools
|
||||
oauthlib==3.0.1 # via requests-oauthlib
|
||||
parsedatetime==2.4
|
||||
pep8-naming==0.4.1 # via prospector
|
||||
pip-tools==1.8.0
|
||||
ply==3.10
|
||||
prospector==0.12.4
|
||||
pycodestyle==2.0.0 # via prospector
|
||||
pydocstyle==1.0.0 # via prospector
|
||||
pyflakes==1.5.0 # via prospector
|
||||
pip-tools==3.8.0
|
||||
ply==3.11
|
||||
prospector==1.1.6.4
|
||||
pycodestyle==2.4.0 # via prospector
|
||||
pydocstyle==3.0.0 # via prospector
|
||||
pyflakes==1.6.0 # via prospector
|
||||
pylint-celery==0.3 # via prospector
|
||||
pylint-common==0.2.2 # via prospector
|
||||
pylint-django==0.7.2 # via prospector
|
||||
pylint-flask==0.5 # via prospector
|
||||
pylint-plugin-utils==0.2.4 # via prospector, pylint-celery, pylint-django, pylint-flask
|
||||
pylint==1.6.5 # via prospector, pylint-celery, pylint-common, pylint-django, pylint-flask, pylint-plugin-utils
|
||||
pyparsing==2.1.10 # via packaging
|
||||
python-dateutil==2.6.0
|
||||
python-gitlab==0.18
|
||||
python-mpd2==0.5.5
|
||||
pytz==2016.10
|
||||
pyyaml==3.12 # via prospector
|
||||
requests-oauthlib==0.7.0 # via twython
|
||||
requests==2.13.0 # via python-gitlab, requests-oauthlib, twython
|
||||
requirements-detector==0.5.2 # via prospector
|
||||
pylint-django==2.0.9 # via prospector
|
||||
pylint-flask==0.6 # via prospector
|
||||
pylint-plugin-utils==0.5 # via prospector, pylint-celery, pylint-django, pylint-flask
|
||||
pylint==2.3.1 # via prospector, pylint-celery, pylint-django, pylint-flask, pylint-plugin-utils
|
||||
python-dateutil==2.8.0
|
||||
python-gitlab==1.9.0
|
||||
python-mpd2==1.0.0
|
||||
pytz==2019.1
|
||||
pyyaml==5.1.1 # via prospector
|
||||
requests-oauthlib==1.2.0 # via twython
|
||||
requests==2.22.0 # via python-gitlab, requests-oauthlib, twython
|
||||
requirements-detector==0.6 # via prospector
|
||||
setoptconf==0.2.0 # via prospector
|
||||
six==1.10.0 # via astroid, django-extensions, irc, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, logilab-common, more-itertools, packaging, pip-tools, pylint, python-dateutil, python-gitlab, setuptools, tempora
|
||||
tempora==1.6.1 # via irc, jaraco.logging
|
||||
twython==3.4.0
|
||||
wrapt==1.10.8 # via astroid
|
||||
six==1.12.0 # via astroid, django-extensions, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, logilab-common, pip-tools, pydocstyle, python-dateutil, python-gitlab, tempora
|
||||
snowballstemmer==1.2.1 # via pydocstyle
|
||||
sqlparse==0.3.0 # via django
|
||||
tempora==1.14.1 # via irc, jaraco.logging
|
||||
twython==3.7.0
|
||||
typed-ast==1.4.0 # via astroid
|
||||
urllib3==1.25.3 # via requests
|
||||
wrapt==1.11.2 # via astroid
|
||||
zipp==0.5.1 # via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# setuptools # via logilab-common
|
||||
# setuptools==41.0.1 # via logilab-common
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
-r requirements.in
|
||||
|
||||
psycopg2
|
|
@ -1,36 +0,0 @@
|
|||
#
|
||||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --output-file requirements-server.txt requirements-server.in
|
||||
#
|
||||
django-adminplus==0.5
|
||||
django-bootstrap3==8.1.0
|
||||
django-extensions==1.7.6
|
||||
django-registration-redux==1.4
|
||||
django==1.10.5
|
||||
djangorestframework==3.5.3
|
||||
future==0.16.0 # via parsedatetime
|
||||
inflect==0.2.5 # via jaraco.itertools
|
||||
irc==15.0.6
|
||||
jaraco.classes==1.4 # via jaraco.collections
|
||||
jaraco.collections==1.5 # via irc, jaraco.text
|
||||
jaraco.functools==1.15.1 # via irc, jaraco.text
|
||||
jaraco.itertools==2.0 # via irc
|
||||
jaraco.logging==1.5 # via irc
|
||||
jaraco.stream==1.1.1 # via irc
|
||||
jaraco.text==1.9 # via irc, jaraco.collections
|
||||
more-itertools==2.5.0 # via irc, jaraco.functools, jaraco.itertools
|
||||
oauthlib==2.0.1 # via requests-oauthlib
|
||||
parsedatetime==2.2
|
||||
ply==3.10
|
||||
psycopg2==2.6.2
|
||||
python-dateutil==2.6.0
|
||||
python-gitlab==0.18
|
||||
python-mpd2==0.5.5
|
||||
pytz==2016.10
|
||||
requests-oauthlib==0.7.0 # via twython
|
||||
requests==2.13.0 # via python-gitlab, requests-oauthlib, twython
|
||||
six==1.10.0 # via django-extensions, irc, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, more-itertools, python-dateutil, python-gitlab, tempora
|
||||
tempora==1.6.1 # via irc, jaraco.logging
|
||||
twython==3.4.0
|
|
@ -2,34 +2,41 @@
|
|||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --output-file requirements.txt requirements.in
|
||||
# pip-compile --output-file=requirements.txt requirements.in
|
||||
#
|
||||
certifi==2019.6.16 # via requests
|
||||
chardet==3.0.4 # via requests
|
||||
django-adminplus==0.5
|
||||
django-bootstrap3==8.1.0
|
||||
django-extensions==1.7.6
|
||||
django-registration-redux==1.4
|
||||
django==1.10.5
|
||||
djangorestframework==3.5.3
|
||||
future==0.16.0 # via parsedatetime
|
||||
inflect==0.2.5 # via jaraco.itertools
|
||||
irc==15.0.6
|
||||
jaraco.classes==1.4 # via jaraco.collections
|
||||
jaraco.collections==1.5 # via irc, jaraco.text
|
||||
jaraco.functools==1.15.1 # via irc, jaraco.text
|
||||
jaraco.itertools==2.0 # via irc
|
||||
jaraco.logging==1.5 # via irc
|
||||
jaraco.stream==1.1.1 # via irc
|
||||
jaraco.text==1.9 # via irc, jaraco.collections
|
||||
more-itertools==2.5.0 # via irc, jaraco.functools, jaraco.itertools
|
||||
oauthlib==2.0.1 # via requests-oauthlib
|
||||
parsedatetime==2.2
|
||||
ply==3.10
|
||||
python-dateutil==2.6.0
|
||||
python-gitlab==0.18
|
||||
python-mpd2==0.5.5
|
||||
pytz==2016.10
|
||||
requests-oauthlib==0.7.0 # via twython
|
||||
requests==2.13.0 # via python-gitlab, requests-oauthlib, twython
|
||||
six==1.10.0 # via django-extensions, irc, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, more-itertools, python-dateutil, python-gitlab, tempora
|
||||
tempora==1.6.1 # via irc, jaraco.logging
|
||||
twython==3.4.0
|
||||
django-bootstrap3==11.0.0
|
||||
django-extensions==2.1.9
|
||||
django-registration-redux==2.6
|
||||
django==2.2.2
|
||||
djangorestframework==3.9.4
|
||||
future==0.17.1 # via parsedatetime
|
||||
idna==2.8 # via requests
|
||||
importlib-metadata==0.18 # via irc
|
||||
inflect==2.1.0 # via jaraco.itertools
|
||||
irc==17.1
|
||||
jaraco.classes==2.0 # via jaraco.collections
|
||||
jaraco.collections==2.0 # via irc
|
||||
jaraco.functools==2.0 # via irc, jaraco.text, tempora
|
||||
jaraco.itertools==4.4.2 # via irc
|
||||
jaraco.logging==2.0 # via irc
|
||||
jaraco.stream==2.0 # via irc
|
||||
jaraco.text==3.0 # via irc, jaraco.collections
|
||||
more-itertools==7.0.0 # via irc, jaraco.functools, jaraco.itertools
|
||||
oauthlib==3.0.1 # via requests-oauthlib
|
||||
parsedatetime==2.4
|
||||
ply==3.11
|
||||
python-dateutil==2.8.0
|
||||
python-gitlab==1.9.0
|
||||
python-mpd2==1.0.0
|
||||
pytz==2019.1
|
||||
requests-oauthlib==1.2.0 # via twython
|
||||
requests==2.22.0 # via python-gitlab, requests-oauthlib, twython
|
||||
six==1.12.0 # via django-extensions, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, python-dateutil, python-gitlab, tempora
|
||||
sqlparse==0.3.0 # via django
|
||||
tempora==1.14.1 # via irc, jaraco.logging
|
||||
twython==3.7.0
|
||||
urllib3==1.25.3 # via requests
|
||||
zipp==0.5.1 # via importlib-metadata
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
"""Use dr.botzo's Dispatch to send mpd notifications."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
import getpass
|
||||
import logging
|
||||
|
|
|
@ -29,7 +29,7 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('line', models.TextField(default='')),
|
||||
('time', models.DateTimeField(auto_now_add=True)),
|
||||
('game', models.ForeignKey(to='storycraft.StorycraftGame')),
|
||||
('game', models.ForeignKey(to='storycraft.StorycraftGame', on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -38,12 +38,12 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('nick', models.CharField(max_length=64)),
|
||||
('nickmask', models.CharField(max_length=200)),
|
||||
('game', models.ForeignKey(to='storycraft.StorycraftGame')),
|
||||
('game', models.ForeignKey(to='storycraft.StorycraftGame', on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='storycraftline',
|
||||
name='player',
|
||||
field=models.ForeignKey(to='storycraft.StorycraftPlayer'),
|
||||
field=models.ForeignKey(to='storycraft.StorycraftPlayer', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -13,16 +13,16 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='storycraftline',
|
||||
name='game',
|
||||
field=models.ForeignKey(related_name='lines', to='storycraft.StorycraftGame'),
|
||||
field=models.ForeignKey(related_name='lines', to='storycraft.StorycraftGame', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='storycraftline',
|
||||
name='player',
|
||||
field=models.ForeignKey(related_name='lines', to='storycraft.StorycraftPlayer'),
|
||||
field=models.ForeignKey(related_name='lines', to='storycraft.StorycraftPlayer', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='storycraftplayer',
|
||||
name='game',
|
||||
field=models.ForeignKey(related_name='players', to='storycraft.StorycraftGame'),
|
||||
field=models.ForeignKey(related_name='players', to='storycraft.StorycraftGame', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -89,7 +89,7 @@ class StorycraftPlayer(models.Model):
|
|||
|
||||
"""Contain entire games of storycraft."""
|
||||
|
||||
game = models.ForeignKey('StorycraftGame', related_name='players')
|
||||
game = models.ForeignKey('StorycraftGame', related_name='players', on_delete=models.CASCADE)
|
||||
nick = models.CharField(max_length=64)
|
||||
nickmask = models.CharField(max_length=200)
|
||||
|
||||
|
@ -103,8 +103,8 @@ class StorycraftLine(models.Model):
|
|||
|
||||
"""Handle requests to dispatchers and do something with them."""
|
||||
|
||||
game = models.ForeignKey('StorycraftGame', related_name='lines')
|
||||
player = models.ForeignKey('StorycraftPlayer', related_name='lines')
|
||||
game = models.ForeignKey('StorycraftGame', related_name='lines', on_delete=models.CASCADE)
|
||||
player = models.ForeignKey('StorycraftPlayer', related_name='lines', on_delete=models.CASCADE)
|
||||
line = models.TextField(default="")
|
||||
time = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -19,6 +17,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='twitterclient',
|
||||
name='mentions_output_channel',
|
||||
field=models.ForeignKey(blank=True, related_name='mentions_twitter_client', null=True, to='ircbot.IrcChannel', default=None),
|
||||
field=models.ForeignKey(blank=True, related_name='mentions_twitter_client', null=True, to='ircbot.IrcChannel', default=None, on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class TwitterClient(models.Model):
|
|||
oauth_token_secret = models.CharField(max_length=256, default='', blank=True)
|
||||
|
||||
mentions_output_channel = models.ForeignKey(IrcChannel, related_name='mentions_twitter_client', default=None,
|
||||
null=True, blank=True)
|
||||
null=True, blank=True, on_delete=models.CASCADE)
|
||||
mentions_since_id = models.PositiveIntegerField(default=1, blank=True)
|
||||
|
||||
class Meta:
|
||||
|
|
Loading…
Reference in New Issue