Should be working

Need to check lnurl logic, and debug
This commit is contained in:
Ben Arc 2021-04-15 09:39:27 +01:00
parent 34d659f9f3
commit 1af84b2b3d
8 changed files with 227 additions and 260 deletions

View file

@ -15,7 +15,8 @@ from quart import jsonify
async def create_copilot( async def create_copilot(
title: str, title: str,
user: str, user: str,
wallet: str, lnurl_toggle: str,
wallet: Optional[str] = None,
animation1: Optional[str] = None, animation1: Optional[str] = None,
animation2: Optional[str] = None, animation2: Optional[str] = None,
animation3: Optional[str] = None, animation3: Optional[str] = None,
@ -37,6 +38,7 @@ async def create_copilot(
INSERT INTO copilots ( INSERT INTO copilots (
id, id,
user, user,
lnurl_toggle,
wallet, wallet,
title, title,
animation1, animation1,
@ -54,11 +56,12 @@ async def create_copilot(
lnurl_title, lnurl_title,
amount_made amount_made
) )
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", """,
( (
copilot_id, copilot_id,
user, user,
lnurl_toggle,
wallet, wallet,
title, title,
animation1, animation1,

View file

@ -67,6 +67,7 @@ async def lnurl_callback(cp_id):
wallet_id=cp.wallet, wallet_id=cp.wallet,
amount=int(amount_received / 1000), amount=int(amount_received / 1000),
memo=cp.lnurl_title, memo=cp.lnurl_title,
webhook="/copilot/api/v1/copilot/hook/" + cp_id,
description_hash=hashlib.sha256( description_hash=hashlib.sha256(
(cp.lnurl_title).encode("utf-8") (cp.lnurl_title).encode("utf-8")
).digest(), ).digest(),
@ -83,8 +84,5 @@ async def lnurl_callback(cp_id):
success_action=success_action, success_action=success_action,
routes=[], routes=[],
) )
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()) return jsonify(resp.dict())

View file

@ -9,6 +9,7 @@ async def m001_initial(db):
id TEXT NOT NULL PRIMARY KEY, id TEXT NOT NULL PRIMARY KEY,
user TEXT, user TEXT,
title TEXT, title TEXT,
lnurl_toggle INTEGER,
wallet TEXT, wallet TEXT,
animation1 TEXT, animation1 TEXT,
animation2 TEXT, animation2 TEXT,

View file

@ -10,6 +10,7 @@ class Copilots(NamedTuple):
id: str id: str
user: str user: str
title: str title: str
lnurl_toggle: str
wallet: str wallet: str
animation1: str animation1: str
animation2: str animation2: str

View file

@ -16,6 +16,7 @@
<img src="" style="width: 100%" id="animations" class="fixed-bottom-left" /> <img src="" style="width: 100%" id="animations" class="fixed-bottom-left" />
<qrcode <qrcode
v-if="'{{ lnurl_toggle }}' == 'True'"
style="width: 20%; z-index: 9999" style="width: 20%; z-index: 9999"
:value="'{{ lnurl }}'" :value="'{{ lnurl }}'"
:options="{width:222}" :options="{width:222}"
@ -79,80 +80,6 @@
self.connection.send('') self.connection.send('')
}, 1000) }, 1000)
}, 2000) }, 2000)
},
reconnect: function () {
this.connection.addEventListener('open', function (event) {
this.connection.send('')
})
this.connection.addEventListener('message', function (event) {
res = event.data.split('-')
console.log(res[1])
if (res[0] != this.oldRes) {
this.oldRes = res[0]
if (res[1] == 'rocket') {
document.getElementById('animations').style.width = '50%'
document.getElementById('animations').src =
'/copilot/static/rocket.gif'
setTimeout(function () {
document.getElementById('animations').src = ''
}, 5000)
}
if (res[1] == 'face') {
document.getElementById('animations').style.width = '50%'
document.getElementById('animations').src =
'/copilot/static/face.gif'
setTimeout(function () {
document.getElementById('animations').src = ''
}, 5000)
}
if (res[1] == 'bitcoin') {
document.getElementById('animations').style.width = '30%'
document.getElementById('animations').src =
'/copilot/static/bitcoin.gif'
setTimeout(function () {
document.getElementById('animations').src = ''
}, 5000)
}
if (res[1] == 'confetti') {
document.getElementById('animations').style.width = '100%'
document.getElementById('animations').src =
'/copilot/static/confetti.gif'
setTimeout(function () {
document.getElementById('animations').src = ''
}, 5000)
}
if (res[1] == 'martijn') {
document.getElementById('animations').style.width = '50%'
document.getElementById('animations').src =
'/copilot/static/martijn.gif'
setTimeout(function () {
document.getElementById('animations').src = ''
}, 5000)
}
if (res[1] == 'rick') {
document.getElementById('animations').style.width = '50%'
document.getElementById('animations').src =
'/copilot/static/rick.gif'
setTimeout(function () {
document.getElementById('animations').src = ''
}, 5000)
}
if (res[1] == 'true') {
document.getElementById('videoElement').style.width = '20%'
}
if (res[1] == 'false') {
document.getElementById('videoElement').style.width = '100%'
}
if (res[1].substring(0, 3) == 'htt') {
document.getElementById('iframe_main').src = res[1]
}
}
})
this.connection.addEventListener('close', function (event) {
console.log('The connection has been closed')
})
} }
}, },
mounted() { mounted() {

View file

@ -49,8 +49,9 @@
> >
<template v-slot:header="props"> <template v-slot:header="props">
<q-tr :props="props"> <q-tr :props="props">
<q-th auto-width></q-th> <q-th style="width: 5%"></q-th>
<q-th auto-width></q-th> <q-th style="width: 5%"></q-th>
<q-th style="width: 5%"></q-th>
<q-th <q-th
v-for="col in props.cols" v-for="col in props.cols"
@ -147,6 +148,14 @@
type="text" type="text"
label="Title" label="Title"
></q-input> ></q-input>
<div class="row">
<q-checkbox
v-model="formDialogCopilot.data.lnurl_toggle"
label="Include lnurl payment QR? (requires https)"
left-label
></q-checkbox>
</div>
<div v-if="formDialogCopilot.data.lnurl_toggle">
<q-select <q-select
filled filled
dense dense
@ -182,6 +191,7 @@
v-model.trim="formDialogCopilot.data.animation1threshold" v-model.trim="formDialogCopilot.data.animation1threshold"
type="number" type="number"
label="From *sats" label="From *sats"
:min="10"
> >
</q-input> </q-input>
</div> </div>
@ -204,7 +214,7 @@
group="api" group="api"
dense dense
expand-separator expand-separator
label="Payment threshold 2" label="Payment threshold 2 (Must be higher than last)"
> >
<q-card> <q-card>
<q-card-section> <q-card-section>
@ -223,10 +233,10 @@
<q-input <q-input
filled filled
dense dense
v-model.trim="formDialogCopilot.data.animation2threshold" v-model="formDialogCopilot.data.animation2threshold"
type="number" type="number"
label="From *sats" label="From *sats"
:rules="[ val <= formDialogCopilot.data.animation1threshold || 'Must be higher than last']" :min="formDialogCopilot.data.animation1threshold"
> >
</q-input> </q-input>
</div> </div>
@ -249,7 +259,7 @@
group="api" group="api"
dense dense
expand-separator expand-separator
label="Payment threshold 3" label="Payment threshold 3 (Must be higher than last)"
> >
<q-card> <q-card>
<q-card-section> <q-card-section>
@ -268,10 +278,10 @@
<q-input <q-input
filled filled
dense dense
v-model.trim="formDialogCopilot.data.animation3threshold" v-model="formDialogCopilot.data.animation3threshold"
type="number" type="number"
label="From *sats" label="From *sats"
:rules="[ val <= formDialogCopilot.data.animation2threshold || 'Must be higher than last']" :min="formDialogCopilot.data.animation2threshold"
> >
</q-input> </q-input>
</div> </div>
@ -299,26 +309,22 @@
label="Lnurl title (message with QR code)" label="Lnurl title (message with QR code)"
> >
</q-input> </q-input>
<div class="row">
<div class="col">
<div class="q-gutter-sm"> <div class="q-gutter-sm">
<q-checkbox <q-checkbox
v-model="formDialogCopilot.data.show_message" v-model="formDialogCopilot.data.show_message"
left-label left-label
label="Show lnurl-pay messages?" label="Show lnurl-pay messages?"
/> ></q-checkbox>
</div> </div>
</div> </div>
<div class="col q-pl-xs">
<div class="q-gutter-sm"> <div class="q-gutter-sm">
<div class="row">
<q-checkbox <q-checkbox
v-model="formDialogCopilot.data.show_ack" v-model="formDialogCopilot.data.show_ack"
left-label left-label
label="Show 'powered by LNbits'" label="Show 'powered by LNbits'"
/> ></q-checkbox>
</div>
</div> </div>
</div> </div>
@ -393,6 +399,12 @@
label: 'id', label: 'id',
field: 'id' field: 'id'
}, },
{
name: 'lnurl_toggle',
align: 'left',
label: 'Show lnurl pay link',
field: 'lnurl_toggle'
},
{ {
name: 'title', name: 'title',
align: 'left', align: 'left',
@ -417,6 +429,7 @@
formDialogCopilot: { formDialogCopilot: {
show: false, show: false,
data: { data: {
lnurl_toggle: false,
show_message: false, show_message: false,
show_ack: true, show_ack: true,
title: '' title: ''

View file

@ -40,7 +40,9 @@ async def compose(copilot_id):
copilot = await get_copilot(copilot_id) or abort( copilot = await get_copilot(copilot_id) or abort(
HTTPStatus.NOT_FOUND, "Copilot link does not exist." HTTPStatus.NOT_FOUND, "Copilot link does not exist."
) )
return await render_template("copilot/compose.html", copilot=copilot, lnurl=copilot.lnurl) if copilot.lnurl_toggle:
return await render_template("copilot/compose.html", copilot=copilot, lnurl=copilot.lnurl, lnurl_toggle=copilot.lnurl_toggle)
return await render_template("copilot/compose.html", copilot=copilot, lnurl_toggle=copilot.lnurl_toggle)
@copilot_ext.route("/<copilot_id>") @copilot_ext.route("/<copilot_id>")
async def panel(copilot_id): async def panel(copilot_id):

View file

@ -1,5 +1,5 @@
import hashlib import hashlib
from quart import g, jsonify, url_for from quart import g, jsonify, url_for, websocket
from http import HTTPStatus from http import HTTPStatus
import httpx import httpx
@ -26,18 +26,19 @@ from .crud import (
@api_validate_post_request( @api_validate_post_request(
schema={ schema={
"title": {"type": "string", "empty": False, "required": True}, "title": {"type": "string", "empty": False, "required": True},
"wallet": {"type": "string", "empty": False, "required": True}, "lnurl_toggle": {"type": "integer", "empty": False, "required": True},
"wallet": {"type": "string", "empty": False, "required": False},
"animation1": {"type": "string", "required": False}, "animation1": {"type": "string", "required": False},
"animation2": {"type": "string", "required": False}, "animation2": {"type": "string", "required": False},
"animation3": {"type": "string", "required": False}, "animation3": {"type": "string", "required": False},
"animation1threshold": {"type": "string", "required": False}, "animation1threshold": {"type": "integer", "required": False},
"animation2threshold": {"type": "string", "required": False}, "animation2threshold": {"type": "integer", "required": False},
"animation3threshold": {"type": "string", "required": False}, "animation3threshold": {"type": "integer", "required": False},
"animation1webhook": {"type": "string", "required": False}, "animation1webhook": {"type": "string", "required": False},
"animation2webhook": {"type": "string", "required": False}, "animation2webhook": {"type": "string", "required": False},
"animation3webhook": {"type": "string", "required": False}, "animation3webhook": {"type": "string", "required": False},
"lnurl_title": {"type": "string", "empty": False, "required": True}, "lnurl_title": {"type": "string", "empty": False, "required": False},
"show_message": {"type": "integer", "empty": False, "required": True}, "show_message": {"type": "integer", "empty": False, "required": False},
"show_ack": {"type": "integer", "empty": False, "required": True}, "show_ack": {"type": "integer", "empty": False, "required": True},
} }
) )
@ -97,3 +98,24 @@ async def api_copilot_delete(copilot_id):
await delete_copilot(copilot_id) await delete_copilot(copilot_id)
return "", HTTPStatus.NO_CONTENT return "", HTTPStatus.NO_CONTENT
#############################PAYMENTHOOK##########################
@copilot_ext.route("/api/v1/copilot/hook/<copilot_id>", methods=["POST"])
async def api_copilot_delete(copilot_id, trigger):
copilot = await get_copilot(copilot_id)
if not copilot:
return jsonify({"message": "Copilot link link does not exist."}), HTTPStatus.NOT_FOUND
socket_sendererer = app.socket_sendererer()
if copilot.animation1threshold and g.data['amount'] > copilot.animation1threshold:
data = copilot.animation1
if copilot.animation2threshold and g.data['amount'] > copilot.animation2threshold:
data = copilot.animation2
if copilot.animation3threshold and g.data['amount'] > copilot.animation3threshold:
data = copilot.animation3
async with socket_sendererer.websocket('/ws/compose/' + copilot_id) as the_websocket:
await the_websocket.send(data)
return "", HTTPStatus.OK