sol-vote/main.py
Nathan Woodburn f8c98214bf
All checks were successful
Build Docker / Build Image (push) Successful in 39s
feat: Add initial code
2024-02-19 15:18:49 +11:00

184 lines
5.1 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 threading
import nacl.signing
import nacl.encoding
import nacl.exceptions
import base58
import render
app = Flask(__name__)
dotenv.load_dotenv()
# If votes file doesn't exist, create it
if not os.path.isfile('data/votes.json'):
with open('data/votes.json', 'w') as file:
json.dump([], file)
#Assets routes
@app.route('/assets/<path:path>')
def send_report(path):
return send_from_directory('templates/assets', path)
@app.route('/assets/js/bundle.js')
def send_bundle():
return send_from_directory('dist', 'bundle.js')
@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')
# Main routes
@app.route('/')
def index():
year = datetime.datetime.now().year
votes = render.votes()
return render_template('index.html',year=year,votes=votes)
@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 redirect('/')
@app.route('/vote')
def vote():
print('Voting')
# Get args
args = request.args
# Convert to json
data = args.to_dict()
print(data)
# Verify signature
message = data["message"]
signature = data["signature"]
public_key = data["walletAddress"]
percent = data["percent"]
# Verify signature
try:
# Decode base58 encoded strings
public_key_bytes = base58.b58decode(public_key)
signature_bytes = base58.b58decode(signature)
message_bytes = message.encode('utf-8')
# Verify the signature
verify_key = nacl.signing.VerifyKey(public_key_bytes)
verify_key.verify(message_bytes, signature_bytes)
# Signature is valid
data["verified"] = True
except (nacl.exceptions.BadSignatureError, nacl.exceptions.CryptoError) as e:
# Signature is invalid
data["verified"] = False
# Send message to discord
send_discord_message(data)
save_vote(data)
return render_template('success.html', year=datetime.datetime.now().year, vote=data["message"],percent=percent,signature=signature,votes=render.votes())
def save_vote(data):
# Load votes
with open('data/votes.json') as file:
votes = json.load(file)
address = data["walletAddress"]
# Remove old vote
for vote in votes:
if vote["walletAddress"] == address:
votes.remove(vote)
# Add new vote
votes.append(data)
# Save votes
with open('data/votes.json', 'w') as file:
json.dump(votes, file, indent=4)
def send_discord_message(data):
# Define the webhook URL
webhook_url = 'https://discord.com/api/webhooks/1208977249232228362/jPtFZKD7MWzaRbiHwc9rgEOQx-d8DWSDyr7oVMzfoC5QUayts8BF1oi1xxoE8O6ouTFi'
text = f"New vote for `{data['message']}`"
tokens = data['votes']
# Convert to have commas
tokens = "{:,}".format(int(tokens))
# Define the message content
message = {
"embeds": [
{
"title": "New Vote",
"description": text,
"color": 65280 if data["verified"] else 16711680,
"footer": {
"text": "Nathan.Woodburn/"
},
"fields": [
{
"name": "Wallet Address",
"value": '`'+data["walletAddress"]+'`'
},
{
"name": "Vote",
"value": '`'+data["message"]+'`'
},
{
"name": "Verified",
"value": "Yes" if data["verified"] else "No"
},
{
"name": "Signature",
"value": '`'+data["signature"]+'`'
},
{
"name": "Number of tokens",
"value": tokens
}
]
}
]
}
# Send the message as a POST request to the webhook URL
response = requests.post(webhook_url, data=json.dumps(message), headers={'Content-Type': 'application/json'})
# Print the response from the webhook (for debugging purposes)
print(response.text)
# 404 catch all
@app.errorhandler(404)
def not_found(e):
return redirect('/')
if __name__ == '__main__':
app.run(debug=True, port=5000, host='0.0.0.0')