Compare commits

...

3 Commits

Author SHA1 Message Date
247fc6729a increase dice size 2018-09-24 09:59:11 -04:00
fb7ffc4d78 basic support for new pages 2018-09-24 08:22:01 -04:00
5eb19761bd stop passing quest_id in socket events 2018-09-24 08:02:53 -04:00
8 changed files with 117 additions and 66 deletions

View File

@ -24,9 +24,9 @@ def message(socket, data):
"""
# TODO: validation
message = data.get('message')
quest_id = data.get('quest_id')
# cleaning
message = message[:512]
message = message.strip()
if not message:
return
@ -62,9 +62,9 @@ def message(socket, data):
try:
groups = [0 if d is None else int(d) for d in reg.groups()]
dice_num, dice_sides, dice_mod = groups
assert 0 < dice_num < 100
assert 0 < dice_sides < 100
assert -1000 < dice_mod < 1000
assert 1 <= dice_num <= 256
assert 1 <= dice_sides <= 256
assert -65536 <= dice_mod <= 65536
except (ValueError, AssertionError):
return
dice_results = [random.randint(1, dice_sides) for _ in range(dice_num)]
@ -82,7 +82,7 @@ def message(socket, data):
user = socket.scope['user']
m = Message(
quest=Quest.objects.get(id=quest_id),
quest=Quest.objects.get(id=socket.quest_id),
message=message)
if user.username:
m.user = user
@ -98,7 +98,10 @@ def message(socket, data):
# append rolls to dicecall
if any(map(message.startswith, ["/dice", "/roll"])):
try:
dc = DiceCall.objects.get(post__quest__id=quest_id, open=True)
dc = DiceCall.objects.get(
post__quest__id=socket.quest_id,
open=True
)
except DiceCall.DoesNotExist:
return
dice_roll = f"{dice_num}d{dice_sides}"
@ -141,7 +144,6 @@ def text_post(socket, data):
Called when the QM creates a new text post.
"""
# TODO: security
quest_id = data.get('quest_id')
post_text = data.get('text')
page_num = data.get('page_num')
@ -152,7 +154,7 @@ def text_post(socket, data):
# handle image
p = Post(
quest=Quest.objects.get(id=quest_id),
quest=Quest.objects.get(id=socket.quest_id),
page_num=page_num,
post_type='text',
post_text=post_text)
@ -170,7 +172,6 @@ def dice_post(socket, data):
"""
Called when the QM makes a new dice post.
"""
quest_id = data.get('quest_id')
page_num = data.get('page_num')
form = DiceCallForm(data)
if not form.is_valid():
@ -178,7 +179,7 @@ def dice_post(socket, data):
form = form.cleaned_data
posts = Post.objects.filter(
quest__id=quest_id, post_type='dice', dicecall__open=True)
quest__id=socket.quest_id, post_type='dice', dicecall__open=True)
for post in posts:
post.dicecall.open = False
post.dicecall.save()
@ -196,7 +197,7 @@ def dice_post(socket, data):
post_text += " vs DC" + str(form['diceChal'])
p = Post(
quest=Quest.objects.get(id=quest_id),
quest=Quest.objects.get(id=socket.quest_id),
page_num=page_num,
post_type='dice',
post_text=post_text
@ -224,7 +225,6 @@ def poll_post(socket, data):
"""
Called when the QM makes a new dice post.
"""
quest_id = data.get('quest_id')
page_num = data.get('page_num')
form = PollForm(data)
if not form.is_valid():
@ -232,7 +232,7 @@ def poll_post(socket, data):
form = form.cleaned_data
p = Post(
quest=Quest.objects.get(id=quest_id),
quest=Quest.objects.get(id=socket.quest_id),
page_num=page_num,
post_type='poll',
post_text="Poll"
@ -292,7 +292,6 @@ def close_post(socket, data):
Called when the QM closes an open post.
"""
post_id = data.get('post_id')
quest_id = data.get('quest_id')
p = Post.objects.get(id=post_id)
if data.get('post_type') == 'dice':
p.dicecall.open = False
@ -312,11 +311,10 @@ def open_post(socket, data):
"""
# TODO: only posts on last page can be opened
post_id = data.get('post_id')
quest_id = data.get('quest_id')
p = Post.objects.get(id=post_id)
if data.get('post_type') == 'dice':
posts = Post.objects.filter(
quest__id=quest_id, post_type='dice', dicecall__open=True)
quest__id=socket.quest_id, post_type='dice', dicecall__open=True)
for post in posts:
post.dicecall.open = False
post.dicecall.save()
@ -337,7 +335,6 @@ def vote(socket, data):
"""
Called when a player votes in a poll.
"""
quest_id = data.get('quest_id')
post_id = data.get('post_id')
option_id = data.get('option_id')
polarity = data.get('polarity')
@ -409,6 +406,21 @@ def write_in(socket, data):
socket.send('update_post', data)
def new_page(socket, data):
"""
Called when the QM creates a new page.
"""
title = data.get('page_title')
quest = Quest.objects.get(id=socket.quest_id)
p = PageTitle(
quest=quest,
page_num=PageTitle.objects.filter(quest=quest).count() + 1,
title=title,
)
p.save()
events = {}
for obj in dir():
if type(locals()[obj]) == types.FunctionType:

View File

@ -8,14 +8,14 @@ class DiceCallForm(forms.Form):
"""
The form for the QM making dice calls.
"""
diceNum = forms.IntegerField(min_value=1, max_value=99)
diceSides = forms.IntegerField(min_value=1, max_value=99)
diceNum = forms.IntegerField(min_value=1, max_value=256)
diceSides = forms.IntegerField(min_value=1, max_value=65536)
diceMod = forms.IntegerField(
min_value=-999, max_value=999, required=False)
min_value=-65536, max_value=65536, required=False)
diceChal = forms.IntegerField(
min_value=1, max_value=999, required=False)
min_value=1, max_value=65536, required=False)
diceRollsTaken = forms.IntegerField(
min_value=1, max_value=99, required=False)
min_value=1, max_value=256, required=False)
diceStrict = forms.BooleanField(required=False)
@ -37,7 +37,7 @@ class PollForm(forms.Form):
continue
self.fields[key] = forms.CharField(max_length=200)
class EditQuest(forms.Form):
class EditQuestForm(forms.Form):
"""
Form for the /edit_quest page.
"""

View File

@ -46,13 +46,13 @@
{{ localtime(post.timestamp).strftime('%Y-%m-%d %H:%M') }}
{% if request.user == quest.owner %}
{% if post.post_type == "text" %}
<br /><a href="javascript:void(0);" id="editPost-{{ post.id }}" onclick="edit_post({{ post.id }})">Edit</a>
<br><a href="javascript:void(0);" id="editPost-{{ post.id }}" onclick="edit_post({{ post.id }})">Edit</a>
<a href="javascript:void(0);" id="savePost-{{ post.id }}" onclick="save_post('{{ post.id }}')" style="display:none;">Save</a>
{% elif post.post_type == "dice" %}
<br /><a href="javascript:void(0);" id="closePost-{{ post.id }}" onclick="close_post_send({{ post.id }})"{% if not post.dicecall.open %} style="display:none;"{% endif %}>Close</a>
<br><a href="javascript:void(0);" id="closePost-{{ post.id }}" onclick="close_post_send({{ post.id }})"{% if not post.dicecall.open %} style="display:none;"{% endif %}>Close</a>
<a href="javascript:void(0);" id="openPost-{{ post.id }}" onclick="open_post_send({{ post.id }})"{% if post.dicecall.open %} style="display:none;"{% endif %}>Open</a>
{% elif post.post_type == "poll" %}
<br /><a href="javascript:void(0);" id="closePost-{{ post.id }}" onclick="close_post_send({{ post.id }})"{% if not post.poll.open %} style="display:none;"{% endif %}>Close</a>
<br><a href="javascript:void(0);" id="closePost-{{ post.id }}" onclick="close_post_send({{ post.id }})"{% if not post.poll.open %} style="display:none;"{% endif %}>Close</a>
<a href="javascript:void(0);" id="openPost-{{ post.id }}" onclick="open_post_send({{ post.id }})"{% if post.poll.open %} style="display:none;"{% endif %}>Open</a>
{% endif %}
{% endif %}
@ -75,7 +75,7 @@
{% for option in poll_options.filter(poll=post.poll).order_by("id") %}
<tr id="optionRow-{{ option.id }}">
<td class="pollCheckBox">
<input type="checkbox" {% if poll_votes.filter(option=option, ip_address=ip_address) %}checked="true"{% endif %} id="pollInput-{{ option.id }}" onchange="vote({{ post.id }}, {{ option.id }})"{% if not post.poll.open %} disabled{% endif %}/>
<input type="checkbox" {% if poll_votes.filter(option=option, ip_address=ip_address) %}checked="true"{% endif %} id="pollInput-{{ option.id }}" onchange="vote({{ post.id }}, {{ option.id }})"{% if not post.poll.open %} disabled{% endif %}>
<label for="pollInput-{{ option.id }}"></label>
</td>
<td class="option_text">{{ option.text }}</td>
@ -85,8 +85,8 @@
</table>
{% if post.poll.open and post.poll.allow_writein %}
<div id="writeinContainer-{{ post.id }}">
Write-in: <input type="text" id="writeinInput-{{ post.id }}" placeholder="Custom choice..." maxlength="200" /><br />
<input type="submit" id="writeinSubmit-{{ post.id }}" value="Submit" onclick="submitWritein({{ post.id }});"/>
Write-in: <input type="text" id="writeinInput-{{ post.id }}" placeholder="Custom choice..." maxlength="200"><br>
<input type="submit" id="writeinSubmit-{{ post.id }}" value="Submit" onclick="submitWritein({{ post.id }});">
</div>
{% endif %}
{% endif %}
@ -101,27 +101,28 @@
<li><a class="QMPostTab active" href="javascript:void(0);" onclick="openPostTab(event, 'QMPostText')">Text</a></li>
<li><a class="QMPostTab" href="javascript:void(0);" onclick="openPostTab(event, 'QMPostDice')">Dice</a></li>
<li><a class="QMPostTab" href="javascript:void(0);" onclick="openPostTab(event, 'QMPostPoll')">Poll</a></li>
<li><a class="QMPostTab" href="javascript:void(0);" onclick="openPostTab(event, 'QMPage')">Page</a></li>
</ul>
</div>
<div id="QMPostText" class="QMPostTabContent" style="display:initial;">
<textarea id="postTextArea"></textarea><br />
<input type="submit" name="newPost" value="Post" onclick="makePost();"/>
<textarea id="postTextArea"></textarea><br>
<input type="submit" name="newPost" value="Post" onclick="makePost();">
</div>
<div id="QMPostDice" class="QMPostTabContent" style="display:none;">
Dice for the dice god.<br />
Dice for the dice god.<br>
<form id="QMDicePostForm" action="javascript:void(0);" onsubmit="form_post('QMDicePostForm', 'dice_post');">
Dice: <input type="number" name="diceNum" min="1" max="99" required/>
d <input type="number" name="diceSides" min="1" max="99" required/>
±<input type="number" name="diceMod" min="-999" max="999"/>
<input type="checkbox" name="diceStrict"/>
<span class="tooltip" title="Only take matching rolls.">Strict</span><br />
<input type="checkbox" onclick="document.getElementById('diceChal').disabled=!this.checked;"/>
Dice: <input type="number" name="diceNum" min="1" max="256" required>
d <input type="number" name="diceSides" min="1" max="65536" required>
±<input type="number" name="diceMod" min="-65536" max="65536">
<input type="checkbox" name="diceStrict">
<span class="tooltip" title="Only take matching rolls.">Strict</span><br>
<input type="checkbox" onclick="document.getElementById('diceChal').disabled=!this.checked;">
<span class="tooltip" title="Dice challenge">DC:</span>
<input type="number" name="diceChal" id="diceChal" min="1" max="999" disabled/><br />
<input type="checkbox" onclick="document.getElementById('diceRollsTaken').disabled=!this.checked;"/>
<input type="number" name="diceChal" id="diceChal" min="1" max="65536" disabled><br>
<input type="checkbox" onclick="document.getElementById('diceRollsTaken').disabled=!this.checked;">
<span class="tooltip" title="Automatically close the dice call after this many rolls have been made.">Rolls Taken:</span>
<input type="number" name="diceRollsTaken" id="diceRollsTaken" min="1" max="99" disabled/><br />
<input type="submit" name="submit" value="Roll 'em"/>
<input type="number" name="diceRollsTaken" id="diceRollsTaken" min="1" max="256" disabled><br>
<input type="submit" name="submit" value="Roll 'em">
</form>
</div>
<div id="QMPostPoll" class="QMPostTabContent" style="display:none;">
@ -130,13 +131,19 @@
<a href="javascript:void(0);" id="pollInsertNewOption" onclick="insertPollOption()">[+]</a>
<a href="javascript:void(0);" onclick="removePollOption()">[-]</a>
<div id="pollOptions">
<div><input type="text" name="pollOption-1" class="pollOption" placeholder="Option 1" maxlength="200" /></div>
<div><input type="text" name="pollOption-2" class="pollOption" placeholder="Option 2" maxlength="200" /></div>
<div><input type="text" name="pollOption-1" class="pollOption" placeholder="Option 1" maxlength="200"></div>
<div><input type="text" name="pollOption-2" class="pollOption" placeholder="Option 2" maxlength="200"></div>
</div>
<hr>
<input type="checkbox" name="multi_choice" />Allow multiple choices<br />
<input type="checkbox" name="allow_writein" />Allow user-created options<br />
<input type="submit" name="submit" value="Submit" />
<input type="checkbox" name="multi_choice">Allow multiple choices<br>
<input type="checkbox" name="allow_writein">Allow user-created options<br>
<input type="submit" name="submit" value="Submit">
</form>
</div>
<div id="QMPage" class="QMPostTabContent" style="display:none;">
<form id="QMPageForm" action="javascript:void(0);" onsubmit="form_post('QMPageForm', 'new_page');">
New Page: <input type="text" name="page_title" maxlength="200" value="Page {{ pages.count() + 1 }}"><br>
<input type="submit" name="submit" value="Submit">
</form>
</div>
</div>
@ -159,7 +166,7 @@
{% endfor %}
{% endautoescape %}
</div>
<div id="messageTextDiv"><textarea id="messageTextArea"></textarea></div>
<div id="messageTextDiv"><textarea id="messageTextArea" maxlength="512"></textarea></div>
</div>
<div id="preview" style="display:none;"></div>
{% endblock %}

View File

@ -0,0 +1,34 @@
# Generated by Django 2.1.1 on 2018-09-24 13:31
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('quest', '0003_quest_anon_name'),
]
operations = [
migrations.AlterField(
model_name='dicecall',
name='dice_challenge',
field=models.IntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65536)]),
),
migrations.AlterField(
model_name='dicecall',
name='dice_roll',
field=models.CharField(max_length=16),
),
migrations.AlterField(
model_name='dicecall',
name='rolls_taken',
field=models.IntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(256)]),
),
migrations.AlterField(
model_name='diceroll',
name='roll',
field=models.CharField(max_length=16),
),
]

View File

@ -56,22 +56,22 @@ class DiceCall(models.Model):
on_delete=models.CASCADE,
primary_key=True,
)
dice_roll = models.CharField(max_length=9)
dice_roll = models.CharField(max_length=16)
strict = models.BooleanField()
dice_challenge = models.IntegerField(
null=True,
blank=True,
validators=[
MaxValueValidator(999),
MinValueValidator(1)
MinValueValidator(1),
MaxValueValidator(65536),
]
)
rolls_taken = models.IntegerField(
null=True,
blank=True,
validators=[
MaxValueValidator(99),
MinValueValidator(1)
MinValueValidator(1),
MaxValueValidator(256),
]
)
open = models.BooleanField()
@ -87,7 +87,7 @@ class DiceRoll(models.Model):
on_delete=models.CASCADE,
primary_key=True,
)
roll = models.CharField(max_length=9)
roll = models.CharField(max_length=16)
results = models.TextField()
total = models.IntegerField()

View File

@ -41,8 +41,7 @@ function load() {
let text = mtarea.value.trim();
mtarea.value = '';
if (text === '') { return; }
document.getElementById('chatWindow').scrollTop = document.getElementById('chatWindow').scrollHeight;
socket.send('message', {message: text, quest_id: quest_id});
socket.send('message', {message: text});
}
});
}
@ -57,7 +56,7 @@ socket.events['message'] = function(data) {
let mbox = document.getElementById('chatWindow');
mbox.innerHTML = mbox.innerHTML + msg_str;
if ((mbox.scrollTop + mbox.offsetHeight) >= (mbox.scrollHeight - mbox.clientHeight / 2)) {
if ((mbox.scrollTop + mbox.offsetHeight) >= (mbox.scrollHeight - mbox.clientHeight)) {
mbox.scrollTop = mbox.scrollHeight;
}
}
@ -82,7 +81,7 @@ socket.events['new_post'] = function(data) {
post_str += '<table class="poll" id="poll-' + data.post_id + '">';
for (let i = 0; i < data.options.length; i++) {
post_str += '<tr id="optionRow-' + data.options[i] + '">';
post_str += '<td class="pollCheckBox"><input type="checkbox" id="pollInput-' + data.options[i][0] + '" onchange="vote(' + data.post_id + ',' + data.options[i][0] + ')"/>';
post_str += '<td class="pollCheckBox"><input type="checkbox" id="pollInput-' + data.options[i][0] + '" onchange="vote(' + data.post_id + ',' + data.options[i][0] + ')">';
post_str += '<label for="pollInput-' + data.options[i][0] + '"></label></td>';
post_str += '<td class="option_text">' + data.options[i][1] + '</td>';
post_str += '<td class="optionVotes">0</td></tr>';
@ -159,7 +158,7 @@ socket.events['set_option_box'] = function(data) {
/* Websocket send */
function vote(post_id, option_id) {
let polarity = document.getElementById('pollInput-' + option_id).checked;
socket.send('vote', {post_id: post_id, option_id: option_id, polarity: polarity, quest_id: quest_id});
socket.send('vote', {post_id: post_id, option_id: option_id, polarity: polarity});
}
function submitWritein(post_id) {
let writeinInput = document.getElementById('writeinInput-' + post_id);

View File

@ -51,7 +51,7 @@ function makePost() {
let text = qparea.value.trim();
qparea.value = '';
if (text === '') { return; }
socket.send('text_post', {text: text, page_num: page_num, quest_id: quest_id});
socket.send('text_post', {text: text, page_num: page_num});
}
function save_post(post_id) {
let post = document.getElementById('questPostData-' + post_id);
@ -68,13 +68,12 @@ function form_post(form_id, event) {
formData.forEach(function(value, key) {
obj[key] = value;
});
obj.quest_id = quest_id;
obj.page_num = page_num;
socket.send(event, obj);
document.getElementById(form_id).reset();
}
function close_post_send(post_id) {
data = {post_id: post_id, quest_id: quest_id}
data = {post_id: post_id}
let post = document.getElementById('questPostData-' + post_id);
if (post.parentElement.classList.contains('dicePost')) {
data.post_type = 'dice';
@ -84,7 +83,7 @@ function close_post_send(post_id) {
socket.send('close_post', data);
}
function open_post_send(post_id) {
data = {post_id: post_id, quest_id: quest_id}
data = {post_id: post_id}
let post = document.getElementById('questPostData-' + post_id);
if (post.parentElement.classList.contains('dicePost')) {
data.post_type = 'dice';

View File

@ -6,7 +6,7 @@ from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Quest, DiceRoll, PollOption, PollVote, PageTitle
from .forms import EditQuest
from .forms import EditQuestForm
def index(request):
"""
@ -22,7 +22,7 @@ def quest(request, quest_id, page_num=1):
quest = Quest.objects.get(id=quest_id)
pages = PageTitle.objects.filter(quest=quest).order_by('page_num')
messages = quest.message_set.all()
posts = quest.post_set.all()
posts = quest.post_set.filter(page_num=page_num)
dice_rolls = DiceRoll.objects.filter(dicecall__post__quest=quest)
poll_options = PollOption.objects.filter(poll__post__quest=quest)
poll_votes = PollVote.objects.filter(option__poll__post__quest=quest)
@ -39,7 +39,7 @@ def edit_quest(request, quest_id, page_num=1):
if quest.owner != request.user:
return redirect('quest:quest', quest_id=quest_id, page_num=page_num)
if request.method == 'POST':
form = EditQuest(request.POST)
form = EditQuestForm(request.POST)
if form.is_valid():
quest.anon_name = form.cleaned_data['anon_name']
quest.save()