diff --git a/blueprints/acme.py b/blueprints/acme.py index a51c7b9..f543551 100644 --- a/blueprints/acme.py +++ b/blueprints/acme.py @@ -7,7 +7,7 @@ acme_bp = Blueprint('acme', __name__) @acme_bp.route("/hnsdoh-acme", methods=["POST"]) -def acme_post(): +def post(): # Get the TXT record from the request if not request.is_json or not request.json: return json_response(request, "415 Unsupported Media Type", 415) diff --git a/blueprints/api.py b/blueprints/api.py index a22eac9..986c769 100644 --- a/blueprints/api.py +++ b/blueprints/api.py @@ -1,13 +1,16 @@ -from flask import Blueprint, request, jsonify, make_response +from flask import Blueprint, request, jsonify import os import datetime import requests from mail import sendEmail -from sol import create_transaction from tools import getClientIP, getGitCommit, json_response +from blueprints.sol import sol_bp api_bp = Blueprint('api', __name__) +# Register solana blueprint + +api_bp.register_blueprint(sol_bp) NC_CONFIG = requests.get( "https://cloud.woodburn.au/s/4ToXgFe3TnnFcN7/download/website-conf.json" @@ -19,7 +22,7 @@ if 'time-zone' not in NC_CONFIG: @api_bp.route("/") @api_bp.route("/help") -def help_get(): +def help(): return jsonify({ "message": "Welcome to Nathan.Woodburn/ API! This is a personal website. For more information, visit https://nathan.woodburn.au", "endpoints": { @@ -39,12 +42,12 @@ def help_get(): @api_bp.route("/version") -def version_get(): +def version(): return jsonify({"version": getGitCommit()}) @api_bp.route("/time") -def time_get(): +def time(): timezone_offset = datetime.timedelta(hours=NC_CONFIG["time-zone"]) timezone = datetime.timezone(offset=timezone_offset) time = datetime.datetime.now(tz=timezone) @@ -59,7 +62,7 @@ def time_get(): @api_bp.route("/timezone") -def timezone_get(): +def timezone(): return jsonify({ "timezone": NC_CONFIG["time-zone"], "ip": getClientIP(request), @@ -67,7 +70,7 @@ def timezone_get(): }) @api_bp.route("/message") -def message_get(): +def message(): return jsonify({ "message": NC_CONFIG["message"], "ip": getClientIP(request), @@ -76,7 +79,7 @@ def message_get(): @api_bp.route("/ip") -def ip_get(): +def ip(): return jsonify({ "ip": getClientIP(request), "status": 200 @@ -105,7 +108,7 @@ def email_post(): @api_bp.route("/project") -def project_get(): +def project(): gitinfo = { "website": None, } @@ -135,83 +138,3 @@ def project_get(): "ip": getClientIP(request), "status": 200 }) - - -# region Solana Links -SOLANA_HEADERS = { - "Content-Type": "application/json", - "X-Action-Version": "2.4.2", - "X-Blockchain-Ids": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" -} - - -@api_bp.route("/donate", methods=["GET", "OPTIONS"]) -def sol_donate_get(): - data = { - "icon": "https://nathan.woodburn.au/assets/img/profile.png", - "label": "Donate to Nathan.Woodburn/", - "title": "Donate to Nathan.Woodburn/", - "description": "Student, developer, and crypto enthusiast", - "links": { - "actions": [ - {"label": "0.01 SOL", "href": "/api/v1/donate/0.01"}, - {"label": "0.1 SOL", "href": "/api/v1/donate/0.1"}, - {"label": "1 SOL", "href": "/api/v1/donate/1"}, - { - "href": "/api/v1/donate/{amount}", - "label": "Donate", - "parameters": [ - {"name": "amount", "label": "Enter a custom SOL amount"} - ], - }, - ] - }, - } - - response = make_response(jsonify(data), 200, SOLANA_HEADERS) - - if request.method == "OPTIONS": - response.headers["Access-Control-Allow-Origin"] = "*" - response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, OPTIONS" - response.headers["Access-Control-Allow-Headers"] = ( - "Content-Type,Authorization,Content-Encoding,Accept-Encoding,X-Action-Version,X-Blockchain-Ids" - ) - - return response - - -@api_bp.route("/donate/") -def sol_donate_amount_get(amount): - data = { - "icon": "https://nathan.woodburn.au/assets/img/profile.png", - "label": f"Donate {amount} SOL to Nathan.Woodburn/", - "title": "Donate to Nathan.Woodburn/", - "description": f"Donate {amount} SOL to Nathan.Woodburn/", - } - return jsonify(data), 200, SOLANA_HEADERS - - -@api_bp.route("/donate/", methods=["POST"]) -def sol_donate_post(amount): - - if not request.json: - return jsonify({"message": "Error: No JSON data provided"}), 400, SOLANA_HEADERS - - if "account" not in request.json: - return jsonify({"message": "Error: No account provided"}), 400, SOLANA_HEADERS - - sender = request.json["account"] - - # Make sure amount is a number - try: - amount = float(amount) - except ValueError: - amount = 1 # Default to 1 SOL if invalid - - if amount < 0.0001: - return jsonify({"message": "Error: Amount too small"}), 400, SOLANA_HEADERS - - transaction = create_transaction(sender, amount) - return jsonify({"message": "Success", "transaction": transaction}), 200, SOLANA_HEADERS - -# endregion diff --git a/blueprints/blog.py b/blueprints/blog.py index 2d66461..1f913f4 100644 --- a/blueprints/blog.py +++ b/blueprints/blog.py @@ -8,7 +8,7 @@ from tools import isCurl, getClientIP blog_bp = Blueprint('blog', __name__) -def list_blog_page_files(): +def list_page_files(): blog_pages = os.listdir("data/blog") # Remove .md extension blog_pages = [page.removesuffix(".md") @@ -17,7 +17,7 @@ def list_blog_page_files(): return blog_pages -def render_blog_page(date, handshake_scripts=None): +def render_page(date, handshake_scripts=None): # Convert md to html if not os.path.exists(f"data/blog/{date}.md"): return render_template("404.html"), 404 @@ -83,9 +83,9 @@ def fix_numbered_lists(html): return str(soup) -def render_blog_home(handshake_scripts=None): +def render_home(handshake_scripts=None): # Get a list of pages - blog_pages = list_blog_page_files() + blog_pages = list_page_files() # Create a html list of pages blog_pages = [ f"""
  • @@ -105,7 +105,7 @@ def render_blog_home(handshake_scripts=None): @blog_bp.route("/") -def blog_index_get(): +def index(): if not isCurl(request): global handshake_scripts @@ -117,10 +117,10 @@ def blog_index_get(): or request.host == "test.nathan.woodburn.au" ): handshake_scripts = "" - return render_blog_home(handshake_scripts) + return render_home(handshake_scripts) # Get a list of pages - blog_pages = list_blog_page_files() + blog_pages = list_page_files() # Create a html list of pages blog_pages = [ {"name":page.replace("_", " "),"url":f"/blog/{page}", "download": f"/blog/{page}.md"} for page in blog_pages @@ -138,7 +138,7 @@ def blog_index_get(): @blog_bp.route("/") -def blog_path_get(path): +def path(path): if not isCurl(request): global handshake_scripts # If localhost, don't load handshake @@ -150,7 +150,7 @@ def blog_path_get(path): ): handshake_scripts = "" - return render_blog_page(path, handshake_scripts) + return render_page(path, handshake_scripts) # Convert md to html if not os.path.exists(f"data/blog/{path}.md"): @@ -170,7 +170,7 @@ def blog_path_get(path): }), 200 @blog_bp.route("/.md") -def blog_path_md_get(path): +def path_md(path): if not os.path.exists(f"data/blog/{path}.md"): return render_template("404.html"), 404 @@ -178,4 +178,4 @@ def blog_path_md_get(path): content = f.read() # Return the raw markdown file - return content, 200, {'Content-Type': 'text/plain; charset=utf-8'} \ No newline at end of file + return content, 200, {'Content-Type': 'text/plain; charset=utf-8'} diff --git a/blueprints/now.py b/blueprints/now.py index f0cc590..25d7e91 100644 --- a/blueprints/now.py +++ b/blueprints/now.py @@ -5,7 +5,7 @@ import os # Create blueprint now_bp = Blueprint('now', __name__) -def list_now_page_files(): +def list_page_files(): now_pages = os.listdir("templates/now") now_pages = [ page for page in now_pages if page != "template.html" and page != "old.html" @@ -13,31 +13,31 @@ def list_now_page_files(): now_pages.sort(reverse=True) return now_pages -def list_now_dates(): - now_pages = list_now_page_files() +def list_dates(): + now_pages = list_page_files() now_dates = [page.split(".")[0] for page in now_pages] return now_dates -def get_latest_now_date(formatted=False): +def get_latest_date(formatted=False): if formatted: - date=list_now_dates()[0] + date=list_dates()[0] date = datetime.datetime.strptime(date, "%y_%m_%d") date = date.strftime("%A, %B %d, %Y") return date - return list_now_dates()[0] + return list_dates()[0] -def render_latest_now(handshake_scripts=None): - now_page = list_now_dates()[0] - return render_now_page(now_page,handshake_scripts=handshake_scripts) +def render_latest(handshake_scripts=None): + now_page = list_dates()[0] + return render(now_page,handshake_scripts=handshake_scripts) -def render_now_page(date,handshake_scripts=None): +def render(date,handshake_scripts=None): # If the date is not available, render the latest page if date is None: - return render_latest_now(handshake_scripts=handshake_scripts) + return render_latest(handshake_scripts=handshake_scripts) # Remove .html date = date.removesuffix(".html") - if date not in list_now_dates(): + if date not in list_dates(): return render_template("404.html"), 404 @@ -46,7 +46,7 @@ def render_now_page(date,handshake_scripts=None): return render_template(f"now/{date}.html",DATE=date_formatted,handshake_scripts=handshake_scripts) @now_bp.route("/") -def now_index_get(): +def index(): handshake_scripts = '' # If localhost, don't load handshake if ( @@ -59,11 +59,11 @@ def now_index_get(): else: handshake_scripts = '' - return render_latest_now(handshake_scripts) + return render_latest(handshake_scripts) @now_bp.route("/") -def now_path_get(path): +def path(path): handshake_scripts = '' # If localhost, don't load handshake if ( @@ -76,12 +76,12 @@ def now_path_get(path): else: handshake_scripts = '' - return render_now_page(path, handshake_scripts) + return render(path, handshake_scripts) @now_bp.route("/old") @now_bp.route("/old/") -def now_old_get(): +def old(): handshake_scripts = '' # If localhost, don't load handshake if ( @@ -94,9 +94,9 @@ def now_old_get(): else: handshake_scripts = '' - now_dates = list_now_dates()[1:] + now_dates = list_dates()[1:] html = '
      ' - html += f'
    • {get_latest_now_date(True)}
    • ' + html += f'
    • {get_latest_date(True)}
    • ' for date in now_dates: link = date @@ -113,12 +113,12 @@ def now_old_get(): @now_bp.route("/now.rss") @now_bp.route("/now.xml") @now_bp.route("/rss.xml") -def now_rss_get(): +def rss(): host = "https://" + request.host if ":" in request.host: host = "http://" + request.host # Generate RSS feed - now_pages = list_now_page_files() + now_pages = list_page_files() rss = f'Nathan.Woodburn/{host}See what I\'ve been up toen-us{datetime.datetime.now(tz=datetime.timezone.utc).strftime("%a, %d %b %Y %H:%M:%S %z")}' for page in now_pages: link = page.strip(".html") @@ -130,8 +130,8 @@ def now_rss_get(): @now_bp.route("/now.json") -def now_json_get(): - now_pages = list_now_page_files() +def json(): + now_pages = list_page_files() host = "https://" + request.host if ":" in request.host: host = "http://" + request.host diff --git a/blueprints/podcast.py b/blueprints/podcast.py index 3e124f9..2810062 100644 --- a/blueprints/podcast.py +++ b/blueprints/podcast.py @@ -5,7 +5,7 @@ import requests podcast_bp = Blueprint('podcast', __name__) @podcast_bp.route("/ID1") -def podcast_index_get(): +def index(): # Proxy to ID1 url req = requests.get("https://podcasts.c.woodburn.au/ID1") if req.status_code != 200: @@ -17,7 +17,7 @@ def podcast_index_get(): @podcast_bp.route("/ID1/") -def podcast_contents_get(): +def contents(): # Proxy to ID1 url req = requests.get("https://podcasts.c.woodburn.au/ID1/") if req.status_code != 200: @@ -28,7 +28,7 @@ def podcast_contents_get(): @podcast_bp.route("/ID1/") -def podcast_path_get(path): +def path(path): # Proxy to ID1 url req = requests.get("https://podcasts.c.woodburn.au/ID1/" + path) if req.status_code != 200: @@ -39,7 +39,7 @@ def podcast_path_get(path): @podcast_bp.route("/ID1.xml") -def podcast_xml_get(): +def xml(): # Proxy to ID1 url req = requests.get("https://podcasts.c.woodburn.au/ID1.xml") if req.status_code != 200: @@ -50,10 +50,10 @@ def podcast_xml_get(): @podcast_bp.route("/podsync.opml") -def podcast_podsync_get(): +def podsync(): req = requests.get("https://podcasts.c.woodburn.au/podsync.opml") if req.status_code != 200: return error_response(request, "Error from Podcast Server", req.status_code) return make_response( req.content, 200, {"Content-Type": req.headers["Content-Type"]} - ) \ No newline at end of file + ) diff --git a/blueprints/sol.py b/blueprints/sol.py new file mode 100644 index 0000000..f64e8a6 --- /dev/null +++ b/blueprints/sol.py @@ -0,0 +1,125 @@ +from flask import Blueprint, request, jsonify, make_response +from solders.pubkey import Pubkey +from solana.rpc.api import Client +from solders.system_program import TransferParams, transfer +from solders.message import MessageV0 +from solders.transaction import VersionedTransaction +from solders.null_signer import NullSigner +import binascii +import base64 +import os + +sol_bp = Blueprint('sol', __name__) + +SOLANA_HEADERS = { + "Content-Type": "application/json", + "X-Action-Version": "2.4.2", + "X-Blockchain-Ids": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" +} + +SOLANA_ADDRESS = None +if os.path.isfile(".well-known/wallets/SOL"): + with open(".well-known/wallets/SOL") as file: + address = file.read() + SOLANA_ADDRESS = Pubkey.from_string(address.strip()) + +def create_transaction(sender_address: str, amount: float) -> str: + if SOLANA_ADDRESS is None: + raise ValueError("SOLANA_ADDRESS is not set. Please ensure the .well-known/wallets/SOL file exists and contains a valid address.") + # Create transaction + sender = Pubkey.from_string(sender_address) + transfer_ix = transfer( + TransferParams( + from_pubkey=sender, to_pubkey=SOLANA_ADDRESS, lamports=int( + amount * 1000000000) + ) + ) + solana_client = Client("https://api.mainnet-beta.solana.com") + blockhashData = solana_client.get_latest_blockhash() + blockhash = blockhashData.value.blockhash + + msg = MessageV0.try_compile( + payer=sender, + instructions=[transfer_ix], + address_lookup_table_accounts=[], + recent_blockhash=blockhash, + ) + tx = VersionedTransaction(message=msg, keypairs=[NullSigner(sender)]) + tx = bytes(tx).hex() + raw_bytes = binascii.unhexlify(tx) + base64_string = base64.b64encode(raw_bytes).decode("utf-8") + return base64_string + +def get_solana_address() -> str: + if SOLANA_ADDRESS is None: + raise ValueError("SOLANA_ADDRESS is not set. Please ensure the .well-known/wallets/SOL file exists and contains a valid address.") + return str(SOLANA_ADDRESS) + +@sol_bp.route("/donate", methods=["GET", "OPTIONS"]) +def sol_donate(): + data = { + "icon": "https://nathan.woodburn.au/assets/img/profile.png", + "label": "Donate to Nathan.Woodburn/", + "title": "Donate to Nathan.Woodburn/", + "description": "Student, developer, and crypto enthusiast", + "links": { + "actions": [ + {"label": "0.01 SOL", "href": "/api/v1/donate/0.01"}, + {"label": "0.1 SOL", "href": "/api/v1/donate/0.1"}, + {"label": "1 SOL", "href": "/api/v1/donate/1"}, + { + "href": "/api/v1/donate/{amount}", + "label": "Donate", + "parameters": [ + {"name": "amount", "label": "Enter a custom SOL amount"} + ], + }, + ] + }, + } + + response = make_response(jsonify(data), 200, SOLANA_HEADERS) + + if request.method == "OPTIONS": + response.headers["Access-Control-Allow-Origin"] = "*" + response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, OPTIONS" + response.headers["Access-Control-Allow-Headers"] = ( + "Content-Type,Authorization,Content-Encoding,Accept-Encoding,X-Action-Version,X-Blockchain-Ids" + ) + + return response + + +@sol_bp.route("/donate/") +def sol_donate_amount(amount): + data = { + "icon": "https://nathan.woodburn.au/assets/img/profile.png", + "label": f"Donate {amount} SOL to Nathan.Woodburn/", + "title": "Donate to Nathan.Woodburn/", + "description": f"Donate {amount} SOL to Nathan.Woodburn/", + } + return jsonify(data), 200, SOLANA_HEADERS + + +@sol_bp.route("/donate/", methods=["POST"]) +def sol_donate_post(amount): + + if not request.json: + return jsonify({"message": "Error: No JSON data provided"}), 400, SOLANA_HEADERS + + if "account" not in request.json: + return jsonify({"message": "Error: No account provided"}), 400, SOLANA_HEADERS + + sender = request.json["account"] + + # Make sure amount is a number + try: + amount = float(amount) + except ValueError: + amount = 1 # Default to 1 SOL if invalid + + if amount < 0.0001: + return jsonify({"message": "Error: Amount too small"}), 400, SOLANA_HEADERS + + transaction = create_transaction(sender, amount) + return jsonify({"message": "Success", "transaction": transaction}), 200, SOLANA_HEADERS \ No newline at end of file diff --git a/blueprints/wellknown.py b/blueprints/wellknown.py index 5ef7e9e..2007f4d 100644 --- a/blueprints/wellknown.py +++ b/blueprints/wellknown.py @@ -5,12 +5,12 @@ wk_bp = Blueprint('well-known', __name__) @wk_bp.route("/") -def wk_index_get(path): +def index(path): return send_from_directory(".well-known", path) @wk_bp.route("/wallets/") -def wk_wallet_get(path): +def wallets(path): if path[0] == "." and 'proof' not in path: return send_from_directory( ".well-known/wallets", path, mimetype="application/json" @@ -29,7 +29,7 @@ def wk_wallet_get(path): @wk_bp.route("/nostr.json") -def wk_nostr_get(): +def nostr(): # Get name parameter name = request.args.get("name") if name: @@ -51,7 +51,7 @@ def wk_nostr_get(): @wk_bp.route("/xrp-ledger.toml") -def wk_xrp_get(): +def xrp(): # Create a response with the xrp-ledger.toml file with open(".well-known/xrp-ledger.toml") as file: toml = file.read() diff --git a/server.py b/server.py index 81ec28e..861562b 100644 --- a/server.py +++ b/server.py @@ -81,7 +81,7 @@ NC_CONFIG = requests.get( @app.route("/assets/") -def asset_get(path): +def asset(path): if path.endswith(".json"): return send_from_directory( "templates/assets", path, mimetype="application/json" @@ -121,7 +121,7 @@ def asset_get(path): @app.route("/sitemap") @app.route("/sitemap.xml") -def sitemap_get(): +def sitemap(): # Remove all .html from sitemap if not os.path.isfile("templates/sitemap.xml"): return error_response(request) @@ -133,14 +133,14 @@ def sitemap_get(): @app.route("/favicon.") -def favicon_get(ext): +def favicon(ext): if ext not in ("png", "svg", "ico"): return error_response(request) return send_from_directory("templates/assets/img/favicon", f"favicon.{ext}") @app.route("/.js") -def javascript_get(name): +def javascript(name): # Check if file in js directory if not os.path.isfile("templates/assets/js/" + request.path.split("/")[-1]): return error_response(request) @@ -148,7 +148,7 @@ def javascript_get(name): @app.route("/download/") -def download_get(path): +def download(path): if path not in DOWNLOAD_ROUTES: return error_response(request, message="Invalid download") # Check if file exists @@ -163,7 +163,7 @@ def download_get(path): @app.route("/manifest.json") -def manifest_get(): +def manifest(): host = request.host # Read as json @@ -179,7 +179,7 @@ def manifest_get(): @app.route("/sw.js") -def serviceWorker_get(): +def serviceWorker(): return send_from_directory("pwa", "sw.js") # endregion @@ -191,19 +191,19 @@ def serviceWorker_get(): @app.route("/meet") @app.route("/meeting") @app.route("/appointment") -def meetingLink_get(): +def meetingLink(): return redirect( "https://cloud.woodburn.au/apps/calendar/appointment/PamrmmspWJZr", code=302 ) @app.route("/links") -def links_get(): +def links(): return render_template("link.html") @app.route("/api/") -def api_legacy_get(function): +def api_legacy(function): # Check if function is in api blueprint for rule in app.url_map.iter_rules(): # Check if the redirect route exists @@ -213,7 +213,7 @@ def api_legacy_get(function): @app.route("/actions.json") -def sol_actions_get(): +def sol_actions(): return jsonify( {"rules": [{"pathPattern": "/donate**", "apiPath": "/api/v1/donate**"}]} ) @@ -224,7 +224,7 @@ def sol_actions_get(): @app.route("/") -def index_get(): +def index(): global HANDSHAKE_SCRIPTS global PROJECTS global PROJECTS_UPDATED @@ -413,7 +413,7 @@ def index_get(): @app.route("/donate") -def donate_get(): +def donate(): global HANDSHAKE_SCRIPTS # If localhost, don't load handshake if ( @@ -539,7 +539,7 @@ def donate_get(): @app.route("/address/") -def qraddress_get(address): +def qraddress(address): qr = qrcode.QRCode( version=1, error_correction=ERROR_CORRECT_L, @@ -560,7 +560,7 @@ def qraddress_get(address): @app.route("/qrcode/") @app.route("/qr/") -def qrcode_get(data): +def qrcodee(data): qr = qrcode.QRCode( error_correction=ERROR_CORRECT_H, box_size=10, border=2) qr.add_data(data) @@ -586,7 +586,7 @@ def qrcode_get(data): @app.route("/supersecretpath") -def supersecretpath_get(): +def supersecretpath(): ascii_art = "" if os.path.isfile("data/ascii.txt"): with open("data/ascii.txt") as file: @@ -704,7 +704,7 @@ def hosting_post(): @app.route("/resume.pdf") -def resume_pdf_get(): +def resume_pdf(): # Check if file exists if os.path.isfile("data/resume.pdf"): return send_file("data/resume.pdf") @@ -717,7 +717,7 @@ def resume_pdf_get(): @app.route("/") -def catch_all_get(path: str): +def catch_all(path: str): global HANDSHAKE_SCRIPTS # If localhost, don't load handshake if ( diff --git a/sol.py b/sol.py deleted file mode 100644 index b10bfed..0000000 --- a/sol.py +++ /dev/null @@ -1,47 +0,0 @@ -from solders.pubkey import Pubkey -from solana.rpc.api import Client -from solders.system_program import TransferParams, transfer -from solders.message import MessageV0 -from solders.transaction import VersionedTransaction -from solders.null_signer import NullSigner -import binascii -import base64 -import os - -SOLANA_ADDRESS = None -if os.path.isfile(".well-known/wallets/SOL"): - with open(".well-known/wallets/SOL") as file: - address = file.read() - SOLANA_ADDRESS = Pubkey.from_string(address.strip()) - -def create_transaction(sender_address: str, amount: float) -> str: - if SOLANA_ADDRESS is None: - raise ValueError("SOLANA_ADDRESS is not set. Please ensure the .well-known/wallets/SOL file exists and contains a valid address.") - # Create transaction - sender = Pubkey.from_string(sender_address) - transfer_ix = transfer( - TransferParams( - from_pubkey=sender, to_pubkey=SOLANA_ADDRESS, lamports=int( - amount * 1000000000) - ) - ) - solana_client = Client("https://api.mainnet-beta.solana.com") - blockhashData = solana_client.get_latest_blockhash() - blockhash = blockhashData.value.blockhash - - msg = MessageV0.try_compile( - payer=sender, - instructions=[transfer_ix], - address_lookup_table_accounts=[], - recent_blockhash=blockhash, - ) - tx = VersionedTransaction(message=msg, keypairs=[NullSigner(sender)]) - tx = bytes(tx).hex() - raw_bytes = binascii.unhexlify(tx) - base64_string = base64.b64encode(raw_bytes).decode("utf-8") - return base64_string - -def get_solana_address() -> str: - if SOLANA_ADDRESS is None: - raise ValueError("SOLANA_ADDRESS is not set. Please ensure the .well-known/wallets/SOL file exists and contains a valid address.") - return str(SOLANA_ADDRESS) \ No newline at end of file diff --git a/tests/api.hurl b/tests/api.hurl new file mode 100644 index 0000000..899619e --- /dev/null +++ b/tests/api.hurl @@ -0,0 +1,17 @@ +GET http://127.0.0.1:5000/api/v1/ +HTTP 200 +GET http://127.0.0.1:5000/api/v1/help +HTTP 200 +GET http://127.0.0.1:5000/api/v1/ip +HTTP 200 +[Asserts] +jsonpath "$.ip" == "127.0.0.1" +GET http://127.0.0.1:5000/api/v1/time +HTTP 200 +GET http://127.0.0.1:5000/api/v1/timezone +HTTP 200 +GET http://127.0.0.1:5000/api/v1/message +HTTP 200 +GET http://127.0.0.1:5000/api/v1/project +HTTP 200 + diff --git a/tests/blog.hurl b/tests/blog.hurl new file mode 100644 index 0000000..a8bfc90 --- /dev/null +++ b/tests/blog.hurl @@ -0,0 +1,9 @@ +GET http://127.0.0.1:5000/blog/ +HTTP 200 + +GET http://127.0.0.1:5000/blog/Fingertip_on_Linux_Mint +HTTP 200 + +GET http://127.0.0.1:5000/blog/Fingertip_on_Linux_Mint.md +HTTP 200 + diff --git a/tests/legacy_api.hurl b/tests/legacy_api.hurl new file mode 100644 index 0000000..a85881c --- /dev/null +++ b/tests/legacy_api.hurl @@ -0,0 +1,41 @@ + +GET http://127.0.0.1:5000/api/help +HTTP 301 +[Asserts] +header "Location" == "/api/v1/help" + +GET http://127.0.0.1:5000/api/ip +HTTP 301 +[Asserts] +header "Location" == "/api/v1/ip" + +GET http://127.0.0.1:5000/api/message +HTTP 301 +[Asserts] +header "Location" == "/api/v1/message" + +GET http://127.0.0.1:5000/api/project +HTTP 301 +[Asserts] +header "Location" == "/api/v1/project" + +GET http://127.0.0.1:5000/api/donate +HTTP 301 +[Asserts] +header "Location" == "/api/v1/donate" + +GET http://127.0.0.1:5000/api/time +HTTP 301 +[Asserts] +header "Location" == "/api/v1/time" + +GET http://127.0.0.1:5000/api/timezone +HTTP 301 +[Asserts] +header "Location" == "/api/v1/timezone" + +GET http://127.0.0.1:5000/api/version +HTTP 301 +[Asserts] +header "Location" == "/api/v1/version" + diff --git a/tests/now.hurl b/tests/now.hurl new file mode 100644 index 0000000..cc01f9f --- /dev/null +++ b/tests/now.hurl @@ -0,0 +1,24 @@ +GET http://127.0.0.1:5000/now/ +HTTP 200 + +GET http://127.0.0.1:5000/now/old +HTTP 200 + +GET http://127.0.0.1:5000/now/24_02_18 +HTTP 200 + +GET http://127.0.0.1:5000/now/24_02_18 +HTTP 200 + +GET http://127.0.0.1:5000/now/now.json +HTTP 200 + +GET http://127.0.0.1:5000/now/now.xml +HTTP 200 + +GET http://127.0.0.1:5000/now/now.rss +HTTP 200 + +GET http://127.0.0.1:5000/now/rss.xml +HTTP 200 + diff --git a/tests/sol.hurl b/tests/sol.hurl new file mode 100644 index 0000000..f3f7d45 --- /dev/null +++ b/tests/sol.hurl @@ -0,0 +1,14 @@ +POST http://127.0.0.1:5000/api/v1/donate/1 +{"account": "1111111111111111111111111111111B"} + +POST http://127.0.0.1:5000/api/v1/donate/0.01 +{"account": "1111111111111111111111111111111C"} + +POST http://127.0.0.1:5000/api/v1/donate/0.1 +{"account": "1111111111111111111111111111111D"} + +POST http://127.0.0.1:5000/api/v1/donate/0.02 +{"account": "1111111111111111111111111111111E"} + +POST http://127.0.0.1:5000/api/v1/donate/{amount} +{"account": "11111111111111111111111111111112"} diff --git a/tests/well-known.hurl b/tests/well-known.hurl new file mode 100644 index 0000000..5de23bb --- /dev/null +++ b/tests/well-known.hurl @@ -0,0 +1,11 @@ +GET http://127.0.0.1:5000/.well-known/xrp-ledger.toml +HTTP 200 + +GET http://127.0.0.1:5000/.well-known/nostr.json?name=hurl +HTTP 200 +[Asserts] +jsonpath "$.names.hurl" == "b57b6a06fdf0a4095eba69eee26e2bf6fa72bd1ce6cbe9a6f72a7021c7acaa82" + +GET http://127.0.0.1:5000/.well-known/wallets/BTC +HTTP 200 + diff --git a/tools.py b/tools.py index 1160003..ae6bc2f 100644 --- a/tools.py +++ b/tools.py @@ -35,7 +35,7 @@ def getGitCommit(): def isCurl(request: Request) -> bool: """ - Check if the request is from curl + Check if the request is from curl or hurl Args: request (Request): The Flask request object @@ -45,7 +45,9 @@ def isCurl(request: Request) -> bool: """ if request.headers and request.headers.get("User-Agent"): # Check if curl - if "curl" in request.headers.get("User-Agent", "curl"): + if "curl" in request.headers.get("User-Agent", ""): + return True + if "hurl" in request.headers.get("User-Agent",""): return True return False