204 lines
4.8 KiB
Python
204 lines
4.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Database tools and functions.
|
|
"""
|
|
import time
|
|
import string
|
|
import urllib
|
|
import functools
|
|
|
|
import bleach
|
|
from flask import session, request, abort, redirect, url_for, render_template
|
|
from flask import Blueprint
|
|
|
|
import database as db
|
|
import tools
|
|
|
|
views = Blueprint("views", __name__)
|
|
|
|
def login_required(url=None):
|
|
"""
|
|
A decorator function to protect certain endpoints by requiring the user
|
|
to either pass a valid session cookie, or pass thier username and
|
|
password along with the request to login.
|
|
"""
|
|
def actual_decorator(func):
|
|
@functools.wraps(func)
|
|
def _nop(*args, **kwargs):
|
|
username = session.get("username")
|
|
if db.verify_username(username):
|
|
return func(*args, **kwargs)
|
|
|
|
username = request.form.get("user")
|
|
password = request.form.get("pass")
|
|
if db.verify_password(username, password):
|
|
return func(*args, **kwargs)
|
|
|
|
if url:
|
|
return redirect(url_for(url))
|
|
else:
|
|
abort(401)
|
|
return _nop
|
|
return actual_decorator
|
|
|
|
|
|
@views.route("/quest/<path:quest_title>")
|
|
def quest(quest_title):
|
|
"""
|
|
An arbituary quest page.
|
|
"""
|
|
then = time.time()
|
|
ident_title, _, extra = quest_title.partition("/")
|
|
data = db.get_quest_meta(ident_title=ident_title)
|
|
if not data:
|
|
abort(404)
|
|
|
|
quest_id = room_id = data[0]
|
|
quest_title = data[1]
|
|
owner_id = data[3]
|
|
open_post_id = data[4]
|
|
|
|
quest_posts = db.get_quest_data(quest_id)
|
|
#dice_rolls = db.get_dice_rolls(quest_id)
|
|
#polls = db.get_polls(quest_id)
|
|
#polls = {poll[0]: poll[1:] for poll in polls}
|
|
|
|
messages = db.get_chat_messages(quest_id)
|
|
|
|
temp = render_template('quest.html', **locals())
|
|
print(time.time() - then)
|
|
return temp
|
|
|
|
|
|
@views.route("/quest/<path:quest_title>/edit_quest", methods=["GET", "POST"])
|
|
def edit_quest(quest_title):
|
|
"""
|
|
Allows the quest owner to edit the quest.
|
|
"""
|
|
ident_title = quest_title
|
|
data = db.get_quest_meta(ident_title=ident_title)
|
|
if not data:
|
|
abort(404)
|
|
quest_id = data[0]
|
|
quest_title = data[1]
|
|
if request.method == "GET":
|
|
return render_template("edit_quest.html",
|
|
quest_title=quest_title,
|
|
ident_title=ident_title)
|
|
return redirect(url_for(".quest", quest_title=ident_title))
|
|
|
|
|
|
@views.route("/profile/<path:username>")
|
|
def profile(username):
|
|
"""
|
|
Shows the profile page of the specified user.
|
|
"""
|
|
data = db.get_user_info(username)
|
|
if not data:
|
|
return "user_not_found"
|
|
user_id, signup_date = data
|
|
quests = db.get_user_quests(user_id)
|
|
return render_template("profile.html",
|
|
username=username,
|
|
signup_date=signup_date,
|
|
num_quests=len(quests))
|
|
|
|
|
|
@views.route("/create_quest", methods=["GET", "POST"])
|
|
@login_required(".login")
|
|
def create_quest():
|
|
"""
|
|
Starts a new quest.
|
|
"""
|
|
if request.method == "GET":
|
|
return render_template("create_quest.html")
|
|
canon_title = request.form.get("quest_title")
|
|
quest_body = request.form.get("quest_body")
|
|
|
|
ident_title = tools.sanitize_title(canon_title)
|
|
quest_body = bleach.clean(quest_body.strip())
|
|
quest_body = quest_body.replace("\n", "<br />")
|
|
|
|
owner_id = session.get("user_id")
|
|
timestamp = int(time.time())
|
|
|
|
quest_id = db.insert_quest(canon_title, ident_title, owner_id)
|
|
db.insert_quest_post(quest_id, "text", quest_body, timestamp)
|
|
|
|
return redirect(url_for('.quest', quest_title=ident_title))
|
|
|
|
|
|
@views.route("/set_session")
|
|
def set_session():
|
|
"""
|
|
Allows certain session values to be set by the client.
|
|
"""
|
|
hide_header = request.args.get("hide_header")
|
|
if hide_header == "on":
|
|
session["hide_header"] = True
|
|
elif hide_header == "off":
|
|
session["hide_header"] = False
|
|
return ""
|
|
|
|
|
|
@views.route("/login", methods=["GET", "POST"])
|
|
def login():
|
|
"""
|
|
Logs the user in.
|
|
"""
|
|
if request.method == "GET":
|
|
return render_template("login.html")
|
|
|
|
username = request.form.get("user")
|
|
password = request.form.get("pass")
|
|
|
|
if db.verify_password(username, password):
|
|
session["username"] = username
|
|
return redirect(url_for(".index"))
|
|
else:
|
|
abort(401)
|
|
|
|
|
|
@views.route("/signup", methods=["GET", "POST"])
|
|
def signup():
|
|
"""
|
|
Create a new account.
|
|
"""
|
|
if request.method == "GET":
|
|
return render_template("signup.html")
|
|
|
|
username = request.form.get("user")
|
|
password = request.form.get("pass")
|
|
password_verify = request.form.get("pass_verify")
|
|
|
|
if len(username) > 20:
|
|
return "username_too_long"
|
|
elif len(username) < 3:
|
|
return "username_too_short"
|
|
chrs = [c not in string.ascii_letters + string.digits for c in username]
|
|
if any(chrs):
|
|
return "username_bad_chars"
|
|
if db.verify_username(username):
|
|
return "username_taken"
|
|
|
|
if len(password) > 1024:
|
|
return "password_too_long"
|
|
elif len(password) < 8:
|
|
return "password_too_short"
|
|
|
|
if password != password_verify:
|
|
return "passwords_dont_match"
|
|
|
|
timestamp = int(time.time())
|
|
res = db.add_user(username, password, timestamp)
|
|
return redirect(url_for(".index"))
|
|
|
|
|
|
@views.route("/")
|
|
def index():
|
|
"""
|
|
The index page.
|
|
"""
|
|
print(request.remote_addr)
|
|
return render_template("index.html")
|