poll post makes poll posts

This commit is contained in:
iou1name 2018-07-11 18:25:10 -04:00
parent b35883146d
commit 0d2f7d0edc
6 changed files with 234 additions and 119 deletions

View File

@ -56,6 +56,7 @@ app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
app.config['SESSION_TYPE'] = 'filesystem' app.config['SESSION_TYPE'] = 'filesystem'
app.jinja_env.trim_blocks = True app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True app.jinja_env.lstrip_blocks = True
app.jinja_env.undefined = "StrictUndefined"
Session(app) Session(app)
socketio.init_app(app) socketio.init_app(app)
paranoid = Paranoid(app) paranoid = Paranoid(app)

View File

@ -11,7 +11,7 @@ CREATE TABLE `quest_meta` (
`canon_title` VARCHAR(300) DEFAULT NULL, `canon_title` VARCHAR(300) DEFAULT NULL,
`ident_title` VARCHAR(300) DEFAULT NULL, `ident_title` VARCHAR(300) DEFAULT NULL,
`owner_id` SMALLINT UNSIGNED DEFAULT NULL, `owner_id` SMALLINT UNSIGNED DEFAULT NULL,
`dice_call` SMALLINT UNSIGNED DEFAULT NULL, `open_post_id` SMALLINT UNSIGNED DEFAULT NULL,
PRIMARY KEY (`quest_id`) PRIMARY KEY (`quest_id`)
) ENGINE=InnoDB CHARSET utf8mb4; ) ENGINE=InnoDB CHARSET utf8mb4;
@ -24,7 +24,7 @@ CREATE TABLE `quest_data` (
PRIMARY KEY (`post_id`) PRIMARY KEY (`post_id`)
) ENGINE=InnoDB CHARSET utf8mb4; ) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `quest_dice_calls` ( CREATE TABLE `dice_calls` (
`post_id` MEDIUMINT UNSIGNED NOT NULL, `post_id` MEDIUMINT UNSIGNED NOT NULL,
`dice_roll` TEXT NOT NULL, `dice_roll` TEXT NOT NULL,
`strict` BOOLEAN DEFAULT FALSE, `strict` BOOLEAN DEFAULT FALSE,
@ -33,16 +33,30 @@ CREATE TABLE `quest_dice_calls` (
PRIMARY KEY (`post_id`) PRIMARY KEY (`post_id`)
) ENGINE=InnoDB CHARSET utf8mb4; ) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `quest_rolls` ( CREATE TABLE `dice_rolls` (
`message_id` MEDIUMINT UNSIGNED NOT NULL, `message_id` MEDIUMINT UNSIGNED NOT NULL,
`quest_id` SMALLINT UNSIGNED NOT NULL, `quest_id` SMALLINT UNSIGNED NOT NULL,
`post_id` MEDIUMINT UNSIGNED NOT NULL, `post_id` MEDIUMINT UNSIGNED NOT NULL,
`roll_dice` TEXT NOT NULL, `roll_dice` TEXT NOT NULL,
`roll_results` TEXT NOT NULL, `roll_results` TEXT NOT NULL,
`roll_total` SMALLINT UNSIGNED NOT NULL `roll_total` SMALLINT UNSIGNED NOT NULL,
PRIMARY KEY (`message_id`) PRIMARY KEY (`message_id`)
) ENGINE=InnoDB CHARSET utf8mb4; ) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `polls` (
`post_id` MEDIUMINT UNSIGNED NOT NULL,
`multi_choice` BOOLEAN DEFAULT FALSE,
`allow_writein` BOOLEAN DEFAULT FALSE,
PRIMARY KEY (`post_id`)
) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `poll_options` (
`post_id` MEDIUMINT UNSIGNED NOT NULL,
`quest_id` SMALLINT UNSIGNED NOT NULL,
`option_text` VARCHAR(200) NOT NULL,
`ips_voted` TEXT DEFAULT NULL
) ENGINE=InnoDB CHARSET utf8mb4;
CREATE TABLE `chat_messages` ( CREATE TABLE `chat_messages` (
`message_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT, `message_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
`room_id` MEDIUMINT UNSIGNED NOT NULL, `room_id` MEDIUMINT UNSIGNED NOT NULL,

View File

@ -214,58 +214,98 @@ def update_quest_post(post_id, new_post):
(new_post, post_id)) (new_post, post_id))
def set_dice_call_open(post_id, quest_id, new_call=None): def set_post_open(post_id, quest_id):
"""Sets an open dice call for the given quest.""" """Sets an active post open for the given quest."""
_DB.execute( _DB.execute(
"UPDATE `quest_meta` SET `dice_call` = %s WHERE `quest_id` = %s", "UPDATE `quest_meta` SET `open_post_id` = %s WHERE `quest_id` = %s",
(post_id, quest_id)) (post_id, quest_id))
if new_call:
dice_roll, strict, dice_challence, rolls_taken = new_call
_DB.execute(
"INSERT INTO `quest_dice_calls`" \
+ "(`post_id`, `dice_roll`, `strict`, " \
+ "`dice_challenge`, `rolls_taken`)" \
+ "VALUES (%s, %s, %s, %s, %s)",
(post_id, dice_roll, strict, dice_challence, rolls_taken))
def set_post_closed(quest_id):
def set_dice_call_closed(quest_id):
"""Closes a quest's dice call.""" """Closes a quest's dice call."""
_DB.execute( _DB.execute(
"UPDATE `quest_meta` SET `dice_call` = NULL WHERE `quest_id` = %s", "UPDATE `quest_meta` SET `open_post_id` = NULL WHERE `quest_id` = %s",
(quest_id,)) (quest_id,))
def insert_dice_call(post_id, quest_id, new_call):
"""Inserts a new dice call."""
dice_roll, strict, dice_challence, rolls_taken = new_call
_DB.execute(
"INSERT INTO `dice_calls`" \
+ "(`post_id`, `dice_roll`, `strict`,`dice_challenge`,`rolls_taken`)" \
+ "VALUES (%s, %s, %s, %s, %s)",
(post_id, dice_roll, strict, dice_challence, rolls_taken))
def get_dice_call(post_id): def get_dice_call(post_id):
"""Retrives the currently open dice call, if there is one.""" """Retrives the currently open dice call, if there is one."""
data = _DB.execute( data = _DB.execute(
"SELECT * FROM `quest_dice_calls` WHERE `post_id` = %s", "SELECT * FROM `dice_calls` WHERE `post_id` = %s",
(post_id,)).fetchone() (post_id,)).fetchone()
return data return data
def insert_quest_roll(message_id, quest_id, post_id, roll_data): def insert_quest_roll(message_id, quest_id, post_id, roll_data):
"""Inserts a user roll into the `quest_rolls` table.""" """Inserts a user roll into the `dice_rolls` table."""
ins = (message_id, quest_id, post_id) + roll_data ins = (message_id, quest_id, post_id) + roll_data
_DB.execute( _DB.execute(
"INSERT INTO `quest_rolls`" \ "INSERT INTO `dice_rolls`" \
+ "(`message_id`, `quest_id`, `post_id`, " \ + "(`message_id`, `quest_id`, `post_id`, " \
+ "`roll_dice`, `roll_results`, `roll_total`)" \ + "`roll_dice`, `roll_results`, `roll_total`)" \
+ "VALUES (%s, %s, %s, %s, %s, %s)", + "VALUES (%s, %s, %s, %s, %s, %s)",
(ins)) (ins))
def get_quest_rolls(quest_id=None, post_id=None): def get_dice_rolls(quest_id=None, post_id=None):
"""Gets all rolls for the given quest.""" """Gets all rolls for the given quest."""
if quest_id: if quest_id:
sql = "SELECT * FROM `quest_rolls` WHERE `quest_id` = %s " sql = "SELECT * FROM `dice_rolls` WHERE `quest_id` = %s "
ins = quest_id ins = quest_id
elif post_id: elif post_id:
sql = "SELECT * FROM `quest_rolls` WHERE `post_id` = %s " sql = "SELECT * FROM `dice_rolls` WHERE `post_id` = %s "
ins = post_id ins = post_id
else: else:
return return
sql += "ORDER BY `message_id` ASC" sql += "ORDER BY `message_id` ASC"
data = _DB.execute(sql, (ins,)).fetchall() data = _DB.execute(sql, (ins,)).fetchall()
return data return data
def insert_poll(post_id, multi_choice, allow_writein):
"""Inserts a new poll post."""
_DB.execute(
"INSERT INTO `polls` " \
+ "(`post_id`, `multi_choice`, `allow_writein`) " \
+ "VALUES (%s, %s, %s)",
(post_id, multi_choice, allow_writein))
def get_poll(post_id):
"""Gets poll information."""
data = _DB.excute(
"SELECT * FROM `polls` WHERE `post_id` = %s", (post_id,))
return data
def insert_poll_option(post_id, quest_id, option_text):
"""Insert a new poll option. ips_voted will be NULL to start."""
_DB.execute(
"INSERT INTO `poll_options` " \
+ "(`post_id`, `quest_id`, `option_text`) VALUES (%s, %s, %s)",
(post_id, quest_id, option_text))
def get_poll_options(quest_id=None, post_id=None):
"""Gets all relevent poll options for a given quest or post."""
sql = "SELECT * FROM `poll_options` WHERE "
if quest_id:
sql += "`quest_id` = %s"
ins = (quest_id,)
elif post_id:
sql += "`post_id` = %s"
ins = (post_id,)
else:
return
data = _DB.execute(sql, ins)
return data

144
events.py
View File

@ -2,9 +2,11 @@
""" """
SocketIO events. SocketIO events.
""" """
# TODO: harden the fuck up
import re import re
import time import time
import random import random
import functools
import bleach import bleach
from flask import session from flask import session
@ -15,6 +17,28 @@ import database as db
socketio = SocketIO() socketio = SocketIO()
def qm_only(msg=""):
"""
A decorator function to protect certain endpoints so that only the
QM can access them.
"""
# TODO: better docstring, test this more thoroughly
def actual_decorator(func):
@functools.wraps(func)
def _nop(*args, **kwargs):
data = args[0]
room = data.get("room")
res = db.get_quest_meta(quest_id=room)
if not res:
return msg
if session.get("user_id") != res[3]:
return msg
return func(*args, **kwargs)
return _nop
return actual_decorator
@socketio.on('joined') @socketio.on('joined')
def joined(data): def joined(data):
""" """
@ -76,7 +100,7 @@ def message(data):
roll_data = (dice_roll, roll_results, roll_total) roll_data = (dice_roll, roll_results, roll_total)
db.insert_quest_roll(message_id, room, dice_call_id, roll_data) db.insert_quest_roll(message_id, room, dice_call_id, roll_data)
if len(db.get_quest_rolls(post_id=dice_call_id)) == dice_call[4]: if len(db.get_dice_rolls(post_id=dice_call_id)) == dice_call[4]:
db.set_dice_call_closed(room) db.set_dice_call_closed(room)
emit("close_dice_call", {"post_id": dice_call_id}, room=room) emit("close_dice_call", {"post_id": dice_call_id}, room=room)
@ -123,46 +147,38 @@ def handle_dice(data):
@socketio.on("new_post") @socketio.on("new_post")
@qm_only()
def new_post(data, internal=False): def new_post(data, internal=False):
""" """
Called when the QM makes a new post. Called when the QM makes a new post.
""" """
room = data["room"] room = data.get("room")
res = db.get_quest_meta(quest_id=room) post = data.get("post")
if not res:
return
if session.get("user_id") != res[3]:
return
post = data["post"]
post = bleach.clean(post.strip()) post = bleach.clean(post.strip())
post = post.replace("\n", "<br />") post = post.replace("\n", "<br />")
post = tools.handle_img(post) post = tools.handle_img(post)
date = int(time.time())
post_id = db.insert_quest_post(room, "text", post, date)
db.set_post_closed(room)
data = {} data = {}
data["post"] = [post] data["post"] = [post]
data["post_type"] = "text" data["post_type"] = "text"
data["date"] = int(time.time()) data["date"] = date
post_id = db.insert_quest_post(room, "text", post, data["date"])
db.set_dice_call_closed(room);
data["post_id"] = post_id data["post_id"] = post_id
emit("new_post", data, room=room) emit("new_post", data, room=room)
@socketio.on("update_post") @socketio.on("update_post")
@qm_only()
def update_post(data): def update_post(data):
""" """
Called when the QM edits and saves a post. Called when the QM edits and saves a post.
""" """
room = data["room"]
res = db.get_quest_meta(quest_id=room)
if not res:
return
if session.get("user_id") != res[3]:
return
# TODO: enforce only update text posts # TODO: enforce only update text posts
room = data["room"]
post = data["post"] post = data["post"]
post = post.strip().replace("<br>", "<br />") post = post.strip().replace("<br>", "<br />")
post = tools.handle_img(post) post = tools.handle_img(post)
@ -178,30 +194,25 @@ def update_post(data):
@socketio.on("dice_post") @socketio.on("dice_post")
@qm_only()
def dice_post(data): def dice_post(data):
""" """
Called when the QM posts a new dice call. Called when the QM posts a new dice call.
""" """
room = data["room"] room = data["room"]
res = db.get_quest_meta(quest_id=room)
if not res:
return
if session.get("user_id") != res[3]:
return
data = {k: v for k, v in data.items() if v} data = {k: v for k, v in data.items() if v}
try: try:
diceNum = int(data.get("diceNum", 0)) diceNum = int(data.get("diceNum", 0))
diceSides = int(data.get("diceSides", 0)) diceSides = int(data.get("diceSides", 0))
diceMod = int(data.get("diceMod", 0)) diceMod = int(data.get("diceMod", 0))
diceChal = int(data.get("diceChal", 0)) diceChal = int(data.get("diceChal", 0))
diceRolls = int(data.get("diceRolls", 0)) diceRollsTaken = int(data.get("diceRollsTaken", 0))
assert 0 < diceNum < 100 assert 0 < diceNum < 100
assert 0 < diceSides < 100 assert 0 < diceSides < 100
assert -1000 < diceMod < 1000 assert -1000 < diceMod < 1000
assert 0 <= diceChal < 100 assert 0 <= diceChal < 100
assert 0 <= diceRolls < 100 assert 0 <= diceRollsTaken < 100
except (ValueError, AssertionError): except (ValueError, AssertionError):
return return
diceStrict = bool(data.get("diceStrict")) diceStrict = bool(data.get("diceStrict"))
@ -215,56 +226,83 @@ def dice_post(data):
post = "Roll " + dice_roll post = "Roll " + dice_roll
if diceChal: if diceChal:
post += " vs DC" + str(diceChal) post += " vs DC" + str(diceChal)
date = int(time.time())
post_id = db.insert_quest_post(room, "dice", post, date)
new_call = (dice_roll, diceStrict, diceChal, diceRollsTaken)
db.insert_dice_call(post_id, room, new_call)
db.set_post_open(post_id, room)
data = {} data = {}
data["post"] = post data["post"] = post
data["post_type"] = "dice" data["post_type"] = "dice"
data["date"] = int(time.time()) data["date"] = date
post_id = db.insert_quest_post(room, "dice", post, data["date"])
data["post_id"] = post_id data["post_id"] = post_id
new_call = (dice_roll, diceStrict, diceChal, diceRolls)
db.set_dice_call_open(post_id, room, new_call)
emit("new_post", data, room=room) emit("new_post", data, room=room)
@socketio.on('close_dice_call') @socketio.on('close_post')
@qm_only()
def close_dice_call(data): def close_dice_call(data):
""" """
Closes an active dice call. Closes an active post.
""" """
room = data["room"] room = data["room"]
res = db.get_quest_meta(quest_id=room)
if not res:
return
if session.get("user_id") != res[3]:
return
post_id = data.get("post_id") post_id = data.get("post_id")
db.set_dice_call_closed(room) db.set_post_closed(room)
data = {} data = {}
data["post_id"] = post_id data["post_id"] = post_id
emit("close_dice_call", data, room=room) emit("close_post", data, room=room)
@socketio.on("open_dice_call") @socketio.on("open_post")
@qm_only()
def open_dice_call(data): def open_dice_call(data):
""" """
Opens a closed dice call. This is only permitted if the dice call is Opens an active post. This is only permitted if the active post is
the last post in the quest. the last post in the quest.
""" """
room = data["room"]
res = db.get_quest_meta(quest_id=room)
if not res:
return
if session.get("user_id") != res[3]:
return
# TODO: enforce only open if last post # TODO: enforce only open if last post
room = data["room"]
post_id = data.get("post_id") post_id = data.get("post_id")
db.set_dice_call_open(post_id, room) db.set_post_open(post_id, room)
data = {} data = {}
data["post_id"] = post_id data["post_id"] = post_id
emit("open_dice_call", data, room=room) emit("open_post", data, room=room)
@socketio.on("poll_post")
@qm_only()
def poll_post(data):
"""
Called when the QM posts a new dice call.
"""
room = data.pop("room", None)
multi_choice = bool(data.pop("pollAllowMultipleChoices", None))
allow_writein = bool(data.pop("pollAllowUserOptions", None))
options = []
for key, value in data.items():
if not value or not key.startswith("pollOption-"):
continue
if len(value) >= 200:
return
options.append(value)
post = "Poll"
date = int(time.time())
post_id = db.insert_quest_post(room, "poll", post, date)
db.insert_poll(post_id, multi_choice, allow_writein)
for option in options:
db.insert_poll_option(post_id, room, option)
db.set_post_open(post_id, room)
data = {}
data["post"] = post
data["post_id"] = post_id
data["post_type"] = "poll"
data["date"] = int(time.time())
data["options"] = options
emit("new_post", data, room=room)

View File

@ -31,15 +31,17 @@
post_str += 'textPost">'; post_str += 'textPost">';
} else if (data.post_type == 'dice') { } else if (data.post_type == 'dice') {
post_str += 'dicePost active_post">'; post_str += 'dicePost active_post">';
} else if (data.post_type == 'poll') {
post_str += 'pollPost active_post">';
} }
post_str += '<div class="questPostMeta">' + strftime(data.date); post_str += '<div class="questPostMeta">' + strftime(data.date);
{% if session.get("user_id") == owner_id %} {% if session.get("user_id") == owner_id %}
if (data.post_type == 'text') { if (data.post_type == 'text') {
post_str += '<br /><a href="javascript:void(0);" onclick="edit_post(\'' + data.post_id + '\')">Edit</a>'; post_str += '<br /><a href="javascript:void(0);" onclick="edit_post(\'' + data.post_id + '\')">Edit</a>';
post_str += '<a href="javascript:void(0);" id="savePost-' + data.post_id + '" onclick="save_post(\'' + data.post_id + '\')" style="display:none;">Save</a>'; post_str += '<a href="javascript:void(0);" id="savePost-' + data.post_id + '" onclick="save_post(\'' + data.post_id + '\')" style="display:none;">Save</a>';
} else if (data.post_type == 'dice') { } else if (data.post_type == 'dice' || data.post_type == 'poll') {
post_str += '<br /><a href="javascript:void(0);" id="close_dc-' + data.post_id + '" onclick="close_dice_call(' + data.post_id + ')">Close</a>'; post_str += '<br /><a href="javascript:void(0);" id="close_post_id-' + data.post_id + '" onclick="close_post(' + data.post_id + ')">Close</a>';
post_str += '<a href="javascript:void(0);" id="open_dc-' + data.post_id + '" onclick="open_dice_call(' + data.post_id + ')" style="display:none;">Open</a>' post_str += '<a href="javascript:void(0);" id="open_post_id-' + data.post_id + '" onclick="open_post(' + data.post_id + ')" style="display:none;">Open</a>'
} }
{% endif %} {% endif %}
post_str += '</div><div class="questPostData" id="questPostData-' + data.post_id + '">'; post_str += '</div><div class="questPostData" id="questPostData-' + data.post_id + '">';
@ -47,6 +49,13 @@
post_str += data.post; post_str += data.post;
} else if (data.post_type == 'dice') { } else if (data.post_type == 'dice') {
post_str += '<h3>' + data.post + ' - Open</h3>'; post_str += '<h3>' + data.post + ' - Open</h3>';
} else if (data.post_type == 'poll') {
post_str += '<h3>' + data.post + ' - Open</h3>';
post_str += '<table id="post-' + data.post_id + '">';
for (i = 0; i < data.options.length; i++) {
post_str += '<tr><td>' + data.options[i] + '</td></tr>';
}
post_str += '</table>';
} }
post_str += '</div></div><br />'; post_str += '</div></div><br />';
qposts.innerHTML = qposts.innerHTML + post_str; qposts.innerHTML = qposts.innerHTML + post_str;
@ -61,17 +70,17 @@
post.innerHTML += '<b>' + data.post + '</b><br />'; post.innerHTML += '<b>' + data.post + '</b><br />';
} }
}); });
socket.on('close_dice_call', function(data) { socket.on('close_post', function(data) {
let post = document.getElementById('questPostData-' + data.post_id); let post = document.getElementById('questPostData-' + data.post_id);
post.children[0].textContent = post.children[0].textContent.replace('Open', 'Closed'); post.children[0].textContent = post.children[0].textContent.replace('Open', 'Closed');
document.getElementById('close_dc-' + data.post_id).style.display = 'none'; document.getElementById('close_post_id-' + data.post_id).style.display = 'none';
document.getElementById('open_dc-' + data.post_id).style.display = 'initial'; document.getElementById('open_post_id-' + data.post_id).style.display = 'initial';
}); });
socket.on('open_dice_call', function(data) { socket.on('open_post', function(data) {
let post = document.getElementById('questPostData-' + data.post_id); let post = document.getElementById('questPostData-' + data.post_id);
post.firstElementChild.textContent = post.firstElementChild.textContent.replace('Closed', 'Open'); post.firstElementChild.textContent = post.firstElementChild.textContent.replace('Closed', 'Open');
document.getElementById('close_dc-' + data.post_id).style.display = 'initial'; document.getElementById('close_post_id-' + data.post_id).style.display = 'initial';
document.getElementById('open_dc-' + data.post_id).style.display = 'none'; document.getElementById('open_post_id-' + data.post_id).style.display = 'none';
}); });
let mtarea = document.getElementById('messageTextArea'); let mtarea = document.getElementById('messageTextArea');
mtarea.addEventListener('keypress', function(event) { mtarea.addEventListener('keypress', function(event) {
@ -120,33 +129,31 @@
document.getElementById('savePost-' + post_id).style.display = 'none'; document.getElementById('savePost-' + post_id).style.display = 'none';
document.getElementById('editPost-' + post_id).style.display = 'initial'; document.getElementById('editPost-' + post_id).style.display = 'initial';
} }
function dice_post() { function form_post(form_id, emit_msg) {
let formData = new FormData(document.getElementById('QMDicePostForm')); let formData = new FormData(document.getElementById(form_id));
let obj = {}; let obj = {};
formData.forEach(function(value, key) { formData.forEach(function(value, key) {
obj[key] = value; obj[key] = value;
}); });
obj.room = {{ room_id }}; obj.room = {{ room_id }};
socket.emit('dice_post', obj); socket.emit(emit_msg, obj);
document.getElementById('QMDicePostForm').reset(); document.getElementById(form_id).reset();
} }
function close_dice_call(post_id) { function close_post(post_id) {
socket.emit('close_dice_call', {post_id: post_id, room: {{ room_id }}}); socket.emit('close_post', {post_id: post_id, room: {{ room_id }}});
} }
function open_dice_call(post_id) { function open_post(post_id) {
socket.emit('open_dice_call', {post_id: post_id, room: {{ room_id }}}); socket.emit('open_post', {post_id: post_id, room: {{ room_id }}});
} }
function deactivate_post() { function deactivate_post() {
let post = document.getElementsByClassName('active_post'); let post = document.getElementsByClassName('active_post');
if (post.length == 0) { return; } if (post.length == 0) { return; }
post = post[0]; post = post[0];
if (post.classList.contains('dicePost')) {
post.children[1].children[0].textContent = post.children[1].children[0].textContent.replace('Open', 'Closed'); post.children[1].children[0].textContent = post.children[1].children[0].textContent.replace('Open', 'Closed');
post.classList.remove("active_post"); post.classList.remove("active_post");
post.children[0].children[2].outerHTML = ""; post.children[0].children[2].outerHTML = "";
post.children[0].children[1].outerHTML = ""; post.children[0].children[1].outerHTML = "";
} }
}
function insertPollOption() { function insertPollOption() {
let opts = document.getElementById('pollOptions'); let opts = document.getElementById('pollOptions');
let num = opts.children.length+1; let num = opts.children.length+1;
@ -195,6 +202,8 @@
<div class="questPost textPost"> <div class="questPost textPost">
{% elif quest_post[2] == "dice" %} {% elif quest_post[2] == "dice" %}
<div class="questPost dicePost{% if quest_post == quest_posts|last %} active_post{% endif %}"> <div class="questPost dicePost{% if quest_post == quest_posts|last %} active_post{% endif %}">
{% elif quest_post[2] == "poll" %}
<div class="questPost pollPost{% if quest_post == quest_posts|last %} active_post{% endif %}">
{% endif %} {% endif %}
<div class="questPostMeta"> <div class="questPostMeta">
{{ quest_post[4] | strftime }} {{ quest_post[4] | strftime }}
@ -202,13 +211,13 @@
{% if quest_post[2] == "text" %} {% if quest_post[2] == "text" %}
<br /><a href="javascript:void(0);" id="editPost-{{ quest_post[0] }}" onclick="edit_post({{ quest_post[0] }})">Edit</a> <br /><a href="javascript:void(0);" id="editPost-{{ quest_post[0] }}" onclick="edit_post({{ quest_post[0] }})">Edit</a>
<a href="javascript:void(0);" id="savePost-{{ quest_post[0] }}" onclick="save_post('{{ quest_post[0] }}')" style="display:none;">Save</a> <a href="javascript:void(0);" id="savePost-{{ quest_post[0] }}" onclick="save_post('{{ quest_post[0] }}')" style="display:none;">Save</a>
{% elif quest_post[2] == "dice" and quest_post == quest_posts|last %} {% elif quest_post[2] == "dice" or quest_post[2] == "poll" and quest_post == quest_posts|last %}
{% if quest_post[0] == dice_call %} {% if quest_post[0] == open_post_id %}
<br /><a href="javascript:void(0);" id="close_dc-{{ quest_post[0] }}" onclick="close_dice_call({{ quest_post[0] }})">Close</a> <br /><a href="javascript:void(0);" id="close_post_id-{{ quest_post[0] }}" onclick="close_post({{ quest_post[0] }})">Close</a>
<a href="javascript:void(0);" id="open_dc-{{ quest_post[0] }}" onclick="open_dice_call({{ quest_post[0] }})" style="display:none;">Open</a> <a href="javascript:void(0);" id="open_post_id-{{ quest_post[0] }}" onclick="open_post({{ quest_post[0] }})" style="display:none;">Open</a>
{% else %} {% else %}
<br /><a href="javascript:void(0);" id="close_dc-{{ quest_post[0] }}" onclick="close_dice_call({{ quest_post[0] }})" style="display:none;">Close</a> <br /><a href="javascript:void(0);" id="close_post_id-{{ quest_post[0] }}" onclick="close_post({{ quest_post[0] }})" style="display:none;">Close</a>
<a href="javascript:void(0);" id="open_dc-{{ quest_post[0] }}" onclick="open_dice_call({{ quest_post[0] }})">Open</a> <a href="javascript:void(0);" id="open_post_id-{{ quest_post[0] }}" onclick="open_post({{ quest_post[0] }})">Open</a>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@ -219,14 +228,25 @@
{{ quest_post[3] }} {{ quest_post[3] }}
{% endautoescape %} {% endautoescape %}
{% elif quest_post[2] == "dice" %} {% elif quest_post[2] == "dice" %}
<h3>{{ quest_post[3] }} - {% if quest_post[0] == dice_call_id %}Open{% else %}Closed{% endif %}</h3> <h3>{{ quest_post[3] }} - {% if quest_post[0] == open_post_id %}Open{% else %}Closed{% endif %}</h3>
{% for quest_roll in quest_rolls %} {% for dice_roll in dice_rolls %}
{% if quest_roll[2] == quest_post[0] %} {% if dice_roll[2] == quest_post[0] %}
<div id="questRollId-{{ quest_roll[0] }}"> <div id="questRollId-{{ dice_roll[0] }}">
<b>Rolled {{ quest_roll[4] }} = {{ quest_roll[5] }} ({{ quest_roll[3] }}){% if quest_post[0]|dice_chal != 0 %} - {% if quest_roll[5] >= quest_post[0]|dice_chal %}Pass{% else %} Fail{% endif %}{% endif %}</b> <b>Rolled {{ dice_roll[4] }} = {{ dice_roll[5] }} ({{ dice_roll[3] }}){% if quest_post[0]|dice_chal != 0 %} - {% if dice_roll[5] >= quest_post[0]|dice_chal %}Pass{% else %} Fail{% endif %}{% endif %}</b>
</div> </div>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% elif quest_post[2] == "poll" %}
<h3>{{ quest_post[3] }} - {% if quest_post[0] == open_post_id %}Open{% else %}Closed{% endif %}</h3>
<table id="poll-{{ quest_post[0] }}">
{% for option in poll_options %}
{% if option[0] == quest_post[0] %}
<tr>
<td>{{ option[2] }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
{% endif %} {% endif %}
</div> </div>
</div><br /> </div><br />
@ -247,7 +267,7 @@
</div> </div>
<div id="QMPostDice" class="QMPostTabContent" style="display:none;"> <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="dice_post();"> <form id="QMDicePostForm" action="javascript:void(0);" onsubmit="form_post('QMDicePostForm', 'dice_post');">
Dice: <input type="number" name="diceNum" min="1" max="99" required/> Dice: <input type="number" name="diceNum" min="1" max="99" required/>
d <input type="number" name="diceSides" 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="number" name="diceMod" min="-999" max="999"/>
@ -256,15 +276,15 @@
<input type="checkbox" onclick="document.getElementById('diceChal').disabled=!this.checked;"/> <input type="checkbox" onclick="document.getElementById('diceChal').disabled=!this.checked;"/>
<span class="tooltip" title="Dice challenge">DC:</span> <span class="tooltip" title="Dice challenge">DC:</span>
<input type="number" name="diceChal" id="diceChal" min="1" max="99" disabled/><br /> <input type="number" name="diceChal" id="diceChal" min="1" max="99" disabled/><br />
<input type="checkbox" onclick="document.getElementById('diceRolls').disabled=!this.checked;"/> <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> <span class="tooltip" title="Automatically close the dice call after this many rolls have been made.">Rolls Taken:</span>
<input type="number" name="diceRolls" id="diceRolls" min="1" max="99" disabled/><br /> <input type="number" name="diceRollsTaken" id="diceRollsTaken" min="1" max="99" disabled/><br />
<input type="submit" name="submit" value="Roll 'em"/> <input type="submit" name="submit" value="Roll 'em"/>
</form> </form>
</div> </div>
<div id="QMPostPoll" class="QMPostTabContent" style="display:none;"> <div id="QMPostPoll" class="QMPostTabContent" style="display:none;">
The polls are rigged. The polls are rigged.
<form id="QMPollPostForm" action="javascript:void(0);" onsubmit="poll_post();"> <form id="QMPollPostForm" action="javascript:void(0);" onsubmit="form_post('QMPollPostForm', 'poll_post');">
<a href="javascript:void(0);" id="pollInsertNewOption" onclick="insertPollOption()">[+]</a> <a href="javascript:void(0);" id="pollInsertNewOption" onclick="insertPollOption()">[+]</a>
<a href="javascript:void(0);" onclick="removePollOption()">[-]</a> <a href="javascript:void(0);" onclick="removePollOption()">[-]</a>
<div id="pollOptions"> <div id="pollOptions">

View File

@ -54,17 +54,19 @@ def quest(quest_title):
quest_id = data[0] quest_id = data[0]
quest_title = data[1] quest_title = data[1]
owner_id = data[3] owner_id = data[3]
dice_call_id = data[4] open_post_id = data[4]
quest_posts = db.get_quest_data(quest_id) quest_posts = db.get_quest_data(quest_id)
quest_rolls = db.get_quest_rolls(quest_id) dice_rolls = db.get_dice_rolls(quest_id)
poll_options = db.get_poll_options(quest_id)
messages = db.get_chat_messages(quest_id) messages = db.get_chat_messages(quest_id)
return render_template('quest.html', return render_template('quest.html',
quest_title=quest_title, quest_title=quest_title,
ident_title=ident_title, ident_title=ident_title,
quest_posts=quest_posts, quest_posts=quest_posts,
quest_rolls=quest_rolls, dice_rolls=dice_rolls,
poll_options=poll_options,
owner_id=owner_id, owner_id=owner_id,
dice_call_id=dice_call_id, open_post_id=open_post_id,
room_id=quest_id, room_id=quest_id,
messages=messages) messages=messages)