feat: Move error responses to new function in tools.py
All checks were successful
Build Docker / BuildImage (push) Successful in 1m6s
All checks were successful
Build Docker / BuildImage (push) Successful in 1m6s
This commit is contained in:
@@ -4,6 +4,7 @@ import datetime
|
|||||||
import requests
|
import requests
|
||||||
from mail import sendEmail
|
from mail import sendEmail
|
||||||
from sol import create_transaction
|
from sol import create_transaction
|
||||||
|
from tools import getClientIP
|
||||||
|
|
||||||
|
|
||||||
api_bp = Blueprint('api', __name__)
|
api_bp = Blueprint('api', __name__)
|
||||||
@@ -17,14 +18,6 @@ if 'time-zone' not in ncConfig:
|
|||||||
ncConfig['time-zone'] = 10
|
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():
|
def getGitCommit():
|
||||||
# if .git exists, get the latest commit hash
|
# if .git exists, get the latest commit hash
|
||||||
if os.path.isdir(".git"):
|
if os.path.isdir(".git"):
|
||||||
|
|||||||
48
server.py
48
server.py
@@ -22,8 +22,8 @@ from PIL import Image
|
|||||||
from blueprints.now import now_bp
|
from blueprints.now import now_bp
|
||||||
from blueprints.blog import blog_bp
|
from blueprints.blog import blog_bp
|
||||||
from blueprints.wellknown import wk_bp
|
from blueprints.wellknown import wk_bp
|
||||||
from blueprints.api import api_bp, getGitCommit, getClientIP
|
from blueprints.api import api_bp, getGitCommit
|
||||||
from tools import isCurl, isCrawler, getAddress, getFilePath
|
from tools import isCurl, isCrawler, getAddress, getFilePath, error_response, getClientIP
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
CORS(app)
|
CORS(app)
|
||||||
@@ -115,13 +115,15 @@ def asset_get(path):
|
|||||||
if os.path.isfile("templates/assets/img/favicon/" + filename):
|
if os.path.isfile("templates/assets/img/favicon/" + filename):
|
||||||
return send_from_directory("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")
|
||||||
@app.route("/sitemap.xml")
|
@app.route("/sitemap.xml")
|
||||||
def sitemap_get():
|
def sitemap_get():
|
||||||
# Remove all .html from sitemap
|
# Remove all .html from sitemap
|
||||||
|
if not os.path.isfile("templates/sitemap.xml"):
|
||||||
|
return error_response(request)
|
||||||
with open("templates/sitemap.xml") as file:
|
with open("templates/sitemap.xml") as file:
|
||||||
sitemap = file.read()
|
sitemap = file.read()
|
||||||
|
|
||||||
@@ -132,7 +134,7 @@ def sitemap_get():
|
|||||||
@app.route("/favicon.<ext>")
|
@app.route("/favicon.<ext>")
|
||||||
def favicon_get(ext):
|
def favicon_get(ext):
|
||||||
if ext not in ("png", "svg", "ico"):
|
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}")
|
return send_from_directory("templates/assets/img/favicon", f"favicon.{ext}")
|
||||||
|
|
||||||
|
|
||||||
@@ -140,7 +142,7 @@ def favicon_get(ext):
|
|||||||
def javascript_get(name):
|
def javascript_get(name):
|
||||||
# Check if file in js directory
|
# Check if file in js directory
|
||||||
if not os.path.isfile("templates/assets/js/" + request.path.split("/")[-1]):
|
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])
|
return send_from_directory("templates/assets/js", request.path.split("/")[-1])
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
@@ -580,12 +582,13 @@ def supersecretpath_get():
|
|||||||
@app.route("/download/<path:path>")
|
@app.route("/download/<path:path>")
|
||||||
def download_get(path):
|
def download_get(path):
|
||||||
if path not in DOWNLOAD_ROUTES:
|
if path not in DOWNLOAD_ROUTES:
|
||||||
return render_template("404.html"), 404
|
return error_response(request, message="Invalid download")
|
||||||
# Check if file exists
|
# Check if file exists
|
||||||
path = DOWNLOAD_ROUTES[path]
|
path = DOWNLOAD_ROUTES[path]
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
return send_file(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"])
|
@app.route("/hosting/send-enquiry", methods=["POST"])
|
||||||
@@ -704,7 +707,7 @@ def resume_pdf_get():
|
|||||||
# Check if file exists
|
# Check if file exists
|
||||||
if os.path.isfile("data/resume.pdf"):
|
if os.path.isfile("data/resume.pdf"):
|
||||||
return send_file("data/resume.pdf")
|
return send_file("data/resume.pdf")
|
||||||
return render_template("404.html"), 404
|
return error_response(request, message="Resume not found")
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
@@ -814,7 +817,7 @@ def catch_all_get(path: str):
|
|||||||
HANDSHAKE_SCRIPTS = ""
|
HANDSHAKE_SCRIPTS = ""
|
||||||
|
|
||||||
if path.lower().replace(".html", "") in RESTRICTED_ROUTES:
|
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:
|
if path in REDIRECT_ROUTES:
|
||||||
return redirect(REDIRECT_ROUTES[path], code=302)
|
return redirect(REDIRECT_ROUTES[path], code=302)
|
||||||
@@ -841,34 +844,11 @@ def catch_all_get(path: str):
|
|||||||
if filename:
|
if filename:
|
||||||
return send_file(filename)
|
return send_file(filename)
|
||||||
|
|
||||||
if isCurl(request):
|
return error_response(request)
|
||||||
return jsonify(
|
|
||||||
{
|
|
||||||
"status": 404,
|
|
||||||
"message": "Page not found",
|
|
||||||
"ip": getClientIP(request),
|
|
||||||
}
|
|
||||||
), 404
|
|
||||||
return render_template("404.html"), 404
|
|
||||||
|
|
||||||
# 404 catch all
|
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
def not_found(e):
|
def not_found(e):
|
||||||
if isCurl(request):
|
return error_response(request)
|
||||||
return jsonify(
|
|
||||||
{
|
|
||||||
"status": 404,
|
|
||||||
"message": "Page not found",
|
|
||||||
"ip": getClientIP(request),
|
|
||||||
}
|
|
||||||
), 404
|
|
||||||
|
|
||||||
return render_template("404.html"), 404
|
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(debug=True, port=5000, host="127.0.0.1")
|
app.run(debug=True, port=5000, host="127.0.0.1")
|
||||||
|
|||||||
53
templates/403.html
Normal file
53
templates/403.html
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-bs-theme="light" lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<title>Nathan.Woodburn/</title>
|
||||||
|
<meta name="theme-color" content="#000000">
|
||||||
|
<link rel="canonical" href="https://nathan.woodburn.au/403">
|
||||||
|
<meta property="og:url" content="https://nathan.woodburn.au/403">
|
||||||
|
<meta name="fediverse:creator" content="@nathanwoodburn@mastodon.woodburn.au">
|
||||||
|
<meta name="twitter:description" content="G'day, this is my personal website. You can find out about me or check out some of my projects.">
|
||||||
|
<meta property="og:title" content="Nathan.Woodburn/">
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:image" content="https://nathan.woodburn.au/assets/img/profile.jpg">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta name="twitter:title" content="Nathan.Woodburn/">
|
||||||
|
<meta property="og:description" content="G'day, this is my personal website. You can find out about me or check out some of my projects.">
|
||||||
|
<meta name="description" content="G'day, this is my personal website. You can find out about me or check out some of my projects.">
|
||||||
|
<meta property="og:image" content="https://nathan.woodburn.au/assets/img/profile.jpg">
|
||||||
|
<link rel="apple-touch-icon" type="image/png" sizes="180x180" href="/assets/img/favicon/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/assets/img/favicon/favicon-16x16.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/assets/img/favicon/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="180x180" href="/assets/img/favicon/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="/assets/img/favicon/android-chrome-192x192.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="512x512" href="/assets/img/favicon/android-chrome-512x512.png">
|
||||||
|
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
|
||||||
|
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic&display=swap">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Cabin:700&display=swap">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Anonymous+Pro&display=swap">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap">
|
||||||
|
<link rel="stylesheet" href="/assets/css/styles.min.css">
|
||||||
|
<link rel="stylesheet" href="/assets/css/404.min.css">
|
||||||
|
<link rel="stylesheet" href="/assets/css/brand-reveal.min.css">
|
||||||
|
<link rel="stylesheet" href="/assets/css/profile.min.css">
|
||||||
|
<link rel="stylesheet" href="/assets/css/Social-Icons.min.css">
|
||||||
|
<link rel="me" href="https://mastodon.woodburn.au/@nathanwoodburn" />
|
||||||
|
<script async src="https://umami.woodburn.au/script.js" data-website-id="6a55028e-aad3-481c-9a37-3e096ff75589"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>HTTP: <span>403</span></p>
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="text-start" style="display: inline-block;"><code><em>this_page</em>.<em>found</em> = true;</code><code><span>if</span> (<em>this_page</em>.<em>readable</em>) {<br><span class="tab-space"></span><b>return</b> <em>this_page</em>;<br>} <span>else</span> {<br><span class="tab-space"></span><b>alert</b>('<i>This page is not readable!</i>');<br>}</code></div>
|
||||||
|
</div>
|
||||||
|
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="/assets/js/script.min.js"></script>
|
||||||
|
<script src="/assets/js/grayscale.min.js"></script>
|
||||||
|
<script src="/assets/js/403.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
1
templates/assets/js/403.min.js
vendored
Normal file
1
templates/assets/js/403.min.js
vendored
Normal file
@@ -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);
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
27
tools.py
27
tools.py
@@ -1,7 +1,15 @@
|
|||||||
from flask import Request
|
from flask import Request, render_template, jsonify
|
||||||
import os
|
import os
|
||||||
from functools import cache
|
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:
|
def isCurl(request: Request) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if the request is from curl
|
Check if the request is from curl
|
||||||
@@ -48,4 +56,19 @@ def getAddress(coin: str) -> str:
|
|||||||
def getFilePath(name, path):
|
def getFilePath(name, path):
|
||||||
for root, dirs, files in os.walk(path):
|
for root, dirs, files in os.walk(path):
|
||||||
if name in files:
|
if name in files:
|
||||||
return os.path.join(root, name)
|
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 <error code>.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
|
||||||
Reference in New Issue
Block a user