All checks were successful
Build Docker / Build Image (push) Successful in 1m23s
456 lines
13 KiB
Python
456 lines
13 KiB
Python
from flask import Flask, make_response, redirect, request, jsonify, render_template, send_from_directory, send_file
|
|
import os
|
|
import dotenv
|
|
import requests
|
|
import datetime
|
|
import json
|
|
import render
|
|
import payments
|
|
import threading
|
|
import account
|
|
import qrcode
|
|
from io import BytesIO
|
|
|
|
app = Flask(__name__)
|
|
dotenv.load_dotenv()
|
|
|
|
# Exchange cache
|
|
exchange = {
|
|
'timestamp': 0,
|
|
'rate': 0
|
|
}
|
|
|
|
|
|
tlds = ['australia','newzealand']
|
|
|
|
#Assets routes
|
|
@app.route('/assets/<path:path>')
|
|
def send_report(path):
|
|
return send_from_directory('templates/assets', path)
|
|
|
|
@app.route('/sitemap')
|
|
@app.route('/sitemap.xml')
|
|
def sitemap():
|
|
# Remove all .html from sitemap
|
|
with open('templates/sitemap.xml') as file:
|
|
sitemap = file.read()
|
|
|
|
sitemap = sitemap.replace('.html', '')
|
|
return make_response(sitemap, 200, {'Content-Type': 'application/xml'})
|
|
|
|
@app.route('/favicon.png')
|
|
def faviconPNG():
|
|
return send_from_directory('templates/assets/img', 'favicon.png')
|
|
|
|
@app.route('/https.js')
|
|
@app.route('/handshake.js')
|
|
@app.route('/redirect.js')
|
|
def handshake():
|
|
# return request.path
|
|
return send_from_directory('templates/', request.path.split('/')[-1])
|
|
|
|
@app.route('/.well-known/wallets/<path:path>')
|
|
def wallet(path):
|
|
return send_from_directory('templates/.well-known/wallets', path, mimetype='text/plain')
|
|
|
|
|
|
|
|
# Special routes
|
|
@app.route('/email')
|
|
def email():
|
|
return redirect('mailto:hns@hns.au')
|
|
|
|
@app.route('/pins')
|
|
def pins():
|
|
global exchange
|
|
|
|
year = datetime.datetime.now().year
|
|
# Get current exchange rate if not in cache
|
|
if exchange['timestamp'] < datetime.datetime.now().timestamp() - 3600:
|
|
response = requests.get('https://api.coingecko.com/api/v3/simple/price?ids=handshake&vs_currencies=usd')
|
|
exchange['rate'] = response.json()['handshake']['usd']
|
|
exchange['timestamp'] = datetime.datetime.now().timestamp()
|
|
|
|
hns_45 = 45 / exchange['rate']
|
|
hns_30 = 30 / exchange['rate']
|
|
hns_50 = 50 / exchange['rate']
|
|
|
|
# Round to the nearest 5 HNS and add commas
|
|
hns_45 = int(hns_45 / 5) * 5
|
|
hns_30 = int(hns_30 / 5) * 5
|
|
hns_50 = int(hns_50 / 5) * 5
|
|
|
|
hns_45 = "{:,}".format(hns_45)
|
|
hns_30 = "{:,}".format(hns_30)
|
|
hns_50 = "{:,}".format(hns_50)
|
|
|
|
|
|
return render_template('pins.html', year=year, hns_45=hns_45, hns_30=hns_30,hns_50=hns_50)
|
|
|
|
@app.route('/pins/<path:path>')
|
|
def pins_redirect(path):
|
|
global exchange
|
|
|
|
if not os.path.isfile('templates/pins/'+path + ".html"):
|
|
return render_template('404.html'), 404
|
|
|
|
year = datetime.datetime.now().year
|
|
# Get current exchange rate if not in cache
|
|
if exchange['timestamp'] < datetime.datetime.now().timestamp() - 3600:
|
|
response = requests.get('https://api.coingecko.com/api/v3/simple/price?ids=handshake&vs_currencies=usd')
|
|
exchange['rate'] = response.json()['handshake']['usd']
|
|
exchange['timestamp'] = datetime.datetime.now().timestamp()
|
|
|
|
hns_45 = 45 / exchange['rate']
|
|
hns_30 = 30 / exchange['rate']
|
|
hns_50 = 50 / exchange['rate']
|
|
|
|
# Round to the nearest 5 HNS and add commas
|
|
hns_45 = int(hns_45 / 5) * 5
|
|
hns_30 = int(hns_30 / 5) * 5
|
|
hns_50 = int(hns_50 / 5) * 5
|
|
|
|
hns_45 = "{:,}".format(hns_45)
|
|
hns_30 = "{:,}".format(hns_30)
|
|
hns_50 = "{:,}".format(hns_50)
|
|
return render_template('pins/'+path + ".html", year=year, hns_45=hns_45, hns_30=hns_30,hns_50=hns_50)
|
|
|
|
@app.route('/pins/order/<path:path>')
|
|
def pins_order(path):
|
|
if not os.path.isfile('templates/pins/'+path + ".html"):
|
|
return render_template('404.html'), 404
|
|
|
|
# Get cookies
|
|
cookies = request.cookies
|
|
if 'cart' in cookies:
|
|
cart = cookies['cart']
|
|
else:
|
|
cart = '[]'
|
|
|
|
cart = json.loads(cart)
|
|
item = {
|
|
'name': path,
|
|
'quantity': 1
|
|
}
|
|
for i in range(len(cart)):
|
|
if cart[i]['name'] == path:
|
|
cart[i]['quantity'] += 1
|
|
item = None
|
|
break
|
|
|
|
if item:
|
|
cart.append(item)
|
|
cart = json.dumps(cart)
|
|
|
|
response = make_response(redirect('/cart'))
|
|
response.set_cookie('cart', cart)
|
|
return response
|
|
|
|
@app.route('/pins/update/<path:path>', methods=['POST'])
|
|
def pins_update(path):
|
|
# Get cookies
|
|
cookies = request.cookies
|
|
if 'cart' in cookies:
|
|
cart = cookies['cart']
|
|
else:
|
|
cart = '[]'
|
|
|
|
cart = json.loads(cart)
|
|
data = request.json
|
|
for i in range(len(cart)):
|
|
if cart[i]['name'] == path:
|
|
cart[i]['quantity'] = data['quantity']
|
|
break
|
|
|
|
|
|
# Remove any item with less than 1 quantity
|
|
cart = [item for item in cart if int(item['quantity']) > 0]
|
|
cart = json.dumps(cart)
|
|
|
|
response = make_response(jsonify({'status': 'ok'}))
|
|
response.set_cookie('cart', cart)
|
|
return response
|
|
|
|
@app.route('/cart')
|
|
def cart():
|
|
year = datetime.datetime.now().year
|
|
# Get cookies
|
|
cookies = request.cookies
|
|
if 'cart' in cookies:
|
|
cart = cookies['cart']
|
|
else:
|
|
cart = '[]'
|
|
|
|
promo_message = ''
|
|
if 'promo' in cookies:
|
|
promo = cookies['promo']
|
|
else:
|
|
promo = ''
|
|
|
|
cart = json.loads(cart)
|
|
cartHtml = render.cart(cart)
|
|
|
|
if promo != '':
|
|
promo = payments.getPromo(promo)
|
|
if not promo:
|
|
promo_message = 'Invalid promo code'
|
|
promo = ''
|
|
else:
|
|
promo_message = f'Promo code {promo["id"]} applied'
|
|
|
|
total_usd = render.total_usd(cart,promo)
|
|
total_hns = render.total_hns(cart,promo)
|
|
promoCode = ''
|
|
if promo:
|
|
promoCode = promo["id"]
|
|
else:
|
|
total_usd = render.total_usd(cart, False)
|
|
total_hns = render.total_hns(cart, False)
|
|
promoCode = ''
|
|
|
|
return render_template('cart.html', year=year, cart=cartHtml, total_usd=total_usd, total_hns=total_hns,promo=promoCode, promo_message=promo_message)
|
|
|
|
@app.route('/cart/promo', methods=['POST'])
|
|
def cart_promo():
|
|
data = request.form
|
|
response = make_response(redirect('/cart'))
|
|
response.set_cookie('promo', data['promo'])
|
|
return response
|
|
|
|
@app.route('/payment')
|
|
def payment():
|
|
year = datetime.datetime.now().year
|
|
# Get cookies
|
|
cookies = request.cookies
|
|
if 'cart' in cookies:
|
|
cart = cookies['cart']
|
|
else:
|
|
cart = '[]'
|
|
|
|
if cart == '[]':
|
|
return redirect('/cart')
|
|
|
|
cart = json.loads(cart)
|
|
cartHtml = render.cart_total(cart)
|
|
|
|
if 'promo' in cookies:
|
|
promo = cookies['promo']
|
|
promo = payments.getPromo(promo)
|
|
total_usd = render.total_usd(cart,promo)
|
|
total_hns = render.total_hns(cart,promo)
|
|
else:
|
|
promo = ''
|
|
total_usd = render.total_usd(cart, False)
|
|
total_hns = render.total_hns(cart, False)
|
|
|
|
|
|
|
|
return render_template('payment.html', year=year, cart=cartHtml, total_usd=total_usd, total_hns=total_hns)
|
|
|
|
@app.route('/payment', methods=['POST'])
|
|
def payment_post():
|
|
# Get cookies
|
|
cookies = request.cookies
|
|
if 'cart' in cookies:
|
|
cart = cookies['cart']
|
|
else:
|
|
cart = '[]'
|
|
|
|
if cart == '[]':
|
|
return redirect('/cart')
|
|
|
|
cart = json.loads(cart)
|
|
if 'promo' in cookies:
|
|
promo = cookies['promo']
|
|
promo = payments.getPromo(promo)
|
|
total_usd = render.total_usd(cart,promo)
|
|
total_hns = render.total_hns(cart,promo)
|
|
else:
|
|
promo = False
|
|
total_usd = render.total_usd(cart, False)
|
|
total_hns = render.total_hns(cart, False)
|
|
|
|
|
|
data = request.form
|
|
if 'email' in data:
|
|
email = data['email']
|
|
else:
|
|
email = ''
|
|
if 'mobile' in data:
|
|
mobile = data['mobile']
|
|
else:
|
|
mobile = ''
|
|
|
|
if 'address' in data:
|
|
address = data['address']
|
|
else:
|
|
address = ''
|
|
|
|
if 'country' in data:
|
|
country = data['country']
|
|
else:
|
|
country = ''
|
|
|
|
if 'name' in data:
|
|
name = data['name']
|
|
else:
|
|
name = ''
|
|
|
|
cartHtml = render.cart_total(cart)
|
|
|
|
if email == '' or address == '' or name == '' or country == '' or mobile == '':
|
|
return render_template('payment.html', error='Please fill all fields',
|
|
email=email, address=address, name=name, mobile=mobile, country=country,
|
|
cart=cartHtml, total_usd=total_usd, total_hns=total_hns)
|
|
|
|
# All good, check out
|
|
payment = payments.generate_payment(name, email, mobile,address,country, cart, render.total_hns(cart, promo,True), promo)
|
|
|
|
if payment == False:
|
|
return render_template('payment.html', error='There was an error processing your payment', email=email, address=address, name=name,
|
|
cart=cartHtml, total_usd=total_usd, total_hns=total_hns)
|
|
|
|
finalPrice = payment['ID']
|
|
HNSaddress = payment['HNSaddress']
|
|
qr = f"<img src='/qr/{HNSaddress}' style='width: 200px; height: 200px;'>"
|
|
|
|
# Center the QR code
|
|
qr = f"<div style='text-align: center;'>{qr}</div>"
|
|
|
|
responce = make_response(render_template('payment_info.html',cart=cartHtml, total_hns=finalPrice,address=HNSaddress, year=datetime.datetime.now().year, qr=qr))
|
|
responce.set_cookie('cart', '[]')
|
|
return responce
|
|
|
|
@app.route('/qr/<path:path>')
|
|
def qr(path):
|
|
# Generate QR code
|
|
qr = qrcode.make(path)
|
|
|
|
# Save the QR code to a bytes buffer
|
|
buffer = BytesIO()
|
|
qr.save(buffer, format='PNG')
|
|
buffer.seek(0)
|
|
|
|
# Serve the image
|
|
return send_file(buffer, mimetype='image/png')
|
|
|
|
|
|
|
|
# Promo routes
|
|
@app.route('/promo')
|
|
def promo():
|
|
year = datetime.datetime.now().year
|
|
# Check user is logged in
|
|
token = request.cookies.get('token')
|
|
if not token:
|
|
return redirect('/login')
|
|
|
|
if not account.token(token):
|
|
return redirect('/login')
|
|
|
|
promos = payments.getPromos()
|
|
promos = render.promoList(promos)
|
|
|
|
return render_template('promo.html', year=year, promos=promos)
|
|
|
|
@app.route('/promo', methods=['POST'])
|
|
def promo_post():
|
|
data = request.form
|
|
token = request.cookies.get('token')
|
|
if not token:
|
|
return redirect('/login')
|
|
|
|
if not account.token(token):
|
|
return redirect('/login')
|
|
|
|
id = data['code']
|
|
constant = data['constant']
|
|
percent = data['percent']
|
|
uses = data['uses']
|
|
payments.addPromo(id, constant, percent, uses)
|
|
|
|
return redirect('/promo')
|
|
|
|
@app.route('/promo/delete/<path:path>')
|
|
def promo_delete(path):
|
|
token = request.cookies.get('token')
|
|
if not token:
|
|
return redirect('/login')
|
|
|
|
if not account.token(token):
|
|
return redirect('/login')
|
|
|
|
payments.deletePromo(path)
|
|
return redirect('/promo')
|
|
|
|
@app.route('/login', methods=['POST'])
|
|
def login():
|
|
data = request.form
|
|
token = account.login(data['email'], data['password'])
|
|
if token:
|
|
response = make_response(redirect('/promo'))
|
|
response.set_cookie('token', token)
|
|
return response
|
|
return redirect('/login')
|
|
|
|
|
|
# Main routes
|
|
@app.route('/')
|
|
def index():
|
|
year = datetime.datetime.now().year
|
|
hns_scripts = '<script src="https://gday.hnsau/handshake.js" domain="gday.hnsau" async></script><script src="https://gday.hnsau/https.js" async></script>'
|
|
|
|
if 'localhost' in request.host or '127.0.0.1' in request.host:
|
|
hns_scripts = ''
|
|
|
|
tld = request.host.split('.')[-1]
|
|
if tld not in tlds and 'localhost' not in tld:
|
|
return render_template('index.html',year=year, handshake_scripts=hns_scripts)
|
|
|
|
hns_scripts = '<script src="https://gday.hnsau/https.js" async></script>'
|
|
if 'localhost' in tld:
|
|
tld = tlds[0]
|
|
hns_scripts = ''
|
|
|
|
return render_template('/tlds/'+tld+'.html',year=year, handshake_scripts=hns_scripts)
|
|
|
|
@app.route('/<path:path>')
|
|
def catch_all(path):
|
|
year = datetime.datetime.now().year
|
|
hns_scripts = '<script src="https://gday.hnsau/handshake.js" domain="gday.hnsau" async></script><script src="https://gday.hnsau/https.js" async></script>'
|
|
|
|
if 'localhost' in request.host or '127.0.0.1' in request.host:
|
|
hns_scripts = ''
|
|
|
|
# If file exists, load it
|
|
if os.path.isfile('templates/' + path):
|
|
return render_template(path, year=year, handshake_scripts=hns_scripts)
|
|
|
|
# Try with .html
|
|
if os.path.isfile('templates/' + path + '.html'):
|
|
return render_template(path + '.html', year=year, handshake_scripts=hns_scripts)
|
|
|
|
if os.path.isfile('templates/' + path.strip('/') + '.html'):
|
|
return render_template(path.strip('/') + '.html', year=year, handshake_scripts=hns_scripts)
|
|
|
|
return render_template('404.html'), 404
|
|
|
|
# 404 catch all
|
|
@app.errorhandler(404)
|
|
def not_found(e):
|
|
return render_template('404.html'), 404
|
|
|
|
|
|
def repeat_check_payments(auto=False):
|
|
# Run check_payments function
|
|
payments.check_payments()
|
|
# Schedule the function to run again after 10 seconds
|
|
if not auto:
|
|
threading.Timer(10, repeat_check_payments).start()
|
|
|
|
def check_payments():
|
|
print('Checking payments', flush=True)
|
|
payments.check_payments()
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True, port=5000, host='0.0.0.0') |