Merge pull request #6 from lnbits/improve-frontend
improve frontend, no reloading. types in views_api, formatting
This commit is contained in:
commit
38f28ac6aa
8 changed files with 60 additions and 68 deletions
|
|
@ -1,9 +1,8 @@
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from starlette.staticfiles import StaticFiles
|
|
||||||
|
|
||||||
from lnbits.db import Database
|
from lnbits.db import Database
|
||||||
from lnbits.helpers import template_renderer
|
from lnbits.helpers import template_renderer
|
||||||
from lnbits.tasks import catch_everything_and_restart
|
from lnbits.tasks import catch_everything_and_restart
|
||||||
|
from starlette.staticfiles import StaticFiles
|
||||||
|
|
||||||
db = Database("ext_nostrclient")
|
db = Database("ext_nostrclient")
|
||||||
|
|
||||||
|
|
@ -22,11 +21,10 @@ def nostr_renderer():
|
||||||
return template_renderer(["lnbits/extensions/nostrclient/templates"])
|
return template_renderer(["lnbits/extensions/nostrclient/templates"])
|
||||||
|
|
||||||
|
|
||||||
|
from .tasks import init_relays, subscribe_events
|
||||||
from .views import * # noqa
|
from .views import * # noqa
|
||||||
from .views_api import * # noqa
|
from .views_api import * # noqa
|
||||||
|
|
||||||
from .tasks import init_relays, subscribe_events
|
|
||||||
|
|
||||||
|
|
||||||
def nostrclient_start():
|
def nostrclient_start():
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
|
||||||
3
crud.py
3
crud.py
|
|
@ -1,7 +1,8 @@
|
||||||
from typing import List, Optional, Union
|
from typing import List, Optional, Union
|
||||||
|
|
||||||
from lnbits.helpers import urlsafe_short_hash
|
|
||||||
import shortuuid
|
import shortuuid
|
||||||
|
from lnbits.helpers import urlsafe_short_hash
|
||||||
|
|
||||||
from . import db
|
from . import db
|
||||||
from .models import Relay, RelayList
|
from .models import Relay, RelayList
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
from typing import List, Dict
|
from dataclasses import dataclass
|
||||||
from typing import Optional
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
from pydantic import BaseModel, Field
|
|
||||||
|
|
||||||
from fastapi.param_functions import Query
|
from fastapi.param_functions import Query
|
||||||
from dataclasses import dataclass
|
|
||||||
from lnbits.helpers import urlsafe_short_hash
|
from lnbits.helpers import urlsafe_short_hash
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
class Relay(BaseModel):
|
class Relay(BaseModel):
|
||||||
|
|
|
||||||
16
services.py
16
services.py
|
|
@ -1,19 +1,17 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
from typing import List, Union
|
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.event import Event as NostrEvent
|
||||||
from .nostr.filter import Filter as NostrFilter
|
from .nostr.filter import Filter as NostrFilter
|
||||||
from .nostr.filter import Filters as NostrFilters
|
from .nostr.filter import Filters as NostrFilters
|
||||||
from .tasks import (
|
from .tasks import (client, received_event_queue,
|
||||||
client,
|
received_subscription_eosenotices,
|
||||||
received_event_queue,
|
received_subscription_events)
|
||||||
received_subscription_events,
|
|
||||||
received_subscription_eosenotices,
|
|
||||||
)
|
|
||||||
from fastapi import WebSocket, WebSocketDisconnect
|
|
||||||
from lnbits.helpers import urlsafe_short_hash
|
|
||||||
|
|
||||||
|
|
||||||
class NostrRouter:
|
class NostrRouter:
|
||||||
|
|
|
||||||
4
tasks.py
4
tasks.py
|
|
@ -4,11 +4,11 @@ import threading
|
||||||
|
|
||||||
from .nostr.client.client import NostrClient
|
from .nostr.client.client import NostrClient
|
||||||
from .nostr.event import Event
|
from .nostr.event import Event
|
||||||
from .nostr.message_pool import EventMessage, NoticeMessage, EndOfStoredEventsMessage
|
|
||||||
from .nostr.key import PublicKey
|
from .nostr.key import PublicKey
|
||||||
|
from .nostr.message_pool import (EndOfStoredEventsMessage, EventMessage,
|
||||||
|
NoticeMessage)
|
||||||
from .nostr.relay_manager import RelayManager
|
from .nostr.relay_manager import RelayManager
|
||||||
|
|
||||||
|
|
||||||
client = NostrClient(
|
client = NostrClient(
|
||||||
connect=False,
|
connect=False,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
</q-table>
|
</q-table>
|
||||||
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div class="text-weight-bold"> Your endpoint:
|
<div class="text-weight-bold"> Your endpoint:
|
||||||
|
|
@ -101,11 +101,11 @@
|
||||||
<div class="col-12 col-md-5 q-gutter-y-md">
|
<div class="col-12 col-md-5 q-gutter-y-md">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<h6 class="text-subtitle1 q-my-none">{{SITE_TITLE}} Nostrclient Extension</h6>
|
<h6 class="text-subtitle1 q-my-none">Nostrclient Extension</h6>
|
||||||
<p>
|
<p>
|
||||||
This extension is a always-on nostr client that other extensions can
|
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
|
Add multiple nostr relays to connect to. The extension then opens a websocket for you to use
|
||||||
at
|
at
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -197,10 +197,8 @@
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
console.log(response.data)
|
|
||||||
response.data.map(maplrelays)
|
response.data.map(maplrelays)
|
||||||
self.nostrrelayLinks = response.data
|
self.nostrrelayLinks = response.data
|
||||||
console.log(self.nostrrelayLinks)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
|
|
@ -219,10 +217,10 @@
|
||||||
message: `Invalid relay URL.`,
|
message: `Invalid relay URL.`,
|
||||||
caption: "Should start with 'wss://'' or 'ws://'"
|
caption: "Should start with 'wss://'' or 'ws://'"
|
||||||
})
|
})
|
||||||
return
|
return false;
|
||||||
}
|
}
|
||||||
console.log('ADD RELAY ' + this.relayToAdd)
|
console.log('ADD RELAY ' + this.relayToAdd)
|
||||||
var self = this
|
let that = this
|
||||||
LNbits.api
|
LNbits.api
|
||||||
.request(
|
.request(
|
||||||
'POST',
|
'POST',
|
||||||
|
|
@ -231,17 +229,17 @@
|
||||||
{url: this.relayToAdd}
|
{url: this.relayToAdd}
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
|
console.log("response:", response)
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
console.log(response.data)
|
|
||||||
response.data.map(maplrelays)
|
response.data.map(maplrelays)
|
||||||
self.nostrrelayLinks = response.data
|
that.nostrrelayLinks = response.data
|
||||||
console.log(self.nostrrelayLinks)
|
that.relayToAdd = ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
})
|
})
|
||||||
location.reload()
|
return false;
|
||||||
},
|
},
|
||||||
deleteRelay(url) {
|
deleteRelay(url) {
|
||||||
console.log('DELETE RELAY ' + url)
|
console.log('DELETE RELAY ' + url)
|
||||||
|
|
@ -260,7 +258,6 @@
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
})
|
})
|
||||||
location.reload()
|
|
||||||
},
|
},
|
||||||
exportlnurldeviceCSV: function () {
|
exportlnurldeviceCSV: function () {
|
||||||
var self = this
|
var self = this
|
||||||
|
|
|
||||||
14
views.py
14
views.py
|
|
@ -1,20 +1,18 @@
|
||||||
from http import HTTPStatus
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
|
# FastAPI good for incoming
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
from fastapi.param_functions import Query
|
from fastapi.param_functions import Query
|
||||||
from fastapi.params import Depends
|
from fastapi.params import Depends
|
||||||
from fastapi.templating import Jinja2Templates
|
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.crud import update_payment_status
|
||||||
from lnbits.core.models import User
|
from lnbits.core.models import User
|
||||||
from lnbits.core.views.api import api_payment
|
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")
|
templates = Jinja2Templates(directory="templates")
|
||||||
|
|
||||||
|
|
|
||||||
54
views_api.py
54
views_api.py
|
|
@ -1,33 +1,25 @@
|
||||||
from http import HTTPStatus
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from fastapi import WebSocket
|
from http import HTTPStatus
|
||||||
from fastapi.params import Depends
|
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 . import nostrclient_ext
|
||||||
from .tasks import client
|
from .crud import add_relay, delete_relay, get_relays
|
||||||
from loguru import logger
|
from .models import Relay, RelayList
|
||||||
|
|
||||||
from .crud import get_relays, add_relay, delete_relay
|
|
||||||
from .models import RelayList, Relay
|
|
||||||
|
|
||||||
from .services import NostrRouter
|
from .services import NostrRouter
|
||||||
|
from .tasks import client, init_relays
|
||||||
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
|
|
||||||
|
|
||||||
# we keep this in
|
# we keep this in
|
||||||
all_routers: list[NostrRouter] = []
|
all_routers: list[NostrRouter] = []
|
||||||
|
|
||||||
|
|
||||||
@nostrclient_ext.get("/api/v1/relays")
|
@nostrclient_ext.get("/api/v1/relays")
|
||||||
async def api_get_relays(): # type: ignore
|
async def api_get_relays() -> RelayList:
|
||||||
relays = RelayList(__root__=[])
|
relays = RelayList(__root__=[])
|
||||||
for url, r in client.relay_manager.relays.items():
|
for url, r in client.relay_manager.relays.items():
|
||||||
status_text = (
|
status_text = (
|
||||||
|
|
@ -52,20 +44,30 @@ async def api_get_relays(): # type: ignore
|
||||||
@nostrclient_ext.post(
|
@nostrclient_ext.post(
|
||||||
"/api/v1/relay", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
|
"/api/v1/relay", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
|
||||||
)
|
)
|
||||||
async def api_add_relay(relay: Relay): # type: ignore
|
async def api_add_relay(relay: Relay) -> Optional[RelayList]:
|
||||||
assert relay.url, "no URL"
|
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:
|
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()
|
relay.id = urlsafe_short_hash()
|
||||||
await add_relay(relay)
|
await add_relay(relay)
|
||||||
await init_relays()
|
await init_relays()
|
||||||
|
return await get_relays()
|
||||||
|
|
||||||
|
|
||||||
@nostrclient_ext.delete(
|
@nostrclient_ext.delete(
|
||||||
"/api/v1/relay", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
|
"/api/v1/relay", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
|
||||||
)
|
)
|
||||||
async def api_delete_relay(relay: Relay): # type: ignore
|
async def api_delete_relay(relay: Relay) -> None:
|
||||||
assert relay.url
|
if not relay.url:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.BAD_REQUEST, detail=f"Relay url not provided."
|
||||||
|
)
|
||||||
client.relay_manager.remove_relay(relay.url)
|
client.relay_manager.remove_relay(relay.url)
|
||||||
await delete_relay(relay)
|
await delete_relay(relay)
|
||||||
|
|
||||||
|
|
@ -91,7 +93,7 @@ async def api_stop():
|
||||||
|
|
||||||
|
|
||||||
@nostrclient_ext.websocket("/api/v1/relay")
|
@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"""
|
"""Relay multiplexer: one client (per endpoint) <-> multiple relays"""
|
||||||
await websocket.accept()
|
await websocket.accept()
|
||||||
router = NostrRouter(websocket)
|
router = NostrRouter(websocket)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue