Files
hnsau/server.py
Nathan Woodburn 4e8052eecb
All checks were successful
Build Docker / Build Image (push) Successful in 22s
feat: Update check for payments timer
2024-02-12 17:57:46 +11:00

311 lines
8.4 KiB
Python

from flask import Flask, make_response, redirect, request, jsonify, render_template, send_from_directory
import os
import dotenv
import requests
import datetime
import json
import render
import payments
import threading
app = Flask(__name__)
dotenv.load_dotenv()
# Exchange cache
exchange = {
'timestamp': 0,
'rate': 0
}
#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']
# Round to the nearest 5 HNS and add commas
hns_45 = int(hns_45 / 5) * 5
hns_30 = int(hns_30 / 5) * 5
hns_45 = "{:,}".format(hns_45)
hns_30 = "{:,}".format(hns_30)
return render_template('pins.html', year=year, hns_45=hns_45, hns_30=hns_30)
@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']
# Round to the nearest 5 HNS and add commas
hns_45 = int(hns_45 / 5) * 5
hns_30 = int(hns_30 / 5) * 5
hns_45 = "{:,}".format(hns_45)
hns_30 = "{:,}".format(hns_30)
return render_template('pins/'+path + ".html", year=year, hns_45=hns_45, hns_30=hns_30)
@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 = '[]'
cart = json.loads(cart)
cartHtml = render.cart(cart)
total_usd = render.total_usd(cart)
total_hns = render.total_hns(cart)
return render_template('cart.html', year=year, cart=cartHtml, total_usd=total_usd, total_hns=total_hns)
@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)
total_usd = render.total_usd(cart)
total_hns = render.total_hns(cart)
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)
total_usd = render.total_usd(cart)
total_hns = render.total_hns(cart)
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, True))
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='https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl={HNSaddress}&choe=UTF-8' alt='QR Code' />"
# 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
# Main routes
@app.route('/')
def index():
year = datetime.datetime.now().year
return render_template('index.html',year=year)
@app.route('/<path:path>')
def catch_all(path):
year = datetime.datetime.now().year
# If file exists, load it
if os.path.isfile('templates/' + path):
return render_template(path, year=year)
# Try with .html
if os.path.isfile('templates/' + path + '.html'):
return render_template(path + '.html', year=year)
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__':
# Set timer for payments
repeat_check_payments()
app.run(debug=True, port=5000, host='0.0.0.0')