diff --git a/__init__.py b/__init__.py index 1555eb9..ace3254 100644 --- a/__init__.py +++ b/__init__.py @@ -1,9 +1,8 @@ from fastapi import APIRouter -from starlette.staticfiles import StaticFiles - from lnbits.db import Database from lnbits.helpers import template_renderer from lnbits.tasks import catch_everything_and_restart +from starlette.staticfiles import StaticFiles db = Database("ext_nostrclient") @@ -22,11 +21,10 @@ def nostr_renderer(): return template_renderer(["lnbits/extensions/nostrclient/templates"]) +from .tasks import init_relays, subscribe_events from .views import * # noqa from .views_api import * # noqa -from .tasks import init_relays, subscribe_events - def nostrclient_start(): loop = asyncio.get_event_loop() diff --git a/crud.py b/crud.py index b1916b7..497fcd7 100644 --- a/crud.py +++ b/crud.py @@ -1,7 +1,8 @@ from typing import List, Optional, Union -from lnbits.helpers import urlsafe_short_hash import shortuuid +from lnbits.helpers import urlsafe_short_hash + from . import db from .models import Relay, RelayList diff --git a/models.py b/models.py index bfbc424..75a086d 100644 --- a/models.py +++ b/models.py @@ -1,12 +1,10 @@ -from typing import List, Dict -from typing import Optional +from dataclasses import dataclass +from typing import Dict, List, Optional from fastapi import Request -from pydantic import BaseModel, Field - from fastapi.param_functions import Query -from dataclasses import dataclass from lnbits.helpers import urlsafe_short_hash +from pydantic import BaseModel, Field class Relay(BaseModel): diff --git a/services.py b/services.py index fa548bf..243af58 100644 --- a/services.py +++ b/services.py @@ -1,19 +1,17 @@ import asyncio import json from typing import List, Union -from .models import RelayList, Relay, Event, Filter, Filters +from fastapi import WebSocket, WebSocketDisconnect +from lnbits.helpers import urlsafe_short_hash + +from .models import Event, Filter, Filters, Relay, RelayList from .nostr.event import Event as NostrEvent from .nostr.filter import Filter as NostrFilter from .nostr.filter import Filters as NostrFilters -from .tasks import ( - client, - received_event_queue, - received_subscription_events, - received_subscription_eosenotices, -) -from fastapi import WebSocket, WebSocketDisconnect -from lnbits.helpers import urlsafe_short_hash +from .tasks import (client, received_event_queue, + received_subscription_eosenotices, + received_subscription_events) class NostrRouter: diff --git a/tasks.py b/tasks.py index 40d8aec..8bbf8aa 100644 --- a/tasks.py +++ b/tasks.py @@ -4,11 +4,11 @@ import threading from .nostr.client.client import NostrClient from .nostr.event import Event -from .nostr.message_pool import EventMessage, NoticeMessage, EndOfStoredEventsMessage from .nostr.key import PublicKey +from .nostr.message_pool import (EndOfStoredEventsMessage, EventMessage, + NoticeMessage) from .nostr.relay_manager import RelayManager - client = NostrClient( connect=False, ) diff --git a/templates/nostrclient/index.html b/templates/nostrclient/index.html index 8ddd362..2a6cf60 100644 --- a/templates/nostrclient/index.html +++ b/templates/nostrclient/index.html @@ -75,7 +75,7 @@ - +
Your endpoint: @@ -101,11 +101,11 @@
-
{{SITE_TITLE}} Nostrclient Extension
+
Nostrclient Extension

This extension is a always-on nostr client that other extensions can - use to send and receive events on nostr. - + use to send and receive events on nostr. + Add multiple nostr relays to connect to. The extension then opens a websocket for you to use at

@@ -197,10 +197,8 @@ ) .then(function (response) { if (response.data) { - console.log(response.data) response.data.map(maplrelays) self.nostrrelayLinks = response.data - console.log(self.nostrrelayLinks) } }) .catch(function (error) { @@ -219,10 +217,10 @@ message: `Invalid relay URL.`, caption: "Should start with 'wss://'' or 'ws://'" }) - return + return false; } console.log('ADD RELAY ' + this.relayToAdd) - var self = this + let that = this LNbits.api .request( 'POST', @@ -231,17 +229,17 @@ {url: this.relayToAdd} ) .then(function (response) { + console.log("response:", response) if (response.data) { - console.log(response.data) response.data.map(maplrelays) - self.nostrrelayLinks = response.data - console.log(self.nostrrelayLinks) + that.nostrrelayLinks = response.data + that.relayToAdd = '' } }) .catch(function (error) { LNbits.utils.notifyApiError(error) }) - location.reload() + return false; }, deleteRelay(url) { console.log('DELETE RELAY ' + url) @@ -260,7 +258,6 @@ .catch(function (error) { LNbits.utils.notifyApiError(error) }) - location.reload() }, exportlnurldeviceCSV: function () { var self = this diff --git a/views.py b/views.py index 90dd31c..7f07f5d 100644 --- a/views.py +++ b/views.py @@ -1,20 +1,18 @@ -from http import HTTPStatus import asyncio +from http import HTTPStatus + +# FastAPI good for incoming from fastapi import Request from fastapi.param_functions import Query from fastapi.params import Depends from fastapi.templating import Jinja2Templates -from starlette.exceptions import HTTPException -from starlette.responses import HTMLResponse -from . import nostrclient_ext, nostr_renderer - -# FastAPI good for incoming -from fastapi import Request from lnbits.core.crud import update_payment_status from lnbits.core.models import User from lnbits.core.views.api import api_payment -from lnbits.decorators import check_user_exists, check_admin +from lnbits.decorators import check_admin, check_user_exists +from starlette.responses import HTMLResponse +from . import nostr_renderer, nostrclient_ext templates = Jinja2Templates(directory="templates") diff --git a/views_api.py b/views_api.py index d2c74fe..1cf7a19 100644 --- a/views_api.py +++ b/views_api.py @@ -1,33 +1,25 @@ -from http import HTTPStatus import asyncio -from fastapi import WebSocket -from fastapi.params import Depends +from http import HTTPStatus +from typing import Optional + +from fastapi import Depends, WebSocket +from lnbits.decorators import check_admin +from lnbits.helpers import urlsafe_short_hash +from loguru import logger +from starlette.exceptions import HTTPException from . import nostrclient_ext -from .tasks import client -from loguru import logger - -from .crud import get_relays, add_relay, delete_relay -from .models import RelayList, Relay - +from .crud import add_relay, delete_relay, get_relays +from .models import Relay, RelayList from .services import NostrRouter - -from lnbits.decorators import ( - WalletTypeInfo, - get_key_type, - require_admin_key, - check_admin, -) - -from lnbits.helpers import urlsafe_short_hash -from .tasks import init_relays +from .tasks import client, init_relays # we keep this in all_routers: list[NostrRouter] = [] @nostrclient_ext.get("/api/v1/relays") -async def api_get_relays(): # type: ignore +async def api_get_relays() -> RelayList: relays = RelayList(__root__=[]) for url, r in client.relay_manager.relays.items(): status_text = ( @@ -52,20 +44,30 @@ async def api_get_relays(): # type: ignore @nostrclient_ext.post( "/api/v1/relay", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)] ) -async def api_add_relay(relay: Relay): # type: ignore - assert relay.url, "no URL" +async def api_add_relay(relay: Relay) -> Optional[RelayList]: + if not relay.url: + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, detail=f"Relay url not provided." + ) if relay.url in client.relay_manager.relays: - return + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, + detail=f"Relay: {relay.url} already exists.", + ) relay.id = urlsafe_short_hash() await add_relay(relay) await init_relays() + return await get_relays() @nostrclient_ext.delete( "/api/v1/relay", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)] ) -async def api_delete_relay(relay: Relay): # type: ignore - assert relay.url +async def api_delete_relay(relay: Relay) -> None: + if not relay.url: + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, detail=f"Relay url not provided." + ) client.relay_manager.remove_relay(relay.url) await delete_relay(relay) @@ -91,7 +93,7 @@ async def api_stop(): @nostrclient_ext.websocket("/api/v1/relay") -async def ws_relay(websocket: WebSocket): +async def ws_relay(websocket: WebSocket) -> None: """Relay multiplexer: one client (per endpoint) <-> multiple relays""" await websocket.accept() router = NostrRouter(websocket)