From e175f68d254f71ca60d8d90067412fa99ebca1a0 Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Sun, 26 Oct 2025 15:13:36 +1100 Subject: [PATCH] feat: Add initial ascii art for curl connections --- curl.py | 121 ++++++++++++++++++++++++++++++++++++ server.py | 19 +++--- templates/contact.ascii | 14 +++++ templates/donate.ascii | 25 ++++++++ templates/donate_coin.ascii | 10 +++ templates/donate_more.ascii | 13 ++++ templates/favicon.ascii | 25 ++++++++ templates/header.ascii | 11 ++++ templates/index.ascii | 28 +++++++++ templates/projects.ascii | 7 +++ 10 files changed, 264 insertions(+), 9 deletions(-) create mode 100644 curl.py create mode 100644 templates/contact.ascii create mode 100644 templates/donate.ascii create mode 100644 templates/donate_coin.ascii create mode 100644 templates/donate_more.ascii create mode 100644 templates/favicon.ascii create mode 100644 templates/header.ascii create mode 100644 templates/index.ascii create mode 100644 templates/projects.ascii diff --git a/curl.py b/curl.py new file mode 100644 index 0000000..81dd50d --- /dev/null +++ b/curl.py @@ -0,0 +1,121 @@ +from flask import render_template +from tools import error_response, getAddress +import os +from functools import lru_cache +import requests + + +def clean_path(path:str): + path = path.strip("/ ").lower() + # Strip any .html extension + if path.endswith(".html"): + path = path[:-5] + + # If the path is empty, set it to "index" + if path == "": + path = "index" + return path + +@lru_cache(maxsize=1) +def get_header(): + with open("templates/header.ascii", "r") as f: + return f.read() + +@lru_cache(maxsize=1) +def get_current_project(): + git = requests.get( + "https://git.woodburn.au/api/v1/users/nathanwoodburn/activities/feeds?only-performed-by=true&limit=1", + headers={"Authorization": os.getenv("GIT_AUTH") if os.getenv("GIT_AUTH") else os.getenv("git_token")}, + ) + git = git.json() + git = git[0] + repo_name = git["repo"]["name"] + repo_name = repo_name.lower() + repo_description = git["repo"]["description"] + return f"{repo_name} - {repo_description}" + + +@lru_cache(maxsize=1) +def get_projects(): + projectsreq = requests.get( + "https://git.woodburn.au/api/v1/users/nathanwoodburn/repos" + ) + + projects = projectsreq.json() + + # Check for next page + pageNum = 1 + while 'rel="next"' in projectsreq.headers["link"]: + projectsreq = requests.get( + "https://git.woodburn.au/api/v1/users/nathanwoodburn/repos?page=" + + str(pageNum) + ) + projects += projectsreq.json() + pageNum += 1 + + # Sort by last updated + projectsList = sorted( + projects, key=lambda x: x["updated_at"], reverse=True) + projects = "" + projectNum = 0 + includedNames = [] + while len(includedNames) < 5 and projectNum < len(projectsList): + # Avoid duplicates + if projectsList[projectNum]["name"] in includedNames: + projectNum += 1 + continue + includedNames.append(projectsList[projectNum]["name"]) + project = projectsList[projectNum] + projects += f"""{project['name']} - {project['description'] if project['description'] else 'No description'} +{project['html_url']} + +""" + projectNum += 1 + + return projects + +def curl_response(request): + # Check if .ascii exists + path = clean_path(request.path) + + # Handle special cases + if path == "index": + # Get current project + return render_template("index.ascii",header=get_header(),repo=get_current_project()), 200, {'Content-Type': 'text/plain; charset=utf-8'} + if path == "projects": + # Get projects + return render_template("projects.ascii",header=get_header(),projects=get_projects()), 200, {'Content-Type': 'text/plain; charset=utf-8'} + + if path == "donate": + # Get donation info + return render_template("donate.ascii",header=get_header(), + HNS=getAddress("HNS"), BTC=getAddress("BTC"), + SOL=getAddress("SOL"), ETH=getAddress("ETH") + ), 200, {'Content-Type': 'text/plain; charset=utf-8'} + + if path == "donate/more": + coinList = os.listdir(".well-known/wallets") + coinList = [file for file in coinList if file[0] != "."] + coinList.sort() + return render_template("donate_more.ascii",header=get_header(), + coins=coinList + ), 200, {'Content-Type': 'text/plain; charset=utf-8'} + + + + # For other donation pages, fall back to ascii if it exists + if path.startswith("donate/"): + coin = path.split("/")[1] + address = getAddress(coin) + if address != "": + return render_template("donate_coin.ascii",header=get_header(),coin=coin.upper(),address=address), 200, {'Content-Type': 'text/plain; charset=utf-8'} + + + if os.path.exists(f"templates/{path}.ascii"): + return render_template(f"{path}.ascii",header=get_header()), 200, {'Content-Type': 'text/plain; charset=utf-8'} + + # Fallback to html if it exists + if os.path.exists(f"templates/{path}.html"): + return render_template(f"{path}.html") + + return error_response(request) \ No newline at end of file diff --git a/server.py b/server.py index 37ced1c..87c568a 100644 --- a/server.py +++ b/server.py @@ -25,7 +25,8 @@ from blueprints.wellknown import wk_bp from blueprints.api import api_bp from blueprints.podcast import podcast_bp from blueprints.acme import acme_bp -from tools import isCurl, isCrawler, getAddress, getFilePath, error_response, getClientIP, json_response, getGitCommit, isDev, getHandshakeScript, get_tools_data +from tools import isCurl, isCrawler, getAddress, getFilePath, error_response, getClientIP, json_response, getHandshakeScript, get_tools_data +from curl import curl_response app = Flask(__name__) CORS(app) @@ -242,14 +243,7 @@ def index(): if request.args.get("load"): loaded = False if isCurl(request): - return jsonify( - { - "message": "Welcome to Nathan.Woodburn/! This is a personal website. For more information, visit https://nathan.woodburn.au", - "ip": getClientIP(request), - "dev": isDev(request.host), - "version": getGitCommit() - } - ) + return curl_response(request) if not loaded and not isCrawler(request): # Set cookie @@ -401,6 +395,9 @@ def index(): # region Donate @app.route("/donate") def donate(): + if isCurl(request): + return curl_response(request) + coinList = os.listdir(".well-known/wallets") coinList = [file for file in coinList if file[0] != "."] coinList.sort() @@ -702,6 +699,10 @@ def catch_all(path: str): if path.lower().replace(".html", "") in RESTRICTED_ROUTES: return error_response(request, message="Restricted route", code=403) + # If curl request, return curl response + if isCurl(request): + return curl_response(request) + if path in REDIRECT_ROUTES: return redirect(REDIRECT_ROUTES[path], code=302) diff --git a/templates/contact.ascii b/templates/contact.ascii new file mode 100644 index 0000000..9264a45 --- /dev/null +++ b/templates/contact.ascii @@ -0,0 +1,14 @@ +{{header}} +─────────────────────────────────────────────── + CONTACT ME  +──────────── + +Here are my socials — I’m most active on Discord 💬 + +- Twitter: https://twitter.com/woodburn_nathan +- GitHub: https://github.com/Nathanwoodburn +- Email: mailto:about@nathan.woodburn.au +- Discord: https://l.woodburn.au/discord +- Mastodon: https://mastodon.woodburn.au/@nathanwoodburn +- YouTube: https://www.youtube.com/@nathanjwoodburn + diff --git a/templates/donate.ascii b/templates/donate.ascii new file mode 100644 index 0000000..cf8b6a3 --- /dev/null +++ b/templates/donate.ascii @@ -0,0 +1,25 @@ +{{header}} +─────────────────────────────────────────────── + DONATE  +──────── + +If you’d like to support my work 💙 + +- PayPal: [https://paypal.me/nathanwoodburn] +- GitHub: [https://github.com/sponsors/Nathanwoodburn] +- Stripe: [https://donate.stripe.com/8wM6pv0VD08Xe408ww] + +HNS: nathan.woodburn +{{ HNS }} + +BTC: thinbadger6@primal.net +{{ BTC }} + +SOL: woodburn.sol +{{ SOL }} + +ETH: woodburn.au +{{ ETH }} + +More donation options → [/donate/more] + diff --git a/templates/donate_coin.ascii b/templates/donate_coin.ascii new file mode 100644 index 0000000..05c846c --- /dev/null +++ b/templates/donate_coin.ascii @@ -0,0 +1,10 @@ +{{header}} +─────────────────────────────────────────────── + DONATE  +──────── + +Here is my {{ coin }} address if you'd like to send a donation 💙 +{{ address }} + +Thank you for your support! 🙏 + diff --git a/templates/donate_more.ascii b/templates/donate_more.ascii new file mode 100644 index 0000000..d030734 --- /dev/null +++ b/templates/donate_more.ascii @@ -0,0 +1,13 @@ +{{header}} +─────────────────────────────────────────────── + DONATE  +──────── + +Here is a list of additional cryptocurrencies and donation methods 💙 +For each coin below, you can get the address from /donate/ + +{% for coin in coins %}{% if loop.index0 % 4 == 0 and loop.index0 != 0 %} +{% endif %}{{ coin }}{% if not loop.last %}, {% endif %}{% endfor %} + +Thank you for your support! 🙏 + diff --git a/templates/favicon.ascii b/templates/favicon.ascii new file mode 100644 index 0000000..f09df9a --- /dev/null +++ b/templates/favicon.ascii @@ -0,0 +1,25 @@ +▒▒▒ ▓▓▓ +▒░░░░▒▓ ▓▓▓▓▓▓▓ +▒░░░░░░▒▒▒▒ ▓▓▓▓▓▓▓▓▓▓▓ +▒░░░░░▒▒▒▒▒▒▒ ▓▓▒▓▓▓▓▓▓▓▓▓▓ +▒░░░▒▒▒▒▒▒▒▒▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒░░▒▒▒▒▒▒▒▒▒▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒ ▒▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓▒▒▒▒ ▒▒▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓▒▒▒▒▒▒ ▒▒▒▒▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓▒▒▒▒▒▒▒▒▒ ▒▒▒▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓▒▒▒▒▒▒▒▒▒▒▒ ▒▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█ + ▓▒▒▒▒▒▒▒▒▒▒▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▒▒▒▒▓▓▓ ▓▓▓▓▓▓▓▓█ + ▓▓▓▓ ▓▓▓█ + diff --git a/templates/header.ascii b/templates/header.ascii new file mode 100644 index 0000000..f50ed64 --- /dev/null +++ b/templates/header.ascii @@ -0,0 +1,11 @@ +───────────────────────────────────────────────────── + . . , . . . .. /  + |\ | _.-+-|_ _.._ | | _ _ _||_ . .._.._ /  + | \|(_] | [ )(_][ ) * |/\|(_)(_)(_][_)(_|[ [ )/  +───────────────────────────────────────────────────── + +Home [/] +Contact [/contact] +Projects [/projects] +Donate [/donate] + diff --git a/templates/index.ascii b/templates/index.ascii new file mode 100644 index 0000000..00c193b --- /dev/null +++ b/templates/index.ascii @@ -0,0 +1,28 @@ +{{header}} +─────────────────────────────────────────────── + ABOUT ME  +────────── + +Hi, I'm Nathan Woodburn from Canberra, Australia. +I've been homeschooled through Year 12 and am now studying a +Bachelor of Computer Science. + +I love building random projects, so this site is always evolving. +I'm also one of the founders of Handshake AU [https://hns.au], +working to grow Handshake adoption across Australia. + +I'm currently working on: {{ repo | safe }} + +─────────────────────────────────────────────── + SKILLS  +──────── + +- Linux servers & CLI +- DNS, DNSSEC, and Trustless SSL +- NGINX web servers +- Programming: + - Python 3 + - C# + - Java + - Bash + diff --git a/templates/projects.ascii b/templates/projects.ascii new file mode 100644 index 0000000..61f4067 --- /dev/null +++ b/templates/projects.ascii @@ -0,0 +1,7 @@ +{{header}} +─────────────────────────────────────────────── + RECENT PROJECTS  +───────────────── + +{{projects}} +