summaryrefslogtreecommitdiff
path: root/app.py
diff options
context:
space:
mode:
authorMorgana <Morgana@icolotl.com>2026-09-25 14:19:20 -0500
committerMorgana <Morgana@icolotl.com>2026-09-25 14:19:20 -0500
commit7fc188b0a4d73856c05eacc9bdf2a1561505a8d6 (patch)
treead2b4132865432a1e8e321a033e62b1838c3dc94 /app.py
Initial Commit
Diffstat (limited to 'app.py')
-rw-r--r--app.py126
1 files changed, 126 insertions, 0 deletions
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..79ad458
--- /dev/null
+++ b/app.py
@@ -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)