From 32cb14f9793cfcacedd8f3684f6a9b72d412f6f4 Mon Sep 17 00:00:00 2001 From: forest Date: Tue, 22 Feb 2022 14:04:38 -0600 Subject: [PATCH] improve BTCPay server down detection and handling --- capsulflask/__init__.py | 13 ++--------- capsulflask/console.py | 3 ++- capsulflask/payment.py | 27 ++++++++++++++++++++-- capsulflask/static/style.css | 13 +++++++++++ capsulflask/templates/account-balance.html | 10 +++++++- capsulflask/templates/btcpay.html | 6 +---- 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/capsulflask/__init__.py b/capsulflask/__init__.py index 352027d..151df92 100644 --- a/capsulflask/__init__.py +++ b/capsulflask/__init__.py @@ -19,7 +19,7 @@ from apscheduler.schedulers.background import BackgroundScheduler from capsulflask.shared import my_exec_info_message from capsulflask import hub_model, spoke_model, cli -from capsulflask.btcpay import client as btcpay +from capsulflask.payment import try_reconnnect_btcpay from capsulflask.http_client import MyHTTPClient class StdoutMockFlaskMail: @@ -142,17 +142,8 @@ else: app.config['HTTP_CLIENT'] = MyHTTPClient(timeout_seconds=int(app.config['INTERNAL_HTTP_TIMEOUT_SECONDS'])) -app.config['BTCPAY_ENABLED'] = False if app.config['BTCPAY_URL'] != "": - try: - response = requests.get(app.config['BTCPAY_URL']) - if response.status_code == 200: - app.config['BTCPAY_CLIENT'] = btcpay.Client(api_uri=app.config['BTCPAY_URL'], pem=app.config['BTCPAY_PRIVATE_KEY']) - app.config['BTCPAY_ENABLED'] = True - else: - app.logger.warn(f"Can't reach BTCPAY_URL {app.config['BTCPAY_URL']}: Response status code: {response.status_code}. Capsul will work fine except cryptocurrency payments will not work.") - except: - app.logger.warn("unable to create btcpay client. Capsul will work fine except cryptocurrency payments will not work. The error was: " + my_exec_info_message(sys.exc_info())) + try_reconnnect_btcpay() # only start the scheduler and attempt to migrate the database if we are running the app. # otherwise we are running a CLI command. diff --git a/capsulflask/console.py b/capsulflask/console.py index a02d446..9be3629 100644 --- a/capsulflask/console.py +++ b/capsulflask/console.py @@ -423,7 +423,8 @@ def account_balance(): has_vms=len(vms_billed)>0, vms_billed=vms_billed, warning_text=warning_text, - btcpay_enabled=current_app.config["BTCPAY_ENABLED"], + btcpay_enabled=current_app.config["BTCPAY_URL"] != "", + btcpay_is_working="BTCPAY_CLIENT" in current_app.config, payments=list(map( lambda x: dict( dollars=x["dollars"], diff --git a/capsulflask/payment.py b/capsulflask/payment.py index 4a1eaa6..796709e 100644 --- a/capsulflask/payment.py +++ b/capsulflask/payment.py @@ -22,6 +22,7 @@ from werkzeug.exceptions import abort from capsulflask.auth import account_required from capsulflask.db import get_model +from capsulflask.btcpay import client as btcpay from capsulflask.shared import my_exec_info_message, get_account_balance, average_number_of_days_in_a_month bp = Blueprint("payment", __name__, url_prefix="/payment") @@ -53,9 +54,13 @@ def validate_dollars(min: float, max: float): def btcpay_payment(): errors = list() - if not current_app.config['BTCPAY_ENABLED']: + if current_app.config['BTCPAY_URL'] == "": flash("BTCPay is not enabled on this server") return redirect(url_for("console.account_balance")) + elif 'BTCPAY_CLIENT' not in current_app.config: + if not try_reconnnect_btcpay(): + flash("can't contact the BTCPay server right now") + return redirect(url_for("console.account_balance")) if request.method == "POST": dollars, errors = validate_dollars(0.01, 1000.0) @@ -93,7 +98,11 @@ def btcpay_payment(): def poll_btcpay_session(invoice_id): - + + if 'BTCPAY_CLIENT' not in current_app.config: + if not try_reconnnect_btcpay(): + return [503, "can't contact btcpay server"] + invoice = None try: invoice = current_app.config['BTCPAY_CLIENT'].get_invoice(invoice_id) @@ -130,6 +139,20 @@ def poll_btcpay_session(invoice_id): return [200, "ok"] +def try_reconnnect_btcpay(): + try: + response = requests.get(current_app.config['BTCPAY_URL']) + if response.status_code == 200: + current_app.config['BTCPAY_CLIENT'] = btcpay.Client(api_uri=current_app.config['BTCPAY_URL'], pem=current_app.config['BTCPAY_PRIVATE_KEY']) + return True + else: + current_app.logger.warn(f"Can't reach BTCPAY_URL {current_app.config['BTCPAY_URL']}: Response status code: {response.status_code}. Capsul will work fine except cryptocurrency payments will not work.") + return False + except: + current_app.logger.warn("unable to create btcpay client. Capsul will work fine except cryptocurrency payments will not work. The error was: " + my_exec_info_message(sys.exc_info())) + return False + + @bp.route("/btcpay/webhook", methods=("POST",)) def btcpay_webhook(): diff --git a/capsulflask/static/style.css b/capsulflask/static/style.css index c82e063..f10468a 100644 --- a/capsulflask/static/style.css +++ b/capsulflask/static/style.css @@ -50,6 +50,19 @@ a:hover, a:active, a:visited { border-color: rgb(8, 173, 137); } +.error { + color: rgb(173, 74, 8); + font-weight: bold; + border: 1px dashed rgb(173, 74, 8); + border-radius: 0.5em; + padding: 1em; +} + +.disabled { + color: #585a5c; +} + + .display-none { display: none; } diff --git a/capsulflask/templates/account-balance.html b/capsulflask/templates/account-balance.html index 3d47e70..5e2076f 100644 --- a/capsulflask/templates/account-balance.html +++ b/capsulflask/templates/account-balance.html @@ -47,7 +47,15 @@ {% if btcpay_enabled %} -
  • Add funds with Bitcoin/Litecoin/Monero (btcpay)
  • + {% if btcpay_is_working %} +
  • Add funds with Bitcoin/Litecoin/Monero (btcpay)
  • + {% else %} +
  • + Add funds with Bitcoin/Litecoin/Monero (btcpay) + ERROR: the BTCPay server cannot be reached +
  • + {% endif %} + {% endif %}
  • Cash: email treasurer@cyberia.club
  • diff --git a/capsulflask/templates/btcpay.html b/capsulflask/templates/btcpay.html index f51a883..5f7e14b 100644 --- a/capsulflask/templates/btcpay.html +++ b/capsulflask/templates/btcpay.html @@ -20,11 +20,7 @@ type="text" /> - - -
    -
    -

    Our BTCPay Server instance is finally back online 🥳

    +