Merge pull request #295 from lnbits/lnticketsflat

Returns lnticket to polling, until listeners are properly tested, and adds a flat rate
This commit is contained in:
Arc 2021-08-16 07:24:18 +01:00 committed by GitHub
commit 1359c1ee39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 160 additions and 71 deletions

View File

@ -49,7 +49,7 @@ async def set_ticket_paid(payment_hash: str) -> Tickets:
amount = formdata.amountmade + row[7]
await db.execute(
"""
UPDATE lnticket.form
UPDATE lnticket.forms
SET amountmade = ?
WHERE id = ?
""",
@ -108,34 +108,35 @@ async def create_form(
name: str,
webhook: Optional[str] = None,
description: str,
costpword: int,
amount: int,
flatrate: int,
) -> Forms:
form_id = urlsafe_short_hash()
await db.execute(
"""
INSERT INTO lnticket.form (id, wallet, name, webhook, description, costpword, amountmade)
VALUES (?, ?, ?, ?, ?, ?, ?)
INSERT INTO lnticket.forms (id, wallet, name, webhook, description, flatrate, amount, amountmade)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""",
(form_id, wallet, name, webhook, description, costpword, 0),
(form_id, wallet, name, webhook, description, flatrate, amount, 0),
)
form = await get_form(form_id)
assert form, "Newly created form couldn't be retrieved"
assert form, "Newly created forms couldn't be retrieved"
return form
async def update_form(form_id: str, **kwargs) -> Forms:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(
f"UPDATE lnticket.form SET {q} WHERE id = ?", (*kwargs.values(), form_id)
f"UPDATE lnticket.forms SET {q} WHERE id = ?", (*kwargs.values(), form_id)
)
row = await db.fetchone("SELECT * FROM lnticket.form WHERE id = ?", (form_id,))
row = await db.fetchone("SELECT * FROM lnticket.forms WHERE id = ?", (form_id,))
assert row, "Newly updated form couldn't be retrieved"
return Forms(**row)
async def get_form(form_id: str) -> Optional[Forms]:
row = await db.fetchone("SELECT * FROM lnticket.form WHERE id = ?", (form_id,))
row = await db.fetchone("SELECT * FROM lnticket.forms WHERE id = ?", (form_id,))
return Forms(**row) if row else None
@ -145,11 +146,11 @@ async def get_forms(wallet_ids: Union[str, List[str]]) -> List[Forms]:
q = ",".join(["?"] * len(wallet_ids))
rows = await db.fetchall(
f"SELECT * FROM lnticket.form WHERE wallet IN ({q})", (*wallet_ids,)
f"SELECT * FROM lnticket.forms WHERE wallet IN ({q})", (*wallet_ids,)
)
return [Forms(**row) for row in rows]
async def delete_form(form_id: str) -> None:
await db.execute("DELETE FROM lnticket.form WHERE id = ?", (form_id,))
await db.execute("DELETE FROM lnticket.forms WHERE id = ?", (form_id,))

View File

@ -145,3 +145,58 @@ async def m003_changed(db):
),
)
await db.execute("DROP TABLE lnticket.forms")
async def m004_changed(db):
await db.execute(
"""
CREATE TABLE lnticket.forms (
id TEXT PRIMARY KEY,
wallet TEXT NOT NULL,
name TEXT NOT NULL,
webhook TEXT,
description TEXT NOT NULL,
flatrate INTEGER DEFAULT 0,
amount INTEGER NOT NULL,
amountmade INTEGER NOT NULL,
time TIMESTAMP NOT NULL DEFAULT """
+ db.timestamp_now
+ """
);
"""
)
for row in [list(row) for row in await db.fetchall("SELECT * FROM lnticket.form")]:
usescsv = ""
for i in range(row[5]):
if row[7]:
usescsv += "," + str(i + 1)
else:
usescsv += "," + str(1)
usescsv = usescsv[1:]
await db.execute(
"""
INSERT INTO lnticket.forms (
id,
wallet,
name,
webhook,
description,
amount,
amountmade,
)
VALUES (?, ?, ?, ?, ?, ?, ?)
""",
(
row[0],
row[1],
row[2],
row[3],
row[4],
row[5],
row[6],
),
)
await db.execute("DROP TABLE lnticket.form")

View File

@ -7,7 +7,8 @@ class Forms(NamedTuple):
name: str
webhook: str
description: str
costpword: int
amount: int
flatrate: int
amountmade: int
time: int

View File

@ -23,11 +23,20 @@
label="Your email (optional, if you want a reply)"
></q-input>
<q-input
v-if="flatrate"
filled
dense
v-model.number="formDialog.data.text"
type="textarea"
label="{{ form_costpword }} sats per word"
label="{{ form_amount }} sats"
></q-input>
<q-input
v-else
filled
dense
v-model.number="formDialog.data.text"
type="textarea"
label="{{ form_amount }} sats per word"
></q-input>
<p>{% raw %}{{amountWords}}{% endraw %}</p>
<div class="row q-mt-lg">
@ -87,13 +96,16 @@
return {
paymentReq: null,
redirectUrl: null,
flatrate: parseInt('{{form_flatrate}}'),
formDialog: {
show: false,
data: {
name: '',
email: '',
text: ''
}
},
dismissMsg: null,
paymentChecker: null
},
receive: {
show: false,
@ -108,21 +120,24 @@
},
computed: {
amountWords() {
var regex = /\s+/gi
var nwords = this.formDialog.data.text
.trim()
.replace(regex, ' ')
.split(' ').length
var sats = nwords * parseInt('{{ form_costpword }}')
if (sats === parseInt('{{ form_costpword }}')) {
if (this.formDialog.data.text.length == '') {
return '0 Sats to pay'
} else {
var regex = /\s+/gi
var nwords = this.formDialog.data.text
.trim()
.replace(regex, ' ')
.split(' ').length
if (this.flatrate) {
var sats = parseInt('{{ form_amount }}')
} else {
var sats = nwords * parseInt('{{ form_amount }}')
}
this.formDialog.data.sats = sats
return sats + ' Sats to pay'
}
}
},
methods: {
resetForm: function (e) {
e.preventDefault()
@ -130,39 +145,9 @@
this.formDialog.data.email = ''
this.formDialog.data.text = ''
},
closeReceiveDialog: function () {
var checker = this.startPaymentNotifier
dismissMsg()
setTimeout(function () {}, 10000)
},
startPaymentNotifier() {
this.cancelListener()
this.cancelListener = LNbits.events.onInvoicePaid(
this.wallet,
payment => {
this.receive = {
show: false,
status: 'complete',
paymentReq: null
}
dismissMsg()
this.formDialog.data.name = ''
this.formDialog.data.email = ''
this.formDialog.data.text = ''
this.$q.notify({
type: 'positive',
message: 'Sent, thank you!',
icon: 'thumb_up'
})
}
)
},
Invoice: function () {
var self = this
var dialog = this.formDialog
axios
.post('/lnticket/api/v1/tickets/{{ form_id }}', {
form: '{{ form_id }}',
@ -175,16 +160,34 @@
self.paymentReq = response.data.payment_request
self.paymentCheck = response.data.payment_hash
dismissMsg = self.$q.notify({
dialog.dismissMsg = self.$q.notify({
timeout: 0,
message: 'Waiting for payment...'
})
self.receive = {
show: true,
status: 'pending',
paymentReq: self.paymentReq
}
dialog.paymentChecker = setInterval(function () {
axios
.get('/lnticket/api/v1/tickets/' + response.data.payment_hash)
.then(function (res) {
if (res.data.paid) {
clearInterval(dialog.paymentChecker)
dialog.dismissMsg()
self.receive.show = false
self.formDialog.data.name = ''
self.formDialog.data.email = ''
self.formDialog.data.text = ''
self.$q.notify({
type: 'positive',
message: 'Sats received, thanks!',
icon: 'thumb_up'
})
}
})
}, 2000)
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
@ -193,7 +196,6 @@
},
created() {
this.wallet.inkey = '{{form_wallet}}'
this.startPaymentNotifier()
}
})
</script>

View File

@ -206,13 +206,25 @@
type="textarea"
label="Description "
></q-input>
<q-input
filled
dense
v-model.number="formDialog.data.costpword"
type="number"
label="Amount per word"
></q-input>
<div class="row">
<div class="col-5">
<q-toggle
:label="`${flatRate}`"
color="primary"
v-model="formDialog.data.flatrate"
></q-toggle>
</div>
<div class="col-7">
<q-input
filled
dense
v-model.number="formDialog.data.amount"
type="number"
label="Amount"
></q-input>
</div>
</div>
<div class="row q-mt-lg">
<q-btn
v-if="formDialog.data.id"
@ -226,7 +238,7 @@
v-else
unelevated
color="primary"
:disable="formDialog.data.costpword == null || formDialog.data.costpword < 0 || formDialog.data.name == null"
:disable="formDialog.data.amount == null || formDialog.data.amount < 0 || formDialog.data.name == null"
type="submit"
>Create Form</q-btn
>
@ -275,10 +287,16 @@
field: 'description'
},
{
name: 'costpword',
name: 'flatrate',
align: 'left',
label: 'Cost Per Word',
field: 'costpword'
label: 'Flat Rate',
field: 'flatrate'
},
{
name: 'amount',
align: 'left',
label: 'Amount',
field: 'amount'
}
],
pagination: {
@ -299,11 +317,20 @@
},
formDialog: {
show: false,
data: {}
data: {flatrate: false}
},
cancelListener: () => {}
}
},
computed: {
flatRate: function () {
if (this.formDialog.data.flatrate) {
return 'Charge flat rate'
} else {
return 'Charge per word'
}
}
},
methods: {
getTickets: function () {
var self = this
@ -400,7 +427,8 @@
this.formDialog.data.wallet = link.wallet
this.formDialog.data.name = link.name
this.formDialog.data.description = link.description
this.formDialog.data.costpword = link.costpword
this.formDialog.data.flatrate = link.flatrate
this.formDialog.data.amount = link.amount
this.formDialog.show = true
},
updateForm: function (wallet, data) {

View File

@ -28,6 +28,7 @@ async def display(form_id):
form_id=form.id,
form_name=form.name,
form_desc=form.description,
form_costpword=form.costpword,
form_amount=form.amount,
form_flatrate=form.flatrate,
form_wallet=wallet.inkey,
)

View File

@ -47,7 +47,8 @@ async def api_forms():
"name": {"type": "string", "empty": False, "required": True},
"webhook": {"type": "string", "empty": False, "required": False},
"description": {"type": "string", "min": 0, "required": True},
"costpword": {"type": "integer", "min": 0, "required": True},
"amount": {"type": "integer", "min": 0, "required": True},
"flatrate": {"type": "integer", "required": True},
}
)
async def api_form_create(form_id=None):