lnbits-legend/lnbits/extensions/scrub/tasks.py

90 lines
2.6 KiB
Python
Raw Normal View History

2022-05-17 20:27:52 +01:00
import asyncio
import json
from http import HTTPStatus
2022-10-06 15:21:53 +01:00
from math import floor
from urllib.parse import urlparse
2022-06-21 10:31:18 +01:00
2022-05-17 20:27:52 +01:00
import httpx
from fastapi import HTTPException
2022-05-17 20:27:52 +01:00
from lnbits import bolt11
2022-06-21 10:31:18 +01:00
from lnbits.core.models import Payment
from lnbits.core.services import pay_invoice
from lnbits.helpers import get_current_extension_name
2022-05-17 20:27:52 +01:00
from lnbits.tasks import register_invoice_listener
from .crud import get_scrub_by_wallet
2022-05-17 20:27:52 +01:00
async def wait_for_paid_invoices():
invoice_queue = asyncio.Queue()
register_invoice_listener(invoice_queue, get_current_extension_name())
2022-05-17 20:27:52 +01:00
while True:
payment = await invoice_queue.get()
await on_invoice_paid(payment)
2023-01-02 11:25:01 +01:00
async def on_invoice_paid(payment: Payment):
2022-06-21 10:31:18 +01:00
# (avoid loops)
2023-01-02 11:25:01 +01:00
if payment.extra and payment.extra.get("tag") == "scrubed":
2022-06-21 10:31:18 +01:00
# already scrubbed
2022-05-17 20:27:52 +01:00
return
2022-06-21 10:31:18 +01:00
scrub_link = await get_scrub_by_wallet(payment.wallet_id)
2022-07-05 16:21:49 +01:00
2022-06-21 10:31:18 +01:00
if not scrub_link:
2022-05-17 20:27:52 +01:00
return
from lnbits.core.views.api import api_lnurlscan
2022-05-17 20:27:52 +01:00
# DECODE LNURLP OR LNADDRESS
data = await api_lnurlscan(scrub_link.payoraddress)
2022-07-05 16:21:49 +01:00
# I REALLY HATE THIS DUPLICATION OF CODE!! CORE/VIEWS/API.PY, LINE 267
domain = urlparse(data["callback"]).netloc
2022-10-06 15:21:53 +01:00
rounded_amount = floor(payment.amount / 1000) * 1000
2022-10-06 15:34:37 +01:00
async with httpx.AsyncClient() as client:
try:
r = await client.get(
data["callback"],
2022-10-06 15:21:53 +01:00
params={"amount": rounded_amount},
timeout=40,
)
if r.is_error:
2023-01-02 11:25:01 +01:00
raise httpx.ConnectError("issue with scrub callback")
except (httpx.ConnectError, httpx.RequestError):
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=f"Failed to connect to {domain}.",
)
params = json.loads(r.text)
if params.get("status") == "ERROR":
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=f"{domain} said: '{params.get('reason', '')}'",
)
2022-07-05 16:21:49 +01:00
invoice = bolt11.decode(params["pr"])
2022-10-06 15:34:37 +01:00
2022-10-06 15:21:53 +01:00
if invoice.amount_msat != rounded_amount:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=f"{domain} returned an invalid invoice. Expected {payment.amount} msat, got {invoice.amount_msat}.",
)
2022-07-05 16:21:49 +01:00
payment_hash = await pay_invoice(
wallet_id=payment.wallet_id,
payment_request=params["pr"],
description=data["description"],
extra={"tag": "scrubed"},
)
return {
"payment_hash": payment_hash,
# maintain backwards compatibility with API clients:
"checking_id": payment_hash,
}