btcpay working! added bitpay client code to source tree to fix a bug
fixed a stripe race condition added account balance warning to account balance page
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import click
|
||||
from flask.cli import with_appcontext
|
||||
@ -60,95 +60,158 @@ def sql_script(f, c):
|
||||
|
||||
model.connection.commit()
|
||||
|
||||
|
||||
@bp.cli.command('cron-task')
|
||||
@with_appcontext
|
||||
def cron_task():
|
||||
|
||||
# make sure btcpay payments get completed (in case we miss a webhook), otherwise invalidate the payment
|
||||
|
||||
unresolved_btcpay_invoices = get_model().get_unresolved_btcpay_invoices()
|
||||
for invoice in unresolved_btcpay_invoices:
|
||||
invoice_id = invoice.id
|
||||
invoice = current_app.config['BTCPAY_CLIENT'].get_invoice(invoice_id)
|
||||
days = float((datetime.now() - invoice.created).total_seconds())/float(60*60*24)
|
||||
|
||||
if invoice['status'] == "complete":
|
||||
get_model().btcpay_invoice_resolved(invoice_id, True)
|
||||
elif days >= 1:
|
||||
get_model().btcpay_invoice_resolved(invoice_id, False)
|
||||
print("cron_task: starting clean_up_unresolved_btcpay_invoices")
|
||||
clean_up_unresolved_btcpay_invoices()
|
||||
print("cron_task: finished clean_up_unresolved_btcpay_invoices")
|
||||
|
||||
# notify when funds run out
|
||||
print("cron_task: starting notify_users_about_account_balance")
|
||||
notify_users_about_account_balance()
|
||||
print("cron_task: finished notify_users_about_account_balance")
|
||||
|
||||
accounts = get_model().accounts_list()
|
||||
# make sure vm system and DB are synced
|
||||
print("cron_task: starting ensure_vms_and_db_are_synced")
|
||||
ensure_vms_and_db_are_synced()
|
||||
print("cron_task: finished ensure_vms_and_db_are_synced")
|
||||
|
||||
|
||||
|
||||
def clean_up_unresolved_btcpay_invoices():
|
||||
unresolved_btcpay_invoices = get_model().get_unresolved_btcpay_invoices()
|
||||
for unresolved_invoice in unresolved_btcpay_invoices:
|
||||
invoice_id = unresolved_invoice['id']
|
||||
btcpay_invoice = current_app.config['BTCPAY_CLIENT'].get_invoice(invoice_id)
|
||||
days = float((datetime.now() - unresolved_invoice['created']).total_seconds())/float(60*60*24)
|
||||
|
||||
if btcpay_invoice['status'] == "complete":
|
||||
print(
|
||||
f"resolving btcpay invoice {invoice_id} "
|
||||
f"({unresolved_invoice['email']}, ${unresolved_invoice['dollars']}) as completed "
|
||||
)
|
||||
get_model().btcpay_invoice_resolved(invoice_id, True)
|
||||
elif days >= 1:
|
||||
print(
|
||||
f"resolving btcpay invoice {invoice_id} "
|
||||
f"({unresolved_invoice['email']}, ${unresolved_invoice['dollars']}) as invalidated, "
|
||||
f"btcpay server invoice status: {btcpay_invoice['status']}"
|
||||
)
|
||||
get_model().btcpay_invoice_resolved(invoice_id, False)
|
||||
|
||||
delete_at_account_balance_dollars = -10
|
||||
|
||||
def get_warning_headline(warning_id, pluralize_capsul):
|
||||
return dict(
|
||||
zero_1w= (
|
||||
"According to our calculations, your Capsul account will run out of funds before this time next week.\n\n"
|
||||
),
|
||||
zero_1d= (
|
||||
"According to our calculations, your Capsul account will run out of funds by this time tomorrow.\n\n"
|
||||
),
|
||||
zero_now= (
|
||||
f"You have run out of funds! You will no longer be able to create Capsuls.\n\n"
|
||||
f"As a courtesy, we'll let your existing Capsul{pluralize_capsul} keep running until your account "
|
||||
"reaches a -$10 balance, at which point they will be deleted.\n\n"
|
||||
),
|
||||
delete_1w= (
|
||||
"You have run out of funds and have not refilled your account.\n\n"
|
||||
f"As a courtesy, we've let your existing Capsul{pluralize_capsul} keep running. "
|
||||
f"However, your account will reach a -$10 balance some time next week and your Capsul{pluralize_capsul} "
|
||||
"will be deleted.\n\n"
|
||||
),
|
||||
delete_1d= (
|
||||
"You have run out of funds and have not refilled your account.\n\n"
|
||||
f"As a courtesy, we have let your existing Capsul{pluralize_capsul} keep running. "
|
||||
f"However, your account will reach a -$10 balance by this time tomorrow and "
|
||||
f"your Capsul{pluralize_capsul} will be deleted.\n\n"
|
||||
f"Last chance to deposit funds now and keep your Capsul{pluralize_capsul} running! "
|
||||
),
|
||||
delete_now= (
|
||||
f"Your account reached a -$10 balance and your Capsul{pluralize_capsul} were deleted."
|
||||
)
|
||||
)[warning_id]
|
||||
|
||||
def get_warnings_list():
|
||||
return [
|
||||
dict(
|
||||
id='zero_1w',
|
||||
get_active=lambda balance_1w, balance_1d, balance_now: balance_1w < 0,
|
||||
get_subject=lambda _: "Capsul One Week Payment Reminder",
|
||||
get_body=lambda base_url, pluralize_capsul: (
|
||||
f"{get_warning_headline('zero_1w', pluralize_capsul)}"
|
||||
f"Log in now to re-fill your account! {base_url}/console/account-balance\n\n"
|
||||
"If you believe you have recieved this message in error, please let us know: support@cyberia.club"
|
||||
)
|
||||
),
|
||||
dict(
|
||||
id='zero_1d',
|
||||
get_active=lambda balance_1w, balance_1d, balance_now: balance_1d < 0,
|
||||
get_subject=lambda _: "Capsul One Day Payment Reminder",
|
||||
get_body=lambda base_url, pluralize_capsul: (
|
||||
f"{get_warning_headline('zero_1d', pluralize_capsul)}"
|
||||
f"Log in now to re-fill your account! {base_url}/console/account-balance\n\n"
|
||||
"If you believe you have recieved this message in error, please let us know: support@cyberia.club"
|
||||
)
|
||||
),
|
||||
dict(
|
||||
id='zero_now',
|
||||
get_active=lambda balance_1w, balance_1d, balance_now: balance_now < 0,
|
||||
get_subject=lambda _: "Your Capsul Account is No Longer Funded",
|
||||
get_body=lambda base_url, pluralize_capsul: (
|
||||
f"{get_warning_headline('zero_now', pluralize_capsul)}"
|
||||
f"Log in now to re-fill your account! {base_url}/console/account-balance\n\n"
|
||||
f"If you need help decomissioning your Capsul{pluralize_capsul}, "
|
||||
"would like to request backups, or de-activate your account, please contact: support@cyberia.club"
|
||||
)
|
||||
),
|
||||
dict(
|
||||
id='delete_1w',
|
||||
get_active=lambda balance_1w, balance_1d, balance_now: balance_1w < delete_at_account_balance_dollars,
|
||||
get_subject=lambda pluralize_capsul: f"Your Capsul{pluralize_capsul} Will be Deleted In Less Than a Week",
|
||||
get_body=lambda base_url, pluralize_capsul: (
|
||||
f"{get_warning_headline('delete_1w', pluralize_capsul)}"
|
||||
f"Log in now to re-fill your account! {base_url}/console/account-balance\n\n"
|
||||
f"If you need help decomissioning your Capsul{pluralize_capsul}, "
|
||||
"would like to request backups, or de-activate your account, please contact: support@cyberia.club"
|
||||
)
|
||||
),
|
||||
dict(
|
||||
id='delete_1d',
|
||||
get_active=lambda balance_1w, balance_1d, balance_now: balance_1d < delete_at_account_balance_dollars,
|
||||
get_subject=lambda pluralize_capsul: f"Last Chance to Save your Capsul{pluralize_capsul}: Gone Tomorrow",
|
||||
get_body=lambda base_url, pluralize_capsul: (
|
||||
f"{get_warning_headline('delete_1d', pluralize_capsul)}"
|
||||
f"{base_url}/console/account-balance"
|
||||
)
|
||||
),
|
||||
dict(
|
||||
id='delete_now',
|
||||
get_active=lambda balance_1w, balance_1d, balance_now: balance_now < delete_at_account_balance_dollars,
|
||||
get_subject=lambda pluralize_capsul: f"Capsul{pluralize_capsul} Deleted",
|
||||
get_body=lambda base_url, pluralize_capsul: (
|
||||
f"{get_warning_headline('delete_now', pluralize_capsul)}"
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
def notify_users_about_account_balance():
|
||||
accounts = get_model().all_accounts()
|
||||
for account in accounts:
|
||||
vms = get_model().list_vms_for_account(account['email'])
|
||||
payments = get_model().list_payments_for_account(account['email'])
|
||||
balance_1w = get_account_balance(vms, payments, datetime.utcnow() + datetime.timedelta(days=7))
|
||||
balance_1d = get_account_balance(vms, payments, datetime.utcnow() + datetime.timedelta(days=1))
|
||||
balance_1w = get_account_balance(vms, payments, datetime.utcnow() + timedelta(days=7))
|
||||
balance_1d = get_account_balance(vms, payments, datetime.utcnow() + timedelta(days=1))
|
||||
balance_now = get_account_balance(vms, payments, datetime.utcnow())
|
||||
current_warning = account['account_balance_warning']
|
||||
|
||||
delete_at_account_balance = -10
|
||||
|
||||
pluralize_capsul = "s" if len(vms) > 1 else ""
|
||||
|
||||
warnings = [
|
||||
dict(
|
||||
id='zero_1w',
|
||||
active=balance_1w < 0,
|
||||
subject="Capsul One Week Payment Reminder",
|
||||
body=("According to our calculations, your Capsul account will run out of funds in one week.\n\n"
|
||||
f"Log in now to re-fill your account! {current_app.config['BASE_URL']}/console/account-balance\n\n"
|
||||
"If you believe you have recieved this message in error, please let us know: support@cyberia.club")
|
||||
),
|
||||
dict(
|
||||
id='zero_1d',
|
||||
active=balance_1d < 0,
|
||||
subject="Capsul One Day Payment Reminder",
|
||||
body=("According to our calculations, your Capsul account will run out of funds tomorrow.\n\n"
|
||||
f"Log in now to re-fill your account! {current_app.config['BASE_URL']}/console/account-balance\n\n"
|
||||
"If you believe you have recieved this message in error, please let us know: support@cyberia.club")
|
||||
),
|
||||
dict(
|
||||
id='zero_now',
|
||||
active=balance_now < 0,
|
||||
subject="Your Capsul Account is No Longer Funded",
|
||||
body=(f"You have run out of funds! You will no longer be able to create Capsul{pluralize_capsul}.\n\n"
|
||||
f"As a courtesy, we'll let your existing Capsul{pluralize_capsul} keep running until your account "
|
||||
"reaches a -$10 balance, at which point they will be deleted.\n\n"
|
||||
f"Log in now to re-fill your account! {current_app.config['BASE_URL']}/console/account-balance\n\n"
|
||||
f"If you need help decomissioning your Capsul{pluralize_capsul}, "
|
||||
"would like to request backups, or de-activate your account, please contact: support@cyberia.club")
|
||||
),
|
||||
dict(
|
||||
id='delete_1w',
|
||||
active=balance_1w < delete_at_account_balance,
|
||||
subject=f"Your Capsul{pluralize_capsul} Will be Deleted In Less Than a Week",
|
||||
body=("You have run out of funds and have not refilled your account.\n\n"
|
||||
f"As a courtesy, we have let your existing Capsul{pluralize_capsul} keep running. "
|
||||
f"However, your account will reach a -$10 balance some time next week and your Capsul{pluralize_capsul}"
|
||||
"will be deleted.\n\n"
|
||||
f"Log in now to re-fill your account! {current_app.config['BASE_URL']}/console/account-balance\n\n"
|
||||
f"If you need help decomissioning your Capsul{pluralize_capsul}, "
|
||||
"would like to request backups, or de-activate your account, please contact: support@cyberia.club")
|
||||
),
|
||||
dict(
|
||||
id='delete_1d',
|
||||
active=balance_1d < delete_at_account_balance,
|
||||
subject=f"Last Chance to Save your Capsul{pluralize_capsul}: Gone Tomorrow",
|
||||
body=("You have run out of funds and have not refilled your account.\n\n"
|
||||
f"As a courtesy, we have let your existing Capsul{pluralize_capsul} keep running. "
|
||||
f"However, your account will reach a -$10 balance tomorrow and your Capsul{pluralize_capsul} will be deleted.\n\n"
|
||||
f"Last chance to deposit funds now and keep your Capsul{pluralize_capsul} running! {current_app.config['BASE_URL']}/console/account-balance")
|
||||
),
|
||||
dict(
|
||||
id='delete_now',
|
||||
active=balance_now < delete_at_account_balance,
|
||||
subject=f"Capsul{pluralize_capsul} Deleted",
|
||||
body=(f"Your account reached a -$10 balance and your Capsul{pluralize_capsul} were deleted.")
|
||||
)
|
||||
]
|
||||
|
||||
warnings = get_warnings_list()
|
||||
current_warning_index = -1
|
||||
if current_warning:
|
||||
for i in range(0, len(warnings)):
|
||||
@ -157,15 +220,17 @@ def cron_task():
|
||||
|
||||
index_to_send = -1
|
||||
for i in range(0, len(warnings)):
|
||||
if i > current_warning_index and warnings[i].active:
|
||||
if i > current_warning_index and warnings[i]['get_active'](balance_1w, balance_1d, balance_now):
|
||||
index_to_send = i
|
||||
|
||||
if index_to_send > -1:
|
||||
print(f"cron_task: sending {warnings[index_to_send]['id']} warning email to {account['email']}.")
|
||||
get_body = warnings[index_to_send]['get_body']
|
||||
get_subject = warnings[index_to_send]['get_subject']
|
||||
current_app.config["FLASK_MAIL_INSTANCE"].send(
|
||||
Message(
|
||||
warnings[index_to_send]['subject'],
|
||||
body=warnings[index_to_send]['body'],
|
||||
get_subject(pluralize_capsul),
|
||||
body=get_body(current_app.config['BASE_URL'], pluralize_capsul),
|
||||
recipients=[account['email']]
|
||||
)
|
||||
)
|
||||
@ -176,6 +241,5 @@ def cron_task():
|
||||
current_app.config["VIRTUALIZATION_MODEL"].destroy(email=account["email"], id=vm['id'])
|
||||
get_model().delete_vm(email=account["email"], id=vm['id'])
|
||||
|
||||
|
||||
|
||||
# make sure vm system and DB are synced
|
||||
def ensure_vms_and_db_are_synced():
|
||||
print("a")
|
Reference in New Issue
Block a user