From 22cd49a012d13b2ef7894e2d39558637384c0651 Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Sat, 11 Oct 2025 17:39:46 +1100 Subject: [PATCH] feat: Move error responses to new function in tools.py --- blueprints/api.py | 9 +- server.py | 48 ++-- templates/403.html | 53 ++++ templates/assets/js/403.min.js | 1 + templates/assets/js/404.js | 446 --------------------------------- tools.py | 27 +- 6 files changed, 94 insertions(+), 490 deletions(-) create mode 100644 templates/403.html create mode 100644 templates/assets/js/403.min.js delete mode 100644 templates/assets/js/404.js diff --git a/blueprints/api.py b/blueprints/api.py index 5d368b3..cafc8d9 100644 --- a/blueprints/api.py +++ b/blueprints/api.py @@ -4,6 +4,7 @@ import datetime import requests from mail import sendEmail from sol import create_transaction +from tools import getClientIP api_bp = Blueprint('api', __name__) @@ -17,14 +18,6 @@ if 'time-zone' not in ncConfig: ncConfig['time-zone'] = 10 -def getClientIP(request): - x_forwarded_for = request.headers.get("X-Forwarded-For") - if x_forwarded_for: - ip = x_forwarded_for.split(",")[0] - else: - ip = request.remote_addr - return ip - def getGitCommit(): # if .git exists, get the latest commit hash if os.path.isdir(".git"): diff --git a/server.py b/server.py index 48c908f..d4b8d78 100644 --- a/server.py +++ b/server.py @@ -22,8 +22,8 @@ from PIL import Image from blueprints.now import now_bp from blueprints.blog import blog_bp from blueprints.wellknown import wk_bp -from blueprints.api import api_bp, getGitCommit, getClientIP -from tools import isCurl, isCrawler, getAddress, getFilePath +from blueprints.api import api_bp, getGitCommit +from tools import isCurl, isCrawler, getAddress, getFilePath, error_response, getClientIP app = Flask(__name__) CORS(app) @@ -115,13 +115,15 @@ def asset_get(path): if os.path.isfile("templates/assets/img/favicon/" + filename): return send_from_directory("templates/assets/img/favicon", filename) - return render_template("404.html"), 404 + return error_response(request) @app.route("/sitemap") @app.route("/sitemap.xml") def sitemap_get(): # Remove all .html from sitemap + if not os.path.isfile("templates/sitemap.xml"): + return error_response(request) with open("templates/sitemap.xml") as file: sitemap = file.read() @@ -132,7 +134,7 @@ def sitemap_get(): @app.route("/favicon.") def favicon_get(ext): if ext not in ("png", "svg", "ico"): - return render_template("404.html"), 404 + return error_response(request) return send_from_directory("templates/assets/img/favicon", f"favicon.{ext}") @@ -140,7 +142,7 @@ def favicon_get(ext): def javascript_get(name): # Check if file in js directory if not os.path.isfile("templates/assets/js/" + request.path.split("/")[-1]): - return render_template("404.html"), 404 + return error_response(request) return send_from_directory("templates/assets/js", request.path.split("/")[-1]) # endregion @@ -580,12 +582,13 @@ def supersecretpath_get(): @app.route("/download/") def download_get(path): if path not in DOWNLOAD_ROUTES: - return render_template("404.html"), 404 + return error_response(request, message="Invalid download") # Check if file exists path = DOWNLOAD_ROUTES[path] if os.path.isfile(path): return send_file(path) - return render_template("404.html"), 404 + + return error_response(request, message="File not found") @app.route("/hosting/send-enquiry", methods=["POST"]) @@ -704,7 +707,7 @@ def resume_pdf_get(): # Check if file exists if os.path.isfile("data/resume.pdf"): return send_file("data/resume.pdf") - return render_template("404.html"), 404 + return error_response(request, message="Resume not found") # endregion @@ -814,7 +817,7 @@ def catch_all_get(path: str): HANDSHAKE_SCRIPTS = "" if path.lower().replace(".html", "") in RESTRICTED_ROUTES: - return render_template("404.html"), 404 + return error_response(request, message="Restricted route", code=403) if path in REDIRECT_ROUTES: return redirect(REDIRECT_ROUTES[path], code=302) @@ -841,34 +844,11 @@ def catch_all_get(path: str): if filename: return send_file(filename) - if isCurl(request): - return jsonify( - { - "status": 404, - "message": "Page not found", - "ip": getClientIP(request), - } - ), 404 - return render_template("404.html"), 404 - -# 404 catch all - + return error_response(request) @app.errorhandler(404) def not_found(e): - if isCurl(request): - return jsonify( - { - "status": 404, - "message": "Page not found", - "ip": getClientIP(request), - } - ), 404 - - return render_template("404.html"), 404 - - -# endregion + return error_response(request) if __name__ == "__main__": app.run(debug=True, port=5000, host="127.0.0.1") diff --git a/templates/403.html b/templates/403.html new file mode 100644 index 0000000..6d0c3f5 --- /dev/null +++ b/templates/403.html @@ -0,0 +1,53 @@ + + + + + + + Nathan.Woodburn/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

HTTP: 403

+
+
this_page.found = true;if (this_page.readable) {
return this_page;
else {
alert('This page is not readable!');
}
+
+ + + + + + + \ No newline at end of file diff --git a/templates/assets/js/403.min.js b/templates/assets/js/403.min.js new file mode 100644 index 0000000..35d53cf --- /dev/null +++ b/templates/assets/js/403.min.js @@ -0,0 +1 @@ +const trigger="s",secret="/supersecretpath",home="/";var isSecret=!1;function error_check(){return function(){isSecret?(alert("You found the secret path"),window.location=secret):(alert("This page is not readable!"))}}function type(e,t){var n=document.getElementsByTagName("code")[e].innerHTML.toString(),o=0;document.getElementsByTagName("code")[e].innerHTML="",setTimeout((function(){var t=setInterval((function(){o++,document.getElementsByTagName("code")[e].innerHTML=n.slice(0,o)+"|",o==n.length&&(clearInterval(t),document.getElementsByTagName("code")[e].innerHTML=n)}),10)}),t)}setTimeout(error_check(),5e3),document.addEventListener("keydown",(function(e){"s"==e.key&&(isSecret=!0)})),type(0,0),type(1,600),type(2,1300); \ No newline at end of file diff --git a/templates/assets/js/404.js b/templates/assets/js/404.js deleted file mode 100644 index fad922c..0000000 --- a/templates/assets/js/404.js +++ /dev/null @@ -1,446 +0,0 @@ -;(function() { - "use strict"; - - // General - var canvas, - screen, - gameSize, - game; - - // Assets - var invaderCanvas, - invaderMultiplier, - invaderSize = 20, - initialOffsetInvader, - invaderAttackRate, - invaderSpeed, - invaderSpawnDelay = 250; - - // Counter - var i = 0, - kills = 0, - spawnDelayCounter = invaderSpawnDelay; - - var invaderDownTimer; - - // Text - var blocks = [ - [3, 4, 8, 9, 10, 15, 16], - [2, 4, 7, 11, 14, 16], - [1, 4, 7, 11, 13, 16], - [1, 2, 3, 4, 5, 7, 11, 13, 14, 15, 16, 17], - [4, 7, 11, 16], - [4, 8, 9, 10, 16] - ]; - - // Game Controller - // --------------- - var Game = function() { - - this.level = -1; - this.lost = false; - - this.player = new Player(); - this.invaders = []; - this.invaderShots = []; - - if (invaderDownTimer === undefined) { - invaderDownTimer = setInterval(function() { - for (i = 0; i < game.invaders.length; i++) game.invaders[i].move(); - }, 1000 - (this.level * 1.8)); - - }; - } - - Game.prototype = { - update: function() { - - // Next level - if (game.invaders.length === 0) { - - spawnDelayCounter += 1; - if (spawnDelayCounter < invaderSpawnDelay) return; - - this.level += 1; - - invaderAttackRate -= 0.002; - invaderSpeed += 10; - - game.invaders = createInvaders(); - - spawnDelayCounter = 0; - } - - if (!this.lost) { - - // Collision - game.player.projectile.forEach(function(projectile) { - game.invaders.forEach(function(invader) { - if (collides(projectile, invader)) { - invader.destroy(); - projectile.active = false; - } - }); - }); - - this.invaderShots.forEach(function(invaderShots) { - if (collides(invaderShots, game.player)) { - game.player.destroy(); - } - }); - - for (i = 0; i < game.invaders.length; i++) game.invaders[i].update(); - - } - - // Don't stop player & projectiles.. they look nice - game.player.update(); - for (i = 0; i < game.invaderShots.length; i++) game.invaderShots[i].update(); - - this.invaders = game.invaders.filter(function(invader) { - return invader.active; - }); - - }, - - draw: function() { - - if (this.lost) { - screen.fillStyle = "rgba(0, 0, 0, 0.03)"; - screen.fillRect(0, 0, gameSize.width, gameSize.height); - - screen.font = "55px Lucida Console"; - screen.textAlign = "center"; - screen.fillStyle = "white"; - screen.fillText("You lost", gameSize.width / 2, gameSize.height / 2); - screen.font = "20px Lucida Console"; - screen.fillText("Points: " + kills, gameSize.width / 2, gameSize.height / 2 + 30); - - } else { - screen.clearRect(0, 0, gameSize.width, gameSize.height); - - screen.font = "10px Lucida Console"; - screen.textAlign = "right"; - screen.fillText("Points: " + kills, gameSize.width, gameSize.height - 12); - } - - screen.beginPath(); - - var i; - this.player.draw(); - if (!this.lost) - for (i = 0; i < this.invaders.length; i++) this.invaders[i].draw(); - for (i = 0; i < this.invaderShots.length; i++) this.invaderShots[i].draw(); - - screen.fill(); - - }, - - invadersBelow: function(invader) { - return this.invaders.filter(function(b) { - return Math.abs(invader.coordinates.x - b.coordinates.x) === 0 && - b.coordinates.y > invader.coordinates.y; - }).length > 0; - } - - }; - - // Invaders - // -------- - var Invader = function(coordinates) { - this.active = true; - this.coordinates = coordinates; - this.size = { - width: invaderSize, - height: invaderSize - }; - - this.patrolX = 0; - this.speedX = invaderSpeed; - - }; - - Invader.prototype = { - update: function() { - - if (Math.random() > invaderAttackRate && !game.invadersBelow(this)) { - var projectile = new Projectile({ - x: this.coordinates.x + this.size.width / 2, - y: this.coordinates.y + this.size.height - 5 - }, { - x: 0, - y: 2 - }); - game.invaderShots.push(projectile); - } - - }, - draw: function() { - if (this.active) screen.drawImage(invaderCanvas, this.coordinates.x, this.coordinates.y); - - }, - move: function() { - if (this.patrolX < 0 || this.patrolX > 100) { - this.speedX = -this.speedX; - this.patrolX += this.speedX; - this.coordinates.y += this.size.height; - - if (this.coordinates.y + this.size.height * 2 > gameSize.height) game.lost = true; - - } else { - this.coordinates.x += this.speedX; - this.patrolX += this.speedX; - } - - }, - destroy: function() { - this.active = false; - kills += 1; - - } - - }; - - // Player - // ------ - var Player = function() { - this.active = true; - this.size = { - width: 16, - height: 8 - }; - this.shooterHeat = -3; - this.coordinates = { - x: gameSize.width / 2 - (this.size.width / 2) | 0, - y: gameSize.height - this.size.height * 2 - }; - - this.projectile = []; - this.keyboarder = new KeyController(); - }; - - Player.prototype = { - update: function() { - - for (var i = 0; i < this.projectile.length; i++) this.projectile[i].update(); - - this.projectile = this.projectile.filter(function(projectile) { - return projectile.active; - }); - - if (!this.active) return; - - if (this.keyboarder.isDown(this.keyboarder.KEYS.LEFT) && this.coordinates.x > 0) this.coordinates.x -= 2; - else if (this.keyboarder.isDown(this.keyboarder.KEYS.RIGHT) && this.coordinates.x < gameSize.width - this.size.width) this.coordinates.x += 2; - - if (this.keyboarder.isDown(this.keyboarder.KEYS.Space)) { - this.shooterHeat += 1; - if (this.shooterHeat < 0) { - var projectile = new Projectile({ - x: this.coordinates.x + this.size.width / 2 - 1, - y: this.coordinates.y - 1 - }, { - x: 0, - y: -7 - }); - this.projectile.push(projectile); - } else if (this.shooterHeat > 12) this.shooterHeat = -3; - } else { - this.shooterHeat = -3; - } - - }, - draw: function() { - if (this.active) { - screen.rect(this.coordinates.x, this.coordinates.y, this.size.width, this.size.height); - screen.rect(this.coordinates.x - 2, this.coordinates.y + 2, 20, 6); - screen.rect(this.coordinates.x + 6, this.coordinates.y - 4, 4, 4); - } - - for (var i = 0; i < this.projectile.length; i++) this.projectile[i].draw(); - - }, - destroy: function() { - this.active = false; - game.lost = true; - } - }; - - // Projectile - // ------ - var Projectile = function(coordinates, velocity) { - this.active = true; - this.coordinates = coordinates; - this.size = { - width: 3, - height: 3 - }; - this.velocity = velocity; - }; - - Projectile.prototype = { - update: function() { - this.coordinates.x += this.velocity.x; - this.coordinates.y += this.velocity.y; - - if (this.coordinates.y > gameSize.height || this.coordinates.y < 0) this.active = false; - - }, - draw: function() { - if (this.active) screen.rect(this.coordinates.x, this.coordinates.y, this.size.width, this.size.height); - - } - }; - - // Keyboard input tracking - // ----------------------- - var KeyController = function() { - this.KEYS = { - LEFT: 37, - RIGHT: 39, - Space: 32 - }; - var keyCode = [37, 39, 32]; - var keyState = {}; - - var counter; - window.addEventListener('keydown', function(e) { - for (counter = 0; counter < keyCode.length; counter++) - if (keyCode[counter] == e.keyCode) { - keyState[e.keyCode] = true; - e.preventDefault(); - } - - }); - - window.addEventListener('keyup', function(e) { - for (counter = 0; counter < keyCode.length; counter++) - if (keyCode[counter] == e.keyCode) { - keyState[e.keyCode] = false; - e.preventDefault(); - } - }); - - this.isDown = function(keyCode) { - return keyState[keyCode] === true; - }; - - }; - - // Other functions - // --------------- - function collides(a, b) { - return a.coordinates.x < b.coordinates.x + b.size.width && - a.coordinates.x + a.size.width > b.coordinates.x && - a.coordinates.y < b.coordinates.y + b.size.height && - a.coordinates.y + a.size.height > b.coordinates.y; - } - - function getPixelRow(rowRaw) { - var textRow = [], - placer = 0, - row = Math.floor(rowRaw / invaderMultiplier); - if (row >= blocks.length) return []; - for (var i = 0; i < blocks[row].length; i++) { - var tmpContent = blocks[row][i] * invaderMultiplier; - for (var j = 0; j < invaderMultiplier; j++) textRow[placer + j] = tmpContent + j; - placer += invaderMultiplier; - } - return textRow; - } - - // Write Text - // ----------- - function createInvaders() { - var invaders = []; - - var i = blocks.length * invaderMultiplier; - while (i--) { - var j = getPixelRow(i); - for (var k = 0; k < j.length; k++) { - invaders.push(new Invader({ - x: j[k] * invaderSize, - y: i * invaderSize - })); - } - } - return invaders; - } - - // Start game - // ---------- - window.addEventListener('load', function() { - - var invaderAsset = new Image; - invaderAsset.onload = function() { - - invaderCanvas = document.createElement('canvas'); - invaderCanvas.width = invaderSize; - invaderCanvas.height = invaderSize; - invaderCanvas.getContext("2d").drawImage(invaderAsset, 0, 0); - - // Game Creation - canvas = document.getElementById("space-invaders"); - screen = canvas.getContext('2d'); - - initGameStart(); - loop(); - - }; - invaderAsset.src = "/assets/img/invader.gif"; - - }); - - window.addEventListener('resize', function() { - initGameStart(); - }); - document.getElementById('restart').addEventListener('click', function() { - initGameStart(); - }); - - function initGameStart() { - if (window.innerWidth > 1200) { - screen.canvas.width = 1200; - screen.canvas.height = 500; - gameSize = { - width: 1200, - height: 500 - }; - invaderMultiplier = 3; - initialOffsetInvader = 420; - } else if (window.innerWidth > 800) { - screen.canvas.width = 900; - screen.canvas.height = 600; - gameSize = { - width: 900, - height: 600 - }; - invaderMultiplier = 2; - initialOffsetInvader = 280; - } else { - screen.canvas.width = 600; - screen.canvas.height = 300; - gameSize = { - width: 600, - height: 300 - }; - invaderMultiplier = 1; - initialOffsetInvader = 140; - } - - kills = 0; - invaderAttackRate = 0.999; - invaderSpeed = 20; - spawnDelayCounter = invaderSpawnDelay; - - game = new Game(); - } - - function loop() { - game.update(); - game.draw(); - - requestAnimationFrame(loop); - } - -})(); \ No newline at end of file diff --git a/tools.py b/tools.py index dc6fd17..a40101c 100644 --- a/tools.py +++ b/tools.py @@ -1,7 +1,15 @@ -from flask import Request +from flask import Request, render_template, jsonify import os from functools import cache +def getClientIP(request): + x_forwarded_for = request.headers.get("X-Forwarded-For") + if x_forwarded_for: + ip = x_forwarded_for.split(",")[0] + else: + ip = request.remote_addr + return ip + def isCurl(request: Request) -> bool: """ Check if the request is from curl @@ -48,4 +56,19 @@ def getAddress(coin: str) -> str: def getFilePath(name, path): for root, dirs, files in os.walk(path): if name in files: - return os.path.join(root, name) \ No newline at end of file + return os.path.join(root, name) + +def error_response(request: Request, message: str = "404 Not Found", code: int = 404): + if isCurl(request): + return jsonify( + { + "status": code, + "message": message, + "ip": getClientIP(request), + } + ), code + + # Check if .html exists in templates + if os.path.isfile(f"templates/{code}.html"): + return render_template(f"{code}.html"), code + return render_template("404.html"), code \ No newline at end of file