38 Commits

Author SHA1 Message Date
Alfie King 936cadfea8 small update
Deploy website / deploy (push) Successful in 3m11s
2026-07-03 00:24:59 +01:00
Alfie King cb7ec029eb update music api to listenbrainz
Deploy website / deploy (push) Successful in 3m1s
2026-06-15 21:56:41 +01:00
Alfie King af5116d931 update idk
Deploy website / deploy (push) Successful in 2m1s
2026-03-29 15:50:47 +01:00
Alfie King 8dae4c1b5d ring fix
Deploy website / deploy (push) Successful in 1m8s
2026-03-08 23:27:30 +00:00
Alfie King 8e67e714d0 news post and "ads" XD
Deploy website / deploy (push) Successful in 56s
2026-03-05 00:23:01 +00:00
Alfie King 7c9aaa04ba volume and icon
Deploy website / deploy (push) Successful in 54s
2026-03-04 22:07:03 +00:00
Alfie King 93ecd4999f deploy fix
Deploy website / deploy (push) Successful in 1m19s
2026-03-04 21:58:57 +00:00
Alfie King 0d367e43a6 audio "fix"
Deploy website / deploy (push) Successful in 26s
2026-03-04 21:54:21 +00:00
Alfie King 3afab4c7fa smileos
Deploy website / deploy (push) Successful in 39s
2026-03-04 21:32:30 +00:00
Alfie King 885d2559af webrings and buttons
Deploy website / deploy (push) Successful in 26s
2026-03-03 18:01:44 +00:00
Alfie King 8f1e4e60e1 more logs
Deploy website / deploy (push) Successful in 35s
2026-03-03 15:13:51 +00:00
Alfie King a47c2a3886 f*ck
Deploy website / deploy (push) Successful in 22s
2026-03-03 15:06:57 +00:00
Alfie King 11d8621f9b pls work :3
Deploy website / deploy (push) Failing after 23s
2026-03-03 15:05:38 +00:00
Alfie King b683a2721a fix
Deploy website / deploy (push) Failing after 11s
2026-03-03 15:03:40 +00:00
Alfie King 7a60ca468d deploy script
Deploy website / deploy (push) Failing after 1m46s
2026-03-03 15:00:11 +00:00
Alfie King 1a5380e17e major update 2026-03-03 14:11:55 +00:00
Alfie King 6e92e40f1c markdown support
Build and push container image / build-and-push-image (push) Successful in 5m35s
2026-02-26 23:14:36 +00:00
Alfie King b4e6b4c296 scratch
Build and push container image / build-and-push-image (push) Successful in 6m3s
2026-02-09 13:34:47 +00:00
Alfie King 9700a5dc7f music update
Build and push container image / build-and-push-image (push) Successful in 4m39s
2026-02-02 01:24:14 +00:00
Alfie King 067f0e189d toaster button
Build and push container image / build-and-push-image (push) Successful in 4m7s
2026-01-29 01:24:53 +00:00
Alfie King 639a8e2fb0 Merge pull request 'major update :O' (#2) from major-redesign into main
Build and push container image / build-and-push-image (push) Successful in 5m57s
Reviewed-on: https://git.alfieking.dev/acetheking987/alfieking.dev/pulls/2
2026-01-18 23:25:17 +00:00
Alfie King 25b03aa105 major update :O 2026-01-18 23:21:44 +00:00
Alfie King 53cd3852aa update
Build and push container image / build-and-push-image (push) Successful in 6m29s
2025-08-27 21:53:25 +01:00
Alfie King f67f377be1 new images 2025-08-23 16:10:25 +01:00
Alfie King bfb1b8a21e sitemap
Build and push container image / build-and-push-image (push) Successful in 3m59s
2025-08-13 22:54:24 +01:00
Alfie King ef459d728a update link
Build and push container image / build-and-push-image (push) Successful in 3m16s
2025-08-10 19:53:31 +01:00
Alfie King 5690bcadf9 I fkin found em
Build and push container image / build-and-push-image (push) Successful in 4m21s
2025-08-08 20:31:55 +01:00
Alfie King 8b5b80f7c5 Merge remote-tracking branch 'refs/remotes/gitea/main'
Build and push container image / build-and-push-image (push) Successful in 3m7s
2025-08-07 21:26:35 +01:00
Alfie King 66806ad922 events 2025-08-07 21:25:10 +01:00
Alfie King b29a61a44b fix name box
Build and push container image / build-and-push-image (push) Successful in 3m2s
2025-08-07 11:28:24 +00:00
Alfie King a0562330a3 more updates
Build and push container image / build-and-push-image (push) Successful in 2m59s
2025-08-06 22:39:06 +01:00
Alfie King df59a2c097 fix typos and css
Build and push container image / build-and-push-image (push) Successful in 2m31s
2025-08-06 01:33:56 +01:00
Alfie King 8209f52fa7 update og image
Build and push container image / build-and-push-image (push) Successful in 2m19s
2025-08-06 01:15:44 +01:00
Alfie King b029eba456 fix
Build and push container image / build-and-push-image (push) Successful in 2m27s
2025-08-06 00:54:30 +01:00
Alfie King 1b2425a493 toaster update :3
Build and push container image / build-and-push-image (push) Failing after 5m28s
2025-08-06 00:41:26 +01:00
Alfie King e66f7e0588 update 2025-06-28 18:12:09 +01:00
Alfie King d48dd04af9 snake "security" 2025-06-22 16:07:01 +01:00
Alfie King f3d5cb9d53 cleaned backend 2025-06-22 15:56:38 +01:00
106 changed files with 1571 additions and 792 deletions
+65
View File
@@ -0,0 +1,65 @@
name: Deploy website
run-name: ${{ gitea.actor }} is deploying update
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
- name: Deploy
run: |
ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'EOF'
set -e
APP_DIR=/var/www/alfieking.dev
RELEASES_DIR=$APP_DIR/releases
TIMESTAMP=$(date +%Y%m%d%H%M%S)
NEW_RELEASE=$RELEASES_DIR/$TIMESTAMP
KEEP_RELEASES=5
echo "Creating release directory..."
mkdir -p $NEW_RELEASE
echo "Cloning public repository..."
git clone --depth 1 -b main \
https://git.alfieking.dev/acetheking987/alfieking.dev.git \
$NEW_RELEASE
echo "Installing dependencies..."
source $APP_DIR/venv/bin/activate
pip install -r $NEW_RELEASE/requirements.txt
echo "Switching symlink..."
ln -sfn $NEW_RELEASE $APP_DIR/current
echo "Changing ownership..."
chown -R www-data:www-data /var/www/alfieking.dev/releases/$TIMESTAMP
chown -R www-data:www-data /var/www/alfieking.dev/current
echo "Restarting Gunicorn (downtime incomming XD)..."
systemctl restart alfieking.dev.service
echo "Cleaning old releases..."
CURRENT_TARGET=$(readlink -f $APP_DIR/current)
cd $RELEASES_DIR
for dir in $(ls -dt */ | tail -n +$((KEEP_RELEASES+1))); do
FULL_PATH="$RELEASES_DIR/${dir%/}"
if [ "$FULL_PATH" != "$CURRENT_TARGET" ]; then
rm -rf "$FULL_PATH"
fi
done
echo "Deployment successful."
EOF
+2 -4
View File
@@ -1,5 +1,3 @@
.venv
.env
db.sqlite
flask_session
__pycache__
__pycache__
.venv
BIN
View File
Binary file not shown.
-25
View File
@@ -1,25 +0,0 @@
FROM python:alpine
# Set the working directory
WORKDIR /app
# Copy the requirements file into the container
COPY requirements.txt .
# Install the required packages
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install gunicorn
# Copy the rest of the application code into the container
COPY src src
COPY templates templates
COPY static static
# Expose the port the app runs on
EXPOSE 5000
# Set environment variables
ENV FLASK_APP=main.py
# run the application
ENTRYPOINT [ "gunicorn", "-b", ":5000", "--access-logfile", "-", "--error-logfile", "-", "src.main:app" ]
Binary file not shown.
+4 -1
View File
@@ -1,4 +1,7 @@
psycopg2-binary
python-dotenv
flask-session
requests
flask
flask
markdown
gunicorn
+16
View File
@@ -0,0 +1,16 @@
from os import getenv as env
import psycopg2, logging
log = logging.getLogger("blog")
log.info("connecting to database")
conn = psycopg2.connect(
host = env("PG_HOST"),
port = env("PG_PORT"),
dbname = env("PG_DBNAME"),
user= env("PG_USER"),
password = env("PG_PASSWORD")
)
cursor = conn.cursor()
-42
View File
@@ -1,42 +0,0 @@
import sqlite3
class Database:
def __init__(self, db_name='db.sqlite'):
self.connection = sqlite3.connect(db_name, check_same_thread=False)
self.cursor = self.connection.cursor()
self.create_snake_table()
def create_snake_table(self):
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS snake (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
score INTEGER NOT NULL
)
''')
self.connection.commit()
def insert_snake(self, name, score):
old_score = self.get_snake_score(name)
print(f"Old score for {name}: {old_score}")
print(f"New score for {name}: {score}")
if old_score is not None and score <= old_score:
return
self.cursor.execute('''
INSERT INTO snake (name, score)
VALUES (?, ?)
''', (name, score))
self.connection.commit()
def get_snake_score(self, name):
self.cursor.execute('SELECT score FROM snake WHERE name = ? ORDER BY score DESC LIMIT 1', (name,))
result = self.cursor.fetchone()
return result[0] if result else None
def get_snake_scores(self):
self.cursor.execute('SELECT * FROM snake ORDER BY score DESC')
return self.cursor.fetchall()
def close(self):
self.connection.close()
+73
View File
@@ -0,0 +1,73 @@
# Imports
from flask import Blueprint, render_template, abort
import os, importlib, logging
# Logging
log = logging.getLogger("__main__")
# Create blueprint
bp = Blueprint('dynamic', __name__)
template_folder = "templates"
# helper func
def get_path(file) -> str:
return os.path.join(template_folder, "pages", file)
# Get all files in folder
def ListFiles(path):
path = get_path(path)
files = []
for root, dirs, files_in_dir in os.walk(path):
for file in files_in_dir:
files.append(os.path.relpath(os.path.join(root, file), path))
for dir in dirs:
files.append(os.path.relpath(os.path.join(root, dir), path) + '/')
return files
# Import handlers
handlers_unloaded = os.listdir("src/handlers")
handlers_unloaded = [handler for handler in handlers_unloaded if handler.endswith(".py")]
handlers = {}
for handler in handlers_unloaded:
try:
try: module = importlib.import_module(f'src.handlers.{handler[:-3]}')
except ImportError: module = importlib.import_module(f'handlers.{handler[:-3]}')
handlers[handler[:-3]] = module.callback
log.info(f"Loaded handler {handler}: {module.callback}")
except Exception as e:
log.error(f"Failed to load handler {handler}: {e}")
continue
# Catch-all route for generic pages
@bp.route('/<path:filename>')
def catch_all(filename):
if os.path.exists(get_path(filename)):
if os.path.isdir(get_path(filename)):
return render_template(
'bases/directory.html',
directory=filename + "/" if not filename.endswith('/') else filename,
pages=ListFiles(filename)
)
if filename.split('.')[-1] in handlers.keys():
return handlers[filename.split('.')[-1]](filename)
return render_template(f'pages/{filename}')
elif os.path.exists(get_path(filename + '.html')):
return render_template(f'pages/{filename}.html')
else:
for ext in handlers.keys():
if os.path.exists(get_path(filename + f".{ext}")):
return handlers[ext](filename + f".{ext}")
abort(404, f"'{filename}' not found")
+38
View File
@@ -0,0 +1,38 @@
from flask import Blueprint, render_template
from werkzeug.exceptions import HTTPException
bp = Blueprint("errors", __name__)
@bp.route('/500')
@bp.app_errorhandler(500)
def internal_server_error(error:HTTPException=None):
return render_template('errors/500.html', error=error), 500
@bp.route('/404')
@bp.app_errorhandler(404)
def not_found(error:HTTPException=None):
return render_template('errors/404.html', error=error), 404
@bp.route('/400')
@bp.app_errorhandler(400)
def bad_request(error:HTTPException=None):
return render_template('errors/400.html', error=error), 400
@bp.route('/idk')
@bp.app_errorhandler(Exception)
def idk(error:HTTPException=None):
if not isinstance(error, HTTPException):
error = HTTPException("I honestly dont know")
error.code = 418
return render_template(
'errors/error.html',
code = error.code,
description = error.description,
err_name = error.name,
), error.code
+10
View File
@@ -0,0 +1,10 @@
from flask import render_template
import markdown, os
def callback(filename):
output = markdown.markdown(open(os.path.join("templates", "pages", filename), "r").read())
return render_template(
f'bases/md.html',
title = filename.split("/")[-1],
markdown = output
)
+67 -100
View File
@@ -1,117 +1,84 @@
from flask import Flask, request, render_template, send_from_directory, abort
from flask_session import Session
from dotenv import load_dotenv
# IMPORTS
from flask import Flask, render_template, request
from os import getenv as env
import logging, requests
import logging
try:
import src.database as database
import src.pg_log as pg_log
except ImportError:
import database
import pg_log
from dotenv import load_dotenv
load_dotenv()
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
load_dotenv()
# LOGGING
pg_log_handler = pg_log.PgLog(
host = env("PG_HOST"),
port = env("PG_PORT"),
dbname = env("PG_DBNAME"),
user= env("PG_USER"),
password = env("PG_PASSWORD")
)
pg_log_handler.setLevel(logging.DEBUG)
stream_log_handler = logging.StreamHandler()
stream_log_handler.setFormatter(
logging.Formatter("%(asctime)s - %(levelname)s: %(message)s")
)
stream_log_handler.setLevel(logging.INFO)
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log.addHandler(stream_log_handler)
log.addHandler(pg_log_handler)
werkzeug_logger = logging.getLogger("werkzeug")
werkzeug_logger.setLevel(logging.DEBUG)
werkzeug_logger.addHandler(pg_log_handler)
werkzeug_logger.addHandler(stream_log_handler)
log.info("Logging initialized.")
try:
import src.dynamic as dynamic
import src.errors as errors
import src.music_metadata as music_metadata
except ImportError:
import dynamic, errors, music_metadata
# CREATE FLASK APP
app = Flask(
__name__,
template_folder=env('TEMPLATE_FOLDER', default='../templates'),
static_folder=env('STATIC_FOLDER', default='../static'),
static_url_path=env('STATIC_URL_PATH', default='/static')
template_folder="../templates",
static_folder="../static"
)
app.config["SESSION_PERMANENT"] = True
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
log.info("Flask initialized.")
db = database.Database(db_name=env('DB_NAME', default='db.sqlite'))
# BLUEPRINTS
app.register_blueprint(errors.bp, url_prefix="/errors")
app.register_blueprint(music_metadata.bp, url_prefix="/music")
app.register_blueprint(dynamic.bp, url_prefix="/")
log.info("Blueprints registered.")
@app.route('/')
# ROUTES
@app.route("/")
def index():
return render_template('index.html')
return render_template("index.html")
@app.route("/toaster")
def toaster():
return render_template("toaster.html")
@app.route("/terminal")
def terminal():
return render_template("terminal.html")
@app.route('/robots.txt')
@app.route('/sitemap.xml')
@app.route('/favicon.ico')
def web_stuffs():
return send_from_directory(
app.static_folder,
request.path[1:],
)
@app.route('/<path:path>')
def catch_all(path):
try:
return render_template(path + '.html')
except Exception as e:
abort(404)
@app.route('/404')
@app.errorhandler(404)
def not_found():
unformatted_scores = db.get_snake_scores()
scores = [{'position': i + 1, 'name': score[1], 'score': score[2]} for i, score in enumerate(unformatted_scores)]
return render_template('404.html', scores=scores)
@app.route('/404/submit', methods=['POST'])
def snake_submit():
unformatted_scores = db.get_snake_scores()
scores = [{'position': i + 1, 'name': score[1], 'score': score[2]} for i, score in enumerate(unformatted_scores)]
data = request.form
username = data.get('username', '').strip()
score = data.get('snake-score', '').strip()
token = data.get('cap-token', '').strip()
if not username or not score or not token:
logging.error("Missing required fields: username=%s, score=%s, token=%s", username, score, token)
return render_template('404.html', scores=scores, error='Missing required fields'), 400
try:
score = int(score)
except ValueError:
logging.error("Invalid score value: %s", score)
return render_template('404.html', scores=scores, error='Invalid score value'), 400
if score <= 0 or score > 10000 or len(username) < 3 or len(username) > 15:
logging.error("Invalid score or username length: score=%s, username=%s", score, username)
return render_template('404.html', scores=scores, error='Invalid score or username length'), 400
cap_response = requests.post(
env('CAP_VERIFY_URL', default='https://<instance_url>/<key_id>/siteverify'),
json={
'secret': env('CAP_SECRET', default=''),
'response': token,
}
)
if cap_response.status_code != 200 or not cap_response.json().get('success', "false") != "true":
logging.error("Captcha verification failed: %s", cap_response.json())
return render_template('404.html', scores=scores, error='Captcha verification failed'), 400
db.insert_snake(name=username, score=int(score))
logging.info("Snake submitted: name=%s, score=%d", username, score)
unformatted_scores = db.get_snake_scores()
scores = [{'position': i + 1, 'name': score[1], 'score': score[2]} for i, score in enumerate(unformatted_scores)]
return render_template('404.html', scores=scores, success='Score submitted successfully!')
@app.route('/500')
@app.errorhandler(500)
def internal_error(error="An internal server error occurred."):
logging.error("Internal server error: %s", error)
return render_template('500.html'), 500
if __name__ == '__main__':
app.run(
host=env('HOST', default='0.0.0.0'),
port=env('PORT', default=5000),
debug=env('DEBUG', default="false").lower() == 'true'
)
# DEBUG (DONT RUN LIKE THIS IN PROD)
if __name__ == "__main__":
log.warning(f"RUNNING IN DEBUG MODE DO NOT USE FOR PRODUCTION!")
app.run(debug=True)
+25
View File
@@ -0,0 +1,25 @@
from flask import Blueprint, request, abort
from os import getenv as env
from urllib.parse import quote
import requests
bp = Blueprint("music", __name__)
@bp.route("/metadata")
def metadata():
if not request.args.get("recording_name"):
abort(400, "Recording name is required")
if not request.args.get("artist_name"):
abort(400, "Artist name is required")
data = requests.get(
f"https://api.listenbrainz.org/1/metadata/lookup/?recording_name={quote(request.args.get('recording_name'))}&artist_name={quote(request.args.get('artist_name'))}&metadata=true&inc=artist+tag+release",
headers={
"Authorization": f"Token {env("LISTENBRAINZ_TOKEN")}"
}
)
if data.status_code == 200:
return data.json()
else:
abort(500, "Failed to retrieve metadata")
+35
View File
@@ -0,0 +1,35 @@
import psycopg2, logging
class PgLog(logging.StreamHandler):
def __init__(self, host, port, dbname, user, password):
super().__init__()
self.host = host
self.port = port
self.dbname = dbname
self.user = user
self.password = password
self.conn = psycopg2.connect(
database = dbname,
user = user,
password = password,
host = host,
port = port
)
self.cursor = self.conn.cursor()
def __del__(self):
self.cursor.close()
self.conn.close()
def emit(self, record):
self.cursor.execute(
f"INSERT INTO logs (level, message) VALUES (%s, %s)",
(
record.levelname,
record.getMessage(),
)
)
self.conn.commit()
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -3,7 +3,6 @@ https://cyber.dabamos.de/88x31/anythingbut.gif
https://cyber.dabamos.de/88x31/bestdesktop.gif
https://kopawz.neocities.org/buttonhoard/buttonsfldr2/diagnosedwithGAY.gif
https://kopawz.neocities.org/indexgraphics/buttondecor/ilikecomputer.png
https://identity-crisis.carrd.co/assets/images/gallery04/ad4f8d52.jpg?v=4e55d939
https://anlucas.neocities.org/best_viewed_with_eyes.gif
https://anlucas.neocities.org/html_learn_it_today.gif
https://highway.eightyeightthirty.one/badge/5d58a8f32b007d4897db6f862a895a81674fb35f5cc3947fc66595817ca174db
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 743 KiB

After

Width:  |  Height:  |  Size: 743 KiB

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Before

Width:  |  Height:  |  Size: 240 KiB

After

Width:  |  Height:  |  Size: 240 KiB

@@ -1,6 +1,6 @@
User-agent: *
Allow: /
Disallow: /404.html
Disallow: /errors
Sitemap: https://alfieking.dev/sitemap.xml
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.example.com/index.html</loc>
<loc>https://alfieking.dev/</loc>
</url>
<url>
<loc>https://alfieking.dev/toaster</loc>
</url>
</urlset>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 KiB

-155
View File
@@ -1,155 +0,0 @@
#snakeContainer {
padding: 15px;
}
canvas#snakeCanvas {
box-sizing: border-box;
border: 2px solid var(--secondary-background-color);
border-radius: 10px;
width: 100%;
}
form {
display: flex;
flex-direction: column;
width: min-content;
gap: 1rem;
padding: 15px;
}
form input[type="text"] {
padding: 10px;
box-sizing: border-box;
border: 1px solid var(--secondary-background-color);
border-radius: 6px;
background-color: var(--secondary-background-color-but-slightly-transparent);
color: var(--text-color);
}
form button[type="submit"] {
padding: 10px;
box-sizing: border-box;
border: 1px solid var(--secondary-background-color);
border-radius: 6px;
background-color: var(--secondary-background-color-but-slightly-transparent);
color: var(--text-color);
font-weight: bold;
cursor: pointer;
}
.flex-row {
display: flex;
flex-direction: row;
gap: 1rem;
}
.min-width {
width: min-content;
}
.max-width {
width: 100%;
}
#snakeLeaderboardSection {
display: flex;
flex-direction: column;
align-items: center;
padding: 0;
max-height: 272px ;
}
#snakeLeaderboard {
display: flex;
flex-direction: column;
list-style: none;
padding: 0;
margin: 0;
width: 100%;
overflow-y: scroll;
}
#snakeLeaderboard li {
padding: 5px 20px;
background-color: var(--secondary-background-color-but-slightly-transparent);
color: var(--text-color);
font-size: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
}
#snakeLeaderboard li:nth-child(even) {
background-color: var(--secondary-background-color);
}
dialog {
width: 90%;
max-width: 500px;
padding: 20px;
background-color: var(--background-color);
color: var(--text-color);
border: 2px solid var(--secondary-background-color);
border-radius: 8px;
}
dialog button {
padding: 10px;
width: 100%;
box-sizing: border-box;
border: 2px solid var(--secondary-background-color);
border-radius: 6px;
background-color: var(--secondary-background-color-but-slightly-transparent);
color: var(--text-color);
font-weight: bold;
cursor: pointer;
margin-top: 10px;
}
dialog h2 {
margin: 0;
font-size: 1.5rem;
}
dialog p {
margin: 0;
font-size: 1rem;
}
@media screen and (max-width: 850px) {
.flex-row {
flex-direction: column;
}
form {
align-items: center;
width: 100%;
}
.min-width {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
}
@media screen and (max-width: 650px) {
.mobileOnly {
display: flex;
}
.pcOnly {
display: none;
}
}
@media screen and (min-width: 651px) {
.mobileOnly {
display: none !important;
}
.pcOnly {
display: flex;
}
}
@@ -1,7 +1,25 @@
@import url('https://fonts.googleapis.com/css2?family=Fredoka:wdth,wght@125,700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap');
@font-face {
font-family:"Irken";
src:url("/static/content/Irken-Like-AllCaps.woff") format("woff");
src:url("/static/content/fonts/Irken-Like-AllCaps.woff") format("woff");
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;
}
@font-face {
font-family:"Ultrafont";
src:url("/static/content/fonts/ultrakill-font.woff2") format("woff2");
font-weight:normal;
font-style:normal;
}
@font-face {
font-family:"Ultrafont2";
src:url("/static/content/fonts/ultrakill-font-2.woff2") format("woff2");
font-weight:normal;
font-style:normal;
}
@@ -17,6 +35,13 @@
--font-family: "Space Mono", "serif";
--title-font: 'Roboto Mono', sans-serif;
--irken-font: 'Irken';
--scratch-font: 'Scratch';
--ultrafont-font: 'Ultrafont';
--smileos2-box: url(/static/content/smileos/SmileOS_2_Box.webp) 17 3 3 fill / 51px 9px 9px;
--smileos2-font: 'Ultrafont2';
--smileos2-emphasis: #FF4343;
--line-height: normal;
--header-line-height: normal;
}
body {
@@ -25,6 +50,7 @@ body {
color: var(--text-color);
font-size: var(--font-size);
font-family: var(--font-family);
line-height: var(--line-height);
display: grid;
grid-template-columns: auto auto;
grid-template-rows: 1fr;
@@ -35,6 +61,10 @@ body {
width: 940px;
}
h1, h2, h3, h4, h5, h6 {
line-height: var(--header-line-height);
}
#sidebar {
grid-area: sidebar;
display: flex;
@@ -220,6 +250,15 @@ main section a {
text-decoration: none;
}
.smileos {
border-image: var(--smileos2-box);
padding: 54px 15px 12px;
image-rendering: pixelated;
font-size: 1.25rem;
font-family: var(--smileos2-font);
color: #fff;
}
#furry {
position: fixed;
left: 0;
@@ -227,7 +266,7 @@ main section a {
right: 0;
bottom: 0;
opacity: 0.1;
background-image: url('/static/content/background.png');
background-image: url('/static/content/general_images/background.png');
background-repeat: no-repeat;
background-position: 50% 0;
background-size: cover;
@@ -244,6 +283,14 @@ main section a {
font-family: var(--irken-font);
}
.scratch {
font-family: var(--scratch-font);
}
.ultrafont {
font-family: var(--ultrafont-font);
}
#alt-nav {
display: none;
backdrop-filter: blur(2px) brightness(0.6);
@@ -304,6 +351,45 @@ main section a {
box-sizing: border-box;
}
a {
text-decoration: none;
}
code {
background-color: var(--secondary-background-color-but-slightly-transparent);
padding: 4px 6px;
border-radius: 4px;
font-size: 0.9rem;
color: var(--primary-color);
}
#toaster-wave {
position: absolute;
left: -145px;
top: 200px;
}
.webring {
text-align: center;
}
.webring a {
text-decoration: none;
color: var(--primary-color);
font-size: 1.2rem;
}
.webring a:hover {
font-weight: 900;
text-shadow: 0px 0px 10px var(--primary-color-but-slightly-transparent);
}
@media screen and (max-width: 1240px) {
#toaster-wave {
display: none;
}
}
@media screen and (max-width: 1000px) {
body {
background-color: var(--background-color);
+13
View File
@@ -0,0 +1,13 @@
section#directory ul {
list-style: none;
padding: 0;
margin: 0;
}
section#directory li {
margin: 0.5rem 0;
}
section#directory a:hover {
scale: 1.05;
}
-21
View File
@@ -1,21 +0,0 @@
cap-widget {
--cap-background: var(--secondary-background-color-but-slightly-transparent);
--cap-border-color: var(--secondary-background-color);
--cap-border-radius: 14px;
--cap-widget-height: 30px;
--cap-widget-width: 230px;
--cap-widget-padding: 14px;
--cap-gap: 15px;
--cap-color: var(--text-color);
--cap-checkbox-size: 25px;
--cap-checkbox-border: 1px solid var(--secondary-background-color);
--cap-checkbox-border-radius: 6px;
--cap-checkbox-background: none;
--cap-checkbox-margin: 2px;
--cap-font: "Space Mono", "serif";
--cap-spinner-color: var(--primary-color);
--cap-spinner-background-color: var(--secondary-background-color-but-slightly-transparent);
--cap-spinner-thickness: 5px;
--cap-credits-font-size: 12px;
--cap-opacity-hover: 0.8;
}
+3
View File
@@ -0,0 +1,3 @@
section h2 {
margin-top: 2rem !important;
}
+23
View File
@@ -0,0 +1,23 @@
.gallery {
width: 100%;
}
.gallery .gallery-images {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 1rem;
overflow: hidden;
}
.gallery .gallery-images img {
max-width: 100%;
height: auto;
border-radius: 10px;
}
.gallery h2.gallery-date {
position: relative;
top: 0;
left: 0;
}
+19 -5
View File
@@ -43,7 +43,7 @@
transform: scale(1.1) rotate(-5deg);
}
#spotify {
#listenbrainz {
background-image: none;
backdrop-filter: blur(2px) brightness(0.6);
border: var(--secondary-background-color) 2px solid;
@@ -58,8 +58,8 @@
flex-direction: column;
}
#spotify-title {
font-size: 1.5rem;
#listenbrainz-title {
font-size: 1.2rem;
font-weight: 900;
margin: 0;
padding: 0;
@@ -67,15 +67,29 @@
color: white;
}
#spotify-artist {
#listenbrainz-artist {
color: white;
font-size: 1rem;
font-size: 0.7rem;
font-weight: 900;
margin: 0;
padding: 0;
mix-blend-mode: difference;
}
#listenbrainz-live {
color: white;
font-size: 0.6rem;
font-weight: 900;
margin: 0;
padding: 0;
margin-top: auto;
margin-left: auto;
background-color: gray;
border-radius: 30px;
padding: 2px 6px;
font-family: var(--ultrafont-font);
}
#button-collection {
display: flex;
flex-direction: row;
+131
View File
@@ -0,0 +1,131 @@
@font-face {
font-family:"Ultrafont2";
src:url("/static/content/fonts/ultrakill-font-2.woff2") format("woff2");
font-weight:normal;
font-style:normal;
}
#terminal {
aspect-ratio: 4/3;
padding: 0;
font-family: "Ultrafont2";
font-size: 1.2rem;
color: #ffffff;
border: none;
}
.smileos-header {
height: 9%;
border-image: url(/static/content/smileos/SmileOS_2_Header.webp) 3 fill / 9px;
display: flex;
flex-direction: row;
align-items: center;
padding: 0;
font-size: 1.4rem;
font-weight: 900;
padding-left: 7px;
padding-right: 7px;
image-rendering: pixelated;
}
.smileos-header img {
height: 100%;
object-fit: contain;
}
#terminal-container {
border-image: url(/static/content/smileos/SmileOS_2_Content.webp) 1 3 3 fill / 3px 9px 9px;
height: 100%;
display: grid;
grid-template-areas:
"logo window"
"buttons window";
grid-template-columns: 40% 1fr;
grid-template-rows: 25% 1fr;
padding: 15px;
box-sizing: border-box;
image-rendering: pixelated;
}
#smileos-logo {
width: 250px;
grid-area: logo;
margin: auto;
image-rendering: pixelated;
}
#terminal-window {
height: 100%;
grid-area: window;
}
#window-container {
border-image: url(/static/content/smileos/SmileOS_2_Content.webp) 1 3 3 fill / 3px 9px 9px;
height: 91%;
padding: 35px;
box-sizing: border-box;
image-rendering: pixelated;
}
#window-content {
border-image: url(/static/content/smileos/SmileOS_2_inset_panel.webp) 1 fill / 3px;
height: 100%;
box-sizing: border-box;
padding: 15px;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
image-rendering: pixelated;
}
.red {
color: #ff4343;
}
#terminal-buttons {
grid-area: buttons;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.terminal-button {
border-image: url(/static/content/smileos/SmileOS_2_Button_transparent.png) 2 / 9px;
background: url(/static/content/smileos/SmileOS_2_Button_Background.png);
background-repeat: repeat-x;
background-size: 100% 100%;
border-radius: 15px;
height: 75px;
width: 270px;
image-rendering: pixelated;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-family: "Ultrafont2";
font-size: 1.2rem;
color: #ffffff;
}
.terminal-button:hover {
filter: contrast(110%);
}
.terminal-button:active {
filter: contrast(125%);
}
#smileos-window-content img {
width: 100%;
}
#smileos-restart-music {
color: #FF4343;
cursor: pointer;
}
#smileos-restart-music:hover {
font-weight: 700;
}
+40
View File
@@ -4,6 +4,7 @@ ul#toaster-specs {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 400px;
}
ul#toaster-specs li {
@@ -33,6 +34,35 @@ ul#toaster-specs li {
height: 100%;
}
.fur-meet-gallery-small {
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.fur-meet-gallery-small img {
width: 150px;
height: 150px;
object-fit: cover;
border-radius: 10px;
border: 2px solid var(--secondary-background-color);
}
.fur-meet-gallery-small img:hover {
transform: scale(1.05);
transition: transform 0.2s ease-in-out;
cursor: pointer;
}
#fur-meets {
list-style: none;
padding: 0;
margin: 10px;
display: flex;
flex-direction: column;
gap: 10px;
}
@media screen and (max-width: 740px) {
.flex-row {
flex-direction: column;
@@ -45,4 +75,14 @@ ul#toaster-specs li {
#toaster-img {
width: 100%;
}
}
@media screen and (max-width: 690px) {
.flex-col {
flex-direction: column;
}
}
#toaster-wave {
display: none;
}
+24 -55
View File
@@ -72,67 +72,36 @@ 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("owo")) {
console.log("owo, whats this?");
document.getElementById('furry').style.display = 'block';
last15Chars = "";
}
if (last5Chars == "irken") {
console.log("doom doom doom!");
if (last15Chars.includes("doom")) {
console.log("Im gonna sing the doom song now");
document.querySelector(":root").style.setProperty('--font-family', 'Irken');
document.querySelector(":root").style.setProperty('--ultrafont-font', 'Irken');
document.querySelector(":root").style.setProperty('--smileos2-font', 'Irken');
document.querySelector(":root").style.setProperty('--title-font', '1.5em');
document.querySelector(":root").style.setProperty('--line-height', 'default');
document.querySelector(":root").style.setProperty('--header-line-height', 'default');
last15Chars = "";
}
while (last5Chars.length >= 5) {
last5Chars = last5Chars.slice(1);
if (last15Chars.includes("kfc")) {
console.log("space chicken");
document.querySelector(":root").style.setProperty('--font-family', 'Scratch');
document.querySelector(":root").style.setProperty('--title-font', '1em');
document.querySelector(":root").style.setProperty('--line-height', '120%');
document.querySelector(":root").style.setProperty('--header-line-height', '150%');
document.querySelector(":root").style.setProperty('--ultrafont-font', 'Scratch');
document.querySelector(":root").style.setProperty('--smileos2-font', 'Scratch');
last15Chars = "";
}
});
// Spotify API
function getSpotify() {
fetch('https://api.alfieking.dev/spotify/nowplaying/xz02oolstlvwxqu1pfcua9exz').then(response => {
return response.json();
}).then(data => {
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, 15000);
}
// load buttons
function loadButtons() {
fetch('/static/content/buttons.txt').then(response => {
return response.text();
}).then(data => {
container = document.getElementById('button-collection');
for (let line of data.split('\n')) {
if (line == "") {
continue;
}
let img = document.createElement('img');
img.src = line;
container.appendChild(img);
}
});
}
if (document.getElementById('button-collection')) {
loadButtons();
}
while (last15Chars.length >= 15) {
last15Chars = last15Chars.slice(1);
}
});
+70
View File
@@ -0,0 +1,70 @@
// onionring.js is made up of four files - onionring-widget.js (this one!), onionring-index.js, onionring-variables.js and onionring.css
// it's licensed under the cooperative non-violent license (CNPL) v4+ (https://thufie.lain.haus/NPL.html)
// it was originally made by joey + mord of allium (蒜) house, last updated 2020-11-24
// === ONIONRING-WIDGET ===
//this file contains the code which builds the widget shown on each page in the ring. ctrl+f 'EDIT THIS' if you're looking to change the actual html of the widget
var tag = document.getElementById(ringID); //find the widget on the page
thisSite = window.location.href; //get the url of the site we're currently on
thisIndex = null;
// FIX
thisSite = thisSite.replace("alfieking.dev", "proot.uk"); // fix domain
thisSite = thisSite.replace("http:\/\/127.0.0.1:5000", "https:\/\/proot.uk"); // For debug purposes
// go through the site list to see if this site is on it and find its position
for (i = 0; i < sites.length; i++) {
if (thisSite.startsWith(sites[i])) { //we use startswith so this will match any subdirectory, users can put the widget on multiple pages
thisIndex = i;
break; //when we've found the site, we don't need to search any more, so stop the loop
}
}
function randomSite() {
otherSites = sites.slice(); //create a copy of the sites list
otherSites.splice(thisIndex, 1); //remove the current site so we don't just land on it again
randomIndex = Math.floor(Math.random() * otherSites.length);
location.href = otherSites[randomIndex];
}
//if we didn't find the site in the list, the widget displays a warning instead
if (thisIndex == null) {
tag.insertAdjacentHTML('afterbegin', `
<table>
<tr>
<td>This site isn't part of the ${ringName} webring yet 😿</td>
</tr>
</table>
`);
}
else {
//find the 'next' and 'previous' sites in the ring. this code looks complex
//because it's using a shorthand version of an if-else statement to make sure
//the first and last sites in the ring join together correctly
previousIndex = (thisIndex-1 < 0) ? sites.length-1 : thisIndex-1;
nextIndex = (thisIndex+1 >= sites.length) ? 0 : thisIndex+1;
indexText = ""
//if you've chosen to include an index, this builds the link to that
if (useIndex) {
indexText = `<a href='${indexPage}'>index</a> | `;
}
randomText = ""
//if you've chosen to include a random button, this builds the link that does that
if (useRandom) {
randomText = `<a href='javascript:void(0)' onclick='randomSite()'>random</a> | `;
}
tag.classList = "webring";
//this is the code that displays the widget - EDIT THIS if you want to change the structure
tag.insertAdjacentHTML('afterbegin', `
<a href='${indexPage}'>${ringName}</a><br>
<a href='${sites[previousIndex]}'><--</a>
<a href='${sites[nextIndex]}'>--></a>
`);
}
+57
View File
@@ -0,0 +1,57 @@
function loadButtons() {
fetch('/static/content/buttons/non_link_buttons.txt').then(response => {
return response.text();
}).then(data => {
container = document.getElementById('button-collection');
for (let line of data.split('\n')) {
if (line == "") {
continue;
}
let img = document.createElement('img');
img.src = line;
container.appendChild(img);
}
});
}
function getAlbumArt(songName, artistName) {
fetch("/music/metadata?recording_name=" + encodeURIComponent(songName) + "&artist_name=" + encodeURIComponent(artistName)).then(response => response.json()).then(data => {
if (Object.keys(data).length > 0) {
document.getElementById('listenbrainz').style.backgroundImage = "url(https://coverartarchive.org/release/" + data.release_mbid + "/front)";
} else {
console.log("No album art found for the given song and artist");
document.getElementById('listenbrainz').style.backgroundImage = "url(https://placehold.co/512x512/transparent/777?text=[Insert%20art%20here])";
}
});
}
function getMusic() {
fetch("https://api.listenbrainz.org/1/user/acetheking987/playing-now").then(response => response.json()).then(data => {
if (data.payload.count != 0) {
let song_data = data.payload.listens[0].track_metadata;
getAlbumArt(song_data.track_name, song_data.artist_name);
document.getElementById('listenbrainz-title').innerHTML = song_data.track_name;
document.getElementById('listenbrainz-artist').innerHTML = song_data.artist_name;
document.getElementById('listenbrainz-link').href = "https://listenbrainz.org/user/acetheking987/";
document.getElementById('listenbrainz-live').style.backgroundColor = "red";
document.getElementById('listenbrainz-live').innerHTML = "Live";
} else {
fetch("https://api.listenbrainz.org/1/user/acetheking987/listens?count=1").then(response => response.json()).then(data => {
if (data.payload.count != 0) {
let song_data = data.payload.listens[0].track_metadata;
getAlbumArt(song_data.track_name, song_data.artist_name);
document.getElementById('listenbrainz-title').innerHTML = song_data.track_name;
document.getElementById('listenbrainz-artist').innerHTML = song_data.artist_name;
document.getElementById('listenbrainz-link').href = "https://listenbrainz.org/user/acetheking987/";
document.getElementById('listenbrainz-live').style.backgroundColor = "grey";
document.getElementById('listenbrainz-live').innerHTML = "Not Live :<";
}
});
}
});
}
loadButtons();
getMusic();
setInterval(getMusic, 15000);
+115
View File
@@ -0,0 +1,115 @@
const tips_of_the_day = [
`The Revolver deals <span style="color:var(--smileos2-emphasis)">locational damage</span>.<br>A <span style="color:var(--smileos2-emphasis)">headshot</span> deals <span style="color:var(--smileos2-emphasis)">2x</span> damage and a <span style="color:var(--smileos2-emphasis)">limbshot</span> deals <span style="color:var(--smileos2-emphasis)">1.5x</span> damage.`,
`<span style="color:var(--smileos2-emphasis)">Dash</span>: Fully invincible, costs stamina<br><span style="color:var(--smileos2-emphasis)">Slide</span>: Greater distance, no invincibility<br><span style="color:var(--smileos2-emphasis)">Jump</span>: Quickly out of melee range, less control`,
`<span style="color:var(--smileos2-emphasis)">Shotgun parries</span>: A <span style="color:var(--smileos2-emphasis)">point-blank</span> Shotgun shot to the torso right before an enemy attack lands will deal massive damage.`,
`<span style="color:var(--smileos2-emphasis)">Attack sound cues</span> allow you to keep track of enemies who are off screen.`,
`Some enemies make <span style="color:var(--smileos2-emphasis)">idle sounds</span> to make them easier to track.`,
`Use the <span style="color:cyan">ATTRACTOR NAILGUN</span>'s magnets to form concentrated <span style="color:var(--smileos2-emphasis)">orbs</span> of nails that can be <span style="color:var(--smileos2-emphasis)">moved</span> around using the pull force of <span style="color:var(--smileos2-emphasis)">other magnets</span>.`,
`Enemies <span style="color:var(--smileos2-emphasis)">can hurt</span> other enemy types. With quick thinking and positioning, powerful enemies can turn into powerful weapons.`,
`The <span style="color:cyan">ATTRACTOR NAILGUN</span>'s magnets can be attached to enemies to make mobile targets easy to hit with nails.`,
`Enemies <span style="color:var(--smileos2-emphasis)">scream</span> when falling from a <span style="color:var(--smileos2-emphasis)">fatal height</span>.`,
`<span style="color:var(--smileos2-emphasis)">SLAM BOUNCING</span>: Jump immediately after landing from a <span style="color:var(--smileos2-emphasis)">ground slam</span> to jump higher. The longer the ground slam fall, the higher the bounce.`,
`<span style="color:var(--smileos2-emphasis)">RAILCANNON</span> variations all share the same cooldown. Choose wisely which variation best fits the situation.`,
`<span style="color:var(--smileos2-emphasis)">SLIDING</span> will retain previous momentum for a short amount of time. Chaining quick <span style="color:var(--smileos2-emphasis)">SLIDE JUMPS</span> after a <span style="color:var(--smileos2-emphasis)">DASH JUMP</span> will give you incredible sustained speed.`,
`<span style="color:var(--smileos2-emphasis)">Environmental hazards</span> such as harmful liquids will hurt enemies as well.`,
`If you're having trouble keeping up with a tough enemy, <span style="color:var(--smileos2-emphasis)">stand back and observe</span>. Every enemy has its <span style="color:var(--smileos2-emphasis)">tells</span> and <span style="color:var(--smileos2-emphasis)">patterns</span> and learning those can be your key to victory.`,
`<span style="color:var(--smileos2-emphasis)">HITSCAN</span> weapons can be used to hit the shotgun's <span style="color:cyan">CORE EJECT</span> in mid-air to increase its damage and blast radius.`,
`<span style="color:var(--smileos2-emphasis)">POWER-UPS</span> can be stacked.`,
`Hitting an enemy with only the <span style="color:var(--smileos2-emphasis)">edge</span> of an <span style="color:var(--smileos2-emphasis)">explosion</span> will launch them without dealing much damage, making it a risky but effective tool against <span style="color:var(--smileos2-emphasis)">Stalkers</span>.`,
`Airborne <span style="color:var(--smileos2-emphasis)">coins</span> can be shot with any <span style="color:var(--smileos2-emphasis)">hitscan</span> weapon.`,
`Falling <span style="color:var(--smileos2-emphasis)">underwater</span> is slow, but a <span style="color:var(--smileos2-emphasis)">ground slam</span> allows for a quick return to the ground.`,
`<span style="color:var(--smileos2-emphasis)">Sliding</span> onto water will cause one to <span style="color:var(--smileos2-emphasis)">skip across</span> its surface.`,
`If an enemy is <span style="color:var(--smileos2-emphasis)">blessed</span> by an <span style="color:var(--smileos2-emphasis)">Idol</span>, a direct visible connection is formed between the two, allowing one to easily <span style="color:var(--smileos2-emphasis)">track down</span> and destroy the protector.`,
`<span style="color:var(--smileos2-emphasis)">Explosions</span> deflect <span style="color:var(--smileos2-emphasis)">projectiles</span>.<br><br>If an explosion is caused right from where an enemy shoots a projectile, it can <span style="color:var(--smileos2-emphasis)">backfire</span> and <span style="color:var(--smileos2-emphasis)">hit them</span> instead.`,
`The space of a <span style="color:var(--smileos2-emphasis)">large</span> arena can be used to one's advantage. Using the environment to <span style="color:var(--smileos2-emphasis)">break line-of-sight</span> with enemies allows for some breathing room and time to consider <span style="color:var(--smileos2-emphasis)">target prioritization</span>.`,
`<span style="color:var(--smileos2-emphasis)">DON'T</span> WASTE STAMINA! Dashing <span style="color:var(--smileos2-emphasis)">needlessly</span> while fighting very <span style="color:var(--smileos2-emphasis)">aggressive foes</span> will quickly cause one to have none left when it is most needed.`,
`<span style="color:var(--smileos2-emphasis)">Homing projectiles</span> may be more difficult to dodge, but their tracking and slower speed makes them much <span style="color:var(--smileos2-emphasis)">easier</span> to <span style="color:var(--smileos2-emphasis)">parry</span>.`,
`<span style="color:var(--smileos2-emphasis)">Mannequins</span> can be hard to hit due to their speed, but they lose air control when <span style="color:var(--smileos2-emphasis)">launched</span> or <span style="color:var(--smileos2-emphasis)">shot down</span> from a surface, making them <span style="color:var(--smileos2-emphasis)">unable to move</span> for a short moment.`,
`The <span style="color:red">Knuckleblaster</span>'s <span style="color:var(--smileos2-emphasis)">blast wave</span> is also capable of breaking a <span style="color:var(--smileos2-emphasis)">Gutterman's shield</span>, and is much easier to land in a chaotic scenario.`,
`A <span style="color:var(--smileos2-emphasis)">direct hit</span> from the <span style="color:red">Knuckleblaster</span> has extremely powerful <span style="color:var(--smileos2-emphasis)">knockback</span>, making it extremely powerful for launching enemies into <span style="color:var(--smileos2-emphasis)">pits</span> and other <span style="color:var(--smileos2-emphasis)">environmental hazards</span>.`,
`Didn't expect me, huh?`,
`<span style="color:#FF0078">Magenta</span> colored attacks can <span style="color:var(--smileos2-emphasis)">not</span> be dashed through and must be <span style="color:var(--smileos2-emphasis)">avoided entirely</span>.`,
`<span style="color:var(--smileos2-emphasis)">Blood Puppets</span> do not grant kills or style points, but their <span style="color:var(--smileos2-emphasis)">blood</span> can still <span style="color:var(--smileos2-emphasis)">heal</span>.`,
`When facing down <span style="color:var(--smileos2-emphasis)">a difficult foe</span>, it may be beneficial to first get rid of the <span style="color:var(--smileos2-emphasis)">fodder</span> to reduce distractions.`,
`Sometimes it may be more beneficial to <span style="color:var(--smileos2-emphasis)">stay at a distance</span> and wait for an opening <span style="color:var(--smileos2-emphasis)">before</span> getting close.`,
`If you're having <span style="color:var(--smileos2-emphasis)">trouble</span> with a specific encounter, take a moment to <span style="color:var(--smileos2-emphasis)">weigh your options</span>. <br> There may be some <span style="color:var(--smileos2-emphasis)">trick</span>, <span style="color:var(--smileos2-emphasis)">tool</span> or <span style="color:var(--smileos2-emphasis)">alternative prioritization</span> that will tip the scales in your favor.`,
`<span style="color:var(--smileos2-emphasis)">ENEMY STEP</span>: Jump while in mid-air <span style="color:var(--smileos2-emphasis)">near an enemy</span> to jump off the enemy. This resets the amount of available walljumps without needing to land.`,
`<span style="color:var(--smileos2-emphasis)">Parries</span> can be used as a powerful healing tool.<br><br>Parrying any enemy projectile or melee attack will <span style="color:red">fully replenish your health</span> up to the hard damage limit.`,
`H a v e &nbsp; f u n .`,
`If blown too far off the arena, <span style="color:lime">PUMP CHARGE</span>'s overcharge is a good way to get back.`,
`<span style="color:var(--smileos2-emphasis)">CHEATS</span> can be enabled in other levels by inputting <span style="color:var(--smileos2-emphasis)">🡡 🡡 🡣 🡣 🡠 🡢 🡠 🡢 B A</span> Enabling cheats will disable ranks`,
`You can pick up the cut weapons on the second floor.`
]
var click = new Audio('/static/content/smileos/SmileOS2Click.ogx');
document.getElementById("smileos-about").addEventListener("click", function() {
click.play();
document.getElementById("smileos-window-title").innerHTML = "About";
document.getElementById("smileos-window-content").innerHTML = `
<span class="red">SmileOS</span>: is the operating system found on most digital interfaces found throughout
<span class="red">Hell</span>. <span class="red">SmileOS 1.0</span> is employed on pannels despite its poor user and developer experience to conserve
blood after the war, while <span class="red">SmileOS 2.0</span> is used for terminals requireing higher blood consumption.
`;
});
document.getElementById("smileos-snake").addEventListener("click", function() {
click.play();
document.getElementById("smileos-window-title").innerHTML = "Snake";
document.getElementById("smileos-window-content").innerHTML = `
<img src="/static/content/smileos/KITR_Build.webp" alt="under construction">
`;
});
document.getElementById("smileos-leaderboard").addEventListener("click", function() {
click.play();
document.getElementById("smileos-window-title").innerHTML = "Leaderboard";
document.getElementById("smileos-window-content").innerHTML = `
<img src="/static/content/smileos/KITR_Build.webp" alt="under construction">
`;
});
document.getElementById("smileos-tip").addEventListener("click", function() {
click.play();
document.getElementById("smileos-window-title").innerHTML = "Tip of the Day";
document.getElementById("smileos-window-content").innerHTML = tips_of_the_day[Math.floor(Math.random() * tips_of_the_day.length)];
});
async function playAudio(url) {
return new Promise((resolve) => {
const audio = new Audio(url);
audio.addEventListener('ended', resolve); // Resolve the promise when audio ends
audio.volume = 0.4;
audio.play();
});
}
document.addEventListener("DOMContentLoaded", async function() {
document.getElementById("smileos-window-title").innerHTML = "Tip of the Day";
document.getElementById("smileos-window-content").innerHTML = tips_of_the_day[Math.floor(Math.random() * tips_of_the_day.length)];
await playAudio('/static/content/smileos/SmileOS2Startup.ogx');
var music = new Audio('/static/content/smileos/Shopmusic.ogx');
music.loop = true;
music.volume = 0.2;
music.play();
});
document.getElementById("smileos-restart-music").addEventListener("click", async function() {
await playAudio('/static/content/smileos/SmileOS2Startup.ogx');
var music = new Audio('/static/content/smileos/Shopmusic.ogx');
music.loop = true;
music.volume = 0.2;
music.play();
});
document.getElementById("secret").addEventListener("click", function() {
click.play();
document.getElementById("smileos-window-title").innerHTML = "Secret :3";
document.getElementById("smileos-window-content").innerHTML = `
Well you found me, here's your <a class="red" href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">Prize</a> :3
`;
});
-174
View File
@@ -1,174 +0,0 @@
const canvas = document.getElementById('snakeCanvas');
const ctx = canvas.getContext('2d');
const gridSize = 20;
const tileSize = 100;
const snakeSize = 60;
const foodSize = 80;
canvas.width = gridSize * tileSize;
canvas.height = gridSize * tileSize;
let snake = [{ x: 10, y: 10 }, { x: 10, y: 11 }, { x: 10, y: 12 }];
let direction = { x: 0, y: 0 };
let food = { x: Math.floor(Math.random() * gridSize), y: Math.floor(Math.random() * gridSize) };
let score = 0;
let gameOver = false;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw grid of checkerboard pattern
for (let x = 0; x < gridSize; x++) {
for (let y = 0; y < gridSize; y++) {
ctx.fillStyle = (x + y) % 2 === 0 ?
getComputedStyle(document.documentElement).getPropertyValue('--background-color') :
getComputedStyle(document.documentElement).getPropertyValue('--secondary-background-color');
ctx.fillRect(x * tileSize, y * tileSize, tileSize, tileSize);
}
}
// Draw snake
snake.forEach(segment => {
let nextVec = { x: 0, y: 0 };
// if there is a segment after the current segment
if (snake.indexOf(segment) < snake.length - 1) {
const nextSegment = snake[snake.indexOf(segment) + 1];
nextVec.x = nextSegment.x - segment.x;
nextVec.y = nextSegment.y - segment.y;
}
ctx.fillStyle = getComputedStyle(document.documentElement).getPropertyValue('--primary-color');
if (nextVec.x === 0 && nextVec.y === 0) {
ctx.fillRect(
segment.x * tileSize + (tileSize - snakeSize) / 2,
segment.y * tileSize + (tileSize - snakeSize) / 2,
snakeSize,
snakeSize
);
} else if (nextVec.x > 0 || nextVec.y > 0) {
ctx.fillRect(
segment.x * tileSize + (tileSize - snakeSize) / 2,
segment.y * tileSize + (tileSize - snakeSize) / 2,
snakeSize + nextVec.x * (tileSize - snakeSize),
snakeSize + nextVec.y * (tileSize - snakeSize)
);
} else {
ctx.fillRect(
segment.x * tileSize + (tileSize - snakeSize) / 2 + nextVec.x * (tileSize - snakeSize),
segment.y * tileSize + (tileSize - snakeSize) / 2 + nextVec.y * (tileSize - snakeSize),
snakeSize + Math.abs(nextVec.x) * (tileSize - snakeSize),
snakeSize + Math.abs(nextVec.y) * (tileSize - snakeSize)
);
}
});
// Draw food
ctx.fillStyle = '#ff4d4d';
ctx.fillRect(
food.x * tileSize + (tileSize - foodSize) / 2,
food.y * tileSize + (tileSize - foodSize) / 2,
foodSize,
foodSize
);
}
function update() {
if (gameOver) return;
// Move snake
const head = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };
// Add new head
snake.unshift(head);
// Check for food collision
if (head.x === food.x && head.y === food.y) {
score += 10; // Increase score
placeFood();
} else {
snake.pop(); // Remove tail if no food eaten
}
// Check for wall collision
if (head.x < 0 || head.x >= gridSize || head.y < 0 || head.y >= gridSize) {
gameOver = true;
return;
}
// Check for self collision
for (let i = 1; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
gameOver = true;
return;
}
}
}
function placeFood() {
do {
food.x = Math.floor(Math.random() * gridSize);
food.y = Math.floor(Math.random() * gridSize);
} while (snake.some(segment => segment.x === food.x && segment.y === food.y));
}
function changeDirection(event) {
switch (event.key) {
case 'w':
if (direction.y === 0) direction = { x: 0, y: -1 };
break;
case 's':
if (direction.y === 0) direction = { x: 0, y: 1 };
break;
case 'a':
if (direction.x === 0) direction = { x: -1, y: 0 };
break;
case 'd':
if (direction.x === 0) direction = { x: 1, y: 0 };
break;
}
}
// Menu to start the game
function menu() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = getComputedStyle(document.documentElement).getPropertyValue('--background-color');
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.textAlign = 'center';
ctx.fillStyle = getComputedStyle(document.documentElement).getPropertyValue('--text-color');
ctx.font = '200px Arial';
ctx.fillText('Snake Game', canvas.width / 2, canvas.height / 2);
ctx.font = '100px Arial';
ctx.fillText('Press W/A/S/D to move', canvas.width / 2, canvas.height / 2 + 100);
ctx.fillText('Click to start', canvas.width / 2, canvas.height / 2 + 200);
canvas.addEventListener('click', startGame);
}
function gameLoop() {
if (!gameOver) {
update();
draw();
setTimeout(gameLoop, 100);
} else {
document.removeEventListener('keydown', changeDirection);
document.getElementById('snake-score').value = score;
alert(`Game Over! Your score: ${score}`);
menu();
}
}
function startGame() {
snake = [{ x: 10, y: 10 }, { x: 10, y: 11 }, { x: 10, y: 12 }];
direction = { x: 1, y: 0 };
food = { x: Math.floor(Math.random() * gridSize), y: Math.floor(Math.random() * gridSize) };
score = 0;
gameOver = false;
canvas.removeEventListener('click', startGame);
document.addEventListener('keydown', changeDirection);
gameLoop();
}
menu();
+78
View File
@@ -0,0 +1,78 @@
//YELLOW TERMINAL
// onionring.js is made up of four files - onionring-widget.js (this one!), onionring-index.js, onionring-variables.js and onionring.css
// it's licensed under the cooperative non-violent license (CNPL) v4+ (https://thufie.lain.haus/NPL.html)
// it was originally made by joey + mord of allium (蒜) house, last updated 2020-11-24
// === ONIONRING-WIDGET ===
//this file contains the code which builds the widget shown on each page in the ring. ctrl+f 'EDIT THIS' if you're looking to change the actual html of the widget
var tag = document.getElementById(ringID); //find the widget on the page
thisSite = window.location.href; //get the url of the site we're currently on
thisIndex = null;
// FIX
thisSite = thisSite.replace("alfieking.dev", "proot.uk"); // fix domain
thisSite = thisSite.replace("http:\/\/127.0.0.1:5000", "https:\/\/proot.uk"); // For debug purposes
// go through the site list to see if this site is on it and find its position
for (i = 0; i < sites.length; i++) {
if (thisSite.startsWith(sites[i])) { //we use startswith so this will match any subdirectory, users can put the widget on multiple pages
thisIndex = i;
break; //when we've found the site, we don't need to search any more, so stop the loop
}
}
function randomUltraRingSite() {
otherSites = sites.slice(); //create a copy of the sites list
otherSites.splice(thisIndex, 1); //remove the current site so we don't just land on it again
randomIndex = Math.floor(Math.random() * otherSites.length);
location.href = otherSites[randomIndex];
}
//if we didn't find the site in the list, the widget displays a warning instead
if (thisIndex == null) {
tag.insertAdjacentHTML('afterbegin', `
<table>
<tr>
<td>This site isn't part of <a href="https://jack-dawlia.neocities.org/page/shrines/ultrakill/ULTRARING" target='_parent'>${ringName}</a> yet!</td>
</tr>
</table>
`);
}
else {
//find the 'next' and 'previous' sites in the ring. this code looks complex
//because it's using a shorthand version of an if-else statement to make sure
//the first and last sites in the ring join together correctly
previousIndex = (thisIndex-1 < 0) ? sites.length-1 : thisIndex-1;
nextIndex = (thisIndex+1 >= sites.length) ? 0 : thisIndex+1;
indexText = ""
//if you've chosen to include an index, this builds the link to that
if (useIndex) {
indexText = `<a href='${indexPage}' class="textshadow" target='_parent'>[INDEX]</a> | `;
}
randomText = ""
//if you've chosen to include a random button, this builds the link that does that
if (useRandom) {
randomText = `<a href='javascript:void(0)' onclick='randomUltraRingSite()' style="color: red;" class="textshadow" target='_parent'>[RANDOM]</a>`;
}
//this is the code that displays the widget - EDIT THIS if you want to change the structure
tag.insertAdjacentHTML('afterbegin', `
<table>
<tr>
<td class='webring-prev'><a href='${sites[previousIndex]}' style="color: red;" class="textshadow" title="[PREV]" target='_parent'><<</a></td>
<td class='webring-info'><a href="https://jack-dawlia.neocities.org/page/shrines/ultrakill/ULTRARING" style="color: red;" target='_parent'><img src="https://jack-dawlia.neocities.org/image/ultraring-yellow-terminal.png" alt="This site is part of ULTRARING" title="ULTRARING" style="max-width:100%"></a></br>
<span class='webring-links'>
${randomText}
${indexText}
<td class='webring-next'><a href='${sites[nextIndex]}' style="color: red;" title="[NEXT]" target='_parent'>>></a></td>
</tr>
</table>
`);
}
-81
View File
@@ -1,81 +0,0 @@
{% extends "base.html" %}
{% block title %}404 - Not Found{% endblock %}
{% block description %}The page you are looking for does not exist.{% endblock %}
{% block head %}
<link rel="stylesheet" href="/static/css/404.css">
<link rel="stylesheet" href="/static/css/cap.css">
{% endblock %}
{% block content %}
<section>
<h1>404</h1>
<p>
It seems like the thing you are looking for is not here :[
<br><br>
<span class="pcOnly">
while you're here, why not play some snake?
</span>
<span class="mobileOnly">
You can't play snake on mobile, sorry :(
</span>
</p>
<div class="pcOnly" id="snakeContainer">
<canvas id="snakeCanvas"></canvas>
</div>
</section>
<section class="pcOnly flex-row">
<section class="min-width">
<h2>Submit score</h2>
<form action="/404/submit" method="POST" id="snakeForm">
<input type="text" id="username" name="username" placeholder="Your name" required>
<cap-widget id="captcha" data-cap-api-endpoint="https://cap.alfieking.dev/57d36430b9cb/api/"></cap-widget>
<input type="hidden" id="snake-score" name="snake-score" value="0">
<button type="submit" id="submit">Submit</button>
</form>
</section>
<section class="max-width" id="snakeLeaderboardSection">
<h2>Leaderboard</h2>
<ul id="snakeLeaderboard">
{% for score in scores %}
<li>
<span>{{ score.position }}</span>
<span>{{ score.name }}</span>
<span>{{ score.score }}</span>
</li>
{% endfor %}
</ul>
</section>
</section>
<section class="max-width mobileOnly" id="snakeLeaderboardSection">
<h2>Leaderboard</h2>
<ul id="snakeLeaderboard">
{% for score in scores %}
<li>
<span>{{ score.position }}</span>
<span>{{ score.name }}</span>
<span>{{ score.score }}</span>
</li>
{% endfor %}
</ul>
</section>
{% if error %}
<dialog id="errorDialog">
<h2>Error</h2>
<p>{{ error }}</p>
<button onclick="errorDialog.close()">Close</button>
</dialog>
<script>
const errorDialog = document.getElementById('errorDialog');
if (errorDialog) {
errorDialog.showModal();
}
</script>
{% endif %}
{% endblock %}
{% block scripts %}
<script src="/static/js/snake.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@cap.js/widget"></script>
{% endblock %}
-101
View File
@@ -1,101 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Alfie's basement{% endblock %}</title>
<link rel="icon" href="/static/content/icon.webp">
<link rel="stylesheet" href="/static/css/base.css">
<meta name="description" content="{% block description %}server backend survivor{% endblock %}">
<meta name="keywords" content="Alfie King, Alfie, King, Alfieking, Alfieking.dev, dev, server">
<meta name="author" content="Alfie King">
<meta name="robots" content="all">
<meta name="theme-color" content="#63de90" data-react-helmet="true">
<meta property="og:site_name" content="Alfieking.dev">
<meta property="og:url" content="https://alfieking.dev">
<meta property="og:title" content="{{ self.title() }}">
<meta property="og:description" content="{{ self.description() }}">
<meta property="og:image" content="/static/content/icon.webp">
{% block head %}
{% endblock %}
</head>
<body>
<div id="furry"></div>
<div id="sidebar">
<nav>
<section>
<h1>Things to see :3</h1>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/toaster">Toaster</a></li>
<li><a href="https://git.alfieking.dev/acetheking987">Gitea</a></li>
<li><a href="https://www.last.fm/user/acetheking987">LastFm</a></li>
<li><a href="https://prismic.alfieking.dev">Prismic</a></li>
<li><a href="https://open.spotify.com/user/xz02oolstlvwxqu1pfcua9exz?si=14396e637f284e03">Spotify</a></li>
<li><a href="https://steamcommunity.com/id/acetheking987/">Steam</a></li>
<li><a href="https://www.youtube.com/@acetheking987">YouTube</a></li>
<li><a href="https://acetheking987.tumblr.com/">Tumblr</a></li>
<li><a href="https://www.reddit.com/user/acetheking987">Reddit</a></li>
<li><a href="/404">404 >:3</a></li>
</ul>
</section>
</nav>
<section>
<h6 class="irken">heya, try typing "furry" and "irken" into this page!</h6>
</section>
<section id="buttons">
<h1>BUTTONS</h1>
<ul>
<li><a href="https://dimden.dev/"><img src="https://dimden.dev/services/images/88x31.gif" alt="dimden"></a></li>
<li><a href="https://ne0nbandit.neocities.org/"><img src="https://ne0nbandit.github.io/assets/img/btn/mine/nbbanner.png" alt="ne0nbandit"></a></li>
<li><a href="https://thinliquid.dev"><img src="https://thinliquid.dev/thnlqd.png" alt="thinliquid"></a></li>
<li><a href="https://nekoweb.org/"><img src="https://nekoweb.org/assets/buttons/button6.gif" alt="nekoweb"></a><!-- button by s1nez.nekoweb.org --></li>
<li><a href="https://s1nez.nekoweb.org/"><img src="https://s1nez.nekoweb.org/BUTTON.gif" alt="s1nez"></a></li>
<li><a href="https://beeps.website"><img src="https://beeps.website/assets/images/88x31-d.gif" alt="beeps"></a></li>
<li><a href="https://itsnotstupid.com"><img src="https://itsnotstupid.com/pics/button1.gif" alt="itsnotstupid"></a></li>
<li><a href='https://blinkies.cafe'><img src='https://blinkies.cafe/b/display/blinkiesCafe-badge.gif' alt='blinkies.cafe | make your own blinkies!'></a></li>
<li><a href="https://eightyeightthirty.one"><img src="https://eightyeightthirty.one/88x31.png" alt="88x31"></a></li>
<li><a href="https://neocities.org"><img src="https://cyber.dabamos.de/88x31/neocities-now.gif" alt="neocities"></a></li>
<li><a href="https://tuxedodragon.art"><img src="https://tuxedodragon.art/tuxedodragon%2088x31.gif" alt="tuxedodragon"></a></li>
</ul>
</section>
<section>
<pre class="vsmoltext"> |\ _,,,---,,_<br>ZZZzz /,`.-'`' -. ;-;;,_<br> |,4- ) )-,_. ,\ ( `'-'<br> '---''(_/--' `-'\_)</pre>
</section>
<img src="/static/content/haj.gif" alt="haj" class="haj">
</div>
<main id="main">
<header id="home">
<div class="row">
<img src="/static/content/icon.webp">
<div>
<h1>Alfie King</h1>
<h2 id="typing">server backend survivor</h2>
</div>
</div>
</header>
<nav id="alt-nav">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/toaster">Toaster</a></li>
<li><a href="https://git.alfieking.dev/acetheking987">Gitea</a></li>
<li><a href="https://www.last.fm/user/acetheking987">LastFm</a></li>
<li><a href="https://prismic.alfieking.dev">Prismic</a></li>
<li><a href="https://open.spotify.com/user/xz02oolstlvwxqu1pfcua9exz?si=14396e637f284e03">Spotify</a></li>
<li><a href="https://steamcommunity.com/id/acetheking987/">Steam</a></li>
<li><a href="https://www.youtube.com/@acetheking987">YouTube</a></li>
<li><a href="https://acetheking987.tumblr.com/">Tumblr</a></li>
<li><a href="https://www.reddit.com/user/acetheking987">Reddit</a></li>
</ul>
</nav>
{% block content %}{% endblock %}
<section>
<footer>
<p>legal stuff idk :3 | icba to &copy; this :P | made with &hearts; and caffine</p>
</footer>
</section>
</main>
{% block scripts %}{% endblock %}
<script src="/static/js/base.js"></script>
</body>
</html>
+137
View File
@@ -0,0 +1,137 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Toasters's basement{% endblock %}</title>
<link rel="icon" href="toaster/Toaster_v1.0_sticker.png">
<link rel="stylesheet" href="/static/css/bases/base.css">
<meta name="description" content="{% block description %}server backend survivor{% endblock %}">
<meta name="keywords" content="{% block keywords %}Alfie King, Alfie, King, Alfieking, Alfieking.dev, dev, server, developer, backend, selfhost, homelab, Toaster, Toastergen, proot.uk, protogen, furry, fursona{% endblock %}">
<meta name="author" content="Alfie King">
<meta name="robots" content="all">
<meta name="theme-color" content="#63de90" data-react-helmet="true">
<meta property="og:site_name" content="proot.uk">
<meta property="og:url" content="https://proot.uk/">
<meta property="og:title" content="{{ self.title() }}">
<meta property="og:description" content="{{ self.description() }}">
<meta property="og:image" content="toaster/Toaster_v1.0_sticker.png">
{% block head %}
{% endblock %}
</head>
<body>
<div id="furry"></div>
<div id="sidebar">
<nav>
<section>
<h1>Things to see :3</h1>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/toaster">Toaster</a></li>
<li><a href="/terminal" class="ultrafont">Terminal</a></li>
<li><a href="/events">Events</a></li>
<li><a href="https://git.alfieking.dev/acetheking987">Gitea</a></li>
<li><a href="https://listenbrainz.org/user/acetheking987/">Music</a></li>
<li><a href="https://prismic.alfieking.dev">Prismic</a></li>
<li><a href="https://open.spotify.com/user/xz02oolstlvwxqu1pfcua9exz?si=14396e637f284e03">Spotify</a></li>
<li><a href="https://steamcommunity.com/id/acetheking987/">Steam</a></li>
<li><a href="https://www.youtube.com/@acetheking987">YouTube</a></li>
<li><a href="https://acetheking987.tumblr.com/">Tumblr</a></li>
<li><a href="https://www.reddit.com/user/acetheking987">Reddit</a></li>
</ul>
</section>
</nav>
<section>
<h6 class="irken">heya, try typing "owo", "doom" or "<span class="scratch">kfc</span>" into this page!</h6>
</section>
<section id="buttons">
<h1>BUTTONS</h1>
<ul>
<li><a herf="https://hijpixel.nekoweb.org/"><img src="/static/content/buttons/hijpixel.gif" alt="hijpixel"></a></li>
<li><a href="https://lensdeer.neocities.org/"><img src="/static/content/buttons/lensdeer.gif" alt="lensdeer"></a></li>
<li><a href="https://emmixis.net/"><img src="/static/content/buttons/emmixis.gif" alt="emmixis"></a></li>
<li><a href="https://dimden.dev/"><img src="https://dimden.dev/services/images/88x31.gif" alt="dimden"></a></li><!-- hotlink on purpose -->
<li><a href="https://ne0nbandit.neocities.org/"><img src="/static/content/buttons/ne0nbandit.png" alt="ne0nbandit"></a></li>
<li><a href="https://thinliquid.dev"><img src="/static/content/buttons/thnlqd.png" alt="thinliquid"></a></li>
<li><a href="https://nekoweb.org/"><img src="/static/content/buttons/nekoweb.gif" alt="nekoweb"></a><!-- button by s1nez.nekoweb.org --></li>
<li><a href="https://s1nez.nekoweb.org/"><img src="/static/content/buttons/s1nez.gif" alt="s1nez"></a></li>
<li><a href="https://beeps.website"><img src="/static/content/buttons/beeps.gif" alt="beeps"></a></li>
<li><a href="https://itsnotstupid.com"><img src="/static/content/buttons/insia.gif" alt="itsnotstupid"></a></li>
<li><a href='https://blinkies.cafe'><img src='/static/content/buttons/blinkiescafe.gif' alt='blinkies.cafe | make your own blinkies!'></a></li>
<li><a href="https://eightyeightthirty.one"><img src="/static/content/buttons/8831.png" alt="88x31"></a></li>
<li><a href="https://neocities.org"><img src="/static/content/buttons/neocities.gif" alt="neocities"></a></li>
<li><a href="https://tuxedodragon.art"><img src="/static/content/buttons/tuxedodragon.gif" alt="tuxedodragon"></a></li>
<li><a href="https://beepi.ng"><img src="https://beepi.ng/88x31.png" width="88" height="31" alt="unnick"></a></li>
<li><a href="https://sneexy.synth.download"><img src="https://synth.download/assets/buttons/sneexy.svg" alt="Sneexy"></a></li>
<li><a href="https://kraafter.me/"><img src="https://kraafter.me/assets/img/button.png" alt="Kraafter.me button" title="kraaftersite"></a></li>
</ul>
</section>
<section>
<div id='furnix'>
<script type="text/javascript" src="https://tapeykatt.neocities.org/furnix/onionring-variables.js"></script>
<script type="text/javascript" src="/static/js/furnix_widget.js"></script>
</div>
</section>
<section class="webring">
<a href="https://stellophiliac.github.io/roboring">Roboring</a><br>
<a href="https://stellophiliac.github.io/roboring/Toaster/previous"><--</a>
<a href="https://stellophiliac.github.io/roboring/Toaster/next">--></a>
</section>
<section>
<div id='ultraring'>
<script type="text/javascript" src="https://jack-dawlia.neocities.org/page/shrines/ultrakill/ULTRARING/onionring-variables.js"></script>
<script type="text/javascript" src="/static/js/ultraring_widget.js"></script>
<noscript>
This site is part of <a href="https://jack-dawlia.neocities.org/page/shrines/ultrakill/ULTRARING">ULTRARING</a>!
</noscript>
</div>
</section>
<section class="webring">
<a href="https://keithhacks.cyou/furryring.php">Furryring</a><br>
<a href="https://keithhacks.cyou/furryring.php?prev=proot.uk"><--</a>
<a href="https://keithhacks.cyou/furryring.php?next=proot.uk">--></a>
</section>
<iframe width="150" height="450" style="border:none" src="https://dogspit.nekoweb.org/sidelink.html" name="sidelink"></iframe>
<section>
<pre class="vsmoltext"> |\ _,,,---,,_<br>ZZZzz /,`.-'`' -. ;-;;,_<br> |,4- ) )-,_. ,\ ( `'-'<br> '---''(_/--' `-'\_)</pre>
</section>
<img src="/static/content/general_images/haj.gif" alt="haj" class="haj">
</div>
<main id="main">
<header id="home">
<div class="row">
<img src="/static/content/toaster/Toaster_v1.0_sticker.png">
<div>
<h1>Toaster</h1>
<h2 id="typing">server backend survivor</h2>
</div>
</div>
<a href="/toaster" id="toaster-wave">
<img src="/static/content/toaster/Toaster_v1.1.png" alt="toaster">
</a>
</header>
<nav id="alt-nav">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/toaster">Toaster</a></li>
<li><a href="https://git.alfieking.dev/acetheking987">Gitea</a></li>
<li><a href="https://www.last.fm/user/acetheking987">LastFm</a></li>
<li><a href="https://prismic.alfieking.dev">Prismic</a></li>
<li><a href="https://open.spotify.com/user/xz02oolstlvwxqu1pfcua9exz?si=14396e637f284e03">Spotify</a></li>
<li><a href="https://steamcommunity.com/id/acetheking987/">Steam</a></li>
<li><a href="https://www.youtube.com/@acetheking987">YouTube</a></li>
<li><a href="https://acetheking987.tumblr.com/">Tumblr</a></li>
<li><a href="https://www.reddit.com/user/acetheking987">Reddit</a></li>
</ul>
</nav>
{% block content %}{% endblock %}
<section>
<footer>
<p>legal stuff idk :3 | icba to &copy; this :P | made with &hearts; and caffine</p>
</footer>
</section>
</main>
{% block scripts %}{% endblock %}
<script src="/static/js/base.js"></script>
</body>
</html>
+22
View File
@@ -0,0 +1,22 @@
{% extends "bases/base.html" %}
{% block title %}/{{ directory }} - Toaster's basement{% endblock %}
{% block description %}server backend survivor{% endblock %}
{% block head %}
<link rel="stylesheet" href="/static/css/bases/directory.css">
{% endblock %}
{% block scripts %}
{% endblock %}
{% block content %}
<section id="directory">
<h1>/{{ directory }}</h1>
<ul>
{% for page in pages %}
<li><a href="/{{ directory }}{{ page.split('.')[0] }}">{{ page.split('.')[0] }}</a></li>
{% endfor %}
</ul>
</section>
{% endblock %}
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Gallery - Toasters's basement{% endblock %}</title>
</head>
<body>
</body>
</html>
+10
View File
@@ -0,0 +1,10 @@
{% extends "bases/base.html" %}
{% block title %}{{ title }} - Toaster's basement{% endblock %}
{% block description %}server backend survivor{% endblock %}
{% block content %}
<section>
{{ markdown|safe }}
</section>
{% endblock %}
+29
View File
@@ -0,0 +1,29 @@
{% extends "bases/base.html" %}
{% block title %}400 - Internal Server Error{% endblock %}
{% block description %}Bad request. The server could not understand the request due to invalid syntax.{% endblock %}
{% block head %}
<link rel="stylesheet" href="/static/css/errors/400.css">
{% endblock %}
{% block content %}
<section>
<h1>400 - Bad Request</h1>
<p>
What did you do? The server could not understand the request due to invalid syntax. Please check your request and try again.
</p>
<h2>The fuckup in question</h2>
<p>
{% if error %}
{{ error }}
{% else %}
No specific error message provided.
{% endif %}
</p>
<h2>What to do now</h2>
<p>
idk :P
</p>
</section>
{% endblock %}
+19
View File
@@ -0,0 +1,19 @@
{% extends "bases/base.html" %}
{% block title %}404 - Not Found{% endblock %}
{% block description %}The page you are looking for does not exist.{% endblock %}
{% block content %}
<section>
<h1>404</h1>
<p>
It seems like the thing you are looking for does not exist or <code>rm -rf</code> itself out of exsistance.
</p>
</section>
<section>
<h2>Actual error</h2>
<p>
{{ error }}
</p>
</section>
{% endblock %}
@@ -1,10 +1,10 @@
{% extends "base.html" %}
{% extends "bases/base.html" %}
{% block title %}500 - Internal Server Error{% endblock %}
{% block description %}An unexpected error occurred on the server.{% endblock %}
{% block head %}
<link rel="stylesheet" href="/static/css/500.css">
<link rel="stylesheet" href="/static/css/errors/500.css">
{% endblock %}
{% block content %}
@@ -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!
</p>
</section>
<section>
<h2>Actual error</h2>
<p>
{{ error }}
</p>
</section>
{% endblock %}
+16
View File
@@ -0,0 +1,16 @@
{% extends "bases/base.html" %}
{% block title %}{{ code }} - {{ err_name }}{% endblock %}
{% block description %}The page you are looking for does not exist.{% endblock %}
{% block content %}
<section>
<img src="https://http.cat/images/{{ code }}.jpg" alt="">
</section>
<section>
<h2>Actual error</h2>
<p>
{{ description }}
</p>
</section>
{% endblock %}

Some files were not shown because too many files have changed in this diff Show More