From 42bd5ea989872a6cc7f332f246a6c605afe1d7a1 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Wed, 24 Mar 2021 00:40:32 -0300 Subject: [PATCH] remove exception to black line-length and reformat. --- lnbits/__main__.py | 9 ++- lnbits/app.py | 15 +++- lnbits/bolt11.py | 4 +- lnbits/commands.py | 18 ++++- lnbits/core/__init__.py | 6 +- lnbits/core/crud.py | 30 +++++-- lnbits/core/migrations.py | 7 +- lnbits/core/models.py | 4 +- lnbits/core/services.py | 26 ++++-- lnbits/core/views/api.py | 60 +++++++++++--- lnbits/core/views/generic.py | 56 ++++++++++--- lnbits/db.py | 4 +- lnbits/decorators.py | 8 +- lnbits/extensions/amilk/__init__.py | 4 +- lnbits/extensions/amilk/crud.py | 4 +- lnbits/extensions/amilk/views_api.py | 20 ++++- lnbits/extensions/bleskomat/__init__.py | 4 +- lnbits/extensions/bleskomat/crud.py | 19 ++++- lnbits/extensions/bleskomat/exchange_rates.py | 18 ++++- lnbits/extensions/bleskomat/helpers.py | 35 ++++++-- lnbits/extensions/bleskomat/lnurl_api.py | 29 +++++-- lnbits/extensions/bleskomat/models.py | 12 ++- lnbits/extensions/bleskomat/views.py | 4 +- lnbits/extensions/bleskomat/views_api.py | 49 +++++++++--- lnbits/extensions/captcha/__init__.py | 4 +- lnbits/extensions/captcha/crud.py | 12 ++- lnbits/extensions/captcha/migrations.py | 4 +- lnbits/extensions/captcha/views.py | 4 +- lnbits/extensions/captcha/views_api.py | 44 +++++++--- lnbits/extensions/diagonalley/__init__.py | 4 +- lnbits/extensions/diagonalley/crud.py | 62 +++++++++++--- lnbits/extensions/diagonalley/views_api.py | 80 +++++++++++++++---- lnbits/extensions/events/__init__.py | 4 +- lnbits/extensions/events/crud.py | 20 +++-- lnbits/extensions/events/views.py | 18 ++++- lnbits/extensions/events/views_api.py | 38 +++++++-- lnbits/extensions/example/__init__.py | 4 +- lnbits/extensions/lndhub/__init__.py | 4 +- lnbits/extensions/lndhub/decorators.py | 8 +- lnbits/extensions/lndhub/views_api.py | 46 ++++++++--- lnbits/extensions/lnticket/__init__.py | 4 +- lnbits/extensions/lnticket/crud.py | 22 ++++- lnbits/extensions/lnticket/views_api.py | 24 ++++-- lnbits/extensions/lnurlp/__init__.py | 4 +- lnbits/extensions/lnurlp/crud.py | 8 +- lnbits/extensions/lnurlp/lnurl.py | 26 ++++-- lnbits/extensions/lnurlp/migrations.py | 8 +- lnbits/extensions/lnurlp/views_api.py | 23 +++++- lnbits/extensions/offlineshop/__init__.py | 4 +- lnbits/extensions/offlineshop/lnurl.py | 22 ++++- lnbits/extensions/offlineshop/models.py | 12 ++- lnbits/extensions/offlineshop/views.py | 16 +++- lnbits/extensions/offlineshop/views_api.py | 13 ++- lnbits/extensions/paywall/__init__.py | 4 +- lnbits/extensions/paywall/crud.py | 12 ++- lnbits/extensions/paywall/migrations.py | 4 +- lnbits/extensions/paywall/views.py | 4 +- lnbits/extensions/paywall/views_api.py | 44 +++++++--- lnbits/extensions/subdomains/__init__.py | 4 +- lnbits/extensions/subdomains/cloudflare.py | 26 ++++-- lnbits/extensions/subdomains/crud.py | 34 +++++++- lnbits/extensions/subdomains/tasks.py | 5 +- lnbits/extensions/subdomains/views.py | 4 +- lnbits/extensions/subdomains/views_api.py | 50 +++++++++--- lnbits/extensions/tpos/__init__.py | 4 +- lnbits/extensions/tpos/crud.py | 4 +- lnbits/extensions/tpos/views_api.py | 19 ++++- lnbits/extensions/usermanager/__init__.py | 4 +- lnbits/extensions/usermanager/crud.py | 12 ++- lnbits/extensions/usermanager/views_api.py | 24 ++++-- lnbits/extensions/withdraw/__init__.py | 4 +- lnbits/extensions/withdraw/crud.py | 18 +++-- lnbits/extensions/withdraw/lnurl.py | 53 +++++++++--- lnbits/extensions/withdraw/migrations.py | 6 +- lnbits/extensions/withdraw/models.py | 12 ++- lnbits/extensions/withdraw/views.py | 16 +++- lnbits/extensions/withdraw/views_api.py | 38 +++++++-- lnbits/helpers.py | 20 +++-- lnbits/settings.py | 16 +++- lnbits/tasks.py | 10 ++- lnbits/utils/exchange_rates.py | 7 +- lnbits/wallets/base.py | 5 +- lnbits/wallets/clightning.py | 18 ++++- lnbits/wallets/lnbits.py | 44 ++++++++-- lnbits/wallets/lndgrpc.py | 21 ++++- lnbits/wallets/lndrest.py | 28 +++++-- lnbits/wallets/lnpay.py | 21 ++++- lnbits/wallets/lntxbot.py | 23 +++++- lnbits/wallets/opennode.py | 28 ++++++- lnbits/wallets/spark.py | 22 ++++- lnbits/wallets/void.py | 14 +++- pyproject.toml | 2 - 92 files changed, 1341 insertions(+), 330 deletions(-) delete mode 100644 pyproject.toml diff --git a/lnbits/__main__.py b/lnbits/__main__.py index 89fc6163..fa75231c 100644 --- a/lnbits/__main__.py +++ b/lnbits/__main__.py @@ -10,7 +10,14 @@ from .app import create_app app = create_app() -from .settings import LNBITS_SITE_TITLE, SERVICE_FEE, DEBUG, LNBITS_DATA_FOLDER, WALLET, LNBITS_COMMIT +from .settings import ( + LNBITS_SITE_TITLE, + SERVICE_FEE, + DEBUG, + LNBITS_DATA_FOLDER, + WALLET, + LNBITS_COMMIT, +) print( f"""Starting LNbits with diff --git a/lnbits/app.py b/lnbits/app.py index 15c22fb6..bc2c99d5 100644 --- a/lnbits/app.py +++ b/lnbits/app.py @@ -9,7 +9,12 @@ from secure import SecureHeaders # type: ignore from .commands import db_migrate, handle_assets from .core import core_app -from .helpers import get_valid_extensions, get_js_vendored, get_css_vendored, url_for_vendored +from .helpers import ( + get_valid_extensions, + get_js_vendored, + get_css_vendored, + url_for_vendored, +) from .proxy_fix import ASGIProxyFix from .tasks import ( run_deferred_async, @@ -57,7 +62,9 @@ def check_funding_source(app: QuartTrio) -> None: RuntimeWarning, ) else: - print(f" ✔️ {WALLET.__class__.__name__} seems to be connected and with a balance of {balance} msat.") + print( + f" ✔️ {WALLET.__class__.__name__} seems to be connected and with a balance of {balance} msat." + ) def register_blueprints(app: QuartTrio) -> None: @@ -75,7 +82,9 @@ def register_blueprints(app: QuartTrio) -> None: app.register_blueprint(bp, url_prefix=f"/{ext.code}") except Exception: - raise ImportError(f"Please make sure that the extension `{ext.code}` follows conventions.") + raise ImportError( + f"Please make sure that the extension `{ext.code}` follows conventions." + ) def register_commands(app: QuartTrio): diff --git a/lnbits/bolt11.py b/lnbits/bolt11.py index 1be351be..6acc6db7 100644 --- a/lnbits/bolt11.py +++ b/lnbits/bolt11.py @@ -106,7 +106,9 @@ def decode(pr: str) -> Invoice: key = VerifyingKey.from_string(unhexlify(invoice.payee), curve=SECP256k1) key.verify(sig, message, hashlib.sha256, sigdecode=sigdecode_string) else: - keys = VerifyingKey.from_public_key_recovery(sig, message, SECP256k1, hashlib.sha256) + keys = VerifyingKey.from_public_key_recovery( + sig, message, SECP256k1, hashlib.sha256 + ) signaling_byte = signature[64] key = keys[int(signaling_byte)] invoice.payee = key.to_string("compressed").hex() diff --git a/lnbits/commands.py b/lnbits/commands.py index 8236766e..b546765b 100644 --- a/lnbits/commands.py +++ b/lnbits/commands.py @@ -7,7 +7,12 @@ import os from sqlalchemy.exc import OperationalError # type: ignore from .core import db as core_db, migrations as core_migrations -from .helpers import get_valid_extensions, get_css_vendored, get_js_vendored, url_for_vendored +from .helpers import ( + get_valid_extensions, + get_css_vendored, + get_js_vendored, + url_for_vendored, +) from .settings import LNBITS_PATH @@ -71,18 +76,23 @@ async def migrate_databases(): print(f"running migration {db_name}.{version}") await migrate(db) await core_conn.execute( - "INSERT OR REPLACE INTO dbversions (db, version) VALUES (?, ?)", (db_name, version) + "INSERT OR REPLACE INTO dbversions (db, version) VALUES (?, ?)", + (db_name, version), ) await run_migration(core_conn, core_migrations) for ext in get_valid_extensions(): try: - ext_migrations = importlib.import_module(f"lnbits.extensions.{ext.code}.migrations") + ext_migrations = importlib.import_module( + f"lnbits.extensions.{ext.code}.migrations" + ) ext_db = importlib.import_module(f"lnbits.extensions.{ext.code}").db await run_migration(ext_db, ext_migrations) except ImportError: - raise ImportError(f"Please make sure that the extension `{ext.code}` has a migrations file.") + raise ImportError( + f"Please make sure that the extension `{ext.code}` has a migrations file." + ) await core_txn.commit() await core_conn.close() diff --git a/lnbits/core/__init__.py b/lnbits/core/__init__.py index a2ea1ddf..ca0959a8 100644 --- a/lnbits/core/__init__.py +++ b/lnbits/core/__init__.py @@ -4,7 +4,11 @@ from lnbits.db import Database db = Database("database") core_app: Blueprint = Blueprint( - "core", __name__, template_folder="templates", static_folder="static", static_url_path="/core/static" + "core", + __name__, + template_folder="templates", + static_folder="static", + static_url_path="/core/static", ) diff --git a/lnbits/core/crud.py b/lnbits/core/crud.py index c759482e..11e5ceaa 100644 --- a/lnbits/core/crud.py +++ b/lnbits/core/crud.py @@ -25,7 +25,9 @@ async def create_account() -> User: async def get_account(user_id: str) -> Optional[User]: - row = await db.fetchone("SELECT id, email, pass as password FROM accounts WHERE id = ?", (user_id,)) + row = await db.fetchone( + "SELECT id, email, pass as password FROM accounts WHERE id = ?", (user_id,) + ) return User(**row) if row else None @@ -34,7 +36,9 @@ async def get_user(user_id: str) -> Optional[User]: user = await db.fetchone("SELECT id, email FROM accounts WHERE id = ?", (user_id,)) if user: - extensions = await db.fetchall("SELECT extension FROM extensions WHERE user = ? AND active = 1", (user_id,)) + extensions = await db.fetchall( + "SELECT extension FROM extensions WHERE user = ? AND active = 1", (user_id,) + ) wallets = await db.fetchall( """ SELECT *, COALESCE((SELECT balance FROM balances WHERE wallet = wallets.id), 0) AS balance_msat @@ -45,7 +49,15 @@ async def get_user(user_id: str) -> Optional[User]: ) return ( - User(**{**user, **{"extensions": [e[0] for e in extensions], "wallets": [Wallet(**w) for w in wallets]}}) + User( + **{ + **user, + **{ + "extensions": [e[0] for e in extensions], + "wallets": [Wallet(**w) for w in wallets], + }, + } + ) if user else None ) @@ -72,7 +84,13 @@ async def create_wallet(*, user_id: str, wallet_name: Optional[str] = None) -> W INSERT INTO wallets (id, name, user, adminkey, inkey) VALUES (?, ?, ?, ?, ?) """, - (wallet_id, wallet_name or DEFAULT_WALLET_NAME, user_id, uuid4().hex, uuid4().hex), + ( + wallet_id, + wallet_name or DEFAULT_WALLET_NAME, + user_id, + uuid4().hex, + uuid4().hex, + ), ) new_wallet = await get_wallet(wallet_id=wallet_id) @@ -280,7 +298,9 @@ async def create_payment( int(pending), memo, fee, - json.dumps(extra) if extra and extra != {} and type(extra) is dict else None, + json.dumps(extra) + if extra and extra != {} and type(extra) is dict + else None, webhook, ), ) diff --git a/lnbits/core/migrations.py b/lnbits/core/migrations.py index d0496322..890bf51f 100644 --- a/lnbits/core/migrations.py +++ b/lnbits/core/migrations.py @@ -111,7 +111,12 @@ async def m002_add_fields_to_apipayments(db): UPDATE apipayments SET extra = ?, memo = ? WHERE checking_id = ? AND memo = ? """, - (json.dumps({"tag": ext}), new, row["checking_id"], row["memo"]), + ( + json.dumps({"tag": ext}), + new, + row["checking_id"], + row["memo"], + ), ) break except OperationalError: diff --git a/lnbits/core/models.py b/lnbits/core/models.py index d3e9580d..8e429327 100644 --- a/lnbits/core/models.py +++ b/lnbits/core/models.py @@ -127,7 +127,9 @@ class Payment(NamedTuple): @property def is_uncheckable(self) -> bool: - return self.checking_id.startswith("temp_") or self.checking_id.startswith("internal_") + return self.checking_id.startswith("temp_") or self.checking_id.startswith( + "internal_" + ) async def set_pending(self, pending: bool) -> None: from .crud import update_payment_status diff --git a/lnbits/core/services.py b/lnbits/core/services.py index 266e36a8..2afb2921 100644 --- a/lnbits/core/services.py +++ b/lnbits/core/services.py @@ -18,7 +18,14 @@ from lnbits.settings import WALLET from lnbits.wallets.base import PaymentStatus, PaymentResponse from . import db -from .crud import get_wallet, create_payment, delete_payment, check_internal, update_payment_status, get_wallet_payment +from .crud import ( + get_wallet, + create_payment, + delete_payment, + check_internal, + update_payment_status, + get_wallet_payment, +) async def create_invoice( @@ -101,7 +108,9 @@ async def pay_invoice( internal_checking_id = await check_internal(invoice.payment_hash) if internal_checking_id: # create a new payment from this wallet - await create_payment(checking_id=internal_id, fee=0, pending=False, **payment_kwargs) + await create_payment( + checking_id=internal_id, fee=0, pending=False, **payment_kwargs + ) else: # create a temporary payment here so we can check if # the balance is enough in the next step @@ -143,12 +152,16 @@ async def pay_invoice( else: await delete_payment(temp_id) await db.commit() - raise Exception(payment.error_message or "Failed to pay_invoice on backend.") + raise Exception( + payment.error_message or "Failed to pay_invoice on backend." + ) return invoice.payment_hash -async def redeem_lnurl_withdraw(wallet_id: str, res: LnurlWithdrawResponse, memo: Optional[str] = None) -> None: +async def redeem_lnurl_withdraw( + wallet_id: str, res: LnurlWithdrawResponse, memo: Optional[str] = None +) -> None: _, payment_request = await create_invoice( wallet_id=wallet_id, amount=res.max_sats, @@ -159,7 +172,10 @@ async def redeem_lnurl_withdraw(wallet_id: str, res: LnurlWithdrawResponse, memo async with httpx.AsyncClient() as client: await client.get( res.callback.base, - params={**res.callback.query_params, **{"k1": res.k1, "pr": payment_request}}, + params={ + **res.callback.query_params, + **{"k1": res.k1, "pr": payment_request}, + }, ) diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py index e513a8d6..7290aba2 100644 --- a/lnbits/core/views/api.py +++ b/lnbits/core/views/api.py @@ -41,8 +41,18 @@ async def api_payments(): @api_validate_post_request( schema={ "amount": {"type": "integer", "min": 1, "required": True}, - "memo": {"type": "string", "empty": False, "required": True, "excludes": "description_hash"}, - "description_hash": {"type": "string", "empty": False, "required": True, "excludes": "memo"}, + "memo": { + "type": "string", + "empty": False, + "required": True, + "excludes": "description_hash", + }, + "description_hash": { + "type": "string", + "empty": False, + "required": True, + "excludes": "memo", + }, "lnurl_callback": {"type": "string", "nullable": True, "required": False}, "extra": {"type": "dict", "nullable": True, "required": False}, "webhook": {"type": "string", "empty": False, "required": False}, @@ -108,10 +118,14 @@ async def api_payments_create_invoice(): @api_check_wallet_key("admin") -@api_validate_post_request(schema={"bolt11": {"type": "string", "empty": False, "required": True}}) +@api_validate_post_request( + schema={"bolt11": {"type": "string", "empty": False, "required": True}} +) async def api_payments_pay_invoice(): try: - payment_hash = await pay_invoice(wallet_id=g.wallet.id, payment_request=g.data["bolt11"]) + payment_hash = await pay_invoice( + wallet_id=g.wallet.id, payment_request=g.data["bolt11"] + ) except ValueError as e: return jsonify({"message": str(e)}), HTTPStatus.BAD_REQUEST except PermissionError as e: @@ -147,8 +161,18 @@ async def api_payments_create(): "description_hash": {"type": "string", "empty": False, "required": True}, "callback": {"type": "string", "empty": False, "required": True}, "amount": {"type": "number", "empty": False, "required": True}, - "comment": {"type": "string", "nullable": True, "empty": True, "required": False}, - "description": {"type": "string", "nullable": True, "empty": True, "required": False}, + "comment": { + "type": "string", + "nullable": True, + "empty": True, + "required": False, + }, + "description": { + "type": "string", + "nullable": True, + "empty": True, + "required": False, + }, } ) async def api_payments_pay_lnurl(): @@ -168,7 +192,10 @@ async def api_payments_pay_lnurl(): params = json.loads(r.text) if params.get("status") == "ERROR": - return jsonify({"message": f"{domain} said: '{params.get('reason', '')}'"}), HTTPStatus.BAD_REQUEST + return ( + jsonify({"message": f"{domain} said: '{params.get('reason', '')}'"}), + HTTPStatus.BAD_REQUEST, + ) invoice = bolt11.decode(params["pr"]) if invoice.amount_msat != g.data["amount"]: @@ -236,7 +263,10 @@ async def api_payment(payment_hash): except Exception: return jsonify({"paid": False}), HTTPStatus.OK - return jsonify({"paid": not payment.pending, "preimage": payment.preimage}), HTTPStatus.OK + return ( + jsonify({"paid": not payment.pending, "preimage": payment.preimage}), + HTTPStatus.OK, + ) @core_app.route("/api/v1/payments/sse", methods=["GET"]) @@ -325,12 +355,22 @@ async def api_lnurlscan(code: str): data: lnurl.LnurlResponseModel = lnurl.LnurlResponse.from_dict(jdata) except (json.decoder.JSONDecodeError, lnurl.exceptions.LnurlResponseException): return ( - jsonify({"domain": domain, "message": f"got invalid response '{r.text[:200]}'"}), + jsonify( + { + "domain": domain, + "message": f"got invalid response '{r.text[:200]}'", + } + ), HTTPStatus.SERVICE_UNAVAILABLE, ) if type(data) is lnurl.LnurlChannelResponse: - return jsonify({"domain": domain, "kind": "channel", "message": "unsupported"}), HTTPStatus.BAD_REQUEST + return ( + jsonify( + {"domain": domain, "kind": "channel", "message": "unsupported"} + ), + HTTPStatus.BAD_REQUEST, + ) params.update(**data.dict()) diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py index 3156169d..545b2677 100644 --- a/lnbits/core/views/generic.py +++ b/lnbits/core/views/generic.py @@ -2,7 +2,15 @@ import trio # type: ignore import httpx from os import path from http import HTTPStatus -from quart import g, abort, redirect, request, render_template, send_from_directory, url_for +from quart import ( + g, + abort, + redirect, + request, + render_template, + send_from_directory, + url_for, +) from lnurl import LnurlResponse, LnurlWithdrawResponse, decode as decode_lnurl # type: ignore from lnbits.core import core_app @@ -22,12 +30,16 @@ from ..services import redeem_lnurl_withdraw @core_app.route("/favicon.ico") async def favicon(): - return await send_from_directory(path.join(core_app.root_path, "static"), "favicon.ico") + return await send_from_directory( + path.join(core_app.root_path, "static"), "favicon.ico" + ) @core_app.route("/") async def home(): - return await render_template("core/index.html", lnurl=request.args.get("lightning", None)) + return await render_template( + "core/index.html", lnurl=request.args.get("lightning", None) + ) @core_app.route("/extensions") @@ -38,12 +50,18 @@ async def extensions(): extension_to_disable = request.args.get("disable", type=str) if extension_to_enable and extension_to_disable: - abort(HTTPStatus.BAD_REQUEST, "You can either `enable` or `disable` an extension.") + abort( + HTTPStatus.BAD_REQUEST, "You can either `enable` or `disable` an extension." + ) if extension_to_enable: - await update_user_extension(user_id=g.user.id, extension=extension_to_enable, active=1) + await update_user_extension( + user_id=g.user.id, extension=extension_to_enable, active=1 + ) elif extension_to_disable: - await update_user_extension(user_id=g.user.id, extension=extension_to_disable, active=0) + await update_user_extension( + user_id=g.user.id, extension=extension_to_disable, active=0 + ) return await render_template("core/extensions.html", user=await get_user(g.user.id)) @@ -85,7 +103,9 @@ async def wallet(): if not wallet: abort(HTTPStatus.FORBIDDEN, "Not your wallet.") - return await render_template("core/wallet.html", user=user, wallet=wallet, service_fee=service_fee) + return await render_template( + "core/wallet.html", user=user, wallet=wallet, service_fee=service_fee + ) @core_app.route("/deletewallet") @@ -116,19 +136,33 @@ async def lnurlwallet(): withdraw_res = LnurlResponse.from_dict(r.json()) if not withdraw_res.ok: - return f"Could not process lnurl-withdraw: {withdraw_res.error_msg}", HTTPStatus.BAD_REQUEST + return ( + f"Could not process lnurl-withdraw: {withdraw_res.error_msg}", + HTTPStatus.BAD_REQUEST, + ) if not isinstance(withdraw_res, LnurlWithdrawResponse): - return f"Expected an lnurl-withdraw code, got {withdraw_res.tag}", HTTPStatus.BAD_REQUEST + return ( + f"Expected an lnurl-withdraw code, got {withdraw_res.tag}", + HTTPStatus.BAD_REQUEST, + ) except Exception as exc: - return f"Could not process lnurl-withdraw: {exc}", HTTPStatus.INTERNAL_SERVER_ERROR + return ( + f"Could not process lnurl-withdraw: {exc}", + HTTPStatus.INTERNAL_SERVER_ERROR, + ) account = await create_account() user = await get_user(account.id) wallet = await create_wallet(user_id=user.id) await db.commit() - g.nursery.start_soon(redeem_lnurl_withdraw, wallet.id, withdraw_res, "LNbits initial funding: voucher redeem.") + g.nursery.start_soon( + redeem_lnurl_withdraw, + wallet.id, + withdraw_res, + "LNbits initial funding: voucher redeem.", + ) await trio.sleep(3) return redirect(url_for("core.wallet", usr=user.id, wal=wallet.id)) diff --git a/lnbits/db.py b/lnbits/db.py index e55cad07..6a44b6c2 100644 --- a/lnbits/db.py +++ b/lnbits/db.py @@ -18,7 +18,9 @@ class Database: def session_connection(self) -> Tuple[Optional[Any], Optional[Any]]: try: - return getattr(g, f"{self.db_name}_conn", None), getattr(g, f"{self.db_name}_txn", None) + return getattr(g, f"{self.db_name}_conn", None), getattr( + g, f"{self.db_name}_txn", None + ) except RuntimeError: return None, None diff --git a/lnbits/decorators.py b/lnbits/decorators.py index 1e659e09..5d923c35 100644 --- a/lnbits/decorators.py +++ b/lnbits/decorators.py @@ -77,11 +77,15 @@ def check_user_exists(param: str = "usr"): return wrap -def validate_uuids(params: List[str], *, required: Union[bool, List[str]] = False, version: int = 4): +def validate_uuids( + params: List[str], *, required: Union[bool, List[str]] = False, version: int = 4 +): def wrap(view): @wraps(view) async def wrapped_view(**kwargs): - query_params = {param: request.args.get(param, type=str) for param in params} + query_params = { + param: request.args.get(param, type=str) for param in params + } for param, value in query_params.items(): if not value and (required is True or (required and param in required)): diff --git a/lnbits/extensions/amilk/__init__.py b/lnbits/extensions/amilk/__init__.py index 9aa7047c..0cdd8727 100644 --- a/lnbits/extensions/amilk/__init__.py +++ b/lnbits/extensions/amilk/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_amilk") -amilk_ext: Blueprint = Blueprint("amilk", __name__, static_folder="static", template_folder="templates") +amilk_ext: Blueprint = Blueprint( + "amilk", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/amilk/crud.py b/lnbits/extensions/amilk/crud.py index 5170ca1f..773caa42 100644 --- a/lnbits/extensions/amilk/crud.py +++ b/lnbits/extensions/amilk/crud.py @@ -31,7 +31,9 @@ async def get_amilks(wallet_ids: Union[str, List[str]]) -> List[AMilk]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM amilks WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM amilks WHERE wallet IN ({q})", (*wallet_ids,) + ) return [AMilk(**row) for row in rows] diff --git a/lnbits/extensions/amilk/views_api.py b/lnbits/extensions/amilk/views_api.py index 8ffaa4db..1ebfe02c 100644 --- a/lnbits/extensions/amilk/views_api.py +++ b/lnbits/extensions/amilk/views_api.py @@ -21,7 +21,10 @@ async def api_amilks(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([amilk._asdict() for amilk in await get_amilks(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([amilk._asdict() for amilk in await get_amilks(wallet_ids)]), + HTTPStatus.OK, + ) @amilk_ext.route("/api/v1/amilk/milk/", methods=["GET"]) @@ -35,12 +38,18 @@ async def api_amilkit(amilk_id): abort(HTTPStatus.INTERNAL_SERVER_ERROR, "Could not process withdraw LNURL.") payment_hash, payment_request = await create_invoice( - wallet_id=milk.wallet, amount=withdraw_res.max_sats, memo=memo, extra={"tag": "amilk"} + wallet_id=milk.wallet, + amount=withdraw_res.max_sats, + memo=memo, + extra={"tag": "amilk"}, ) r = httpx.get( withdraw_res.callback.base, - params={**withdraw_res.callback.query_params, **{"k1": withdraw_res.k1, "pr": payment_request}}, + params={ + **withdraw_res.callback.query_params, + **{"k1": withdraw_res.k1, "pr": payment_request}, + }, ) if r.is_error: @@ -68,7 +77,10 @@ async def api_amilkit(amilk_id): ) async def api_amilk_create(): amilk = await create_amilk( - wallet_id=g.wallet.id, lnurl=g.data["lnurl"], atime=g.data["atime"], amount=g.data["amount"] + wallet_id=g.wallet.id, + lnurl=g.data["lnurl"], + atime=g.data["atime"], + amount=g.data["amount"], ) return jsonify(amilk._asdict()), HTTPStatus.CREATED diff --git a/lnbits/extensions/bleskomat/__init__.py b/lnbits/extensions/bleskomat/__init__.py index f7749275..42f9bb46 100644 --- a/lnbits/extensions/bleskomat/__init__.py +++ b/lnbits/extensions/bleskomat/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_bleskomat") -bleskomat_ext: Blueprint = Blueprint("bleskomat", __name__, static_folder="static", template_folder="templates") +bleskomat_ext: Blueprint = Blueprint( + "bleskomat", __name__, static_folder="static", template_folder="templates" +) from .lnurl_api import * # noqa from .views_api import * # noqa diff --git a/lnbits/extensions/bleskomat/crud.py b/lnbits/extensions/bleskomat/crud.py index 69079350..b85477b4 100644 --- a/lnbits/extensions/bleskomat/crud.py +++ b/lnbits/extensions/bleskomat/crud.py @@ -8,7 +8,12 @@ from .helpers import generate_bleskomat_lnurl_hash async def create_bleskomat( - *, wallet_id: str, name: str, fiat_currency: str, exchange_rate_provider: str, fee: str + *, + wallet_id: str, + name: str, + fiat_currency: str, + exchange_rate_provider: str, + fee: str, ) -> Bleskomat: bleskomat_id = uuid4().hex api_key_id = secrets.token_hex(8) @@ -42,7 +47,9 @@ async def get_bleskomat(bleskomat_id: str) -> Optional[Bleskomat]: async def get_bleskomat_by_api_key_id(api_key_id: str) -> Optional[Bleskomat]: - row = await db.fetchone("SELECT * FROM bleskomats WHERE api_key_id = ?", (api_key_id,)) + row = await db.fetchone( + "SELECT * FROM bleskomats WHERE api_key_id = ?", (api_key_id,) + ) return Bleskomat(**row) if row else None @@ -50,13 +57,17 @@ async def get_bleskomats(wallet_ids: Union[str, List[str]]) -> List[Bleskomat]: if isinstance(wallet_ids, str): wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM bleskomats WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM bleskomats WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Bleskomat(**row) for row in rows] async def update_bleskomat(bleskomat_id: str, **kwargs) -> Optional[Bleskomat]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute(f"UPDATE bleskomats SET {q} WHERE id = ?", (*kwargs.values(), bleskomat_id)) + await db.execute( + f"UPDATE bleskomats SET {q} WHERE id = ?", (*kwargs.values(), bleskomat_id) + ) row = await db.fetchone("SELECT * FROM bleskomats WHERE id = ?", (bleskomat_id,)) return Bleskomat(**row) if row else None diff --git a/lnbits/extensions/bleskomat/exchange_rates.py b/lnbits/extensions/bleskomat/exchange_rates.py index 6d9297c6..928a2823 100644 --- a/lnbits/extensions/bleskomat/exchange_rates.py +++ b/lnbits/extensions/bleskomat/exchange_rates.py @@ -3,7 +3,12 @@ import json import os fiat_currencies = json.load( - open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "fiat_currencies.json"), "r") + open( + os.path.join( + os.path.dirname(os.path.realpath(__file__)), "fiat_currencies.json" + ), + "r", + ) ) exchange_rate_providers = { @@ -35,7 +40,9 @@ exchange_rate_providers = { "name": "Kraken", "domain": "kraken.com", "api_url": "https://api.kraken.com/0/public/Ticker?pair=XBT{TO}", - "getter": lambda data, replacements: data["result"]["XXBTZ" + replacements["TO"]]["c"][0], + "getter": lambda data, replacements: data["result"][ + "XXBTZ" + replacements["TO"] + ]["c"][0], }, } @@ -50,7 +57,12 @@ for ref, exchange_rate_provider in exchange_rate_providers.items(): async def fetch_fiat_exchange_rate(currency: str, provider: str): - replacements = {"FROM": "BTC", "from": "btc", "TO": currency.upper(), "to": currency.lower()} + replacements = { + "FROM": "BTC", + "from": "btc", + "TO": currency.upper(), + "to": currency.lower(), + } url = exchange_rate_providers[provider]["api_url"] for key in replacements.keys(): diff --git a/lnbits/extensions/bleskomat/helpers.py b/lnbits/extensions/bleskomat/helpers.py index 9b745c79..a3857b77 100644 --- a/lnbits/extensions/bleskomat/helpers.py +++ b/lnbits/extensions/bleskomat/helpers.py @@ -14,7 +14,9 @@ def generate_bleskomat_lnurl_hash(secret: str): return m.hexdigest() -def generate_bleskomat_lnurl_signature(payload: str, api_key_secret: str, api_key_encoding: str = "hex"): +def generate_bleskomat_lnurl_signature( + payload: str, api_key_secret: str, api_key_encoding: str = "hex" +): if api_key_encoding == "hex": key = unhexlify(api_key_secret) elif api_key_encoding == "base64": @@ -41,7 +43,11 @@ def is_supported_lnurl_subprotocol(tag: str) -> bool: class LnurlHttpError(Exception): - def __init__(self, message: str = "", http_status: HTTPStatus = HTTPStatus.INTERNAL_SERVER_ERROR): + def __init__( + self, + message: str = "", + http_status: HTTPStatus = HTTPStatus.INTERNAL_SERVER_ERROR, + ): self.message = message self.http_status = http_status super().__init__(self.message) @@ -62,11 +68,15 @@ def prepare_lnurl_params(tag: str, query: Dict[str, str]): if not params["minWithdrawable"] > 0: raise LnurlValidationError('"minWithdrawable" must be greater than zero') if not params["maxWithdrawable"] >= params["minWithdrawable"]: - raise LnurlValidationError('"maxWithdrawable" must be greater than or equal to "minWithdrawable"') + raise LnurlValidationError( + '"maxWithdrawable" must be greater than or equal to "minWithdrawable"' + ) return params -encode_uri_component_safe_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()" +encode_uri_component_safe_chars = ( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()" +) def query_to_signing_payload(query: Dict[str, str]) -> str: @@ -76,19 +86,30 @@ def query_to_signing_payload(query: Dict[str, str]) -> str: for key in sorted_keys: if not key == "signature": encoded_key = urllib.parse.quote(key, safe=encode_uri_component_safe_chars) - encoded_value = urllib.parse.quote(query[key], safe=encode_uri_component_safe_chars) + encoded_value = urllib.parse.quote( + query[key], safe=encode_uri_component_safe_chars + ) payload.append(f"{encoded_key}={encoded_value}") return "&".join(payload) unshorten_rules = { "query": {"n": "nonce", "s": "signature", "t": "tag"}, - "tags": {"c": "channelRequest", "l": "login", "p": "payRequest", "w": "withdrawRequest"}, + "tags": { + "c": "channelRequest", + "l": "login", + "p": "payRequest", + "w": "withdrawRequest", + }, "params": { "channelRequest": {"pl": "localAmt", "pp": "pushAmt"}, "login": {}, "payRequest": {"pn": "minSendable", "px": "maxSendable", "pm": "metadata"}, - "withdrawRequest": {"pn": "minWithdrawable", "px": "maxWithdrawable", "pd": "defaultDescription"}, + "withdrawRequest": { + "pn": "minWithdrawable", + "px": "maxWithdrawable", + "pd": "defaultDescription", + }, }, } diff --git a/lnbits/extensions/bleskomat/lnurl_api.py b/lnbits/extensions/bleskomat/lnurl_api.py index c7df81d1..e2743292 100644 --- a/lnbits/extensions/bleskomat/lnurl_api.py +++ b/lnbits/extensions/bleskomat/lnurl_api.py @@ -47,7 +47,10 @@ async def api_bleskomat_lnurl(): # The API key ID, nonce, and tag should be present in the query string. for field in ["id", "nonce", "tag"]: if not field in query: - raise LnurlHttpError(f'Failed API key signature check: Missing "{field}"', HTTPStatus.BAD_REQUEST) + raise LnurlHttpError( + f'Failed API key signature check: Missing "{field}"', + HTTPStatus.BAD_REQUEST, + ) # URL signing scheme is described here: # https://github.com/chill117/lnurl-node#how-to-implement-url-signing-scheme @@ -58,7 +61,9 @@ async def api_bleskomat_lnurl(): raise LnurlHttpError("Unknown API key", HTTPStatus.BAD_REQUEST) api_key_secret = bleskomat.api_key_secret api_key_encoding = bleskomat.api_key_encoding - expected_signature = generate_bleskomat_lnurl_signature(payload, api_key_secret, api_key_encoding) + expected_signature = generate_bleskomat_lnurl_signature( + payload, api_key_secret, api_key_encoding + ) if signature != expected_signature: raise LnurlHttpError("Invalid API key signature", HTTPStatus.FORBIDDEN) @@ -72,13 +77,16 @@ async def api_bleskomat_lnurl(): params = prepare_lnurl_params(tag, query) if "f" in query: rate = await fetch_fiat_exchange_rate( - currency=query["f"], provider=bleskomat.exchange_rate_provider + currency=query["f"], + provider=bleskomat.exchange_rate_provider, ) # Convert fee (%) to decimal: fee = float(bleskomat.fee) / 100 if tag == "withdrawRequest": for key in ["minWithdrawable", "maxWithdrawable"]: - amount_sats = int(math.floor((params[key] / rate) * 1e8)) + amount_sats = int( + math.floor((params[key] / rate) * 1e8) + ) fee_sats = int(math.floor(amount_sats * fee)) amount_sats_less_fee = amount_sats - fee_sats # Convert to msats: @@ -87,7 +95,9 @@ async def api_bleskomat_lnurl(): raise LnurlHttpError(e.message, HTTPStatus.BAD_REQUEST) # Create a new LNURL using the query parameters provided in the signed URL. params = json.JSONEncoder().encode(params) - lnurl = await create_bleskomat_lnurl(bleskomat=bleskomat, secret=secret, tag=tag, params=params, uses=1) + lnurl = await create_bleskomat_lnurl( + bleskomat=bleskomat, secret=secret, tag=tag, params=params, uses=1 + ) # Reply with LNURL response object. return jsonify(lnurl.get_info_response_object(secret)), HTTPStatus.OK @@ -104,7 +114,9 @@ async def api_bleskomat_lnurl(): raise LnurlHttpError("Invalid secret", HTTPStatus.BAD_REQUEST) if not lnurl.has_uses_remaining(): - raise LnurlHttpError("Maximum number of uses already reached", HTTPStatus.BAD_REQUEST) + raise LnurlHttpError( + "Maximum number of uses already reached", HTTPStatus.BAD_REQUEST + ) try: await lnurl.execute_action(query) @@ -115,6 +127,9 @@ async def api_bleskomat_lnurl(): return jsonify({"status": "ERROR", "reason": str(e)}), e.http_status except Exception as e: traceback.print_exc() - return jsonify({"status": "ERROR", "reason": "Unexpected error"}), HTTPStatus.INTERNAL_SERVER_ERROR + return ( + jsonify({"status": "ERROR", "reason": "Unexpected error"}), + HTTPStatus.INTERNAL_SERVER_ERROR, + ) return jsonify({"status": "OK"}), HTTPStatus.OK diff --git a/lnbits/extensions/bleskomat/models.py b/lnbits/extensions/bleskomat/models.py index 8ea97338..0ec2673b 100644 --- a/lnbits/extensions/bleskomat/models.py +++ b/lnbits/extensions/bleskomat/models.py @@ -62,11 +62,17 @@ class BleskomatLnurl(NamedTuple): try: invoice = bolt11.decode(pr) except ValueError as e: - raise LnurlValidationError('Invalid parameter ("pr"): Lightning payment request expected') + raise LnurlValidationError( + 'Invalid parameter ("pr"): Lightning payment request expected' + ) if invoice.amount_msat < params["minWithdrawable"]: - raise LnurlValidationError('Amount in invoice must be greater than or equal to "minWithdrawable"') + raise LnurlValidationError( + 'Amount in invoice must be greater than or equal to "minWithdrawable"' + ) if invoice.amount_msat > params["maxWithdrawable"]: - raise LnurlValidationError('Amount in invoice must be less than or equal to "maxWithdrawable"') + raise LnurlValidationError( + 'Amount in invoice must be less than or equal to "maxWithdrawable"' + ) else: raise LnurlValidationError(f'Unknown subprotocol: "{tag}"') diff --git a/lnbits/extensions/bleskomat/views.py b/lnbits/extensions/bleskomat/views.py index 52f63499..3a7f7263 100644 --- a/lnbits/extensions/bleskomat/views.py +++ b/lnbits/extensions/bleskomat/views.py @@ -17,4 +17,6 @@ async def index(): "exchange_rate_providers": exchange_rate_providers_serializable, "fiat_currencies": fiat_currencies, } - return await render_template("bleskomat/index.html", user=g.user, bleskomat_vars=bleskomat_vars) + return await render_template( + "bleskomat/index.html", user=g.user, bleskomat_vars=bleskomat_vars + ) diff --git a/lnbits/extensions/bleskomat/views_api.py b/lnbits/extensions/bleskomat/views_api.py index 8256ece8..7e9a1f1a 100644 --- a/lnbits/extensions/bleskomat/views_api.py +++ b/lnbits/extensions/bleskomat/views_api.py @@ -28,7 +28,12 @@ async def api_bleskomats(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([bleskomat._asdict() for bleskomat in await get_bleskomats(wallet_ids)]), HTTPStatus.OK + return ( + jsonify( + [bleskomat._asdict() for bleskomat in await get_bleskomats(wallet_ids)] + ), + HTTPStatus.OK, + ) @bleskomat_ext.route("/api/v1/bleskomat/", methods=["GET"]) @@ -37,7 +42,10 @@ async def api_bleskomat_retrieve(bleskomat_id): bleskomat = await get_bleskomat(bleskomat_id) if not bleskomat or bleskomat.wallet != g.wallet.id: - return jsonify({"message": "Bleskomat configuration not found."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Bleskomat configuration not found."}), + HTTPStatus.NOT_FOUND, + ) return jsonify(bleskomat._asdict()), HTTPStatus.OK @@ -48,8 +56,16 @@ async def api_bleskomat_retrieve(bleskomat_id): @api_validate_post_request( schema={ "name": {"type": "string", "empty": False, "required": True}, - "fiat_currency": {"type": "string", "allowed": fiat_currencies.keys(), "required": True}, - "exchange_rate_provider": {"type": "string", "allowed": exchange_rate_providers.keys(), "required": True}, + "fiat_currency": { + "type": "string", + "allowed": fiat_currencies.keys(), + "required": True, + }, + "exchange_rate_provider": { + "type": "string", + "allowed": exchange_rate_providers.keys(), + "required": True, + }, "fee": {"type": ["string", "float", "number", "integer"], "required": True}, } ) @@ -58,23 +74,35 @@ async def api_bleskomat_create_or_update(bleskomat_id=None): try: fiat_currency = g.data["fiat_currency"] exchange_rate_provider = g.data["exchange_rate_provider"] - rate = await fetch_fiat_exchange_rate(currency=fiat_currency, provider=exchange_rate_provider) + rate = await fetch_fiat_exchange_rate( + currency=fiat_currency, provider=exchange_rate_provider + ) except Exception as e: print(e) return ( - jsonify({"message": f'Failed to fetch BTC/{fiat_currency} currency pair from "{exchange_rate_provider}"'}), + jsonify( + { + "message": f'Failed to fetch BTC/{fiat_currency} currency pair from "{exchange_rate_provider}"' + } + ), HTTPStatus.INTERNAL_SERVER_ERROR, ) if bleskomat_id: bleskomat = await get_bleskomat(bleskomat_id) if not bleskomat or bleskomat.wallet != g.wallet.id: - return jsonify({"message": "Bleskomat configuration not found."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Bleskomat configuration not found."}), + HTTPStatus.NOT_FOUND, + ) bleskomat = await update_bleskomat(bleskomat_id, **g.data) else: bleskomat = await create_bleskomat(wallet_id=g.wallet.id, **g.data) - return jsonify(bleskomat._asdict()), HTTPStatus.OK if bleskomat_id else HTTPStatus.CREATED + return ( + jsonify(bleskomat._asdict()), + HTTPStatus.OK if bleskomat_id else HTTPStatus.CREATED, + ) @bleskomat_ext.route("/api/v1/bleskomat/", methods=["DELETE"]) @@ -83,7 +111,10 @@ async def api_bleskomat_delete(bleskomat_id): bleskomat = await get_bleskomat(bleskomat_id) if not bleskomat or bleskomat.wallet != g.wallet.id: - return jsonify({"message": "Bleskomat configuration not found."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Bleskomat configuration not found."}), + HTTPStatus.NOT_FOUND, + ) await delete_bleskomat(bleskomat_id) diff --git a/lnbits/extensions/captcha/__init__.py b/lnbits/extensions/captcha/__init__.py index 66eed22b..f25dccce 100644 --- a/lnbits/extensions/captcha/__init__.py +++ b/lnbits/extensions/captcha/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_captcha") -captcha_ext: Blueprint = Blueprint("captcha", __name__, static_folder="static", template_folder="templates") +captcha_ext: Blueprint = Blueprint( + "captcha", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/captcha/crud.py b/lnbits/extensions/captcha/crud.py index 735d05a7..7526306b 100644 --- a/lnbits/extensions/captcha/crud.py +++ b/lnbits/extensions/captcha/crud.py @@ -7,7 +7,13 @@ from .models import Captcha async def create_captcha( - *, wallet_id: str, url: str, memo: str, description: Optional[str] = None, amount: int = 0, remembers: bool = True + *, + wallet_id: str, + url: str, + memo: str, + description: Optional[str] = None, + amount: int = 0, + remembers: bool = True, ) -> Captcha: captcha_id = urlsafe_short_hash() await db.execute( @@ -34,7 +40,9 @@ async def get_captchas(wallet_ids: Union[str, List[str]]) -> List[Captcha]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM captchas WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM captchas WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Captcha.from_row(row) for row in rows] diff --git a/lnbits/extensions/captcha/migrations.py b/lnbits/extensions/captcha/migrations.py index 455cf0ff..9fe2e604 100644 --- a/lnbits/extensions/captcha/migrations.py +++ b/lnbits/extensions/captcha/migrations.py @@ -46,7 +46,9 @@ async def m002_redux(db): ) await db.execute("CREATE INDEX IF NOT EXISTS wallet_idx ON captchas (wallet)") - for row in [list(row) for row in await db.fetchall("SELECT * FROM captchas_old")]: + for row in [ + list(row) for row in await db.fetchall("SELECT * FROM captchas_old") + ]: await db.execute( """ INSERT INTO captchas ( diff --git a/lnbits/extensions/captcha/views.py b/lnbits/extensions/captcha/views.py index 9e4cbe9e..2b3643fa 100644 --- a/lnbits/extensions/captcha/views.py +++ b/lnbits/extensions/captcha/views.py @@ -16,5 +16,7 @@ async def index(): @captcha_ext.route("/") async def display(captcha_id): - captcha = await get_captcha(captcha_id) or abort(HTTPStatus.NOT_FOUND, "captcha does not exist.") + captcha = await get_captcha(captcha_id) or abort( + HTTPStatus.NOT_FOUND, "captcha does not exist." + ) return await render_template("captcha/display.html", captcha=captcha) diff --git a/lnbits/extensions/captcha/views_api.py b/lnbits/extensions/captcha/views_api.py index 2062e541..c1b5ade8 100644 --- a/lnbits/extensions/captcha/views_api.py +++ b/lnbits/extensions/captcha/views_api.py @@ -17,7 +17,10 @@ async def api_captchas(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([captcha._asdict() for captcha in await get_captchas(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([captcha._asdict() for captcha in await get_captchas(wallet_ids)]), + HTTPStatus.OK, + ) @captcha_ext.route("/api/v1/captchas", methods=["POST"]) @@ -26,7 +29,12 @@ async def api_captchas(): schema={ "url": {"type": "string", "empty": False, "required": True}, "memo": {"type": "string", "empty": False, "required": True}, - "description": {"type": "string", "empty": True, "nullable": True, "required": False}, + "description": { + "type": "string", + "empty": True, + "nullable": True, + "required": False, + }, "amount": {"type": "integer", "min": 0, "required": True}, "remembers": {"type": "boolean", "required": True}, } @@ -53,26 +61,41 @@ async def api_captcha_delete(captcha_id): @captcha_ext.route("/api/v1/captchas//invoice", methods=["POST"]) -@api_validate_post_request(schema={"amount": {"type": "integer", "min": 1, "required": True}}) +@api_validate_post_request( + schema={"amount": {"type": "integer", "min": 1, "required": True}} +) async def api_captcha_create_invoice(captcha_id): captcha = await get_captcha(captcha_id) if g.data["amount"] < captcha.amount: - return jsonify({"message": f"Minimum amount is {captcha.amount} sat."}), HTTPStatus.BAD_REQUEST + return ( + jsonify({"message": f"Minimum amount is {captcha.amount} sat."}), + HTTPStatus.BAD_REQUEST, + ) try: - amount = g.data["amount"] if g.data["amount"] > captcha.amount else captcha.amount + amount = ( + g.data["amount"] if g.data["amount"] > captcha.amount else captcha.amount + ) payment_hash, payment_request = await create_invoice( - wallet_id=captcha.wallet, amount=amount, memo=f"{captcha.memo}", extra={"tag": "captcha"} + wallet_id=captcha.wallet, + amount=amount, + memo=f"{captcha.memo}", + extra={"tag": "captcha"}, ) except Exception as e: return jsonify({"message": str(e)}), HTTPStatus.INTERNAL_SERVER_ERROR - return jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), HTTPStatus.CREATED + return ( + jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), + HTTPStatus.CREATED, + ) @captcha_ext.route("/api/v1/captchas//check_invoice", methods=["POST"]) -@api_validate_post_request(schema={"payment_hash": {"type": "string", "empty": False, "required": True}}) +@api_validate_post_request( + schema={"payment_hash": {"type": "string", "empty": False, "required": True}} +) async def api_paywal_check_invoice(captcha_id): captcha = await get_captcha(captcha_id) @@ -90,6 +113,9 @@ async def api_paywal_check_invoice(captcha_id): payment = await wallet.get_payment(g.data["payment_hash"]) await payment.set_pending(False) - return jsonify({"paid": True, "url": captcha.url, "remembers": captcha.remembers}), HTTPStatus.OK + return ( + jsonify({"paid": True, "url": captcha.url, "remembers": captcha.remembers}), + HTTPStatus.OK, + ) return jsonify({"paid": False}), HTTPStatus.OK diff --git a/lnbits/extensions/diagonalley/__init__.py b/lnbits/extensions/diagonalley/__init__.py index 41afebb6..ac907f5c 100644 --- a/lnbits/extensions/diagonalley/__init__.py +++ b/lnbits/extensions/diagonalley/__init__.py @@ -1,7 +1,9 @@ from quart import Blueprint -diagonalley_ext: Blueprint = Blueprint("diagonalley", __name__, static_folder="static", template_folder="templates") +diagonalley_ext: Blueprint = Blueprint( + "diagonalley", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/diagonalley/crud.py b/lnbits/extensions/diagonalley/crud.py index a7ef5822..a6543d1d 100644 --- a/lnbits/extensions/diagonalley/crud.py +++ b/lnbits/extensions/diagonalley/crud.py @@ -21,7 +21,14 @@ regex = re.compile( def create_diagonalleys_product( - *, wallet_id: str, product: str, categories: str, description: str, image: str, price: int, quantity: int + *, + wallet_id: str, + product: str, + categories: str, + description: str, + image: str, + price: int, + quantity: int, ) -> Products: with open_ext_db("diagonalley") as db: product_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8") @@ -30,7 +37,16 @@ def create_diagonalleys_product( INSERT INTO products (id, wallet, product, categories, description, image, price, quantity) VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, - (product_id, wallet_id, product, categories, description, image, price, quantity), + ( + product_id, + wallet_id, + product, + categories, + description, + image, + price, + quantity, + ), ) return get_diagonalleys_product(product_id) @@ -40,7 +56,9 @@ def update_diagonalleys_product(product_id: str, **kwargs) -> Optional[Indexers] q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) with open_ext_db("diagonalley") as db: - db.execute(f"UPDATE products SET {q} WHERE id = ?", (*kwargs.values(), product_id)) + db.execute( + f"UPDATE products SET {q} WHERE id = ?", (*kwargs.values(), product_id) + ) row = db.fetchone("SELECT * FROM products WHERE id = ?", (product_id,)) return get_diagonalleys_indexer(product_id) @@ -59,7 +77,9 @@ def get_diagonalleys_products(wallet_ids: Union[str, List[str]]) -> List[Product with open_ext_db("diagonalley") as db: q = ",".join(["?"] * len(wallet_ids)) - rows = db.fetchall(f"SELECT * FROM products WHERE wallet IN ({q})", (*wallet_ids,)) + rows = db.fetchall( + f"SELECT * FROM products WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Products(**row) for row in rows] @@ -110,7 +130,9 @@ def update_diagonalleys_indexer(indexer_id: str, **kwargs) -> Optional[Indexers] q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) with open_ext_db("diagonalley") as db: - db.execute(f"UPDATE indexers SET {q} WHERE id = ?", (*kwargs.values(), indexer_id)) + db.execute( + f"UPDATE indexers SET {q} WHERE id = ?", (*kwargs.values(), indexer_id) + ) row = db.fetchone("SELECT * FROM indexers WHERE id = ?", (indexer_id,)) return get_diagonalleys_indexer(indexer_id) @@ -154,7 +176,9 @@ def get_diagonalleys_indexers(wallet_ids: Union[str, List[str]]) -> List[Indexer with open_ext_db("diagonalley") as db: q = ",".join(["?"] * len(wallet_ids)) - rows = db.fetchall(f"SELECT * FROM indexers WHERE wallet IN ({q})", (*wallet_ids,)) + rows = db.fetchall( + f"SELECT * FROM indexers WHERE wallet IN ({q})", (*wallet_ids,) + ) for r in rows: try: @@ -181,7 +205,9 @@ def get_diagonalleys_indexers(wallet_ids: Union[str, List[str]]) -> List[Indexer print("An exception occurred") with open_ext_db("diagonalley") as db: q = ",".join(["?"] * len(wallet_ids)) - rows = db.fetchall(f"SELECT * FROM indexers WHERE wallet IN ({q})", (*wallet_ids,)) + rows = db.fetchall( + f"SELECT * FROM indexers WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Indexers(**row) for row in rows] @@ -213,7 +239,19 @@ def create_diagonalleys_order( INSERT INTO orders (id, productid, wallet, product, quantity, shippingzone, address, email, invoiceid, paid, shipped) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, - (order_id, productid, wallet, product, quantity, shippingzone, address, email, invoiceid, False, False), + ( + order_id, + productid, + wallet, + product, + quantity, + shippingzone, + address, + email, + invoiceid, + False, + False, + ), ) return get_diagonalleys_order(order_id) @@ -232,7 +270,9 @@ def get_diagonalleys_orders(wallet_ids: Union[str, List[str]]) -> List[Orders]: with open_ext_db("diagonalley") as db: q = ",".join(["?"] * len(wallet_ids)) - rows = db.fetchall(f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,)) + rows = db.fetchall( + f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,) + ) for r in rows: PAID = WALLET.get_invoice_status(r["invoiceid"]).paid if PAID: @@ -244,7 +284,9 @@ def get_diagonalleys_orders(wallet_ids: Union[str, List[str]]) -> List[Orders]: r["id"], ), ) - rows = db.fetchall(f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,)) + rows = db.fetchall( + f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Orders(**row) for row in rows] diff --git a/lnbits/extensions/diagonalley/views_api.py b/lnbits/extensions/diagonalley/views_api.py index 9ded7c2c..cfb83566 100644 --- a/lnbits/extensions/diagonalley/views_api.py +++ b/lnbits/extensions/diagonalley/views_api.py @@ -36,7 +36,12 @@ async def api_diagonalley_products(): if "all_wallets" in request.args: wallet_ids = get_user(g.wallet.user).wallet_ids - return jsonify([product._asdict() for product in get_diagonalleys_products(wallet_ids)]), HTTPStatus.OK + return ( + jsonify( + [product._asdict() for product in get_diagonalleys_products(wallet_ids)] + ), + HTTPStatus.OK, + ) @diagonalley_ext.route("/api/v1/diagonalley/products", methods=["POST"]) @@ -58,16 +63,25 @@ async def api_diagonalley_product_create(product_id=None): product = get_diagonalleys_indexer(product_id) if not product: - return jsonify({"message": "Withdraw product does not exist."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Withdraw product does not exist."}), + HTTPStatus.NOT_FOUND, + ) if product.wallet != g.wallet.id: - return jsonify({"message": "Not your withdraw product."}), HTTPStatus.FORBIDDEN + return ( + jsonify({"message": "Not your withdraw product."}), + HTTPStatus.FORBIDDEN, + ) product = update_diagonalleys_product(product_id, **g.data) else: product = create_diagonalleys_product(wallet_id=g.wallet.id, **g.data) - return jsonify(product._asdict()), HTTPStatus.OK if product_id else HTTPStatus.CREATED + return ( + jsonify(product._asdict()), + HTTPStatus.OK if product_id else HTTPStatus.CREATED, + ) @diagonalley_ext.route("/api/v1/diagonalley/products/", methods=["DELETE"]) @@ -97,7 +111,12 @@ async def api_diagonalley_indexers(): if "all_wallets" in request.args: wallet_ids = get_user(g.wallet.user).wallet_ids - return jsonify([indexer._asdict() for indexer in get_diagonalleys_indexers(wallet_ids)]), HTTPStatus.OK + return ( + jsonify( + [indexer._asdict() for indexer in get_diagonalleys_indexers(wallet_ids)] + ), + HTTPStatus.OK, + ) @diagonalley_ext.route("/api/v1/diagonalley/indexers", methods=["POST"]) @@ -120,16 +139,25 @@ async def api_diagonalley_indexer_create(indexer_id=None): indexer = get_diagonalleys_indexer(indexer_id) if not indexer: - return jsonify({"message": "Withdraw indexer does not exist."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Withdraw indexer does not exist."}), + HTTPStatus.NOT_FOUND, + ) if indexer.wallet != g.wallet.id: - return jsonify({"message": "Not your withdraw indexer."}), HTTPStatus.FORBIDDEN + return ( + jsonify({"message": "Not your withdraw indexer."}), + HTTPStatus.FORBIDDEN, + ) indexer = update_diagonalleys_indexer(indexer_id, **g.data) else: indexer = create_diagonalleys_indexer(wallet_id=g.wallet.id, **g.data) - return jsonify(indexer._asdict()), HTTPStatus.OK if indexer_id else HTTPStatus.CREATED + return ( + jsonify(indexer._asdict()), + HTTPStatus.OK if indexer_id else HTTPStatus.CREATED, + ) @diagonalley_ext.route("/api/v1/diagonalley/indexers/", methods=["DELETE"]) @@ -159,7 +187,10 @@ async def api_diagonalley_orders(): if "all_wallets" in request.args: wallet_ids = get_user(g.wallet.user).wallet_ids - return jsonify([order._asdict() for order in get_diagonalleys_orders(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([order._asdict() for order in get_diagonalleys_orders(wallet_ids)]), + HTTPStatus.OK, + ) @diagonalley_ext.route("/api/v1/diagonalley/orders", methods=["POST"]) @@ -221,13 +252,20 @@ async def api_diagonalleys_order_shipped(order_id): ) order = db.fetchone("SELECT * FROM orders WHERE id = ?", (order_id,)) - return jsonify([order._asdict() for order in get_diagonalleys_orders(order["wallet"])]), HTTPStatus.OK + return ( + jsonify( + [order._asdict() for order in get_diagonalleys_orders(order["wallet"])] + ), + HTTPStatus.OK, + ) ###List products based on indexer id -@diagonalley_ext.route("/api/v1/diagonalley/stall/products/", methods=["GET"]) +@diagonalley_ext.route( + "/api/v1/diagonalley/stall/products/", methods=["GET"] +) async def api_diagonalleys_stall_products(indexer_id): with open_ext_db("diagonalley") as db: rows = db.fetchone("SELECT * FROM indexers WHERE id = ?", (indexer_id,)) @@ -239,13 +277,20 @@ async def api_diagonalleys_stall_products(indexer_id): if not products: return jsonify({"message": "No products"}), HTTPStatus.NOT_FOUND - return jsonify([products._asdict() for products in get_diagonalleys_products(rows[1])]), HTTPStatus.OK + return ( + jsonify( + [products._asdict() for products in get_diagonalleys_products(rows[1])] + ), + HTTPStatus.OK, + ) ###Check a product has been shipped -@diagonalley_ext.route("/api/v1/diagonalley/stall/checkshipped/", methods=["GET"]) +@diagonalley_ext.route( + "/api/v1/diagonalley/stall/checkshipped/", methods=["GET"] +) async def api_diagonalleys_stall_checkshipped(checking_id): with open_ext_db("diagonalley") as db: rows = db.fetchone("SELECT * FROM orders WHERE invoiceid = ?", (checking_id,)) @@ -276,7 +321,9 @@ async def api_diagonalley_stall_order(indexer_id): shippingcost = shipping.zone2cost checking_id, payment_request = create_invoice( - wallet_id=product.wallet, amount=shippingcost + (g.data["quantity"] * product.price), memo=g.data["id"] + wallet_id=product.wallet, + amount=shippingcost + (g.data["quantity"] * product.price), + memo=g.data["id"], ) selling_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8") with open_ext_db("diagonalley") as db: @@ -299,4 +346,7 @@ async def api_diagonalley_stall_order(indexer_id): False, ), ) - return jsonify({"checking_id": checking_id, "payment_request": payment_request}), HTTPStatus.OK + return ( + jsonify({"checking_id": checking_id, "payment_request": payment_request}), + HTTPStatus.OK, + ) diff --git a/lnbits/extensions/events/__init__.py b/lnbits/extensions/events/__init__.py index 4496b2c1..b8f4deb5 100644 --- a/lnbits/extensions/events/__init__.py +++ b/lnbits/extensions/events/__init__.py @@ -4,7 +4,9 @@ from lnbits.db import Database db = Database("ext_events") -events_ext: Blueprint = Blueprint("events", __name__, static_folder="static", template_folder="templates") +events_ext: Blueprint = Blueprint( + "events", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/events/crud.py b/lnbits/extensions/events/crud.py index efc40731..20faa09a 100644 --- a/lnbits/extensions/events/crud.py +++ b/lnbits/extensions/events/crud.py @@ -9,7 +9,9 @@ from .models import Tickets, Events # TICKETS -async def create_ticket(payment_hash: str, wallet: str, event: str, name: str, email: str) -> Tickets: +async def create_ticket( + payment_hash: str, wallet: str, event: str, name: str, email: str +) -> Tickets: await db.execute( """ INSERT INTO ticket (id, wallet, event, name, email, registered, paid) @@ -64,7 +66,9 @@ async def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM ticket WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM ticket WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Tickets(**row) for row in rows] @@ -113,7 +117,9 @@ async def create_event( async def update_event(event_id: str, **kwargs) -> Events: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute(f"UPDATE events SET {q} WHERE id = ?", (*kwargs.values(), event_id)) + await db.execute( + f"UPDATE events SET {q} WHERE id = ?", (*kwargs.values(), event_id) + ) event = await get_event(event_id) assert event, "Newly updated event couldn't be retrieved" return event @@ -129,7 +135,9 @@ async def get_events(wallet_ids: Union[str, List[str]]) -> List[Events]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM events WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM events WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Events(**row) for row in rows] @@ -142,7 +150,9 @@ async def delete_event(event_id: str) -> None: async def get_event_tickets(event_id: str, wallet_id: str) -> List[Tickets]: - rows = await db.fetchall("SELECT * FROM ticket WHERE wallet = ? AND event = ?", (wallet_id, event_id)) + rows = await db.fetchall( + "SELECT * FROM ticket WHERE wallet = ? AND event = ?", (wallet_id, event_id) + ) return [Tickets(**row) for row in rows] diff --git a/lnbits/extensions/events/views.py b/lnbits/extensions/events/views.py index 86426acb..e1551320 100644 --- a/lnbits/extensions/events/views.py +++ b/lnbits/extensions/events/views.py @@ -23,12 +23,16 @@ async def display(event_id): if event.amount_tickets < 1: return await render_template( - "events/error.html", event_name=event.name, event_error="Sorry, tickets are sold out :(" + "events/error.html", + event_name=event.name, + event_error="Sorry, tickets are sold out :(", ) datetime_object = datetime.strptime(event.closing_date, "%Y-%m-%d").date() if date.today() > datetime_object: return await render_template( - "events/error.html", event_name=event.name, event_error="Sorry, ticket closing date has passed :(" + "events/error.html", + event_name=event.name, + event_error="Sorry, ticket closing date has passed :(", ) return await render_template( @@ -51,7 +55,10 @@ async def ticket(ticket_id): abort(HTTPStatus.NOT_FOUND, "Event does not exist.") return await render_template( - "events/ticket.html", ticket_id=ticket_id, ticket_name=event.name, ticket_info=event.info + "events/ticket.html", + ticket_id=ticket_id, + ticket_name=event.name, + ticket_info=event.info, ) @@ -62,5 +69,8 @@ async def register(event_id): abort(HTTPStatus.NOT_FOUND, "Event does not exist.") return await render_template( - "events/register.html", event_id=event_id, event_name=event.name, wallet_id=event.wallet + "events/register.html", + event_id=event_id, + event_name=event.name, + wallet_id=event.wallet, ) diff --git a/lnbits/extensions/events/views_api.py b/lnbits/extensions/events/views_api.py index 3467cc2d..3ea61843 100644 --- a/lnbits/extensions/events/views_api.py +++ b/lnbits/extensions/events/views_api.py @@ -33,7 +33,10 @@ async def api_events(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([event._asdict() for event in await get_events(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([event._asdict() for event in await get_events(wallet_ids)]), + HTTPStatus.OK, + ) @events_ext.route("/api/v1/events", methods=["POST"]) @@ -92,7 +95,10 @@ async def api_tickets(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([ticket._asdict() for ticket in await get_tickets(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([ticket._asdict() for ticket in await get_tickets(wallet_ids)]), + HTTPStatus.OK, + ) @events_ext.route("/api/v1/tickets//", methods=["POST"]) @@ -108,17 +114,25 @@ async def api_ticket_make_ticket(event_id, sats): return jsonify({"message": "Event does not exist."}), HTTPStatus.NOT_FOUND try: payment_hash, payment_request = await create_invoice( - wallet_id=event.wallet, amount=int(sats), memo=f"{event_id}", extra={"tag": "events"} + wallet_id=event.wallet, + amount=int(sats), + memo=f"{event_id}", + extra={"tag": "events"}, ) except Exception as e: return jsonify({"message": str(e)}), HTTPStatus.INTERNAL_SERVER_ERROR - ticket = await create_ticket(payment_hash=payment_hash, wallet=event.wallet, event=event_id, **g.data) + ticket = await create_ticket( + payment_hash=payment_hash, wallet=event.wallet, event=event_id, **g.data + ) if not ticket: return jsonify({"message": "Event could not be fetched."}), HTTPStatus.NOT_FOUND - return jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), HTTPStatus.OK + return ( + jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), + HTTPStatus.OK, + ) @events_ext.route("/api/v1/tickets/", methods=["GET"]) @@ -163,7 +177,14 @@ async def api_ticket_delete(ticket_id): @events_ext.route("/api/v1/eventtickets//", methods=["GET"]) async def api_event_tickets(wallet_id, event_id): return ( - jsonify([ticket._asdict() for ticket in await get_event_tickets(wallet_id=wallet_id, event_id=event_id)]), + jsonify( + [ + ticket._asdict() + for ticket in await get_event_tickets( + wallet_id=wallet_id, event_id=event_id + ) + ] + ), HTTPStatus.OK, ) @@ -177,4 +198,7 @@ async def api_event_register_ticket(ticket_id): if ticket.registered == True: return jsonify({"message": "Ticket already registered"}), HTTPStatus.FORBIDDEN - return jsonify([ticket._asdict() for ticket in await reg_ticket(ticket_id)]), HTTPStatus.OK + return ( + jsonify([ticket._asdict() for ticket in await reg_ticket(ticket_id)]), + HTTPStatus.OK, + ) diff --git a/lnbits/extensions/example/__init__.py b/lnbits/extensions/example/__init__.py index 43a8223c..e16e0372 100644 --- a/lnbits/extensions/example/__init__.py +++ b/lnbits/extensions/example/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_example") -example_ext: Blueprint = Blueprint("example", __name__, static_folder="static", template_folder="templates") +example_ext: Blueprint = Blueprint( + "example", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/lndhub/__init__.py b/lnbits/extensions/lndhub/__init__.py index ed368c04..7610b0a3 100644 --- a/lnbits/extensions/lndhub/__init__.py +++ b/lnbits/extensions/lndhub/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_lndhub") -lndhub_ext: Blueprint = Blueprint("lndhub", __name__, static_folder="static", template_folder="templates") +lndhub_ext: Blueprint = Blueprint( + "lndhub", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/lndhub/decorators.py b/lnbits/extensions/lndhub/decorators.py index 07a109bc..c9c3bb71 100644 --- a/lnbits/extensions/lndhub/decorators.py +++ b/lnbits/extensions/lndhub/decorators.py @@ -13,11 +13,15 @@ def check_wallet(requires_admin=False): key_type, key = b64decode(token).decode("utf-8").split(":") if requires_admin and key_type != "admin": - return jsonify({"error": True, "code": 2, "message": "insufficient permissions"}) + return jsonify( + {"error": True, "code": 2, "message": "insufficient permissions"} + ) g.wallet = await get_wallet_for_key(key, key_type) if not g.wallet: - return jsonify({"error": True, "code": 2, "message": "insufficient permissions"}) + return jsonify( + {"error": True, "code": 2, "message": "insufficient permissions"} + ) return await view(**kwargs) return wrapped_view diff --git a/lnbits/extensions/lndhub/views_api.py b/lnbits/extensions/lndhub/views_api.py index d7fb409c..09caf54c 100644 --- a/lnbits/extensions/lndhub/views_api.py +++ b/lnbits/extensions/lndhub/views_api.py @@ -23,14 +23,20 @@ async def lndhub_getinfo(): schema={ "login": {"type": "string", "required": True, "excludes": "refresh_token"}, "password": {"type": "string", "required": True, "excludes": "refresh_token"}, - "refresh_token": {"type": "string", "required": True, "excludes": ["login", "password"]}, + "refresh_token": { + "type": "string", + "required": True, + "excludes": ["login", "password"], + }, } ) async def lndhub_auth(): token = ( g.data["refresh_token"] if "refresh_token" in g.data and g.data["refresh_token"] - else urlsafe_b64encode((g.data["login"] + ":" + g.data["password"]).encode("utf-8")).decode("ascii") + else urlsafe_b64encode( + (g.data["login"] + ":" + g.data["password"]).encode("utf-8") + ).decode("ascii") ) return jsonify({"refresh_token": token, "access_token": token}) @@ -120,9 +126,15 @@ async def lndhub_balance(): @check_wallet() async def lndhub_gettxs(): for payment in await g.wallet.get_payments( - complete=False, pending=True, outgoing=True, incoming=False, exclude_uncheckable=True + complete=False, + pending=True, + outgoing=True, + incoming=False, + exclude_uncheckable=True, ): - await payment.set_pending(WALLET.get_payment_status(payment.checking_id).pending) + await payment.set_pending( + WALLET.get_payment_status(payment.checking_id).pending + ) limit = int(request.args.get("limit", 200)) return jsonify( @@ -135,10 +147,16 @@ async def lndhub_gettxs(): "fee": payment.fee, "value": int(payment.amount / 1000), "timestamp": payment.time, - "memo": payment.memo if not payment.pending else "Payment in transition", + "memo": payment.memo + if not payment.pending + else "Payment in transition", } for payment in reversed( - (await g.wallet.get_payments(pending=True, complete=True, outgoing=True, incoming=False))[:limit] + ( + await g.wallet.get_payments( + pending=True, complete=True, outgoing=True, incoming=False + ) + )[:limit] ) ] ) @@ -149,9 +167,15 @@ async def lndhub_gettxs(): async def lndhub_getuserinvoices(): await delete_expired_invoices() for invoice in await g.wallet.get_payments( - complete=False, pending=True, outgoing=False, incoming=True, exclude_uncheckable=True + complete=False, + pending=True, + outgoing=False, + incoming=True, + exclude_uncheckable=True, ): - await invoice.set_pending(WALLET.get_invoice_status(invoice.checking_id).pending) + await invoice.set_pending( + WALLET.get_invoice_status(invoice.checking_id).pending + ) limit = int(request.args.get("limit", 200)) return jsonify( @@ -169,7 +193,11 @@ async def lndhub_getuserinvoices(): "type": "user_invoice", } for invoice in reversed( - (await g.wallet.get_payments(pending=True, complete=True, incoming=True, outgoing=False))[:limit] + ( + await g.wallet.get_payments( + pending=True, complete=True, incoming=True, outgoing=False + ) + )[:limit] ) ] ) diff --git a/lnbits/extensions/lnticket/__init__.py b/lnbits/extensions/lnticket/__init__.py index 21ef19a1..0e0aa146 100644 --- a/lnbits/extensions/lnticket/__init__.py +++ b/lnbits/extensions/lnticket/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_lnticket") -lnticket_ext: Blueprint = Blueprint("lnticket", __name__, static_folder="static", template_folder="templates") +lnticket_ext: Blueprint = Blueprint( + "lnticket", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/lnticket/crud.py b/lnbits/extensions/lnticket/crud.py index 8a071cbc..6c39afb8 100644 --- a/lnbits/extensions/lnticket/crud.py +++ b/lnbits/extensions/lnticket/crud.py @@ -60,7 +60,12 @@ async def set_ticket_paid(payment_hash: str) -> Tickets: try: r = await client.post( formdata.webhook, - json={"form": ticket.form, "name": ticket.name, "email": ticket.email, "content": ticket.ltext}, + json={ + "form": ticket.form, + "name": ticket.name, + "email": ticket.email, + "content": ticket.ltext, + }, timeout=40, ) except AssertionError: @@ -80,7 +85,9 @@ async def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM ticket WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM ticket WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Tickets(**row) for row in rows] @@ -93,7 +100,12 @@ async def delete_ticket(ticket_id: str) -> None: async def create_form( - *, wallet: str, name: str, webhook: Optional[str] = None, description: str, costpword: int + *, + wallet: str, + name: str, + webhook: Optional[str] = None, + description: str, + costpword: int, ) -> Forms: form_id = urlsafe_short_hash() await db.execute( @@ -127,7 +139,9 @@ async def get_forms(wallet_ids: Union[str, List[str]]) -> List[Forms]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM form WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM form WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Forms(**row) for row in rows] diff --git a/lnbits/extensions/lnticket/views_api.py b/lnbits/extensions/lnticket/views_api.py index d22a3eb6..3c77ced0 100644 --- a/lnbits/extensions/lnticket/views_api.py +++ b/lnbits/extensions/lnticket/views_api.py @@ -32,7 +32,10 @@ async def api_forms(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([form._asdict() for form in await get_forms(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([form._asdict() for form in await get_forms(wallet_ids)]), + HTTPStatus.OK, + ) @lnticket_ext.route("/api/v1/forms", methods=["POST"]) @@ -90,7 +93,10 @@ async def api_tickets(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([form._asdict() for form in await get_tickets(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([form._asdict() for form in await get_tickets(wallet_ids)]), + HTTPStatus.OK, + ) @lnticket_ext.route("/api/v1/tickets/", methods=["POST"]) @@ -117,12 +123,20 @@ async def api_ticket_make_ticket(form_id): extra={"tag": "lnticket"}, ) - ticket = await create_ticket(payment_hash=payment_hash, wallet=form.wallet, **g.data) + ticket = await create_ticket( + payment_hash=payment_hash, wallet=form.wallet, **g.data + ) if not ticket: - return jsonify({"message": "LNTicket could not be fetched."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "LNTicket could not be fetched."}), + HTTPStatus.NOT_FOUND, + ) - return jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), HTTPStatus.OK + return ( + jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), + HTTPStatus.OK, + ) @lnticket_ext.route("/api/v1/tickets/", methods=["GET"]) diff --git a/lnbits/extensions/lnurlp/__init__.py b/lnbits/extensions/lnurlp/__init__.py index 7a44f9d5..d820b197 100644 --- a/lnbits/extensions/lnurlp/__init__.py +++ b/lnbits/extensions/lnurlp/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_lnurlp") -lnurlp_ext: Blueprint = Blueprint("lnurlp", __name__, static_folder="static", template_folder="templates") +lnurlp_ext: Blueprint = Blueprint( + "lnurlp", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/lnurlp/crud.py b/lnbits/extensions/lnurlp/crud.py index fe96825b..9c2b182a 100644 --- a/lnbits/extensions/lnurlp/crud.py +++ b/lnbits/extensions/lnurlp/crud.py @@ -74,14 +74,18 @@ async def get_pay_links(wallet_ids: Union[str, List[str]]) -> List[PayLink]: async def update_pay_link(link_id: int, **kwargs) -> Optional[PayLink]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute(f"UPDATE pay_links SET {q} WHERE id = ?", (*kwargs.values(), link_id)) + await db.execute( + f"UPDATE pay_links SET {q} WHERE id = ?", (*kwargs.values(), link_id) + ) row = await db.fetchone("SELECT * FROM pay_links WHERE id = ?", (link_id,)) return PayLink.from_row(row) if row else None async def increment_pay_link(link_id: int, **kwargs) -> Optional[PayLink]: q = ", ".join([f"{field[0]} = {field[0]} + ?" for field in kwargs.items()]) - await db.execute(f"UPDATE pay_links SET {q} WHERE id = ?", (*kwargs.values(), link_id)) + await db.execute( + f"UPDATE pay_links SET {q} WHERE id = ?", (*kwargs.values(), link_id) + ) row = await db.fetchone("SELECT * FROM pay_links WHERE id = ?", (link_id,)) return PayLink.from_row(row) if row else None diff --git a/lnbits/extensions/lnurlp/lnurl.py b/lnbits/extensions/lnurlp/lnurl.py index 31b85559..79076564 100644 --- a/lnbits/extensions/lnurlp/lnurl.py +++ b/lnbits/extensions/lnurlp/lnurl.py @@ -15,7 +15,10 @@ from .crud import increment_pay_link async def api_lnurl_response(link_id): link = await increment_pay_link(link_id, served_meta=1) if not link: - return jsonify({"status": "ERROR", "reason": "LNURL-pay not found."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "LNURL-pay not found."}), + HTTPStatus.OK, + ) rate = await get_fiat_rate_satoshis(link.currency) if link.currency else 1 resp = LnurlPayResponse( @@ -36,7 +39,10 @@ async def api_lnurl_response(link_id): async def api_lnurl_callback(link_id): link = await increment_pay_link(link_id, served_pr=1) if not link: - return jsonify({"status": "ERROR", "reason": "LNURL-pay not found."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "LNURL-pay not found."}), + HTTPStatus.OK, + ) min, max = link.min, link.max rate = await get_fiat_rate_satoshis(link.currency) if link.currency else 1 @@ -51,12 +57,20 @@ async def api_lnurl_callback(link_id): amount_received = int(request.args.get("amount")) if amount_received < min: return ( - jsonify(LnurlErrorResponse(reason=f"Amount {amount_received} is smaller than minimum {min}.").dict()), + jsonify( + LnurlErrorResponse( + reason=f"Amount {amount_received} is smaller than minimum {min}." + ).dict() + ), HTTPStatus.OK, ) elif amount_received > max: return ( - jsonify(LnurlErrorResponse(reason=f"Amount {amount_received} is greater than maximum {max}.").dict()), + jsonify( + LnurlErrorResponse( + reason=f"Amount {amount_received} is greater than maximum {max}." + ).dict() + ), HTTPStatus.OK, ) @@ -75,7 +89,9 @@ async def api_lnurl_callback(link_id): wallet_id=link.wallet, amount=int(amount_received / 1000), memo=link.description, - description_hash=hashlib.sha256(link.lnurlpay_metadata.encode("utf-8")).digest(), + description_hash=hashlib.sha256( + link.lnurlpay_metadata.encode("utf-8") + ).digest(), extra={"tag": "lnurlp", "link": link.id, "comment": comment}, ) diff --git a/lnbits/extensions/lnurlp/migrations.py b/lnbits/extensions/lnurlp/migrations.py index 13dbc959..b7ebd3f1 100644 --- a/lnbits/extensions/lnurlp/migrations.py +++ b/lnbits/extensions/lnurlp/migrations.py @@ -40,8 +40,12 @@ async def m003_min_max_comment_fiat(db): Support for min/max amounts, comments and fiat prices that get converted automatically to satoshis based on some API. """ - await db.execute("ALTER TABLE pay_links ADD COLUMN currency TEXT;") # null = satoshis - await db.execute("ALTER TABLE pay_links ADD COLUMN comment_chars INTEGER DEFAULT 0;") + await db.execute( + "ALTER TABLE pay_links ADD COLUMN currency TEXT;" + ) # null = satoshis + await db.execute( + "ALTER TABLE pay_links ADD COLUMN comment_chars INTEGER DEFAULT 0;" + ) await db.execute("ALTER TABLE pay_links RENAME COLUMN amount TO min;") await db.execute("ALTER TABLE pay_links ADD COLUMN max INTEGER;") await db.execute("UPDATE pay_links SET max = min;") diff --git a/lnbits/extensions/lnurlp/views_api.py b/lnbits/extensions/lnurlp/views_api.py index 33dc8ced..de36345a 100644 --- a/lnbits/extensions/lnurlp/views_api.py +++ b/lnbits/extensions/lnurlp/views_api.py @@ -31,12 +31,21 @@ async def api_links(): try: return ( - jsonify([{**link._asdict(), **{"lnurl": link.lnurl}} for link in await get_pay_links(wallet_ids)]), + jsonify( + [ + {**link._asdict(), **{"lnurl": link.lnurl}} + for link in await get_pay_links(wallet_ids) + ] + ), HTTPStatus.OK, ) except LnurlInvalidUrl: return ( - jsonify({"message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor."}), + jsonify( + { + "message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor." + } + ), HTTPStatus.UPGRADE_REQUIRED, ) @@ -83,7 +92,10 @@ async def api_link_create_or_update(link_id=None): link = await get_pay_link(link_id) if not link: - return jsonify({"message": "Pay link does not exist."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Pay link does not exist."}), + HTTPStatus.NOT_FOUND, + ) if link.wallet != g.wallet.id: return jsonify({"message": "Not your pay link."}), HTTPStatus.FORBIDDEN @@ -92,7 +104,10 @@ async def api_link_create_or_update(link_id=None): else: link = await create_pay_link(wallet_id=g.wallet.id, **g.data) - return jsonify({**link._asdict(), **{"lnurl": link.lnurl}}), HTTPStatus.OK if link_id else HTTPStatus.CREATED + return ( + jsonify({**link._asdict(), **{"lnurl": link.lnurl}}), + HTTPStatus.OK if link_id else HTTPStatus.CREATED, + ) @lnurlp_ext.route("/api/v1/links/", methods=["DELETE"]) diff --git a/lnbits/extensions/offlineshop/__init__.py b/lnbits/extensions/offlineshop/__init__.py index e24fa14b..1f9dd123 100644 --- a/lnbits/extensions/offlineshop/__init__.py +++ b/lnbits/extensions/offlineshop/__init__.py @@ -4,7 +4,9 @@ from lnbits.db import Database db = Database("ext_offlineshop") -offlineshop_ext: Blueprint = Blueprint("offlineshop", __name__, static_folder="static", template_folder="templates") +offlineshop_ext: Blueprint = Blueprint( + "offlineshop", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/offlineshop/lnurl.py b/lnbits/extensions/offlineshop/lnurl.py index d1e11c0c..adee1d03 100644 --- a/lnbits/extensions/offlineshop/lnurl.py +++ b/lnbits/extensions/offlineshop/lnurl.py @@ -18,7 +18,11 @@ async def lnurl_response(item_id): if not item.enabled: return jsonify({"status": "ERROR", "reason": "Item disabled."}) - price_msat = (await fiat_amount_as_satoshis(item.price, item.unit) if item.unit != "sat" else item.price) * 1000 + price_msat = ( + await fiat_amount_as_satoshis(item.price, item.unit) + if item.unit != "sat" + else item.price + ) * 1000 resp = LnurlPayResponse( callback=url_for("offlineshop.lnurl_callback", item_id=item.id, _external=True), @@ -47,16 +51,26 @@ async def lnurl_callback(item_id): amount_received = int(request.args.get("amount")) if amount_received < min: - return jsonify(LnurlErrorResponse(reason=f"Amount {amount_received} is smaller than minimum {min}.").dict()) + return jsonify( + LnurlErrorResponse( + reason=f"Amount {amount_received} is smaller than minimum {min}." + ).dict() + ) elif amount_received > max: - return jsonify(LnurlErrorResponse(reason=f"Amount {amount_received} is greater than maximum {max}.").dict()) + return jsonify( + LnurlErrorResponse( + reason=f"Amount {amount_received} is greater than maximum {max}." + ).dict() + ) shop = await get_shop(item.shop) payment_hash, payment_request = await create_invoice( wallet_id=shop.wallet, amount=int(amount_received / 1000), memo=item.name, - description_hash=hashlib.sha256((await item.lnurlpay_metadata()).encode("utf-8")).digest(), + description_hash=hashlib.sha256( + (await item.lnurlpay_metadata()).encode("utf-8") + ).digest(), extra={"tag": "offlineshop", "item": item.id}, ) diff --git a/lnbits/extensions/offlineshop/models.py b/lnbits/extensions/offlineshop/models.py index 52cf95f2..eb767cdf 100644 --- a/lnbits/extensions/offlineshop/models.py +++ b/lnbits/extensions/offlineshop/models.py @@ -89,7 +89,9 @@ class Item(NamedTuple): @property def lnurl(self) -> str: - return lnurl_encode(url_for("offlineshop.lnurl_response", item_id=self.id, _external=True)) + return lnurl_encode( + url_for("offlineshop.lnurl_response", item_id=self.id, _external=True) + ) def values(self): values = self._asdict() @@ -104,11 +106,15 @@ class Item(NamedTuple): return LnurlPayMetadata(json.dumps(metadata)) - def success_action(self, shop: Shop, payment_hash: str) -> Optional[LnurlPaySuccessAction]: + def success_action( + self, shop: Shop, payment_hash: str + ) -> Optional[LnurlPaySuccessAction]: if not shop.wordlist: return None return UrlAction( - url=url_for("offlineshop.confirmation_code", p=payment_hash, _external=True), + url=url_for( + "offlineshop.confirmation_code", p=payment_hash, _external=True + ), description="Open to get the confirmation code for your purchase.", ) diff --git a/lnbits/extensions/offlineshop/views.py b/lnbits/extensions/offlineshop/views.py index aa4ac3a1..33702f6b 100644 --- a/lnbits/extensions/offlineshop/views.py +++ b/lnbits/extensions/offlineshop/views.py @@ -24,7 +24,13 @@ async def print_qr_codes(): for item_id in request.args.get("items").split(","): item = await get_item(item_id) if item: - items.append({"lnurl": item.lnurl, "name": item.name, "price": f"{item.price} {item.unit}"}) + items.append( + { + "lnurl": item.lnurl, + "name": item.name, + "price": f"{item.price} {item.unit}", + } + ) return await render_template("offlineshop/print.html", items=items) @@ -36,10 +42,14 @@ async def confirmation_code(): payment_hash = request.args.get("p") payment: Payment = await get_standalone_payment(payment_hash) if not payment: - return f"Couldn't find the payment {payment_hash}." + style, HTTPStatus.NOT_FOUND + return ( + f"Couldn't find the payment {payment_hash}." + style, + HTTPStatus.NOT_FOUND, + ) if payment.pending: return ( - f"Payment {payment_hash} wasn't received yet. Please try again in a minute." + style, + f"Payment {payment_hash} wasn't received yet. Please try again in a minute." + + style, HTTPStatus.PAYMENT_REQUIRED, ) diff --git a/lnbits/extensions/offlineshop/views_api.py b/lnbits/extensions/offlineshop/views_api.py index 20a9eced..ee3631a7 100644 --- a/lnbits/extensions/offlineshop/views_api.py +++ b/lnbits/extensions/offlineshop/views_api.py @@ -43,7 +43,11 @@ async def api_shop_from_wallet(): ) except LnurlInvalidUrl: return ( - jsonify({"message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor."}), + jsonify( + { + "message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor." + } + ), HTTPStatus.UPGRADE_REQUIRED, ) @@ -98,7 +102,12 @@ async def api_delete_item(item_id): @api_validate_post_request( schema={ "method": {"type": "string", "required": True, "nullable": False}, - "wordlist": {"type": "string", "empty": True, "nullable": True, "required": False}, + "wordlist": { + "type": "string", + "empty": True, + "nullable": True, + "required": False, + }, } ) async def api_set_method(): diff --git a/lnbits/extensions/paywall/__init__.py b/lnbits/extensions/paywall/__init__.py index 8ab130cf..cf9570a1 100644 --- a/lnbits/extensions/paywall/__init__.py +++ b/lnbits/extensions/paywall/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_paywall") -paywall_ext: Blueprint = Blueprint("paywall", __name__, static_folder="static", template_folder="templates") +paywall_ext: Blueprint = Blueprint( + "paywall", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/paywall/crud.py b/lnbits/extensions/paywall/crud.py index 6c2338e2..b12cc1ec 100644 --- a/lnbits/extensions/paywall/crud.py +++ b/lnbits/extensions/paywall/crud.py @@ -7,7 +7,13 @@ from .models import Paywall async def create_paywall( - *, wallet_id: str, url: str, memo: str, description: Optional[str] = None, amount: int = 0, remembers: bool = True + *, + wallet_id: str, + url: str, + memo: str, + description: Optional[str] = None, + amount: int = 0, + remembers: bool = True, ) -> Paywall: paywall_id = urlsafe_short_hash() await db.execute( @@ -34,7 +40,9 @@ async def get_paywalls(wallet_ids: Union[str, List[str]]) -> List[Paywall]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM paywalls WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM paywalls WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Paywall.from_row(row) for row in rows] diff --git a/lnbits/extensions/paywall/migrations.py b/lnbits/extensions/paywall/migrations.py index fd1dd5ec..f2faae2b 100644 --- a/lnbits/extensions/paywall/migrations.py +++ b/lnbits/extensions/paywall/migrations.py @@ -46,7 +46,9 @@ async def m002_redux(db): ) await db.execute("CREATE INDEX IF NOT EXISTS wallet_idx ON paywalls (wallet)") - for row in [list(row) for row in await db.fetchall("SELECT * FROM paywalls_old")]: + for row in [ + list(row) for row in await db.fetchall("SELECT * FROM paywalls_old") + ]: await db.execute( """ INSERT INTO paywalls ( diff --git a/lnbits/extensions/paywall/views.py b/lnbits/extensions/paywall/views.py index 7373d5c4..0dcbad2f 100644 --- a/lnbits/extensions/paywall/views.py +++ b/lnbits/extensions/paywall/views.py @@ -16,5 +16,7 @@ async def index(): @paywall_ext.route("/") async def display(paywall_id): - paywall = await get_paywall(paywall_id) or abort(HTTPStatus.NOT_FOUND, "Paywall does not exist.") + paywall = await get_paywall(paywall_id) or abort( + HTTPStatus.NOT_FOUND, "Paywall does not exist." + ) return await render_template("paywall/display.html", paywall=paywall) diff --git a/lnbits/extensions/paywall/views_api.py b/lnbits/extensions/paywall/views_api.py index c2a2c62a..45c80af4 100644 --- a/lnbits/extensions/paywall/views_api.py +++ b/lnbits/extensions/paywall/views_api.py @@ -17,7 +17,10 @@ async def api_paywalls(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([paywall._asdict() for paywall in await get_paywalls(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([paywall._asdict() for paywall in await get_paywalls(wallet_ids)]), + HTTPStatus.OK, + ) @paywall_ext.route("/api/v1/paywalls", methods=["POST"]) @@ -26,7 +29,12 @@ async def api_paywalls(): schema={ "url": {"type": "string", "empty": False, "required": True}, "memo": {"type": "string", "empty": False, "required": True}, - "description": {"type": "string", "empty": True, "nullable": True, "required": False}, + "description": { + "type": "string", + "empty": True, + "nullable": True, + "required": False, + }, "amount": {"type": "integer", "min": 0, "required": True}, "remembers": {"type": "boolean", "required": True}, } @@ -53,26 +61,41 @@ async def api_paywall_delete(paywall_id): @paywall_ext.route("/api/v1/paywalls//invoice", methods=["POST"]) -@api_validate_post_request(schema={"amount": {"type": "integer", "min": 1, "required": True}}) +@api_validate_post_request( + schema={"amount": {"type": "integer", "min": 1, "required": True}} +) async def api_paywall_create_invoice(paywall_id): paywall = await get_paywall(paywall_id) if g.data["amount"] < paywall.amount: - return jsonify({"message": f"Minimum amount is {paywall.amount} sat."}), HTTPStatus.BAD_REQUEST + return ( + jsonify({"message": f"Minimum amount is {paywall.amount} sat."}), + HTTPStatus.BAD_REQUEST, + ) try: - amount = g.data["amount"] if g.data["amount"] > paywall.amount else paywall.amount + amount = ( + g.data["amount"] if g.data["amount"] > paywall.amount else paywall.amount + ) payment_hash, payment_request = await create_invoice( - wallet_id=paywall.wallet, amount=amount, memo=f"{paywall.memo}", extra={"tag": "paywall"} + wallet_id=paywall.wallet, + amount=amount, + memo=f"{paywall.memo}", + extra={"tag": "paywall"}, ) except Exception as e: return jsonify({"message": str(e)}), HTTPStatus.INTERNAL_SERVER_ERROR - return jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), HTTPStatus.CREATED + return ( + jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), + HTTPStatus.CREATED, + ) @paywall_ext.route("/api/v1/paywalls//check_invoice", methods=["POST"]) -@api_validate_post_request(schema={"payment_hash": {"type": "string", "empty": False, "required": True}}) +@api_validate_post_request( + schema={"payment_hash": {"type": "string", "empty": False, "required": True}} +) async def api_paywal_check_invoice(paywall_id): paywall = await get_paywall(paywall_id) @@ -90,6 +113,9 @@ async def api_paywal_check_invoice(paywall_id): payment = await wallet.get_payment(g.data["payment_hash"]) await payment.set_pending(False) - return jsonify({"paid": True, "url": paywall.url, "remembers": paywall.remembers}), HTTPStatus.OK + return ( + jsonify({"paid": True, "url": paywall.url, "remembers": paywall.remembers}), + HTTPStatus.OK, + ) return jsonify({"paid": False}), HTTPStatus.OK diff --git a/lnbits/extensions/subdomains/__init__.py b/lnbits/extensions/subdomains/__init__.py index cad9fee8..5013230c 100644 --- a/lnbits/extensions/subdomains/__init__.py +++ b/lnbits/extensions/subdomains/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_subdomains") -subdomains_ext: Blueprint = Blueprint("subdomains", __name__, static_folder="static", template_folder="templates") +subdomains_ext: Blueprint = Blueprint( + "subdomains", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/subdomains/cloudflare.py b/lnbits/extensions/subdomains/cloudflare.py index 7af85f40..9a0fc4cf 100644 --- a/lnbits/extensions/subdomains/cloudflare.py +++ b/lnbits/extensions/subdomains/cloudflare.py @@ -2,11 +2,20 @@ from lnbits.extensions.subdomains.models import Domains import httpx, json -async def cloudflare_create_subdomain(domain: Domains, subdomain: str, record_type: str, ip: str): +async def cloudflare_create_subdomain( + domain: Domains, subdomain: str, record_type: str, ip: str +): # Call to cloudflare sort of a dry-run - if success delete the domain and wait for payment ### SEND REQUEST TO CLOUDFLARE - url = "https://api.cloudflare.com/client/v4/zones/" + domain.cf_zone_id + "/dns_records" - header = {"Authorization": "Bearer " + domain.cf_token, "Content-Type": "application/json"} + url = ( + "https://api.cloudflare.com/client/v4/zones/" + + domain.cf_zone_id + + "/dns_records" + ) + header = { + "Authorization": "Bearer " + domain.cf_token, + "Content-Type": "application/json", + } aRecord = subdomain + "." + domain.domain cf_response = "" async with httpx.AsyncClient() as client: @@ -30,8 +39,15 @@ async def cloudflare_create_subdomain(domain: Domains, subdomain: str, record_ty async def cloudflare_deletesubdomain(domain: Domains, domain_id: str): - url = "https://api.cloudflare.com/client/v4/zones/" + domain.cf_zone_id + "/dns_records" - header = {"Authorization": "Bearer " + domain.cf_token, "Content-Type": "application/json"} + url = ( + "https://api.cloudflare.com/client/v4/zones/" + + domain.cf_zone_id + + "/dns_records" + ) + header = { + "Authorization": "Bearer " + domain.cf_token, + "Content-Type": "application/json", + } async with httpx.AsyncClient() as client: try: r = await client.delete( diff --git a/lnbits/extensions/subdomains/crud.py b/lnbits/extensions/subdomains/crud.py index 69666525..e64d4cd6 100644 --- a/lnbits/extensions/subdomains/crud.py +++ b/lnbits/extensions/subdomains/crud.py @@ -23,7 +23,18 @@ async def create_subdomain( INSERT INTO subdomain (id, domain, email, subdomain, ip, wallet, sats, duration, paid, record_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, - (payment_hash, domain, email, subdomain, ip, wallet, sats, duration, False, record_type), + ( + payment_hash, + domain, + email, + subdomain, + ip, + wallet, + sats, + duration, + False, + record_type, + ), ) subdomain = await get_subdomain(payment_hash) @@ -118,7 +129,18 @@ async def create_domain( INSERT INTO domain (id, wallet, domain, webhook, cf_token, cf_zone_id, description, cost, amountmade, allowed_record_types) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, - (domain_id, wallet, domain, webhook, cf_token, cf_zone_id, description, cost, 0, allowed_record_types), + ( + domain_id, + wallet, + domain, + webhook, + cf_token, + cf_zone_id, + description, + cost, + 0, + allowed_record_types, + ), ) domain = await get_domain(domain_id) @@ -128,7 +150,9 @@ async def create_domain( async def update_domain(domain_id: str, **kwargs) -> Domains: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute(f"UPDATE domain SET {q} WHERE id = ?", (*kwargs.values(), domain_id)) + await db.execute( + f"UPDATE domain SET {q} WHERE id = ?", (*kwargs.values(), domain_id) + ) row = await db.fetchone("SELECT * FROM domain WHERE id = ?", (domain_id,)) assert row, "Newly updated domain couldn't be retrieved" return Domains(**row) @@ -144,7 +168,9 @@ async def get_domains(wallet_ids: Union[str, List[str]]) -> List[Domains]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM domain WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM domain WHERE wallet IN ({q})", (*wallet_ids,) + ) return [Domains(**row) for row in rows] diff --git a/lnbits/extensions/subdomains/tasks.py b/lnbits/extensions/subdomains/tasks.py index f5f193a6..09c3f73d 100644 --- a/lnbits/extensions/subdomains/tasks.py +++ b/lnbits/extensions/subdomains/tasks.py @@ -33,7 +33,10 @@ async def on_invoice_paid(payment: Payment) -> None: ### Create subdomain cf_response = cloudflare_create_subdomain( - domain=domain, subdomain=subdomain.subdomain, record_type=subdomain.record_type, ip=subdomain.ip + domain=domain, + subdomain=subdomain.subdomain, + record_type=subdomain.record_type, + ip=subdomain.ip, ) ### Use webhook to notify about cloudflare registration diff --git a/lnbits/extensions/subdomains/views.py b/lnbits/extensions/subdomains/views.py index 6dafa792..14e4853f 100644 --- a/lnbits/extensions/subdomains/views.py +++ b/lnbits/extensions/subdomains/views.py @@ -19,7 +19,9 @@ async def display(domain_id): domain = await get_domain(domain_id) if not domain: abort(HTTPStatus.NOT_FOUND, "Domain does not exist.") - allowed_records = domain.allowed_record_types.replace('"', "").replace(" ", "").split(",") + allowed_records = ( + domain.allowed_record_types.replace('"', "").replace(" ", "").split(",") + ) print(allowed_records) return await render_template( "subdomains/display.html", diff --git a/lnbits/extensions/subdomains/views_api.py b/lnbits/extensions/subdomains/views_api.py index e7d2d21f..1edc562e 100644 --- a/lnbits/extensions/subdomains/views_api.py +++ b/lnbits/extensions/subdomains/views_api.py @@ -37,7 +37,10 @@ async def api_domains(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([domain._asdict() for domain in await get_domains(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([domain._asdict() for domain in await get_domains(wallet_ids)]), + HTTPStatus.OK, + ) @subdomains_ext.route("/api/v1/domains", methods=["POST"]) @@ -98,7 +101,10 @@ async def api_subdomains(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([domain._asdict() for domain in await get_subdomains(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([domain._asdict() for domain in await get_subdomains(wallet_ids)]), + HTTPStatus.OK, + ) @subdomains_ext.route("/api/v1/subdomains/", methods=["POST"]) @@ -122,24 +128,42 @@ async def api_subdomain_make_subdomain(domain_id): ## If record_type is not one of the allowed ones reject the request if g.data["record_type"] not in domain.allowed_record_types: - return jsonify({"message": g.data["record_type"] + "Not a valid record"}), HTTPStatus.BAD_REQUEST + return ( + jsonify({"message": g.data["record_type"] + "Not a valid record"}), + HTTPStatus.BAD_REQUEST, + ) ## If domain already exist in our database reject it if await get_subdomainBySubdomain(g.data["subdomain"]) is not None: return ( - jsonify({"message": g.data["subdomain"] + "." + domain.domain + " domain already taken"}), + jsonify( + { + "message": g.data["subdomain"] + + "." + + domain.domain + + " domain already taken" + } + ), HTTPStatus.BAD_REQUEST, ) ## Dry run cloudflare... (create and if create is sucessful delete it) cf_response = await cloudflare_create_subdomain( - domain=domain, subdomain=g.data["subdomain"], record_type=g.data["record_type"], ip=g.data["ip"] + domain=domain, + subdomain=g.data["subdomain"], + record_type=g.data["record_type"], + ip=g.data["ip"], ) if cf_response["success"] == True: cloudflare_deletesubdomain(domain=domain, domain_id=cf_response["result"]["id"]) else: return ( - jsonify({"message": "Problem with cloudflare: " + cf_response["errors"][0]["message"]}), + jsonify( + { + "message": "Problem with cloudflare: " + + cf_response["errors"][0]["message"] + } + ), HTTPStatus.BAD_REQUEST, ) @@ -152,12 +176,20 @@ async def api_subdomain_make_subdomain(domain_id): extra={"tag": "lnsubdomain"}, ) - subdomain = await create_subdomain(payment_hash=payment_hash, wallet=domain.wallet, **g.data) + subdomain = await create_subdomain( + payment_hash=payment_hash, wallet=domain.wallet, **g.data + ) if not subdomain: - return jsonify({"message": "LNsubdomain could not be fetched."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "LNsubdomain could not be fetched."}), + HTTPStatus.NOT_FOUND, + ) - return jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), HTTPStatus.OK + return ( + jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), + HTTPStatus.OK, + ) @subdomains_ext.route("/api/v1/subdomains/", methods=["GET"]) diff --git a/lnbits/extensions/tpos/__init__.py b/lnbits/extensions/tpos/__init__.py index 78732d86..daa3022e 100644 --- a/lnbits/extensions/tpos/__init__.py +++ b/lnbits/extensions/tpos/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_tpos") -tpos_ext: Blueprint = Blueprint("tpos", __name__, static_folder="static", template_folder="templates") +tpos_ext: Blueprint = Blueprint( + "tpos", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/tpos/crud.py b/lnbits/extensions/tpos/crud.py index 69f70730..afd4f973 100644 --- a/lnbits/extensions/tpos/crud.py +++ b/lnbits/extensions/tpos/crud.py @@ -31,7 +31,9 @@ async def get_tposs(wallet_ids: Union[str, List[str]]) -> List[TPoS]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM tposs WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM tposs WHERE wallet IN ({q})", (*wallet_ids,) + ) return [TPoS.from_row(row) for row in rows] diff --git a/lnbits/extensions/tpos/views_api.py b/lnbits/extensions/tpos/views_api.py index 22980fce..1f0802c7 100644 --- a/lnbits/extensions/tpos/views_api.py +++ b/lnbits/extensions/tpos/views_api.py @@ -16,7 +16,10 @@ async def api_tposs(): if "all_wallets" in request.args: wallet_ids = (await get_user(g.wallet.user)).wallet_ids - return jsonify([tpos._asdict() for tpos in await get_tposs(wallet_ids)]), HTTPStatus.OK + return ( + jsonify([tpos._asdict() for tpos in await get_tposs(wallet_ids)]), + HTTPStatus.OK, + ) @tpos_ext.route("/api/v1/tposs", methods=["POST"]) @@ -49,7 +52,9 @@ async def api_tpos_delete(tpos_id): @tpos_ext.route("/api/v1/tposs//invoices/", methods=["POST"]) -@api_validate_post_request(schema={"amount": {"type": "integer", "min": 1, "required": True}}) +@api_validate_post_request( + schema={"amount": {"type": "integer", "min": 1, "required": True}} +) async def api_tpos_create_invoice(tpos_id): tpos = await get_tpos(tpos_id) @@ -58,12 +63,18 @@ async def api_tpos_create_invoice(tpos_id): try: payment_hash, payment_request = await create_invoice( - wallet_id=tpos.wallet, amount=g.data["amount"], memo=f"{tpos.name}", extra={"tag": "tpos"} + wallet_id=tpos.wallet, + amount=g.data["amount"], + memo=f"{tpos.name}", + extra={"tag": "tpos"}, ) except Exception as e: return jsonify({"message": str(e)}), HTTPStatus.INTERNAL_SERVER_ERROR - return jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), HTTPStatus.CREATED + return ( + jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), + HTTPStatus.CREATED, + ) @tpos_ext.route("/api/v1/tposs//invoices/", methods=["GET"]) diff --git a/lnbits/extensions/usermanager/__init__.py b/lnbits/extensions/usermanager/__init__.py index 2bdbf0b5..53154812 100644 --- a/lnbits/extensions/usermanager/__init__.py +++ b/lnbits/extensions/usermanager/__init__.py @@ -3,7 +3,9 @@ from lnbits.db import Database db = Database("ext_usermanager") -usermanager_ext: Blueprint = Blueprint("usermanager", __name__, static_folder="static", template_folder="templates") +usermanager_ext: Blueprint = Blueprint( + "usermanager", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/usermanager/crud.py b/lnbits/extensions/usermanager/crud.py index 350a03f9..155290fa 100644 --- a/lnbits/extensions/usermanager/crud.py +++ b/lnbits/extensions/usermanager/crud.py @@ -16,7 +16,9 @@ from .models import Users, Wallets ### Users -async def create_usermanager_user(user_name: str, wallet_name: str, admin_id: str) -> Users: +async def create_usermanager_user( + user_name: str, wallet_name: str, admin_id: str +) -> Users: account = await create_account() user = await get_user(account.id) assert user, "Newly created user couldn't be retrieved" @@ -66,7 +68,9 @@ async def delete_usermanager_user(user_id: str) -> None: ### Wallets -async def create_usermanager_wallet(user_id: str, wallet_name: str, admin_id: str) -> Wallets: +async def create_usermanager_wallet( + user_id: str, wallet_name: str, admin_id: str +) -> Wallets: wallet = await create_wallet(user_id=user_id, wallet_name=wallet_name) await db.execute( """ @@ -91,7 +95,9 @@ async def get_usermanager_wallets(user_id: str) -> List[Wallets]: async def get_usermanager_wallet_transactions(wallet_id: str) -> List[Payment]: - return await get_payments(wallet_id=wallet_id, complete=True, pending=False, outgoing=True, incoming=True) + return await get_payments( + wallet_id=wallet_id, complete=True, pending=False, outgoing=True, incoming=True + ) async def delete_usermanager_wallet(wallet_id: str, user_id: str) -> None: diff --git a/lnbits/extensions/usermanager/views_api.py b/lnbits/extensions/usermanager/views_api.py index 557aa8b9..bd64c070 100644 --- a/lnbits/extensions/usermanager/views_api.py +++ b/lnbits/extensions/usermanager/views_api.py @@ -26,7 +26,10 @@ from lnbits.core import update_user_extension @api_check_wallet_key(key_type="invoice") async def api_usermanager_users(): user_id = g.wallet.user - return jsonify([user._asdict() for user in await get_usermanager_users(user_id)]), HTTPStatus.OK + return ( + jsonify([user._asdict() for user in await get_usermanager_users(user_id)]), + HTTPStatus.OK, + ) @usermanager_ext.route("/api/v1/users", methods=["POST"]) @@ -39,7 +42,9 @@ async def api_usermanager_users(): } ) async def api_usermanager_users_create(): - user = await create_usermanager_user(g.data["user_name"], g.data["wallet_name"], g.data["admin_id"]) + user = await create_usermanager_user( + g.data["user_name"], g.data["wallet_name"], g.data["admin_id"] + ) return jsonify(user._asdict()), HTTPStatus.CREATED @@ -69,7 +74,9 @@ async def api_usermanager_activate_extension(): user = await get_user(g.data["userid"]) if not user: return jsonify({"message": "no such user"}), HTTPStatus.NOT_FOUND - update_user_extension(user_id=g.data["userid"], extension=g.data["extension"], active=g.data["active"]) + update_user_extension( + user_id=g.data["userid"], extension=g.data["extension"], active=g.data["active"] + ) return jsonify({"extension": "updated"}), HTTPStatus.CREATED @@ -80,7 +87,12 @@ async def api_usermanager_activate_extension(): @api_check_wallet_key(key_type="invoice") async def api_usermanager_wallets(): user_id = g.wallet.user - return jsonify([wallet._asdict() for wallet in await get_usermanager_wallets(user_id)]), HTTPStatus.OK + return ( + jsonify( + [wallet._asdict() for wallet in await get_usermanager_wallets(user_id)] + ), + HTTPStatus.OK, + ) @usermanager_ext.route("/api/v1/wallets", methods=["POST"]) @@ -93,7 +105,9 @@ async def api_usermanager_wallets(): } ) async def api_usermanager_wallets_create(): - user = await create_usermanager_wallet(g.data["user_id"], g.data["wallet_name"], g.data["admin_id"]) + user = await create_usermanager_wallet( + g.data["user_id"], g.data["wallet_name"], g.data["admin_id"] + ) return jsonify(user._asdict()), HTTPStatus.CREATED diff --git a/lnbits/extensions/withdraw/__init__.py b/lnbits/extensions/withdraw/__init__.py index 7afbf23c..69e45e4d 100644 --- a/lnbits/extensions/withdraw/__init__.py +++ b/lnbits/extensions/withdraw/__init__.py @@ -4,7 +4,9 @@ from lnbits.db import Database db = Database("ext_withdraw") -withdraw_ext: Blueprint = Blueprint("withdraw", __name__, static_folder="static", template_folder="templates") +withdraw_ext: Blueprint = Blueprint( + "withdraw", __name__, static_folder="static", template_folder="templates" +) from .views_api import * # noqa diff --git a/lnbits/extensions/withdraw/crud.py b/lnbits/extensions/withdraw/crud.py index ae2c48fa..9b86b8d2 100644 --- a/lnbits/extensions/withdraw/crud.py +++ b/lnbits/extensions/withdraw/crud.py @@ -66,7 +66,9 @@ async def get_withdraw_link(link_id: str, num=0) -> Optional[WithdrawLink]: async def get_withdraw_link_by_hash(unique_hash: str, num=0) -> Optional[WithdrawLink]: - row = await db.fetchone("SELECT * FROM withdraw_link WHERE unique_hash = ?", (unique_hash,)) + row = await db.fetchone( + "SELECT * FROM withdraw_link WHERE unique_hash = ?", (unique_hash,) + ) link = [] for item in row: link.append(item) @@ -79,14 +81,18 @@ async def get_withdraw_links(wallet_ids: Union[str, List[str]]) -> List[Withdraw wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall(f"SELECT * FROM withdraw_link WHERE wallet IN ({q})", (*wallet_ids,)) + rows = await db.fetchall( + f"SELECT * FROM withdraw_link WHERE wallet IN ({q})", (*wallet_ids,) + ) return [WithdrawLink.from_row(row) for row in rows] async def update_withdraw_link(link_id: str, **kwargs) -> Optional[WithdrawLink]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute(f"UPDATE withdraw_link SET {q} WHERE id = ?", (*kwargs.values(), link_id)) + await db.execute( + f"UPDATE withdraw_link SET {q} WHERE id = ?", (*kwargs.values(), link_id) + ) row = await db.fetchone("SELECT * FROM withdraw_link WHERE id = ?", (link_id,)) return WithdrawLink.from_row(row) if row else None @@ -123,7 +129,9 @@ async def create_hash_check( async def get_hash_check(the_hash: str, lnurl_id: str) -> Optional[HashCheck]: rowid = await db.fetchone("SELECT * FROM hash_check WHERE id = ?", (the_hash,)) - rowlnurl = await db.fetchone("SELECT * FROM hash_check WHERE lnurl_id = ?", (lnurl_id,)) + rowlnurl = await db.fetchone( + "SELECT * FROM hash_check WHERE lnurl_id = ?", (lnurl_id,) + ) if not rowlnurl: await create_hash_check(the_hash, lnurl_id) return {"lnurl": True, "hash": False} @@ -132,4 +140,4 @@ async def get_hash_check(the_hash: str, lnurl_id: str) -> Optional[HashCheck]: await create_hash_check(the_hash, lnurl_id) return {"lnurl": True, "hash": False} else: - return {"lnurl": True, "hash": True} \ No newline at end of file + return {"lnurl": True, "hash": True} diff --git a/lnbits/extensions/withdraw/lnurl.py b/lnbits/extensions/withdraw/lnurl.py index 0a3cc629..39c3d917 100644 --- a/lnbits/extensions/withdraw/lnurl.py +++ b/lnbits/extensions/withdraw/lnurl.py @@ -17,10 +17,16 @@ async def api_lnurl_response(unique_hash): link = await get_withdraw_link_by_hash(unique_hash) if not link: - return jsonify({"status": "ERROR", "reason": "LNURL-withdraw not found."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "LNURL-withdraw not found."}), + HTTPStatus.OK, + ) if link.is_spent: - return jsonify({"status": "ERROR", "reason": "Withdraw is spent."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "Withdraw is spent."}), + HTTPStatus.OK, + ) return jsonify(link.lnurl_response.dict()), HTTPStatus.OK @@ -33,10 +39,16 @@ async def api_lnurl_multi_response(unique_hash, id_unique_hash): link = await get_withdraw_link_by_hash(unique_hash) if not link: - return jsonify({"status": "ERROR", "reason": "LNURL-withdraw not found."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "LNURL-withdraw not found."}), + HTTPStatus.OK, + ) if link.is_spent: - return jsonify({"status": "ERROR", "reason": "Withdraw is spent."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "Withdraw is spent."}), + HTTPStatus.OK, + ) useslist = link.usescsv.split(",") found = False @@ -45,7 +57,10 @@ async def api_lnurl_multi_response(unique_hash, id_unique_hash): if id_unique_hash == shortuuid.uuid(name=tohash): found = True if not found: - return jsonify({"status": "ERROR", "reason": "LNURL-withdraw not found."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "LNURL-withdraw not found."}), + HTTPStatus.OK, + ) return jsonify(link.lnurl_response.dict()), HTTPStatus.OK @@ -61,16 +76,27 @@ async def api_lnurl_callback(unique_hash): now = int(datetime.now().timestamp()) if not link: - return jsonify({"status": "ERROR", "reason": "LNURL-withdraw not found."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "LNURL-withdraw not found."}), + HTTPStatus.OK, + ) if link.is_spent: - return jsonify({"status": "ERROR", "reason": "Withdraw is spent."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "Withdraw is spent."}), + HTTPStatus.OK, + ) if link.k1 != k1: return jsonify({"status": "ERROR", "reason": "Bad request."}), HTTPStatus.OK if now < link.open_time: - return jsonify({"status": "ERROR", "reason": f"Wait {link.open_time - now} seconds."}), HTTPStatus.OK + return ( + jsonify( + {"status": "ERROR", "reason": f"Wait {link.open_time - now} seconds."} + ), + HTTPStatus.OK, + ) try: await pay_invoice( @@ -85,12 +111,19 @@ async def api_lnurl_callback(unique_hash): usecv = link.usescsv.split(",") usescsv += "," + str(usecv[x]) usescsv = usescsv[1:] - changes = {"open_time": link.wait_time + now, "used": link.used + 1, "usescsv": usescsv} + changes = { + "open_time": link.wait_time + now, + "used": link.used + 1, + "usescsv": usescsv, + } await update_withdraw_link(link.id, **changes) except ValueError as e: return jsonify({"status": "ERROR", "reason": str(e)}), HTTPStatus.OK except PermissionError: - return jsonify({"status": "ERROR", "reason": "Withdraw link is empty."}), HTTPStatus.OK + return ( + jsonify({"status": "ERROR", "reason": "Withdraw link is empty."}), + HTTPStatus.OK, + ) return jsonify({"status": "OK"}), HTTPStatus.OK diff --git a/lnbits/extensions/withdraw/migrations.py b/lnbits/extensions/withdraw/migrations.py index 2cb802d4..197a629c 100644 --- a/lnbits/extensions/withdraw/migrations.py +++ b/lnbits/extensions/withdraw/migrations.py @@ -47,7 +47,9 @@ async def m002_change_withdraw_table(db): """ ) await db.execute("CREATE INDEX IF NOT EXISTS wallet_idx ON withdraw_link (wallet)") - await db.execute("CREATE UNIQUE INDEX IF NOT EXISTS unique_hash_idx ON withdraw_link (unique_hash)") + await db.execute( + "CREATE UNIQUE INDEX IF NOT EXISTS unique_hash_idx ON withdraw_link (unique_hash)" + ) for row in [list(row) for row in await db.fetchall("SELECT * FROM withdraw_links")]: usescsv = "" @@ -107,4 +109,4 @@ async def m003_make_hash_check(db): lnurl_id TEXT ); """ - ) \ No newline at end of file + ) diff --git a/lnbits/extensions/withdraw/models.py b/lnbits/extensions/withdraw/models.py index 4c485ea3..b7a98970 100644 --- a/lnbits/extensions/withdraw/models.py +++ b/lnbits/extensions/withdraw/models.py @@ -45,13 +45,19 @@ class WithdrawLink(NamedTuple): _external=True, ) else: - url = url_for("withdraw.api_lnurl_response", unique_hash=self.unique_hash, _external=True) + url = url_for( + "withdraw.api_lnurl_response", + unique_hash=self.unique_hash, + _external=True, + ) return lnurl_encode(url) @property def lnurl_response(self) -> LnurlWithdrawResponse: - url = url_for("withdraw.api_lnurl_callback", unique_hash=self.unique_hash, _external=True) + url = url_for( + "withdraw.api_lnurl_callback", unique_hash=self.unique_hash, _external=True + ) return LnurlWithdrawResponse( callback=url, k1=self.k1, @@ -67,4 +73,4 @@ class HashCheck(NamedTuple): @classmethod def from_row(cls, row: Row) -> "Hash": - return cls(**dict(row)) \ No newline at end of file + return cls(**dict(row)) diff --git a/lnbits/extensions/withdraw/views.py b/lnbits/extensions/withdraw/views.py index 473ccbea..28f25756 100644 --- a/lnbits/extensions/withdraw/views.py +++ b/lnbits/extensions/withdraw/views.py @@ -17,13 +17,17 @@ async def index(): @withdraw_ext.route("/") async def display(link_id): - link = await get_withdraw_link(link_id, 0) or abort(HTTPStatus.NOT_FOUND, "Withdraw link does not exist.") + link = await get_withdraw_link(link_id, 0) or abort( + HTTPStatus.NOT_FOUND, "Withdraw link does not exist." + ) return await render_template("withdraw/display.html", link=link, unique=True) @withdraw_ext.route("/img/") async def img(link_id): - link = await get_withdraw_link(link_id, 0) or abort(HTTPStatus.NOT_FOUND, "Withdraw link does not exist.") + link = await get_withdraw_link(link_id, 0) or abort( + HTTPStatus.NOT_FOUND, "Withdraw link does not exist." + ) qr = pyqrcode.create(link.lnurl) stream = BytesIO() qr.svg(stream, scale=3) @@ -41,13 +45,17 @@ async def img(link_id): @withdraw_ext.route("/print/") async def print_qr(link_id): - link = await get_withdraw_link(link_id) or abort(HTTPStatus.NOT_FOUND, "Withdraw link does not exist.") + link = await get_withdraw_link(link_id) or abort( + HTTPStatus.NOT_FOUND, "Withdraw link does not exist." + ) if link.uses == 0: return await render_template("withdraw/print_qr.html", link=link, unique=False) links = [] count = 0 for x in link.usescsv.split(","): - linkk = await get_withdraw_link(link_id, count) or abort(HTTPStatus.NOT_FOUND, "Withdraw link does not exist.") + linkk = await get_withdraw_link(link_id, count) or abort( + HTTPStatus.NOT_FOUND, "Withdraw link does not exist." + ) links.append(str(linkk.lnurl)) count = count + 1 page_link = list(chunks(links, 2)) diff --git a/lnbits/extensions/withdraw/views_api.py b/lnbits/extensions/withdraw/views_api.py index 2b6cb600..4979b932 100644 --- a/lnbits/extensions/withdraw/views_api.py +++ b/lnbits/extensions/withdraw/views_api.py @@ -39,7 +39,11 @@ async def api_links(): ) except LnurlInvalidUrl: return ( - jsonify({"message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor."}), + jsonify( + { + "message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor." + } + ), HTTPStatus.UPGRADE_REQUIRED, ) @@ -50,7 +54,10 @@ async def api_link_retrieve(link_id): link = await get_withdraw_link(link_id, 0) if not link: - return jsonify({"message": "Withdraw link does not exist."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Withdraw link does not exist."}), + HTTPStatus.NOT_FOUND, + ) if link.wallet != g.wallet.id: return jsonify({"message": "Not your withdraw link."}), HTTPStatus.FORBIDDEN @@ -74,7 +81,11 @@ async def api_link_retrieve(link_id): async def api_link_create_or_update(link_id=None): if g.data["max_withdrawable"] < g.data["min_withdrawable"]: return ( - jsonify({"message": "`max_withdrawable` needs to be at least `min_withdrawable`."}), + jsonify( + { + "message": "`max_withdrawable` needs to be at least `min_withdrawable`." + } + ), HTTPStatus.BAD_REQUEST, ) @@ -89,14 +100,22 @@ async def api_link_create_or_update(link_id=None): if link_id: link = await get_withdraw_link(link_id, 0) if not link: - return jsonify({"message": "Withdraw link does not exist."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Withdraw link does not exist."}), + HTTPStatus.NOT_FOUND, + ) if link.wallet != g.wallet.id: return jsonify({"message": "Not your withdraw link."}), HTTPStatus.FORBIDDEN link = await update_withdraw_link(link_id, **g.data, usescsv=usescsv, used=0) else: - link = await create_withdraw_link(wallet_id=g.wallet.id, **g.data, usescsv=usescsv) + link = await create_withdraw_link( + wallet_id=g.wallet.id, **g.data, usescsv=usescsv + ) - return jsonify({**link._asdict(), **{"lnurl": link.lnurl}}), HTTPStatus.OK if link_id else HTTPStatus.CREATED + return ( + jsonify({**link._asdict(), **{"lnurl": link.lnurl}}), + HTTPStatus.OK if link_id else HTTPStatus.CREATED, + ) @withdraw_ext.route("/api/v1/links/", methods=["DELETE"]) @@ -105,7 +124,10 @@ async def api_link_delete(link_id): link = await get_withdraw_link(link_id) if not link: - return jsonify({"message": "Withdraw link does not exist."}), HTTPStatus.NOT_FOUND + return ( + jsonify({"message": "Withdraw link does not exist."}), + HTTPStatus.NOT_FOUND, + ) if link.wallet != g.wallet.id: return jsonify({"message": "Not your withdraw link."}), HTTPStatus.FORBIDDEN @@ -119,4 +141,4 @@ async def api_link_delete(link_id): @api_check_wallet_key("invoice") async def api_hash_retrieve(the_hash, lnurl_id): hashCheck = await get_hash_check(the_hash, lnurl_id) - return jsonify(hashCheck), HTTPStatus.OK \ No newline at end of file + return jsonify(hashCheck), HTTPStatus.OK diff --git a/lnbits/helpers.py b/lnbits/helpers.py index ec7ec904..956a8a99 100644 --- a/lnbits/helpers.py +++ b/lnbits/helpers.py @@ -20,15 +20,21 @@ class Extension(NamedTuple): class ExtensionManager: def __init__(self): self._disabled: List[str] = LNBITS_DISABLED_EXTENSIONS - self._extension_folders: List[str] = [x[1] for x in os.walk(os.path.join(LNBITS_PATH, "extensions"))][0] + self._extension_folders: List[str] = [ + x[1] for x in os.walk(os.path.join(LNBITS_PATH, "extensions")) + ][0] @property def extensions(self) -> List[Extension]: output = [] - for extension in [ext for ext in self._extension_folders if ext not in self._disabled]: + for extension in [ + ext for ext in self._extension_folders if ext not in self._disabled + ]: try: - with open(os.path.join(LNBITS_PATH, "extensions", extension, "config.json")) as json_file: + with open( + os.path.join(LNBITS_PATH, "extensions", extension, "config.json") + ) as json_file: config = json.load(json_file) is_valid = True except Exception: @@ -50,7 +56,9 @@ class ExtensionManager: def get_valid_extensions() -> List[Extension]: - return [extension for extension in ExtensionManager().extensions if extension.is_valid] + return [ + extension for extension in ExtensionManager().extensions if extension.is_valid + ] def urlsafe_short_hash() -> str: @@ -91,7 +99,9 @@ def get_css_vendored(prefer_minified: bool = False) -> List[str]: def get_vendored(ext: str, prefer_minified: bool = False) -> List[str]: paths: List[str] = [] - for path in glob.glob(os.path.join(LNBITS_PATH, "static/vendor/**"), recursive=True): + for path in glob.glob( + os.path.join(LNBITS_PATH, "static/vendor/**"), recursive=True + ): if path.endswith(".min" + ext): # path is minified unminified = path.replace(".min" + ext, ext) diff --git a/lnbits/settings.py b/lnbits/settings.py index 1ce46ec2..b42d06ec 100644 --- a/lnbits/settings.py +++ b/lnbits/settings.py @@ -10,7 +10,9 @@ env = Env() env.read_env() wallets_module = importlib.import_module("lnbits.wallets") -wallet_class = getattr(wallets_module, env.str("LNBITS_BACKEND_WALLET_CLASS", default="VoidWallet")) +wallet_class = getattr( + wallets_module, env.str("LNBITS_BACKEND_WALLET_CLASS", default="VoidWallet") +) ENV = env.str("QUART_ENV", default="production") DEBUG = env.bool("QUART_DEBUG", default=False) or ENV == "development" @@ -18,9 +20,15 @@ HOST = env.str("HOST", default="127.0.0.1") PORT = env.int("PORT", default=5000) LNBITS_PATH = path.dirname(path.realpath(__file__)) -LNBITS_DATA_FOLDER = env.str("LNBITS_DATA_FOLDER", default=path.join(LNBITS_PATH, "data")) -LNBITS_ALLOWED_USERS: List[str] = env.list("LNBITS_ALLOWED_USERS", default=[], subcast=str) -LNBITS_DISABLED_EXTENSIONS: List[str] = env.list("LNBITS_DISABLED_EXTENSIONS", default=[], subcast=str) +LNBITS_DATA_FOLDER = env.str( + "LNBITS_DATA_FOLDER", default=path.join(LNBITS_PATH, "data") +) +LNBITS_ALLOWED_USERS: List[str] = env.list( + "LNBITS_ALLOWED_USERS", default=[], subcast=str +) +LNBITS_DISABLED_EXTENSIONS: List[str] = env.list( + "LNBITS_DISABLED_EXTENSIONS", default=[], subcast=str +) LNBITS_SITE_TITLE = env.str("LNBITS_SITE_TITLE", default="LNbits") WALLET = wallet_class() diff --git a/lnbits/tasks.py b/lnbits/tasks.py index 77f55fc9..d671786c 100644 --- a/lnbits/tasks.py +++ b/lnbits/tasks.py @@ -4,7 +4,11 @@ from typing import Optional, List, Callable from quart_trio import QuartTrio from lnbits.settings import WALLET -from lnbits.core.crud import get_payments, get_standalone_payment, delete_expired_invoices +from lnbits.core.crud import ( + get_payments, + get_standalone_payment, + delete_expired_invoices, +) main_app: Optional[QuartTrio] = None @@ -67,7 +71,9 @@ async def invoice_listener(nursery): async def check_pending_payments(): await delete_expired_invoices() while True: - for payment in await get_payments(complete=False, pending=True, exclude_uncheckable=True): + for payment in await get_payments( + complete=False, pending=True, exclude_uncheckable=True + ): print(" - checking pending", payment.checking_id) await payment.check_pending() diff --git a/lnbits/utils/exchange_rates.py b/lnbits/utils/exchange_rates.py index 506f6daf..ef4d3306 100644 --- a/lnbits/utils/exchange_rates.py +++ b/lnbits/utils/exchange_rates.py @@ -212,7 +212,12 @@ exchange_rate_providers = { async def btc_price(currency: str) -> float: - replacements = {"FROM": "BTC", "from": "btc", "TO": currency.upper(), "to": currency.lower()} + replacements = { + "FROM": "BTC", + "from": "btc", + "TO": currency.upper(), + "to": currency.lower(), + } rates = [] send_channel, receive_channel = trio.open_memory_channel(0) diff --git a/lnbits/wallets/base.py b/lnbits/wallets/base.py index d2486c73..adc100cd 100644 --- a/lnbits/wallets/base.py +++ b/lnbits/wallets/base.py @@ -37,7 +37,10 @@ class Wallet(ABC): @abstractmethod def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: pass diff --git a/lnbits/wallets/clightning.py b/lnbits/wallets/clightning.py index 48d304bb..f0028f06 100644 --- a/lnbits/wallets/clightning.py +++ b/lnbits/wallets/clightning.py @@ -10,13 +10,22 @@ import json from os import getenv from typing import Optional, AsyncGenerator -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet, Unsupported +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, + Unsupported, +) class CLightningWallet(Wallet): def __init__(self): if LightningRpc is None: # pragma: nocover - raise ImportError("The `pylightning` library must be installed to use `CLightningWallet`.") + raise ImportError( + "The `pylightning` library must be installed to use `CLightningWallet`." + ) self.rpc = getenv("CLIGHTNING_RPC") self.ln = LightningRpc(self.rpc) @@ -52,7 +61,10 @@ class CLightningWallet(Wallet): return StatusResponse(error_message, 0) def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: label = "lbl{}".format(random.random()) msat = amount * 1000 diff --git a/lnbits/wallets/lnbits.py b/lnbits/wallets/lnbits.py index 30c62c60..c8665872 100644 --- a/lnbits/wallets/lnbits.py +++ b/lnbits/wallets/lnbits.py @@ -3,7 +3,13 @@ import httpx from os import getenv from typing import Optional, Dict, AsyncGenerator -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, +) class LNbitsWallet(Wallet): @@ -12,7 +18,11 @@ class LNbitsWallet(Wallet): def __init__(self): self.endpoint = getenv("LNBITS_ENDPOINT") - key = getenv("LNBITS_KEY") or getenv("LNBITS_ADMIN_KEY") or getenv("LNBITS_INVOICE_KEY") + key = ( + getenv("LNBITS_KEY") + or getenv("LNBITS_ADMIN_KEY") + or getenv("LNBITS_INVOICE_KEY") + ) self.key = {"X-Api-Key": key} def status(self) -> StatusResponse: @@ -20,7 +30,9 @@ class LNbitsWallet(Wallet): try: data = r.json() except: - return StatusResponse(f"Failed to connect to {self.endpoint}, got: '{r.text[:200]}...'", 0) + return StatusResponse( + f"Failed to connect to {self.endpoint}, got: '{r.text[:200]}...'", 0 + ) if r.is_error: return StatusResponse(data["message"], 0) @@ -28,7 +40,10 @@ class LNbitsWallet(Wallet): return StatusResponse(None, data["balance"]) def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: data: Dict = {"out": False, "amount": amount} if description_hash: @@ -41,7 +56,12 @@ class LNbitsWallet(Wallet): headers=self.key, json=data, ) - ok, checking_id, payment_request, error_message = not r.is_error, None, None, None + ok, checking_id, payment_request, error_message = ( + not r.is_error, + None, + None, + None, + ) if r.is_error: error_message = r.json()["message"] @@ -52,7 +72,11 @@ class LNbitsWallet(Wallet): return InvoiceResponse(ok, checking_id, payment_request, error_message) def pay_invoice(self, bolt11: str) -> PaymentResponse: - r = httpx.post(url=f"{self.endpoint}/api/v1/payments", headers=self.key, json={"out": True, "bolt11": bolt11}) + r = httpx.post( + url=f"{self.endpoint}/api/v1/payments", + headers=self.key, + json={"out": True, "bolt11": bolt11}, + ) ok, checking_id, fee_msat, error_message = not r.is_error, None, 0, None if r.is_error: @@ -64,7 +88,9 @@ class LNbitsWallet(Wallet): return PaymentResponse(ok, checking_id, fee_msat, error_message) def get_invoice_status(self, checking_id: str) -> PaymentStatus: - r = httpx.get(url=f"{self.endpoint}/api/v1/payments/{checking_id}", headers=self.key) + r = httpx.get( + url=f"{self.endpoint}/api/v1/payments/{checking_id}", headers=self.key + ) if r.is_error: return PaymentStatus(None) @@ -72,7 +98,9 @@ class LNbitsWallet(Wallet): return PaymentStatus(r.json()["paid"]) def get_payment_status(self, checking_id: str) -> PaymentStatus: - r = httpx.get(url=f"{self.endpoint}/api/v1/payments/{checking_id}", headers=self.key) + r = httpx.get( + url=f"{self.endpoint}/api/v1/payments/{checking_id}", headers=self.key + ) if r.is_error: return PaymentStatus(None) diff --git a/lnbits/wallets/lndgrpc.py b/lnbits/wallets/lndgrpc.py index d92b568f..36384008 100644 --- a/lnbits/wallets/lndgrpc.py +++ b/lnbits/wallets/lndgrpc.py @@ -15,7 +15,13 @@ import hashlib from os import getenv from typing import Optional, Dict, AsyncGenerator -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, +) def get_ssl_context(cert_path: str): @@ -76,10 +82,14 @@ def stringify_checking_id(r_hash: bytes) -> str: class LndWallet(Wallet): def __init__(self): if lndgrpc is None: # pragma: nocover - raise ImportError("The `lndgrpc` library must be installed to use `LndWallet`.") + raise ImportError( + "The `lndgrpc` library must be installed to use `LndWallet`." + ) if purerpc is None: # pragma: nocover - raise ImportError("The `purerpc` library must be installed to use `LndWallet`.") + raise ImportError( + "The `purerpc` library must be installed to use `LndWallet`." + ) endpoint = getenv("LND_GRPC_ENDPOINT") self.endpoint = endpoint[:-1] if endpoint.endswith("/") else endpoint @@ -111,7 +121,10 @@ class LndWallet(Wallet): return StatusResponse(None, resp.balance * 1000) def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: params: Dict = {"value": amount, "expiry": 600, "private": True} diff --git a/lnbits/wallets/lndrest.py b/lnbits/wallets/lndrest.py index 4ee42aa7..1f8c3805 100644 --- a/lnbits/wallets/lndrest.py +++ b/lnbits/wallets/lndrest.py @@ -5,7 +5,13 @@ import base64 from os import getenv from typing import Optional, Dict, AsyncGenerator -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, +) class LndRestWallet(Wallet): @@ -14,7 +20,9 @@ class LndRestWallet(Wallet): def __init__(self): endpoint = getenv("LND_REST_ENDPOINT") endpoint = endpoint[:-1] if endpoint.endswith("/") else endpoint - endpoint = "https://" + endpoint if not endpoint.startswith("http") else endpoint + endpoint = ( + "https://" + endpoint if not endpoint.startswith("http") else endpoint + ) self.endpoint = endpoint macaroon = ( @@ -47,14 +55,19 @@ class LndRestWallet(Wallet): return StatusResponse(None, int(data["balance"]) * 1000) def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: data: Dict = { "value": amount, "private": True, } if description_hash: - data["description_hash"] = base64.b64encode(description_hash).decode("ascii") + data["description_hash"] = base64.b64encode(description_hash).decode( + "ascii" + ) else: data["memo"] = memo or "" @@ -131,7 +144,12 @@ class LndRestWallet(Wallet): # check payment.status: # https://api.lightning.community/rest/index.html?python#peersynctype - statuses = {"UNKNOWN": None, "IN_FLIGHT": None, "SUCCEEDED": True, "FAILED": False} + statuses = { + "UNKNOWN": None, + "IN_FLIGHT": None, + "SUCCEEDED": True, + "FAILED": False, + } # for some reason our checking_ids are in base64 but the payment hashes # returned here are in hex, lnd is weird diff --git a/lnbits/wallets/lnpay.py b/lnbits/wallets/lnpay.py index 9951e4ec..4309b46e 100644 --- a/lnbits/wallets/lnpay.py +++ b/lnbits/wallets/lnpay.py @@ -6,7 +6,13 @@ from http import HTTPStatus from typing import Optional, Dict, AsyncGenerator from quart import request -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, +) class LNPayWallet(Wallet): @@ -31,7 +37,8 @@ class LNPayWallet(Wallet): data = r.json() if data["statusType"]["name"] != "active": return StatusResponse( - f"Wallet {data['user_label']} (data['id']) not active, but {data['statusType']['name']}", 0 + f"Wallet {data['user_label']} (data['id']) not active, but {data['statusType']['name']}", + 0, ) return StatusResponse(None, data["balance"] * 1000) @@ -78,7 +85,9 @@ class LNPayWallet(Wallet): try: data = r.json() except: - return PaymentResponse(False, None, 0, None, f"Got invalid JSON: {r.text[:200]}") + return PaymentResponse( + False, None, 0, None, f"Got invalid JSON: {r.text[:200]}" + ) if r.is_error: return PaymentResponse(False, None, 0, None, data["message"]) @@ -115,7 +124,11 @@ class LNPayWallet(Wallet): except json.decoder.JSONDecodeError: print(f"got something wrong on lnpay webhook endpoint: {text[:200]}") data = None - if type(data) is not dict or "event" not in data or data["event"].get("name") != "wallet_receive": + if ( + type(data) is not dict + or "event" not in data + or data["event"].get("name") != "wallet_receive" + ): return "", HTTPStatus.NO_CONTENT lntx_id = data["data"]["wtx"]["lnTx"]["id"] diff --git a/lnbits/wallets/lntxbot.py b/lnbits/wallets/lntxbot.py index bd3be475..d12766fc 100644 --- a/lnbits/wallets/lntxbot.py +++ b/lnbits/wallets/lntxbot.py @@ -4,7 +4,13 @@ import httpx from os import getenv from typing import Optional, Dict, AsyncGenerator -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, +) class LntxbotWallet(Wallet): @@ -14,7 +20,11 @@ class LntxbotWallet(Wallet): endpoint = getenv("LNTXBOT_API_ENDPOINT") self.endpoint = endpoint[:-1] if endpoint.endswith("/") else endpoint - key = getenv("LNTXBOT_KEY") or getenv("LNTXBOT_ADMIN_KEY") or getenv("LNTXBOT_INVOICE_KEY") + key = ( + getenv("LNTXBOT_KEY") + or getenv("LNTXBOT_ADMIN_KEY") + or getenv("LNTXBOT_INVOICE_KEY") + ) self.auth = {"Authorization": f"Basic {key}"} def status(self) -> StatusResponse: @@ -26,7 +36,9 @@ class LntxbotWallet(Wallet): try: data = r.json() except: - return StatusResponse(f"Failed to connect to {self.endpoint}, got: '{r.text[:200]}...'", 0) + return StatusResponse( + f"Failed to connect to {self.endpoint}, got: '{r.text[:200]}...'", 0 + ) if data.get("error"): return StatusResponse(data["message"], 0) @@ -34,7 +46,10 @@ class LntxbotWallet(Wallet): return StatusResponse(None, data["BTC"]["AvailableBalance"] * 1000) def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: data: Dict = {"amt": str(amount)} if description_hash: diff --git a/lnbits/wallets/opennode.py b/lnbits/wallets/opennode.py index 97b395d0..56db598a 100644 --- a/lnbits/wallets/opennode.py +++ b/lnbits/wallets/opennode.py @@ -7,7 +7,14 @@ from os import getenv from typing import Optional, AsyncGenerator from quart import request, url_for -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet, Unsupported +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, + Unsupported, +) class OpenNodeWallet(Wallet): @@ -17,7 +24,11 @@ class OpenNodeWallet(Wallet): endpoint = getenv("OPENNODE_API_ENDPOINT") self.endpoint = endpoint[:-1] if endpoint.endswith("/") else endpoint - key = getenv("OPENNODE_KEY") or getenv("OPENNODE_ADMIN_KEY") or getenv("OPENNODE_INVOICE_KEY") + key = ( + getenv("OPENNODE_KEY") + or getenv("OPENNODE_ADMIN_KEY") + or getenv("OPENNODE_INVOICE_KEY") + ) self.auth = {"Authorization": key} def status(self) -> StatusResponse: @@ -37,7 +48,10 @@ class OpenNodeWallet(Wallet): return StatusResponse(None, data["balance"]["BTC"] / 100_000_000_000) def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: if description_hash: raise Unsupported("description_hash") @@ -93,7 +107,13 @@ class OpenNodeWallet(Wallet): if r.is_error: return PaymentStatus(None) - statuses = {"initial": None, "pending": None, "confirmed": True, "error": False, "failed": False} + statuses = { + "initial": None, + "pending": None, + "confirmed": True, + "error": False, + "failed": False, + } return PaymentStatus(statuses[r.json()["data"]["status"]]) async def paid_invoices_stream(self) -> AsyncGenerator[str, None]: diff --git a/lnbits/wallets/spark.py b/lnbits/wallets/spark.py index 58bd39bd..715cc0c9 100644 --- a/lnbits/wallets/spark.py +++ b/lnbits/wallets/spark.py @@ -5,7 +5,13 @@ import httpx from os import getenv from typing import Optional, AsyncGenerator -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, +) class SparkError(Exception): @@ -24,7 +30,9 @@ class SparkWallet(Wallet): def __getattr__(self, key): def call(*args, **kwargs): if args and kwargs: - raise TypeError(f"must supply either named arguments or a list of arguments, not both: {args} {kwargs}") + raise TypeError( + f"must supply either named arguments or a list of arguments, not both: {args} {kwargs}" + ) elif args: params = args elif kwargs: @@ -67,7 +75,10 @@ class SparkWallet(Wallet): ) def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: label = "lbs{}".format(random.random()) checking_id = label @@ -81,7 +92,10 @@ class SparkWallet(Wallet): ) else: r = self.invoice( - msatoshi=amount * 1000, label=label, description=memo or "", exposeprivatechannels=True + msatoshi=amount * 1000, + label=label, + description=memo or "", + exposeprivatechannels=True, ) ok, payment_request, error_message = True, r["bolt11"], "" except (SparkError, UnknownError) as e: diff --git a/lnbits/wallets/void.py b/lnbits/wallets/void.py index b6617363..a3c2a982 100644 --- a/lnbits/wallets/void.py +++ b/lnbits/wallets/void.py @@ -1,11 +1,21 @@ from typing import Optional, AsyncGenerator -from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet, Unsupported +from .base import ( + StatusResponse, + InvoiceResponse, + PaymentResponse, + PaymentStatus, + Wallet, + Unsupported, +) class VoidWallet(Wallet): def create_invoice( - self, amount: int, memo: Optional[str] = None, description_hash: Optional[bytes] = None + self, + amount: int, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, ) -> InvoiceResponse: raise Unsupported("") diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 55ec8d78..00000000 --- a/pyproject.toml +++ /dev/null @@ -1,2 +0,0 @@ -[tool.black] -line-length = 120