moved code for generating new dns name and updating the invoice in database to the invoiceListener

This commit is contained in:
Kristjan
2021-01-02 22:38:28 +01:00
parent 8a7652c06f
commit e1abea77f5
5 changed files with 100 additions and 76 deletions

View File

@@ -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))

View File

@@ -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]:

View File

@@ -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

View 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

View File

@@ -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