diff --git a/.env.example b/.env.example index a05683ff..1c6a446f 100644 --- a/.env.example +++ b/.env.example @@ -44,7 +44,9 @@ LND_REST_MACAROON="HEXSTRING" # LNPayWallet LNPAY_API_ENDPOINT=https://api.lnpay.co/v1/ +# Secret API Key under developers tab LNPAY_API_KEY=LNPAY_API_KEY +# Wallet Admin in Wallet Access Keys LNPAY_WALLET_KEY=LNPAY_ADMIN_KEY # LntxbotWallet diff --git a/lnbits/core/__init__.py b/lnbits/core/__init__.py index ca0959a8..12dcded8 100644 --- a/lnbits/core/__init__.py +++ b/lnbits/core/__init__.py @@ -14,6 +14,7 @@ core_app: Blueprint = Blueprint( from .views.api import * # noqa from .views.generic import * # noqa +from .views.public_api import * # noqa from .tasks import register_listeners from lnbits.tasks import record_async diff --git a/lnbits/core/tasks.py b/lnbits/core/tasks.py index 20740c05..3a296e66 100644 --- a/lnbits/core/tasks.py +++ b/lnbits/core/tasks.py @@ -8,7 +8,7 @@ from . import db from .crud import get_balance_notify from .models import Payment -sse_listeners: List[trio.MemorySendChannel] = [] +api_invoice_listeners: List[trio.MemorySendChannel] = [] async def register_listeners(): @@ -20,7 +20,7 @@ async def register_listeners(): async def wait_for_paid_invoices(invoice_paid_chan: trio.MemoryReceiveChannel): async for payment in invoice_paid_chan: # send information to sse channel - await dispatch_sse(payment) + await dispatch_invoice_listener(payment) # dispatch webhook if payment.webhook and not payment.webhook_status: @@ -40,13 +40,13 @@ async def wait_for_paid_invoices(invoice_paid_chan: trio.MemoryReceiveChannel): pass -async def dispatch_sse(payment: Payment): - for send_channel in sse_listeners: +async def dispatch_invoice_listener(payment: Payment): + for send_channel in api_invoice_listeners: try: send_channel.send_nowait(payment) except trio.WouldBlock: print("removing sse listener", send_channel) - sse_listeners.remove(send_channel) + api_invoice_listeners.remove(send_channel) async def dispatch_webhook(payment: Payment): diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py index 2547435e..9a81a1fe 100644 --- a/lnbits/core/views/api.py +++ b/lnbits/core/views/api.py @@ -20,7 +20,7 @@ from ..services import ( pay_invoice, perform_lnurlauth, ) -from ..tasks import sse_listeners +from ..tasks import api_invoice_listeners @core_app.route("/api/v1/wallet", methods=["GET"]) @@ -295,7 +295,7 @@ async def api_payments_sse(): send_payment, receive_payment = trio.open_memory_channel(0) print("adding sse listener", send_payment) - sse_listeners.append(send_payment) + api_invoice_listeners.append(send_payment) send_event, event_to_send = trio.open_memory_channel(0) diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py index f48b054f..ae17839a 100644 --- a/lnbits/core/views/generic.py +++ b/lnbits/core/views/generic.py @@ -153,7 +153,10 @@ async def lnurl_full_withdraw_callback(): pr = request.args.get("pr") async def pay(): - await pay_invoice(wallet_id=wallet.id, payment_request=pr) + try: + await pay_invoice(wallet_id=wallet.id, payment_request=pr) + except: + pass current_app.nursery.start_soon(pay) diff --git a/lnbits/core/views/public_api.py b/lnbits/core/views/public_api.py new file mode 100644 index 00000000..5149d90c --- /dev/null +++ b/lnbits/core/views/public_api.py @@ -0,0 +1,37 @@ +import trio # type: ignore +import datetime +from http import HTTPStatus +from quart import jsonify + +from lnbits import bolt11 + +from .. import core_app +from ..crud import get_standalone_payment +from ..tasks import api_invoice_listeners + + +@core_app.route("/public/v1/payment/", methods=["GET"]) +async def api_public_payment_longpolling(payment_hash): + payment = await get_standalone_payment(payment_hash) + + if not payment: + return jsonify({"message": "Payment does not exist."}), HTTPStatus.NOT_FOUND + elif not payment.pending: + return jsonify({"status": "paid"}), HTTPStatus.OK + + try: + invoice = bolt11.decode(payment.bolt11) + expiration = datetime.datetime.fromtimestamp(invoice.date + invoice.expiry) + if expiration < datetime.datetime.now(): + return jsonify({"status": "expired"}), HTTPStatus.OK + except: + return jsonify({"message": "Invalid bolt11 invoice."}), HTTPStatus.BAD_REQUEST + + send_payment, receive_payment = trio.open_memory_channel(0) + + print("adding standalone invoice listener", payment_hash, send_payment) + api_invoice_listeners.append(send_payment) + + async for payment in receive_payment: + if payment.payment_hash == payment_hash: + return jsonify({"status": "paid"}), HTTPStatus.OK diff --git a/lnbits/extensions/events/README.md b/lnbits/extensions/events/README.md index 9108519c..11b62fec 100644 --- a/lnbits/extensions/events/README.md +++ b/lnbits/extensions/events/README.md @@ -1,3 +1,33 @@ -

Events

-

Events: Sell and register event tickets

-Events alows you to make a wave of tickets for an event, each ticket is in the form of a unqiue QRcode, which the user presents at registration. Events comes with a shareable ticket scanner, which can be used to register attendees. +# Events + +## Sell tickets for events and use the built-in scanner for registering attendants + +Events alows you to make tickets for an event. Each ticket is in the form of a uniqque QR code. After registering, and paying for ticket, the user gets a QR code to present at registration/entrance. + +Events includes a shareable ticket scanner, which can be used to register attendees. + +## Usage + +1. Create an event\ + ![create event](https://i.imgur.com/dadK1dp.jpg) +2. Fill out the event information: + + - event name + - wallet (normally there's only one) + - event information + - closing date for event registration + - begin and end date of the event + + ![event info](https://imgur.com/KAv68Yr.jpg) + +3. Share the event registration link\ + ![event ticket](https://imgur.com/AQWUOBY.jpg) + + - ticket example\ + ![ticket example](https://i.imgur.com/trAVSLd.jpg) + + - QR code ticket, presented after invoice paid, to present at registration\ + ![event ticket](https://i.imgur.com/M0ROM82.jpg) + +4. Use the built-in ticket scanner to validate registered, and paid, attendees\ + ![ticket scanner](https://i.imgur.com/zrm9202.jpg) diff --git a/lnbits/extensions/events/templates/events/register.html b/lnbits/extensions/events/templates/events/register.html index b1a6a6c1..63af65e8 100644 --- a/lnbits/extensions/events/templates/events/register.html +++ b/lnbits/extensions/events/templates/events/register.html @@ -82,7 +82,7 @@