diff --git a/lnbits/extensions/subdomains/__init__.py b/lnbits/extensions/subdomains/__init__.py index 2e8e48361..cad9fee8 100644 --- a/lnbits/extensions/subdomains/__init__.py +++ b/lnbits/extensions/subdomains/__init__.py @@ -12,4 +12,4 @@ from .views import * # noqa from .tasks import register_listeners from lnbits.tasks import record_async -subdomains_ext.record(record_async(register_listeners)) \ No newline at end of file +subdomains_ext.record(record_async(register_listeners)) diff --git a/lnbits/extensions/subdomains/crud.py b/lnbits/extensions/subdomains/crud.py index 42997ae2..cb84ca02 100644 --- a/lnbits/extensions/subdomains/crud.py +++ b/lnbits/extensions/subdomains/crud.py @@ -61,54 +61,8 @@ async def set_subdomain_paid(payment_hash: str) -> Subdomains: (amount, row[1]), ) - subdomain = await get_subdomain(payment_hash) - - ### SEND REQUEST TO CLOUDFLARE - url = "https://api.cloudflare.com/client/v4/zones/" + domaindata.cf_zone_id + "/dns_records" - header = {"Authorization": "Bearer " + domaindata.cf_token, "Content-Type": "application/json"} - aRecord = subdomain.subdomain + "." + subdomain.domain_name - cf_response = "" - async with httpx.AsyncClient() as client: - try: - r = await client.post( - url, - headers=header, - json={ - "type": subdomain.record_type, - "name": aRecord, - "content": subdomain.ip, - "ttl": 0, - "proxed": False, - }, - timeout=40, - ) - cf_response = r.text - except AssertionError: - cf_response = "Error occured" - - ### Use webhook to notify about cloudflare registration - if domaindata.webhook: - async with httpx.AsyncClient() as client: - try: - r = await client.post( - domaindata.webhook, - json={ - "domain": subdomain.domain_name, - "subdomain": subdomain.subdomain, - "record_type": subdomain.record_type, - "email": subdomain.email, - "ip": subdomain.ip, - "cost:": str(subdomain.sats) + " sats", - "duration": str(subdomain.duration) + " days", - "cf_response": cf_response, - }, - timeout=40, - ) - except AssertionError: - webhook = None - subdomain = await get_subdomain(payment_hash) - return + return subdomain async def get_subdomain(subdomain_id: str) -> Optional[Subdomains]: diff --git a/lnbits/extensions/subdomains/tasks.py b/lnbits/extensions/subdomains/tasks.py index 004093f3..611f77b0 100644 --- a/lnbits/extensions/subdomains/tasks.py +++ b/lnbits/extensions/subdomains/tasks.py @@ -1,47 +1,80 @@ +from http import HTTPStatus +from quart.json import jsonify import trio # type: ignore import json import httpx +from .crud import get_domain, set_subdomain_paid +from lnbits.core.crud import get_user, get_wallet from lnbits.core import db as core_db from lnbits.core.models import Payment from lnbits.tasks import register_invoice_listener -from .crud import get_pay_link - async def register_listeners(): invoice_paid_chan_send, invoice_paid_chan_recv = trio.open_memory_channel(2) register_invoice_listener(invoice_paid_chan_send) await wait_for_paid_invoices(invoice_paid_chan_recv) + async def wait_for_paid_invoices(invoice_paid_chan: trio.MemoryReceiveChannel): async for payment in invoice_paid_chan: await on_invoice_paid(payment) + async def on_invoice_paid(payment: Payment) -> None: - if "lnurlp" != payment.extra.get("tag"): + print(payment) + if "lnsubdomain" != payment.extra.get("tag"): # not an lnurlp invoice return - if payment.extra.get("wh_status"): - # this webhook has already been sent - return + wallet = await get_wallet(payment.wallet_id) + await payment.set_pending(False) + subdomain = await set_subdomain_paid(payment_hash=payment.payment_hash) + domain = await get_domain(subdomain.domain) - pay_link = await get_pay_link(payment.extra.get("link", -1)) - if pay_link and pay_link.webhook_url: + ### SEND REQUEST TO CLOUDFLARE + url = "https://api.cloudflare.com/client/v4/zones/" + domain.cf_zone_id + "/dns_records" + header = {"Authorization": "Bearer " + domain.cf_token, "Content-Type": "application/json"} + aRecord = subdomain.subdomain + "." + subdomain.domain_name + cf_response = "" + async with httpx.AsyncClient() as client: + try: + r = await client.post( + url, + headers=header, + json={ + "type": subdomain.record_type, + "name": aRecord, + "content": subdomain.ip, + "ttl": 0, + "proxed": False, + }, + timeout=40, + ) + cf_response = r.text + except AssertionError: + cf_response = "Error occured" + + ### Use webhook to notify about cloudflare registration + if domain.webhook: async with httpx.AsyncClient() as client: try: r = await client.post( - pay_link.webhook_url, + domain.webhook, json={ - "payment_hash": payment.payment_hash, - "payment_request": payment.bolt11, - "amount": payment.amount, - "comment": payment.extra.get("comment"), - "lnurlp": pay_link.id, + "domain": subdomain.domain_name, + "subdomain": subdomain.subdomain, + "record_type": subdomain.record_type, + "email": subdomain.email, + "ip": subdomain.ip, + "cost:": str(subdomain.sats) + " sats", + "duration": str(subdomain.duration) + " days", + "cf_response": cf_response, }, timeout=40, ) - await mark_webhook_sent(payment, r.status_code) - except (httpx.ConnectError, httpx.RequestError): - await mark_webhook_sent(payment, -1) \ No newline at end of file + except AssertionError: + webhook = None + + return jsonify({"paid": True}), HTTPStatus.OK diff --git a/lnbits/extensions/subdomains/util.py b/lnbits/extensions/subdomains/util.py new file mode 100644 index 00000000..aee883cf --- /dev/null +++ b/lnbits/extensions/subdomains/util.py @@ -0,0 +1,39 @@ +from lnbits.extensions.subdomains.models import Subdomains +import trio # type: ignore +import json +import httpx + +# Python3 program to validate +# domain name +# using regular expression +import re +import socket + +# Function to validate domain name. +def isValidDomain(str): + # Regex to check valid + # domain name. + regex = "^((?!-)[A-Za-z0-9-]{1,63}(?", methods=["DELETE"]) @@ -170,4 +169,3 @@ async def api_subdomain_delete(subdomain_id): await delete_subdomain(subdomain_id) return "", HTTPStatus.NO_CONTENT -