[feat] Watchdog and notifications (#2895)
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import asyncio
|
||||
from typing import Tuple
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
from pynostr.encrypted_dm import EncryptedDirectMessage
|
||||
from websocket import WebSocket, create_connection
|
||||
|
||||
from lnbits.core.helpers import is_valid_url
|
||||
from lnbits.utils.nostr import (
|
||||
validate_identifier,
|
||||
validate_pub_key,
|
||||
)
|
||||
|
||||
|
||||
async def send_nostr_dm(
|
||||
from_private_key_hex: str,
|
||||
to_pubkey_hex: str,
|
||||
message: str,
|
||||
relays: list[str],
|
||||
) -> dict:
|
||||
dm = EncryptedDirectMessage()
|
||||
dm.encrypt(
|
||||
private_key_hex=from_private_key_hex,
|
||||
recipient_pubkey=to_pubkey_hex,
|
||||
cleartext_content=message,
|
||||
)
|
||||
|
||||
dm_event = dm.to_event()
|
||||
dm_event.sign(private_key_hex=from_private_key_hex)
|
||||
notification = dm_event.to_message()
|
||||
|
||||
ws_connections: list[WebSocket] = []
|
||||
for relay in relays:
|
||||
try:
|
||||
ws = create_connection(relay, timeout=2)
|
||||
ws.send(notification)
|
||||
ws_connections.append(ws)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error sending notification to relay {relay}: {e}")
|
||||
await asyncio.sleep(1)
|
||||
for ws in ws_connections:
|
||||
try:
|
||||
ws.close()
|
||||
except Exception as e:
|
||||
logger.debug(f"Failed to close websocket connection: {e}")
|
||||
|
||||
return dm_event.to_dict()
|
||||
|
||||
|
||||
async def fetch_nip5_details(identifier: str) -> Tuple[str, list[str]]:
|
||||
identifier, domain = identifier.split("@")
|
||||
if not identifier or not domain:
|
||||
raise ValueError("Invalid NIP5 identifier")
|
||||
|
||||
if not is_valid_url(f"https://{domain}"):
|
||||
raise ValueError("Invalid NIP5 domain")
|
||||
|
||||
validate_identifier(identifier)
|
||||
|
||||
url = f"https://{domain}/.well-known/nostr.json?name={identifier}"
|
||||
async with httpx.AsyncClient() as client:
|
||||
resp = await client.get(url)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
if "names" not in data or identifier not in data["names"]:
|
||||
raise ValueError("NIP5 not name found")
|
||||
pubkey = data["names"][identifier]
|
||||
validate_pub_key(pubkey)
|
||||
|
||||
relays = data["relays"].get(pubkey, []) if "relays" in data else []
|
||||
|
||||
return pubkey, relays
|
||||
Reference in New Issue
Block a user