From b4e6b4c296c4fe3189e3e1cabd844251ae4ddff1 Mon Sep 17 00:00:00 2001
From: Alfie King
Date: Mon, 9 Feb 2026 13:34:47 +0000
Subject: [PATCH] scratch
---
requirements.txt | 3 +-
src/routes/dynamic_routes.py | 34 +++++++++++-----
src/routes/error_handlers.py | 37 ++++++++++++------
src/routes/lastfm.py | 26 -------------
src/wsgi.py | 2 -
static/content/fonts/avali-scratch.otf.woff2 | Bin 0 -> 5064 bytes
static/css/bases/base.css | 11 ++++++
static/js/base.js | 39 +++++++++++++------
templates/bases/base.html | 2 +-
templates/bases/md.html | 10 +++++
templates/errors/404.html | 6 +++
templates/errors/500.html | 6 +++
templates/errors/error.html | 16 ++++++++
templates/pages/test.md | 2 +
14 files changed, 131 insertions(+), 63 deletions(-)
delete mode 100644 src/routes/lastfm.py
create mode 100644 static/content/fonts/avali-scratch.otf.woff2
create mode 100644 templates/bases/md.html
create mode 100644 templates/errors/error.html
create mode 100644 templates/pages/test.md
diff --git a/requirements.txt b/requirements.txt
index 6ca9b0b..72af20f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,4 +2,5 @@ psycopg2-binary
python-dotenv
flask-session
requests
-flask
\ No newline at end of file
+flask
+markdown
\ No newline at end of file
diff --git a/src/routes/dynamic_routes.py b/src/routes/dynamic_routes.py
index 5fbc3eb..d82d3a9 100644
--- a/src/routes/dynamic_routes.py
+++ b/src/routes/dynamic_routes.py
@@ -1,7 +1,7 @@
# Imports
from flask import Blueprint, render_template, abort
from os import getenv as env
-import logging, os, re
+import logging, os, re, markdown
# Create blueprint
bp = Blueprint(
@@ -16,6 +16,7 @@ log = logging.getLogger(__name__)
# Get all files in folder
def ListFiles(path):
+ path = os.path.join(bp.template_folder, 'pages', path)[3:]
files = []
for root, dirs, files_in_dir in os.walk(path):
for file in files_in_dir:
@@ -27,14 +28,27 @@ def ListFiles(path):
# Catch-all route for generic pages
@bp.route('/')
def catch_all(filename):
- try:
- return render_template(f'pages/{filename if re.match(r'^.+\.[a-zA-Z0-9]+$', filename) else filename + '.html'}')
+ if os.path.exists(os.path.join(bp.template_folder, 'pages', filename)[3:]):
+ return render_template(f'pages/{filename}')
- except Exception as e:
- os_path = os.path.join(bp.template_folder, 'pages', filename)[3:]
- if os.path.isdir(os_path):
- if not filename.endswith('/'): filename += '/'
- return render_template('bases/directory.html', directory=filename, pages=ListFiles(os_path))
+ elif os.path.exists(os.path.join(bp.template_folder, 'pages', filename + '.html')[3:]):
+ return render_template(f'pages/{filename}.html')
- # If it is a file, return a 404 error
- abort(404, f"Template '{filename}' not found: {e}")
\ No newline at end of file
+ elif os.path.exists(os.path.join(bp.template_folder, 'pages', filename + '.md')[3:]):
+ print("yay")
+ print(markdown.markdownFromFile("../templates/pages/test.md"))
+ return render_template(
+ f'bases/md.html',
+ title = filename.split("/")[-1],
+ markdown = markdown.markdownFromFile(os.path.join(bp.template_folder, 'pages', filename + '.md'))
+ )
+
+ elif os.path.isdir(os.path.join(bp.template_folder, 'pages', filename)[3:]):
+ return render_template(
+ 'bases/directory.html',
+ directory=filename + "/" if not filename.endswith('/') else filename,
+ pages=ListFiles(filename)
+ )
+
+ else:
+ abort(404, f"'{filename}' not found")
\ No newline at end of file
diff --git a/src/routes/error_handlers.py b/src/routes/error_handlers.py
index 22e19f2..683d69b 100644
--- a/src/routes/error_handlers.py
+++ b/src/routes/error_handlers.py
@@ -1,5 +1,6 @@
# Imports
from flask import Blueprint, render_template
+from werkzeug.exceptions import HTTPException
from os import getenv as env
import logging
@@ -17,23 +18,35 @@ log = logging.getLogger(__name__)
# Route for 500 error
@bp.route('/500')
@bp.app_errorhandler(500)
-def internal_server_error(error=None):
- if error is not None:
- log.error("Internal server error: %s", error)
- return render_template('errors/500.html'), 500
+def internal_server_error(error:HTTPException=None):
+ return render_template('errors/500.html', error=error), 500
# Route for 404 error
@bp.route('/404')
@bp.app_errorhandler(404)
-def not_found(error=None):
- if error is not None:
- log.warning("Page not found: %s", error)
- return render_template('errors/404.html'), 404 if error is not None else 200
+def not_found(error:HTTPException=None):
+ return render_template('errors/404.html', error=error), 404
# Route for 400 error
@bp.route('/400')
@bp.app_errorhandler(400)
-def bad_request(error=None):
- if error is not None:
- log.warning("Bad request: %s", error)
- return render_template('errors/400.html', error=error), 400
\ No newline at end of file
+def bad_request(error:HTTPException=None):
+ return render_template('errors/400.html', error=error), 400
+
+# Route for all other errors
+@bp.route('/error')
+@bp.app_errorhandler(Exception)
+def unauthorized(error:HTTPException=None):
+ if isinstance(error, HTTPException):
+ return render_template(
+ 'errors/error.html',
+ code = error.code,
+ description = error.description,
+ name = error.name
+ ), error.code
+ return render_template(
+ 'errors/error.html',
+ code=418,
+ description="meow :3",
+ name="I'm a teapot"
+ ), 418
\ No newline at end of file
diff --git a/src/routes/lastfm.py b/src/routes/lastfm.py
deleted file mode 100644
index 7c7710c..0000000
--- a/src/routes/lastfm.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from flask import Blueprint, jsonify
-from os import getenv as env
-import logging, requests
-
-# Create blueprint
-bp = Blueprint(
- 'lastfm',
- __name__,
- template_folder=env('TEMPLATE_FOLDER', default='../templates'),
- static_folder=env('STATIC_FOLDER', default='../static')
-)
-
-# Create logger
-log = logging.getLogger(__name__)
-
-# lastfm info
-@bp.route('/info')
-def lastfm_info():
- url = f"http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user={env('LASTFM_USER')}&api_key={env('LASTFM_API_KEY')}&format=json&limit=1"
- response = requests.get(url).json()
- data = {
- 'artist': response['recenttracks']['track'][0]['artist']['#text'],
- 'track': response['recenttracks']['track'][0]['name'],
- 'image': response['recenttracks']['track'][0]['image'][3]['#text']
- }
- return jsonify(data)
\ No newline at end of file
diff --git a/src/wsgi.py b/src/wsgi.py
index 1e90942..3c01824 100644
--- a/src/wsgi.py
+++ b/src/wsgi.py
@@ -8,7 +8,6 @@ import logging
import src.routes.error_handlers
import src.routes.dynamic_routes
-import src.routes.lastfm
# Load env
load_dotenv()
@@ -43,7 +42,6 @@ Session(app)
# Load routes
app.register_blueprint(src.routes.error_handlers.bp, url_prefix='/error')
-app.register_blueprint(src.routes.lastfm.bp, url_prefix='/lastfm')
app.register_blueprint(src.routes.dynamic_routes.bp, url_prefix='/')
# Generic routes
diff --git a/static/content/fonts/avali-scratch.otf.woff2 b/static/content/fonts/avali-scratch.otf.woff2
new file mode 100644
index 0000000000000000000000000000000000000000..ded650d169d7a517e501c8602b35342eb310400c
GIT binary patch
literal 5064
zcmV;(6F2O4Pew9NR8&s@029an2><{908YpN026-z0RR9100000000000000000000
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
literal 0
HcmV?d00001
diff --git a/static/css/bases/base.css b/static/css/bases/base.css
index 9bb5eac..b35ef34 100644
--- a/static/css/bases/base.css
+++ b/static/css/bases/base.css
@@ -5,6 +5,12 @@
font-weight:normal;
font-style:normal;
}
+@font-face {
+ font-family:"Scratch";
+ src:url("/static/content/fonts/avali-scratch.otf.woff2") format("woff2");
+ font-weight:normal;
+ font-style:normal;
+}
:root {
--primary-color: #5cdd8b;
@@ -17,6 +23,7 @@
--font-family: "Space Mono", "serif";
--title-font: 'Roboto Mono', sans-serif;
--irken-font: 'Irken';
+ --scratch-font: 'Scratch';
}
body {
@@ -244,6 +251,10 @@ main section a {
font-family: var(--irken-font);
}
+.scratch {
+ font-family: var(--scratch-font);
+}
+
#alt-nav {
display: none;
backdrop-filter: blur(2px) brightness(0.6);
diff --git a/static/js/base.js b/static/js/base.js
index 35f4e9c..c8a246f 100644
--- a/static/js/base.js
+++ b/static/js/base.js
@@ -72,41 +72,58 @@ typing();
// HIDDEN STUFF (shh don't tell anyone >:3)
-let last5Chars = "";
+let last15Chars = "";
document.addEventListener('keydown', function(event) {
- last5Chars += event.key;
- if (last5Chars == "furry") {
+ last15Chars += event.key;
+ if (last15Chars.includes("furry")) {
console.log("owo, whats this?");
document.getElementById('furry').style.display = 'block';
+ last15Chars = "";
}
- if (last5Chars == "irken") {
+ if (last15Chars.includes("irken")) {
console.log("doom doom doom!");
document.querySelector(":root").style.setProperty('--font-family', 'Irken');
document.querySelector(":root").style.setProperty('--title-font', '1.5em');
+ last15Chars = "";
}
- while (last5Chars.length >= 5) {
- last5Chars = last5Chars.slice(1);
+ if (last15Chars.includes("scratch")) {
+ console.log("space chicken");
+ document.querySelector(":root").style.setProperty('--font-family', 'Scratch');
+ document.querySelector(":root").style.setProperty('--title-font', '1em');
+ last15Chars = "";
+ }
+ while (last15Chars.length >= 15) {
+ last15Chars = last15Chars.slice(1);
}
});
// Spotify API (now lastfm)
function getSpotify() {
- fetch('/lastfm/info').then(response => {
+ fetch('https://api.alfieking.dev/spotify/nowplaying/xz02oolstlvwxqu1pfcua9exz').then(response => {
return response.json();
}).then(data => {
- document.getElementById('spotify').style.backgroundImage = "url(" + data.image + ")";
- document.getElementById('spotify-title').innerHTML = data.track;
- document.getElementById('spotify-artist').innerHTML = data.artist;
+ if (data.item == null) {
+ document.getElementById('spotify').style.backgroundImage = "none";
+ document.getElementById('spotify-title').innerHTML = "Spotify is not playing anything";
+ document.getElementById('spotify-artist').innerHTML = ":(";
+ document.getElementById('spotify-link').href = "https://open.spotify.com/";
+ return;
+ }
+ document.getElementById('spotify').style.backgroundImage = "url(" + data.item.album.images[0].url + ")";
+ document.getElementById('spotify-title').innerHTML = data.item.name;
+ document.getElementById('spotify-artist').innerHTML = data.item.artists[0].name;
+ document.getElementById('spotify-link').href = data.item.external_urls.spotify;
});
}
if (document.getElementById('spotify')) {
getSpotify();
- setInterval(getSpotify, 60000);
+ setInterval(getSpotify, 15000);
}
+
// load buttons
function loadButtons() {
diff --git a/templates/bases/base.html b/templates/bases/base.html
index e5e1041..d01da80 100644
--- a/templates/bases/base.html
+++ b/templates/bases/base.html
@@ -41,7 +41,7 @@
- heya, try typing "furry" and "irken" into this page!
+ heya, try typing "furry", "irken" or scratch into this page!
+
+ Actual error
+
+ {{ error }}
+
+
{% endblock %}
\ No newline at end of file
diff --git a/templates/errors/500.html b/templates/errors/500.html
index eec13f3..58afff4 100644
--- a/templates/errors/500.html
+++ b/templates/errors/500.html
@@ -14,4 +14,10 @@
Oopsie Woopsie! Uwu We made a fucky wucky!! A wittle fucko boingo! The code monkeys at our headquarters are working VEWY HAWD to fix this!
+
+ Actual error
+
+ {{ error }}
+
+
{% endblock %}
\ No newline at end of file
diff --git a/templates/errors/error.html b/templates/errors/error.html
new file mode 100644
index 0000000..c5ea5f8
--- /dev/null
+++ b/templates/errors/error.html
@@ -0,0 +1,16 @@
+{% extends "bases/base.html" %}
+
+{% block title %}{{ code }} - {{ name }}{% endblock %}
+{% block description %}The page you are looking for does not exist.{% endblock %}
+
+{% block content %}
+
+
+
+
+ Actual error
+
+ {{ description }}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/pages/test.md b/templates/pages/test.md
new file mode 100644
index 0000000..17e2883
--- /dev/null
+++ b/templates/pages/test.md
@@ -0,0 +1,2 @@
+# hello
+this is a test
\ No newline at end of file