From 3aa4875558edb1987ea9f8c9c61f395575327a16 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 17 Mar 2023 15:06:09 +0200 Subject: [PATCH 01/38] chore: code format --- __init__.py | 11 +++++------ helpers.py | 2 +- views_api.py | 7 ++++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/__init__.py b/__init__.py index 97dc8bd..12154d0 100644 --- a/__init__.py +++ b/__init__.py @@ -21,17 +21,16 @@ nostrrelay_static_files = [ ] nostrrelay_redirect_paths = [ - { - "from_path": "/", - "redirect_to_path": "/api/v1/relay-info", - "header_filters": { - "accept": "application/nostr+json" + { + "from_path": "/", + "redirect_to_path": "/api/v1/relay-info", + "header_filters": {"accept": "application/nostr+json"}, } - } ] scheduled_tasks: List[asyncio.Task] = [] + def nostrrelay_renderer(): return template_renderer(["lnbits/extensions/nostrrelay/templates"]) diff --git a/helpers.py b/helpers.py index 169c65c..5466e70 100644 --- a/helpers.py +++ b/helpers.py @@ -34,4 +34,4 @@ def relay_info_response(relay_public_data: dict) -> JSONResponse: "Access-Control-Allow-Headers": "*", "Access-Control-Allow-Methods": "GET", }, - ) \ No newline at end of file + ) diff --git a/views_api.py b/views_api.py index 347b197..9c6557f 100644 --- a/views_api.py +++ b/views_api.py @@ -121,7 +121,7 @@ async def api_toggle_relay( ) -> NostrRelay: try: - relay = await get_relay(wallet.wallet.user,relay_id) + relay = await get_relay(wallet.wallet.user, relay_id) if not relay: raise HTTPException( status_code=HTTPStatus.NOT_FOUND, @@ -159,12 +159,13 @@ async def api_get_relays( status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Cannot fetch relays", ) + + @nostrrelay_ext.get("/api/v1/relay-info") async def api_get_relay_info() -> JSONResponse: return relay_info_response(NostrRelay.info()) - @nostrrelay_ext.get("/api/v1/relay/{relay_id}") async def api_get_relay( relay_id: str, wallet: WalletTypeInfo = Depends(require_invoice_key) @@ -288,7 +289,7 @@ async def api_pay_to_join(data: BuyOrder): if data.action == "join": if relay.is_free_to_join: raise ValueError("Relay is free to join") - amount = int(relay.config.cost_to_join) + amount = int(relay.config.cost_to_join) elif data.action == "storage": if relay.config.storage_cost_value == 0: raise ValueError("Relay storage cost is zero. Cannot buy!") From 527afa0c8cfa73fea3c8d9073d83ba2a12b18b5f Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 17 Mar 2023 15:06:59 +0200 Subject: [PATCH 02/38] feat: wait for paid invoce --- tasks.py | 25 +++++++++++++----- templates/nostrrelay/public.html | 44 ++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/tasks.py b/tasks.py index 87b8eed..8b37e1f 100644 --- a/tasks.py +++ b/tasks.py @@ -1,8 +1,10 @@ import asyncio +import json from loguru import logger from lnbits.core.models import Payment +from lnbits.core.services import websocketUpdater from lnbits.helpers import get_current_extension_name from lnbits.tasks import register_invoice_listener @@ -25,27 +27,36 @@ async def on_invoice_paid(payment: Payment): relay_id = payment.extra.get("relay_id") pubkey = payment.extra.get("pubkey") + hash = payment.payment_hash if not relay_id or not pubkey: - logger.warning( - f"Invoice extra data missing for 'relay_id' and 'pubkey'. Payment hash: {payment.payment_hash}" - ) + message = f"Invoice extra data missing for 'relay_id' and 'pubkey'. Payment hash: {hash}" + logger.warning(message) + await websocketUpdater(hash, json.dumps({"success": False, "message": message})) return - if payment.extra.get("action") == "join": + action = payment.extra.get("action") + if action == "join": await invoice_paid_to_join(relay_id, pubkey, payment.amount) + await websocketUpdater(hash, json.dumps({"success": True})) return - if payment.extra.get("action") == "storage": + if action == "storage": storage_to_buy = payment.extra.get("storage_to_buy") if not storage_to_buy: - logger.warning( - f"Invoice extra data missing for 'storage_to_buy'. Payment hash: {payment.payment_hash}" + message = ( + f"Invoice extra data missing for 'storage_to_buy'. Payment hash: {hash}" ) + logger.warning(message) return await invoice_paid_for_storage(relay_id, pubkey, storage_to_buy, payment.amount) + await websocketUpdater(hash, json.dumps({"success": True})) return + await websocketUpdater( + hash, json.dumps({"success": False, "message": f"Bad action name: '{action}'"}) + ) + async def invoice_paid_to_join(relay_id: str, pubkey: str, amount: int): try: diff --git a/templates/nostrrelay/public.html b/templates/nostrrelay/public.html index 7334568..9d4a9a0 100644 --- a/templates/nostrrelay/public.html +++ b/templates/nostrrelay/public.html @@ -144,8 +144,9 @@ - + + +
+
+
+ + +
+
+
+
@@ -192,6 +207,7 @@ relay: JSON.parse('{{relay | tojson | safe}}'), pubkey: '', invoice: '', + invoiceResponse: null, unitsToBuy: 0 } }, @@ -210,7 +226,6 @@ }, methods: { createInvoice: async function (action) { - console.log('### action', action) if (!action) return this.invoice = '' if (!this.pubkey) { @@ -235,9 +250,34 @@ reqData ) this.invoice = data.invoice + const paymentHashTag = decode(data.invoice).data.tags.find( + t => t.description === 'payment_hash' + ) + if (paymentHashTag) { + await this.waitForPaidInvoice(paymentHashTag.value) + } } catch (error) { LNbits.utils.notifyApiError(error) } + }, + waitForPaidInvoice: function (paymentHash) { + try { + const scheme = location.protocol === 'http:' ? 'ws' : 'wss' + const wsUrl = `${scheme}://${document.domain}:${location.port}/api/v1/ws/${paymentHash}` + const wsConnection = new WebSocket(wsUrl) + wsConnection.onmessage = e => { + this.invoiceResponse = JSON.parse(e.data) + this.invoice = null + wsConnection.close() + } + } catch (error) { + this.$q.notify({ + timeout: 5000, + type: 'warning', + message: 'Failed to get invoice status', + caption: `${error}` + }) + } } }, created: function () {} From 28c0947afb78cc6a04a88588ff72a87806ef0b0d Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 17 Mar 2023 15:24:17 +0200 Subject: [PATCH 03/38] fix: invoice can have `undefined` tag --- templates/nostrrelay/public.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/nostrrelay/public.html b/templates/nostrrelay/public.html index 9d4a9a0..53eed80 100644 --- a/templates/nostrrelay/public.html +++ b/templates/nostrrelay/public.html @@ -251,7 +251,7 @@ ) this.invoice = data.invoice const paymentHashTag = decode(data.invoice).data.tags.find( - t => t.description === 'payment_hash' + t => t && t.description === 'payment_hash' ) if (paymentHashTag) { await this.waitForPaidInvoice(paymentHashTag.value) From f7fb926c5223b23d26efb4674dedddeee0fea71a Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 17 Mar 2023 17:24:33 +0200 Subject: [PATCH 04/38] fix: port value --- templates/nostrrelay/public.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/nostrrelay/public.html b/templates/nostrrelay/public.html index 53eed80..98487c5 100644 --- a/templates/nostrrelay/public.html +++ b/templates/nostrrelay/public.html @@ -263,7 +263,8 @@ waitForPaidInvoice: function (paymentHash) { try { const scheme = location.protocol === 'http:' ? 'ws' : 'wss' - const wsUrl = `${scheme}://${document.domain}:${location.port}/api/v1/ws/${paymentHash}` + const port = location.port ? `:${location.port}` : '' + const wsUrl = `${scheme}://${document.domain}${port}/api/v1/ws/${paymentHash}` const wsConnection = new WebSocket(wsUrl) wsConnection.onmessage = e => { this.invoiceResponse = JSON.parse(e.data) From f19fb4a18e42eed48bb7f1ff608fedb5a898ebf4 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 6 Apr 2023 16:59:15 +0300 Subject: [PATCH 05/38] fix: delete account --- crud.py | 10 ++++++ .../relay-details/relay-details.html | 18 +++++++--- .../components/relay-details/relay-details.js | 33 +++++++++++++++++++ views_api.py | 28 ++++++++++++++++ 4 files changed, 85 insertions(+), 4 deletions(-) diff --git a/crud.py b/crud.py index 1f965b1..926cedf 100644 --- a/crud.py +++ b/crud.py @@ -363,6 +363,16 @@ async def update_account(relay_id: str, a: NostrAccount) -> NostrAccount: return a +async def delete_account(relay_id: str, pubkey: str): + await db.execute( + """ + DELETE FROM nostrrelay.accounts + WHERE relay_id = ? AND pubkey = ? + """, + (relay_id, pubkey), + ) + + async def get_account( relay_id: str, pubkey: str, diff --git a/static/components/relay-details/relay-details.html b/static/components/relay-details/relay-details.html index a4e58cc..8896a0d 100644 --- a/static/components/relay-details/relay-details.html +++ b/static/components/relay-details/relay-details.html @@ -545,7 +545,7 @@ >
Public Key:
-
+
Allow
-
+
Block @@ -613,6 +613,16 @@ >