feat: Add image uploading
All checks were successful
Build Docker / Build Main Image (push) Successful in 20s
Build Docker / Build SLDs Image (push) Successful in 21s

This commit is contained in:
Nathan Woodburn 2023-11-18 00:25:59 +11:00
parent cb6dda7fca
commit 40a794c0d4
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
4 changed files with 99 additions and 1 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@ __pycache__/
*.json *.json
sites/templates/ sites/templates/
images/

41
avatar.py Normal file
View File

@ -0,0 +1,41 @@
import os
import dotenv
import db
import random
import json
IMAGE_LOCATION = os.getenv('IMAGE_LOCATION')
if IMAGE_LOCATION == None:
IMAGE_LOCATION = "/data"
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
MAIN_DOMAIN = os.getenv('MAIN_DOMAIN')
if MAIN_DOMAIN == None:
MAIN_DOMAIN = "shakecities.com"
if MAIN_DOMAIN == "127.0.0.1:5000":
MAIN_DOMAIN = f"http://{MAIN_DOMAIN}"
else:
MAIN_DOMAIN = f"https://{MAIN_DOMAIN}"
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def save_avatar(file,owner):
filename = file.filename
while os.path.exists(f"{IMAGE_LOCATION}/{filename}"):
filename = f"{random.randint(0,1000000)}-{filename}"
file.save(f"{IMAGE_LOCATION}/{filename}")
user_data = db.get_website_data_raw(owner)
user_data['avatar'] = MAIN_DOMAIN + "/avatar/" + filename
db.update_website_data_raw(owner,json.dumps(user_data))
return filename
def clear(owner):
user_data = db.get_website_data_raw(owner)
filename = user_data['avatar'].split('/')[-1]
os.remove(f"{IMAGE_LOCATION}/{filename}")
user_data['avatar'] = ""
db.update_website_data_raw(owner,json.dumps(user_data))

54
main.py
View File

@ -10,6 +10,7 @@ import accounts
import db import db
import varo import varo
import re import re
import avatar
app = Flask(__name__) app = Flask(__name__)
dotenv.load_dotenv() dotenv.load_dotenv()
@ -22,9 +23,13 @@ dbargs = {
'database':os.getenv('DB_NAME') 'database':os.getenv('DB_NAME')
} }
CITY_DOMAIN = os.getenv('CITY_DOMAIN') CITY_DOMAIN = os.getenv('CITY_DOMAIN')
if CITY_DOMAIN == None: if CITY_DOMAIN == None:
CITY_DOMAIN = "exampledomainnathan1" CITY_DOMAIN = "exampledomainnathan1"
IMAGE_LOCATION = os.getenv('IMAGE_LOCATION')
if IMAGE_LOCATION == None:
IMAGE_LOCATION = "/data"
random_sites = "" random_sites = ""
@ -33,6 +38,10 @@ random_sites = ""
def assets(path): def assets(path):
return send_from_directory('templates/assets', path) return send_from_directory('templates/assets', path)
@app.route('/avatar/<path:path>')
def avatar_view(path):
return send_from_directory(IMAGE_LOCATION, path)
def error(message): def error(message):
return render_template('error.html', message=message) return render_template('error.html', message=message)
@ -243,6 +252,50 @@ def save_hnschat():
return redirect('/hnschat') return redirect('/hnschat')
@app.route('/upload', methods=['POST'])
def upload_avatar():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
if 'file' not in request.files:
return error('We couldn\'t find a file in your request')
file = request.files['file']
if file.filename == '':
return error('We couldn\'t find a file in your request')
if file and avatar.allowed_file(file.filename):
# Save the file to the upload folder
avatar.save_avatar(file,user['domain'])
return redirect('/edit')
return error('Sorry we couldn\'t upload your file')
@app.route('/avatar/clear')
def avatar_clear():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
avatar.clear(user['domain'])
return redirect('/edit')
@app.route('/<path:path>') @app.route('/<path:path>')
def catch_all(path): def catch_all(path):
@ -282,6 +335,7 @@ def catch_all(path):
return render_template(path + '.html',account=account,account_link=account_link,account_link_name=account_link_name,site=site,CITY_DOMAIN=CITY_DOMAIN,domain=domain) return render_template(path + '.html',account=account,account_link=account_link,account_link_name=account_link_name,site=site,CITY_DOMAIN=CITY_DOMAIN,domain=domain)
return redirect('/') # 404 catch all return redirect('/') # 404 catch all
# 404 catch all # 404 catch all
@app.errorhandler(404) @app.errorhandler(404)
def not_found(e): def not_found(e):

View File

@ -42,7 +42,8 @@
<h1 style="text-align: center;margin-bottom: 30px;">Edit your page</h1> <h1 style="text-align: center;margin-bottom: 30px;">Edit your page</h1>
</section> </section>
<section style="width: 80%;margin: auto;"> <section style="width: 80%;margin: auto;">
<form method="post"><input class="form-control" type="text" style="margin-top: 10px;" name="avatar" value="{{avatar}}" placeholder="Avatar URL"><input class="form-control" type="text" style="margin-top: 10px;" name="location" value="{{location}}" placeholder="Location"><input class="form-control" type="text" style="margin-top: 10px;" name="hnschat" placeholder="HNSChat" value="{{hnschat}}"><input class="form-control" type="text" style="margin-top: 10px;" name="email" placeholder="Public Email" value="{{email}}"> <form action="/upload" method="post" enctype="multipart/form-data"><label class="form-label" style="margin-right: 20px;">Avatar</label><img class="rounded-circle" width="100px" height="100px" src="{{avatar}}" style="margin-right: 25px;"><input class="form-control" type="file" style="display: inline-block;width: 300px;margin-right: 25px;" name="file" accept="image/*" required=""><input class="btn btn-primary" type="submit" style="margin-right: 20px;" value="Upload"><a class="btn btn-primary" role="button" href="/avatar/clear">Clear</a></form>
<form method="post"><input class="form-control" type="text" style="margin-top: 10px;" name="location" value="{{location}}" placeholder="Location"><input class="form-control" type="text" style="margin-top: 10px;" name="hnschat" placeholder="HNSChat" value="{{hnschat}}"><input class="form-control" type="text" style="margin-top: 10px;" name="email" placeholder="Public Email" value="{{email}}">
<div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Background colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="bg_colour" value="{{bg_colour}}"></div> <div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Background colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="bg_colour" value="{{bg_colour}}"></div>
<div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Foreground colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="fg_colour" value="{{fg_colour}}"></div> <div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Foreground colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="fg_colour" value="{{fg_colour}}"></div>
<div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Text colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="text_colour" value="{{text_colour}}"></div><textarea class="form-control form-control-lg" rows="15" name="data" placeholder="HTML Content">{{data}}</textarea><input class="form-control" type="text" style="margin-top: 10px;" placeholder="HNS Address" name="hns" value="{{hns}}"><input class="form-control" type="text" style="margin-top: 10px;" name="btc" placeholder="BTC Address" value="{{btc}}"><input class="form-control" type="text" style="margin-top: 10px;" placeholder="ETH Address" name="eth" value="{{eth}}"> <div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Text colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="text_colour" value="{{text_colour}}"></div><textarea class="form-control form-control-lg" rows="15" name="data" placeholder="HTML Content">{{data}}</textarea><input class="form-control" type="text" style="margin-top: 10px;" placeholder="HNS Address" name="hns" value="{{hns}}"><input class="form-control" type="text" style="margin-top: 10px;" name="btc" placeholder="BTC Address" value="{{btc}}"><input class="form-control" type="text" style="margin-top: 10px;" placeholder="ETH Address" name="eth" value="{{eth}}">