mirror of
https://github.com/lnbits/lnbits.git
synced 2025-09-20 13:04:23 +02:00
moved code for generating new dns name and updating the invoice in database to the invoiceListener
This commit is contained in:
@@ -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))
|
||||
subdomains_ext.record(record_async(register_listeners))
|
||||
|
@@ -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]:
|
||||
|
@@ -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)
|
||||
except AssertionError:
|
||||
webhook = None
|
||||
|
||||
return jsonify({"paid": True}), HTTPStatus.OK
|
||||
|
39
lnbits/extensions/subdomains/util.py
Normal file
39
lnbits/extensions/subdomains/util.py
Normal file
@@ -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}(?<!-)\\.)+[A-Za-z]{2,6}"
|
||||
# Compile the ReGex
|
||||
p = re.compile(regex)
|
||||
|
||||
# If the string is empty
|
||||
# return false
|
||||
if str == None:
|
||||
return False
|
||||
|
||||
# Return if the string
|
||||
# matched the ReGex
|
||||
if re.search(p, str):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
# Function to validate IP address
|
||||
def isvalidIPAddress(str):
|
||||
try:
|
||||
socket.inet_aton(str)
|
||||
return True
|
||||
except socket.error:
|
||||
return False
|
@@ -5,8 +5,8 @@ from http import HTTPStatus
|
||||
from lnbits.core.crud import get_user, get_wallet
|
||||
from lnbits.core.services import create_invoice, check_invoice_status
|
||||
from lnbits.decorators import api_check_wallet_key, api_validate_post_request
|
||||
from .util import validIPAddress
|
||||
|
||||
from .util import isValidDomain, isvalidIPAddress
|
||||
from . import subdomains_ext
|
||||
from .crud import (
|
||||
create_subdomain,
|
||||
@@ -111,11 +111,16 @@ async def api_subdomains():
|
||||
)
|
||||
async def api_subdomain_make_subdomain(domain_id):
|
||||
domain = await get_domain(domain_id)
|
||||
|
||||
|
||||
if not domain:
|
||||
return jsonify({"message": "LNsubdomain does not exist."}), HTTPStatus.NOT_FOUND
|
||||
if not validIPAddress(g.data["ip"]):
|
||||
if not isvalidIPAddress(g.data["ip"]):
|
||||
return jsonify({"message": g.data["ip"] + " Not a valid IP address"}), HTTPStatus.BAD_REQUEST
|
||||
if not isValidDomain(g.data["subdomain"] + "." + domain.domain):
|
||||
return (
|
||||
jsonify({"message": g.data["subdomain"] + "." + domain.domain + " Bad domain name"}),
|
||||
HTTPStatus.BAD_REQUEST,
|
||||
)
|
||||
if g.data["record_type"] not in domain.allowed_record_types:
|
||||
return jsonify({"message": g.data["record_type"] + "Not a valid record"}), HTTPStatus.BAD_REQUEST
|
||||
|
||||
@@ -147,13 +152,7 @@ async def api_subdomain_send_subdomain(payment_hash):
|
||||
return jsonify({"paid": False}), HTTPStatus.OK
|
||||
|
||||
if is_paid:
|
||||
wallet = await get_wallet(subdomain.wallet)
|
||||
payment = await wallet.get_payment(payment_hash)
|
||||
await payment.set_pending(False)
|
||||
subdomain = await set_subdomain_paid(payment_hash=payment_hash)
|
||||
return jsonify({"paid": True}), HTTPStatus.OK
|
||||
|
||||
return jsonify({"paid": False}), HTTPStatus.OK
|
||||
return jsonify({"paid": False}), HTTPStatus.OK
|
||||
|
||||
|
||||
@subdomains_ext.route("/api/v1/subdomains/<subdomain_id>", methods=["DELETE"])
|
||||
@@ -170,4 +169,3 @@ async def api_subdomain_delete(subdomain_id):
|
||||
await delete_subdomain(subdomain_id)
|
||||
|
||||
return "", HTTPStatus.NO_CONTENT
|
||||
|
||||
|
Reference in New Issue
Block a user