diff --git a/lnbits/extensions/copilot/lnurl.py b/lnbits/extensions/copilot/lnurl.py index 1ab8eec4..ee5d0166 100644 --- a/lnbits/extensions/copilot/lnurl.py +++ b/lnbits/extensions/copilot/lnurl.py @@ -9,19 +9,19 @@ from . import copilot_ext from .crud import get_copilot -@copilot_ext.route("/lnurl/", methods=["GET"]) -async def lnurl_response(copilot_id): - copilot = await get_copilot(copilot_id) - if not copilot: +@copilot_ext.route("/lnurl/", methods=["GET"]) +async def lnurl_response(cp_id): + cp = await get_copilot(cp_id) + if not cp: return jsonify({"status": "ERROR", "reason": "Copilot not found."}) resp = LnurlPayResponse( callback=url_for( - "copilot.lnurl_callback", _external=True + "copilot.lnurl_callback", track_id=track.id, _external=True ), - min_sendable=copilot.amount, - max_sendable=copilot.amount, - metadata=copilot.lnurl_title, + min_sendable=10, + max_sendable=50000, + metadata=await cp.lnurl_title, ) params = resp.dict() @@ -30,24 +30,27 @@ async def lnurl_response(copilot_id): return jsonify(params) -@copilot_ext.route("/lnurl/cb", methods=["GET"]) -async def lnurl_callback(): +@copilot_ext.route("/lnurl/cb/", methods=["GET"]) +async def lnurl_callback(cp_id): + cp = await get_copilot(cp_id) + if not cp: + return jsonify({"status": "ERROR", "reason": "Copilot not found."}) amount_received = int(request.args.get("amount")) - if amount_received < track.amount: + if amount_received < 10: return ( jsonify( LnurlErrorResponse( - reason=f"Amount {round(amount_received / 1000)} is smaller than minimum {math.floor(track.min_sendable)}." + reason=f"Amount {round(amount_received / 1000)} is smaller than minimum 10 sats." ).dict() ), ) - elif track.max_sendable < amount_received: + elif 50000 > amount_received/1000: return ( jsonify( LnurlErrorResponse( - reason=f"Amount {round(amount_received / 1000)} is greater than maximum {math.floor(track.max_sendable)}." + reason=f"Amount {round(amount_received / 1000)} is greater than maximum 50000." ).dict() ), ) @@ -60,21 +63,19 @@ async def lnurl_callback(): ).dict() ) - copilot = await get_copilot_by_track(track_id) - payment_hash, payment_request = await create_invoice( - wallet_id=copilot.wallet, + wallet_id=cp.wallet, amount=int(amount_received / 1000), - memo=await track.fullname(), + memo=cp.lnurl_title, description_hash=hashlib.sha256( - (await track.lnurlpay_metadata()).encode("utf-8") + (cp.lnurl_title).encode("utf-8") ).digest(), - extra={"tag": "copilot", "track": track.id, "comment": comment}, + extra={"tag": "copilot", "comment": comment}, ) if amount_received < track.price_msat: success_action = None - ecopilote: + else: success_action = track.success_action(payment_hash) resp = LnurlPayActionResponse( @@ -82,5 +83,8 @@ async def lnurl_callback(): success_action=success_action, routes=[], ) - - return jsonify(resp.dict()) + socket_sendererer = app.socket_sendererer() + async with socket_sendererer.websocket('/ws') as the_websocket: + await the_websocket.send("pay{payment_hash}") + + return jsonify(resp.dict()) \ No newline at end of file diff --git a/lnbits/extensions/copilot/migrations.py b/lnbits/extensions/copilot/migrations.py index 1bfdbed4..783609e5 100644 --- a/lnbits/extensions/copilot/migrations.py +++ b/lnbits/extensions/copilot/migrations.py @@ -9,6 +9,7 @@ async def m001_initial(db): id TEXT NOT NULL PRIMARY KEY, user TEXT, title TEXT, + wallet TEXT, animation1 TEXT, animation2 TEXT, animation3 TEXT, diff --git a/lnbits/extensions/copilot/models.py b/lnbits/extensions/copilot/models.py index 78c295c9..a49da089 100644 --- a/lnbits/extensions/copilot/models.py +++ b/lnbits/extensions/copilot/models.py @@ -2,11 +2,15 @@ from sqlite3 import Row from typing import NamedTuple import time +from lnurl import Lnurl, encode as lnurl_encode # type: ignore +from lnurl.types import LnurlPayMetadata # type: ignore +from lnurl.models import LnurlPaySuccessAction, UrlAction # type: ignore class Copilots(NamedTuple): id: str user: str title: str + wallet: str animation1: str animation2: str animation3: str @@ -28,3 +32,8 @@ class Copilots(NamedTuple): @classmethod def from_row(cls, row: Row) -> "Copilots": return cls(**dict(row)) + + @property + def lnurl(self) -> Lnurl: + url = url_for("copilots.lnurl_response", ls_id=self.id, _external=True) + return lnurl_encode(url) \ No newline at end of file diff --git a/lnbits/extensions/copilot/templates/copilot/index.html b/lnbits/extensions/copilot/templates/copilot/index.html index ddbb93fb..93203eb2 100644 --- a/lnbits/extensions/copilot/templates/copilot/index.html +++ b/lnbits/extensions/copilot/templates/copilot/index.html @@ -147,6 +147,14 @@ type="text" label="Title" > + @@ -218,6 +226,7 @@ v-model.trim="formDialogCopilot.data.animation2threshold" type="number" label="From *sats" + :rules="[ val <= formDialogCopilot.data.animation1threshold || 'Must be higher than last']" > @@ -226,7 +235,7 @@ filled dense v-model.trim="formDialogCopilot.data.animation2webhook" - type="number" + type="text" label="Webhook" > @@ -262,6 +271,7 @@ v-model.trim="formDialogCopilot.data.animation3threshold" type="number" label="From *sats" + :rules="[ val <= formDialogCopilot.data.animation2threshold || 'Must be higher than last']" > @@ -270,7 +280,7 @@ filled dense v-model.trim="formDialogCopilot.data.animation3webhook" - type="number" + type="text" label="Webhook" > @@ -409,20 +419,14 @@ data: { show_message: false, show_ack: true, - title: '', - animation1threshold: 0, - animation2threshold: 0, - animation3threshold: 0, - animation1webhook: '', - animation2webhook: '', - animation3webhook: '' + title: '' } }, qrCodeDialog: { show: false, data: null }, - options: ['moon_rocket', 'confetti', 'roller_coaster'] + options: ['bitcoin', 'confetti', 'rocket', 'face', 'martijn', 'rick'] } }, methods: { @@ -437,19 +441,15 @@ }, sendFormDataCopilot: function () { var self = this - var wallet = this.g.user.wallets[0].adminkey - var data = this.formDialogCopilot.data - console.log(data) - data.animation1threshold = parseInt(data.animation1threshold) - data.animation1threshold = parseInt(data.animation2threshold) - data.animation1threshold = parseInt(data.animation3threshold) - - this.createCopilot(wallet, data) + console.log(self.formDialogCopilot.data.animation1threshold) + this.createCopilot( + self.g.user.wallets[0].adminkey, + self.formDialogCopilot.data + ) }, createCopilot: function (wallet, data) { var self = this - LNbits.api .request('POST', '/copilot/api/v1/copilot', wallet, data) .then(function (response) { diff --git a/lnbits/extensions/copilot/views_api.py b/lnbits/extensions/copilot/views_api.py index e345e94f..85857809 100644 --- a/lnbits/extensions/copilot/views_api.py +++ b/lnbits/extensions/copilot/views_api.py @@ -24,12 +24,13 @@ from .crud import ( @api_validate_post_request( schema={ "title": {"type": "string", "empty": False, "required": True}, + "wallet": {"type": "string", "empty": False, "required": True}, "animation1": {"type": "string", "required": False}, "animation2": {"type": "string", "required": False}, "animation3": {"type": "string", "required": False}, - "animation1threshold": {"type": "integer", "required": False}, - "animation2threshold": {"type": "integer", "required": False}, - "animation3threshold": {"type": "integer", "required": False}, + "animation1threshold": {"type": "string", "required": False}, + "animation2threshold": {"type": "string", "required": False}, + "animation3threshold": {"type": "string", "required": False}, "animation1webhook": {"type": "string", "required": False}, "animation2webhook": {"type": "string", "required": False}, "animation3webhook": {"type": "string", "required": False},