FireSales/sales.py
Nathan Woodburn 6f87b117a9
All checks were successful
Build Docker / BuildImage (push) Successful in 34s
feat: Add thousands separator to price and fixed validation of listing
2025-01-30 18:37:57 +11:00

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