generated from nathanwoodburn/python-webserver-template
All checks were successful
Build Docker / BuildImage (push) Successful in 34s
155 lines
4.2 KiB
Python
155 lines
4.2 KiB
Python
import os
|
|
import json
|
|
import dotenv
|
|
import requests
|
|
import time
|
|
|
|
dotenv.load_dotenv()
|
|
HSD_IP = os.getenv("HSD_IP")
|
|
HSD_API = os.getenv("HSD_API")
|
|
|
|
if not os.path.exists("data/listings.json"):
|
|
with open("data/listings.json", "w") as f:
|
|
f.write("[]")
|
|
|
|
|
|
# region Classes
|
|
class Listing:
|
|
def __init__(self, **kwargs):
|
|
self.domain = ''
|
|
self.price = 0
|
|
self.description = ''
|
|
self.contact = ''
|
|
self.signature = ''
|
|
self.updated = -1
|
|
|
|
for key, value in kwargs.items():
|
|
setattr(self, key, value)
|
|
|
|
self.price = int(self.price)
|
|
# Fix any errors in the data
|
|
if self.price < 0:
|
|
self.price = 0
|
|
|
|
self.description = self.description.replace('\n','')
|
|
self.description = self.description.replace('\r','')
|
|
self.description = self.description.strip()
|
|
self.contact = self.contact.replace('\n','')
|
|
self.updated = int(time.time())
|
|
print(str(self))
|
|
|
|
def __str__(self):
|
|
return f"Domain: {self.domain}\nPrice: {self.price}\nDescription: {self.description}\nContact: {self.contact}"
|
|
|
|
def getMessage(self):
|
|
return str(self).encode('utf-8').hex()
|
|
|
|
def toHTML(self):
|
|
return f"""
|
|
<div class="card" style="margin: 10px;">
|
|
<div class="card-body">
|
|
<h4 class="card-title">{self.domain}/ <a style='text-decoration:none;' href="/verify/{self.domain}">✅</a></h4>
|
|
<h6 class="text-muted card-subtitle mb-2">{self.price:,} HNS</h6>
|
|
<p class="card-text">{self.description}</p>
|
|
<p class="card-text">Contact: <code>{self.contact}</code></p>
|
|
<a href="/delete/{self.domain}" class="btn btn-info">Delete Listing</a>
|
|
</div>
|
|
</div>
|
|
"""
|
|
|
|
def toJSON(self):
|
|
return {
|
|
'domain': self.domain,
|
|
'description': self.description,
|
|
'price': self.price,
|
|
'contact': self.contact,
|
|
'signature': self.signature,
|
|
'updated': self.updated
|
|
}
|
|
|
|
def signed(self):
|
|
return validate_signature(self.domain,self.signature,self.getMessage())
|
|
|
|
def txValid(self):
|
|
# TODO Validate tx is valid
|
|
return False
|
|
|
|
# endregion
|
|
|
|
def get_listings() -> list[Listing]:
|
|
with open("data/listings.json", "r") as f:
|
|
data = json.loads(f.read())
|
|
|
|
listings = []
|
|
for listing in data:
|
|
listings.append(Listing(**listing))
|
|
return listings
|
|
|
|
def search_listings(domain) -> Listing:
|
|
listings = get_listings()
|
|
for listing in listings:
|
|
if listing.domain == domain:
|
|
return listing
|
|
return None
|
|
|
|
def remove_listing(domain) -> bool:
|
|
listings = get_listings()
|
|
for listing in listings:
|
|
if listing.domain == domain:
|
|
listings.remove(listing)
|
|
saveListings(listings)
|
|
return True
|
|
return False
|
|
|
|
def get_listings_rendered() -> str:
|
|
listings = get_listings()
|
|
html = ""
|
|
for listing in listings:
|
|
html += listing.toHTML()
|
|
return html
|
|
|
|
def saveListings(listings:list[Listing]):
|
|
with open("data/listings.json", "w") as f:
|
|
f.write(json.dumps(listings,default=Listing.toJSON,indent=4))
|
|
|
|
def add_listing(listing:Listing):
|
|
# if not listing.txValid():
|
|
# return "Invalid tx"
|
|
|
|
if not listing.signed():
|
|
return "Not signed"
|
|
|
|
# Remove any listings with the same domain
|
|
remove_listing(listing.domain)
|
|
|
|
listings = get_listings()
|
|
listings.append(listing)
|
|
saveListings(listings)
|
|
return True
|
|
|
|
|
|
def validate_signature(domain,signature,message) -> bool:
|
|
response = requests.post(f"http://x:{HSD_API}@{HSD_IP}:12037", json={
|
|
"method":"verifymessagewithname",
|
|
"params":[
|
|
domain,
|
|
signature,
|
|
message
|
|
]
|
|
})
|
|
if response.status_code != 200:
|
|
return False
|
|
|
|
response = response.json()
|
|
if response['result'] != True:
|
|
return False
|
|
return True
|
|
|
|
def validate_buy_tx(domain,tx) -> bool:
|
|
return False
|
|
|
|
def validate_cancel_signature(domain,signature) -> bool:
|
|
message = f"FS: {domain}"
|
|
if (not validate_signature(domain,signature,message)):
|
|
return False
|
|
return True |