diff options
| author | Morgana <Morgana@icolotl.com> | 2026-09-25 14:19:20 -0500 |
|---|---|---|
| committer | Morgana <Morgana@icolotl.com> | 2026-09-25 14:19:20 -0500 |
| commit | 7fc188b0a4d73856c05eacc9bdf2a1561505a8d6 (patch) | |
| tree | ad2b4132865432a1e8e321a033e62b1838c3dc94 /app.py | |
Initial Commit
Diffstat (limited to 'app.py')
| -rw-r--r-- | app.py | 126 |
1 files changed, 126 insertions, 0 deletions
@@ -0,0 +1,126 @@ +import json +from hashlib import scrypt +from os import urandom +from hmac import compare_digest +import sqlite3 + +from flask import ( + Flask, + render_template, + request, + redirect, + url_for, + session, + g, + flash, +) +from werkzeug.exceptions import HTTPException + +SCRYPT_PARAMS = {"n": 16384, "r": 8, "p": 1} +HEX_CHARS = set("0123456789ABCDEF") + + +def get_db(): + if "db" not in g: + g.db = sqlite3.connect("akasha.db", detect_types=sqlite3.PARSE_DECLTYPES) + g.db.row_factory = sqlite3.Row + return g.db + + +def teardown(e=None): + if (db := g.pop("db", None)) is not None: + db.close() + + +app = Flask(__name__) +with open("./config.json", "r", encoding="utf-8") as file: + config = json.load(file) + app.config["SECRET_KEY"] = config["fsk"] + LIGHT_URL = f"http://192.168.1.10/api/{config['light']}" + del config + app.teardown_appcontext(teardown) + + +@app.errorhandler(HTTPException) +def handle_bad_request(e): + if request.endpoint != "static": + # TODO: Create an actual error page. + if "username" not in session: + flash("Guest access is temporarily restricted. Please log in to continue.") + return redirect(url_for("login")) + flash(f"Error {e.code}: {e.name}") + flash("You have been redirected to the main page.") + return redirect(url_for("index")) + return e + + +@app.route("/") +def index(): + db = get_db() + cur = db.cursor() + cur.execute("SELECT * FROM news ORDER BY id DESC LIMIT 1") + results = cur.fetchone() + return render_template("index.html", news=results) + + +@app.route("/login", methods=["GET", "POST"]) +def login(): + db = get_db() + if request.method == "POST": + username = request.form.get("username") + password = request.form.get("password") + if not username or not password: + flash("Error: Empty username or password.") + return redirect(url_for("login")) + if request.form.get("register") == "1": + cur = db.cursor() + cur.execute("SELECT 1 FROM users WHERE username=?", (username,)) + if cur.fetchone(): + flash("Error: User already exists.") + return redirect(url_for("login")) + salt = urandom(32) + hash = scrypt(password.encode("utf-8"), salt=salt, **SCRYPT_PARAMS) + cur.execute( + "INSERT INTO users (username, hash, salt) VALUES (?, ?, ?)", + (username, hash, salt), + ) + flash("Success: User registered.") + db.commit() + else: + cur = db.cursor() + cur.execute("SELECT hash, salt FROM users WHERE username=?", (username,)) + results = cur.fetchone() + if not results: + flash("Error: Invalid username or password.") + return redirect(url_for("login")) + expected_hash, salt = results + actual_hash = scrypt(password.encode("utf-8"), salt=salt, **SCRYPT_PARAMS) + if not compare_digest(expected_hash, actual_hash): + flash("Error: Invalid username or password.") + return redirect(url_for("login")) + session["username"] = username + flash(f"Success: Logged in as {username}.") + return redirect(url_for("index")) + return render_template("login.html") + + +@app.route("/logout") +def logout(): + if "username" in session: + del session["username"] + flash("Success: You have been logged out.") + return redirect(url_for("index")) + + +@app.route("/hyde") +def hydematch(): + if "username" not in session: + flash( + "The Drosera Springs Wrestling Database is only available to logged-in users." + ) + return redirect(url_for("login")) + db = get_db() + cur = db.cursor() + cur.execute("SELECT * FROM matches ORDER BY id DESC") + results = cur.fetchall() + return render_template("hyde.html", matches=results) |