fix: improve nostrclient status detection and display
- Call nostrclient /relays API directly from frontend for accurate status - Show correct error messages from API response (body.detail) - Add orange warning state for no relays configured - Show relay count when connected (X of Y connected) - Simplify status logic: 200 = green, no relays = orange, error = red 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9911a03575
commit
d2755d7232
4 changed files with 118 additions and 60 deletions
|
|
@ -18,21 +18,18 @@ window.app = Vue.createApp({
|
||||||
},
|
},
|
||||||
wsConnection: null,
|
wsConnection: null,
|
||||||
nostrStatus: {
|
nostrStatus: {
|
||||||
nostrclient_available: false,
|
connected: false,
|
||||||
nostrclient_relays: [],
|
error: null,
|
||||||
nostrclient_error: null,
|
relays_connected: 0,
|
||||||
nostrmarket_running: false,
|
relays_total: 0
|
||||||
websocket_connected: false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
nostrStatusColor: function () {
|
nostrStatusColor: function () {
|
||||||
if (!this.nostrStatus.nostrclient_available) {
|
if (this.nostrStatus.connected) {
|
||||||
return 'red'
|
|
||||||
} else if (this.nostrStatus.websocket_connected) {
|
|
||||||
return 'green'
|
return 'green'
|
||||||
} else if (this.nostrStatus.nostrmarket_running) {
|
} else if (this.nostrStatus.warning) {
|
||||||
return 'orange'
|
return 'orange'
|
||||||
}
|
}
|
||||||
return 'red'
|
return 'red'
|
||||||
|
|
@ -218,31 +215,61 @@ window.app = Vue.createApp({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
checkNostrStatus: async function () {
|
checkNostrStatus: async function (showNotification = false) {
|
||||||
try {
|
try {
|
||||||
const {data} = await LNbits.api.request(
|
const response = await fetch('/nostrclient/api/v1/relays')
|
||||||
'GET',
|
const body = await response.json()
|
||||||
'/nostrmarket/api/v1/status',
|
console.log('Nostrclient /relays:', response.status, body)
|
||||||
this.g.user.wallets[0].inkey
|
|
||||||
)
|
if (response.status === 200) {
|
||||||
this.nostrStatus = data
|
const relaysConnected = body.filter(r => r.connected).length
|
||||||
if (!data.nostrclient_available) {
|
if (body.length === 0) {
|
||||||
|
this.nostrStatus = {
|
||||||
|
connected: false,
|
||||||
|
error: 'No relays configured in Nostr Client',
|
||||||
|
relays_connected: 0,
|
||||||
|
relays_total: 0,
|
||||||
|
warning: true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.nostrStatus = {
|
||||||
|
connected: true,
|
||||||
|
error: null,
|
||||||
|
relays_connected: relaysConnected,
|
||||||
|
relays_total: body.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.nostrStatus = {
|
||||||
|
connected: false,
|
||||||
|
error: body.detail,
|
||||||
|
relays_connected: 0,
|
||||||
|
relays_total: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showNotification) {
|
||||||
this.$q.notify({
|
this.$q.notify({
|
||||||
timeout: 5000,
|
timeout: 3000,
|
||||||
type: 'warning',
|
type: this.nostrStatus.connected ? 'positive' : 'warning',
|
||||||
message: 'Nostrclient extension not available',
|
message: this.nostrStatus.connected ? 'Connected' : 'Disconnected',
|
||||||
caption:
|
caption: this.nostrStatus.error || undefined
|
||||||
data.nostrclient_error ||
|
|
||||||
'Please install and configure the nostrclient extension'
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Failed to check nostr status:', error)
|
||||||
this.nostrStatus = {
|
this.nostrStatus = {
|
||||||
nostrclient_available: false,
|
connected: false,
|
||||||
nostrclient_relays: [],
|
error: error.message,
|
||||||
nostrclient_error: 'Failed to check status',
|
relays_connected: 0,
|
||||||
nostrmarket_running: false,
|
relays_total: 0
|
||||||
websocket_connected: false
|
}
|
||||||
|
if (showNotification) {
|
||||||
|
this.$q.notify({
|
||||||
|
timeout: 5000,
|
||||||
|
type: 'negative',
|
||||||
|
message: this.nostrStatus.error
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -253,13 +280,18 @@ window.app = Vue.createApp({
|
||||||
)
|
)
|
||||||
.onOk(async () => {
|
.onOk(async () => {
|
||||||
try {
|
try {
|
||||||
|
this.$q.notify({
|
||||||
|
timeout: 2000,
|
||||||
|
type: 'info',
|
||||||
|
message: 'Reconnecting...'
|
||||||
|
})
|
||||||
await LNbits.api.request(
|
await LNbits.api.request(
|
||||||
'PUT',
|
'PUT',
|
||||||
'/nostrmarket/api/v1/restart',
|
'/nostrmarket/api/v1/restart',
|
||||||
this.g.user.wallets[0].adminkey
|
this.g.user.wallets[0].adminkey
|
||||||
)
|
)
|
||||||
// Check status after restart
|
// Check status after restart (give time for websocket to reconnect)
|
||||||
setTimeout(() => this.checkNostrStatus(), 2000)
|
setTimeout(() => this.checkNostrStatus(true), 3000)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<p class="text-body1">
|
<p>
|
||||||
Create, edit and publish products to your Nostr relays. Customers can
|
Create, edit and publish products to your Nostr relays. Customers can
|
||||||
browse your stalls and pay with Lightning.
|
browse your stalls and pay with Lightning.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item clickable v-close-popup @click="checkNostrStatus">
|
<q-item clickable v-close-popup @click="checkNostrStatus(true)">
|
||||||
<q-item-section avatar>
|
<q-item-section avatar>
|
||||||
<q-icon name="wifi_find" color="primary"></q-icon>
|
<q-icon name="wifi_find" color="primary"></q-icon>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
|
|
@ -185,27 +185,29 @@
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label caption>
|
<q-item-label caption>
|
||||||
<strong>Nostrclient:</strong>
|
<strong>Status:</strong>
|
||||||
<q-badge
|
<q-badge
|
||||||
:color="nostrStatus.nostrclient_available ? 'green' : 'red'"
|
:color="nostrStatus.connected ? 'green' : 'red'"
|
||||||
class="q-ml-xs"
|
class="q-ml-xs"
|
||||||
v-text="nostrStatus.nostrclient_available ? 'Available' : 'Not Available'"
|
v-text="nostrStatus.connected ? 'Connected' : 'Disconnected'"
|
||||||
></q-badge>
|
|
||||||
<br />
|
|
||||||
<strong>Relays:</strong>
|
|
||||||
<span v-text="(nostrStatus.nostrclient_relays || []).length"></span> configured<br />
|
|
||||||
<strong>WebSocket:</strong>
|
|
||||||
<q-badge
|
|
||||||
:color="nostrStatus.websocket_connected ? 'green' : 'orange'"
|
|
||||||
class="q-ml-xs"
|
|
||||||
v-text="nostrStatus.websocket_connected ? 'Connected' : 'Disconnected'"
|
|
||||||
></q-badge>
|
></q-badge>
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item-label
|
<q-item-label
|
||||||
v-if="nostrStatus.nostrclient_error"
|
v-if="nostrStatus.relays_total > 0"
|
||||||
|
caption
|
||||||
|
class="q-mt-xs"
|
||||||
|
>
|
||||||
|
<strong>Relays:</strong>
|
||||||
|
<span v-text="nostrStatus.relays_connected"></span>
|
||||||
|
of
|
||||||
|
<span v-text="nostrStatus.relays_total"></span>
|
||||||
|
connected
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label
|
||||||
|
v-if="nostrStatus.error"
|
||||||
caption
|
caption
|
||||||
class="text-negative q-mt-xs"
|
class="text-negative q-mt-xs"
|
||||||
v-text="nostrStatus.nostrclient_error"
|
v-text="nostrStatus.error"
|
||||||
></q-item-label>
|
></q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
|
||||||
52
views_api.py
52
views_api.py
|
|
@ -1113,31 +1113,55 @@ async def api_get_nostr_status(
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""Get the status of the nostrclient extension."""
|
"""Get the status of the nostrclient extension."""
|
||||||
nostrclient_available = False
|
nostrclient_available = False
|
||||||
nostrclient_relays = []
|
relays = []
|
||||||
nostrclient_error = None
|
error = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
response = await client.get(
|
url = f"http://127.0.0.1:{settings.port}/nostrclient/api/v1/relays"
|
||||||
f"http://localhost:{settings.port}/nostrclient/api/v1/relays",
|
logger.info(f"Calling nostrclient API: {url}")
|
||||||
timeout=5.0,
|
response = await client.get(url, timeout=5.0)
|
||||||
|
logger.info(
|
||||||
|
f"Nostrclient response: status={response.status_code}, "
|
||||||
|
f"body={response.text[:500]}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
nostrclient_available = True
|
nostrclient_available = True
|
||||||
nostrclient_relays = response.json()
|
relays = response.json()
|
||||||
|
else:
|
||||||
|
# Any non-200 response means we can't verify nostrclient is working
|
||||||
|
try:
|
||||||
|
error = response.json().get("detail", f"HTTP {response.status_code}")
|
||||||
|
except Exception:
|
||||||
|
error = f"HTTP {response.status_code}"
|
||||||
except httpx.ConnectError:
|
except httpx.ConnectError:
|
||||||
nostrclient_error = "Cannot connect to nostrclient extension"
|
error = "Cannot connect to nostrclient extension"
|
||||||
except httpx.TimeoutException:
|
except httpx.TimeoutException:
|
||||||
nostrclient_error = "Timeout connecting to nostrclient"
|
error = "Timeout connecting to nostrclient"
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
nostrclient_error = str(ex)
|
error = str(ex)
|
||||||
|
|
||||||
|
# Only show connected if no errors and websocket is connected
|
||||||
|
connected = (
|
||||||
|
nostrclient_available
|
||||||
|
and nostr_client.is_websocket_connected
|
||||||
|
and error is None
|
||||||
|
)
|
||||||
|
|
||||||
|
# If nostrclient exists but websocket not connected, explain why
|
||||||
|
if nostrclient_available and not nostr_client.is_websocket_connected and not error:
|
||||||
|
error = "Websocket not connected"
|
||||||
|
|
||||||
|
# Count connected relays
|
||||||
|
relays_connected = sum(1 for r in relays if r.get("connected", False))
|
||||||
|
relays_total = len(relays)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"nostrclient_available": nostrclient_available,
|
"connected": connected,
|
||||||
"nostrclient_relays": nostrclient_relays,
|
"error": error,
|
||||||
"nostrclient_error": nostrclient_error,
|
"relays_connected": relays_connected,
|
||||||
"nostrmarket_running": nostr_client.running,
|
"relays_total": relays_total,
|
||||||
"websocket_connected": nostr_client.is_websocket_connected,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue