mirror of
https://github.com/aljazceru/nostr-watch.git
synced 2025-12-17 05:24:19 +01:00
Merge branch 'main' into patch-1
This commit is contained in:
@@ -2,11 +2,6 @@
|
||||
|
||||
A client-side nostr network status built with Vue3, [nostr-js](https://github.com/jb55/nostr-js) and [nostr-relay-inspector](https://github.com/dskvr/nostr-relay-inspector). Goal is to produce a client-side app that collects detailed information about nostr relays and the network in general to assist users, developers and relay operators alike.
|
||||
|
||||
## Goals
|
||||
- [x] Rapidly learn Nostr Protocol _Personal Goal_
|
||||
- [ ] Tool that can assist in a visual understanding of Nostr for developers
|
||||
- [ ] Tool that can assist in onboarding for Users
|
||||
|
||||
## Features
|
||||
- [x] Real-time relay status
|
||||
- [x] Real-time, client-centric latency tests
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nostr-watch",
|
||||
"version": "0.0.15",
|
||||
"version": "0.0.16",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"prebuild": "node ./scripts/geo.js",
|
||||
@@ -31,8 +31,7 @@
|
||||
"node-emoji": "1.11.0",
|
||||
"node-polyfill-webpack-plugin": "2.0.1",
|
||||
"nostr": "0.2.5",
|
||||
"nostr-relay-inspector": "0.0.9",
|
||||
"nostr-tools": "0.24.1",
|
||||
"nostr-relay-inspector": "0.0.10",
|
||||
"onion-regex": "2.0.8",
|
||||
"requests": "0.3.0",
|
||||
"sass": "1.56.1",
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
relays:
|
||||
- 'wss://rsslay.fiatjaf.com'
|
||||
- 'wss://relayer.fiatjaf.com'
|
||||
- 'wss://freedom-relay.herokuapp.com/ws'
|
||||
- 'wss://nostr-relay.freeberty.net'
|
||||
- 'wss://nostr-relay.wlvs.space'
|
||||
@@ -40,3 +38,4 @@ relays:
|
||||
- 'wss://nostr-2.zebedee.cloud'
|
||||
- 'wss://nostr.shadownode.org'
|
||||
- 'wss://nostr.nymsrelay.com/'
|
||||
- 'wss://expensive-relay.fiatjaf.com'
|
||||
|
||||
@@ -12,6 +12,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body { margin: 0 !important; }
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<section id="refresh">
|
||||
<span>Updated {{ refreshData?.sinceLast }} ago <button @click="invalidate(true)">Update Now</button></span>
|
||||
<span>Updated {{ refreshData?.sinceLast }} ago <button @click="invalidate(true, this.relay)">Refresh{{ relay ? ` ${relay}` : "" }}</button></span>
|
||||
<span v-if="preferences.refresh"> Next refresh in: {{ refreshData?.untilNext }}</span>
|
||||
</section>
|
||||
</template>
|
||||
@@ -33,7 +33,7 @@ const localMethods = {
|
||||
this.refreshData.sinceLast = this.timeSinceRefresh()
|
||||
|
||||
if(this.isExpired() && this.preferences.refresh)
|
||||
this.invalidate()
|
||||
this.invalidate(false, this.relay)
|
||||
|
||||
}, 1000)
|
||||
}
|
||||
@@ -57,9 +57,7 @@ export default defineComponent({
|
||||
updated(){
|
||||
this.saveState('preferences')
|
||||
|
||||
if(this.isDone()) {
|
||||
this.saveState('lastUpdate')
|
||||
}
|
||||
this.saveState('lastUpdate')
|
||||
|
||||
this.refreshData.untilNext = this.timeUntilRefresh()
|
||||
this.refreshData.sinceLast = this.timeSinceRefresh()
|
||||
@@ -67,6 +65,12 @@ export default defineComponent({
|
||||
computed: {},
|
||||
methods: Object.assign(localMethods, sharedMethods),
|
||||
props: {
|
||||
relay: {
|
||||
type: String,
|
||||
default(){
|
||||
return ""
|
||||
}
|
||||
},
|
||||
relaysProp:{
|
||||
type: Object,
|
||||
default(){
|
||||
|
||||
@@ -43,10 +43,6 @@
|
||||
</ul>
|
||||
</td>
|
||||
|
||||
<!-- <td class="nip nip-11">
|
||||
<a v-if="result?.info" @click="showModal=true">✅ </a>
|
||||
</td> -->
|
||||
|
||||
<vue-final-modal v-model="showModal" classes="modal-container" content-class="modal-content">
|
||||
<div class="modal__title">
|
||||
<span>{{ result?.info?.name }}</span>
|
||||
@@ -83,7 +79,7 @@
|
||||
<script>
|
||||
import { defineComponent} from 'vue'
|
||||
import { VueFinalModal } from 'vue-final-modal'
|
||||
import InspectorRelayResult from 'nostr-relay-inspector'
|
||||
import { InspectorRelayResult } from 'nostr-relay-inspector'
|
||||
import SafeMail from "@2alheure/vue-safe-mail";
|
||||
import { countryCodeEmoji } from 'country-code-emoji';
|
||||
import emoji from 'node-emoji';
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
</column>
|
||||
</row>
|
||||
|
||||
|
||||
<row container :gutter="12">
|
||||
<column :xs="12" :md="12" :lg="12" class="title-card">
|
||||
<div style="display: none">{{result}}</div> <!-- ? -->
|
||||
@@ -30,80 +29,89 @@
|
||||
<span><img :src="badgeCheck('read')" /></span>
|
||||
<span><img :src="badgeCheck('write')" /></span>
|
||||
</span>
|
||||
</column>
|
||||
</row>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<span v-if="result.info?.supported_nips" class="badges">
|
||||
<span v-for="(nip) in result.info.supported_nips" :key="`${relay}_${nip}`">
|
||||
<a :href="nipLink(nip)" target="_blank"><img :src="badgeLink(nip)" /></a>
|
||||
<row container :gutter="12" v-if="!result?.check?.connect">
|
||||
<column :xs="12" :md="12" :lg="12" class="title-card">
|
||||
This relay appears to be offline.
|
||||
</column>
|
||||
</row>
|
||||
|
||||
<br />
|
||||
|
||||
<row container :gutter="12" v-if="result?.check?.connect">
|
||||
<column :xs="12" :md="12" :lg="12" class="title-card">
|
||||
|
||||
<span v-if="result.info?.supported_nips" class="badges">
|
||||
<span v-for="(nip) in result.info.supported_nips" :key="`${relay}_${nip}`">
|
||||
<a :href="nipLink(nip)" target="_blank"><img :src="badgeLink(nip)" /></a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!--table>
|
||||
<tr>
|
||||
<th colspan="3"><h4>Status</h4></th>
|
||||
</tr>
|
||||
<tr v-if="result.checkClass">
|
||||
<td :class="result.checkClass.connect" class="connect indicator">Connected</td>
|
||||
<td :class="result.checkClass.read" class="read indicator">Read</td>
|
||||
<td :class="result.checkClass.write" class="write indicator">Write</td>
|
||||
</tr>
|
||||
</table-->
|
||||
<table v-if="result.info">
|
||||
<tr>
|
||||
<th colspan="2"><h4>Info</h4></th>
|
||||
</tr>
|
||||
<tbody v-if="result.info">
|
||||
<tr v-for="(value, key) in Object.entries(result.info).filter(value => value[0] != 'id' && value[0] != 'supported_nips')" :key="`${value}_${key}`">
|
||||
<td>{{ value[0] }}</td>
|
||||
<td v-if="value[0]!='contact' && value[0]!='pubkey' && value[0]!='software' && value[0]!='version'">{{ value[1] }} </td>
|
||||
<td v-if="value[0]=='contact'"><SafeMail :email="value[1]" /></td>
|
||||
<td v-if="value[0]=='pubkey' || value[0]=='version'"><code>{{ value[1] }}</code></td>
|
||||
<td v-if="value[0]=='software'"><a :href="value[1]">{{ value[1] }}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tr v-if="Object.entries(result.info).length == 0 && result.check.connect">
|
||||
Relay does not have NIP-11 support, or the administrator has not configured the relay to return information.
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<table v-if="result.info">
|
||||
<tr>
|
||||
<th colspan="2"><h4>Info</h4></th>
|
||||
</tr>
|
||||
<tr v-for="(value, key) in Object.entries(result.info).filter(value => value[0] != 'id' && value[0] != 'supported_nips')" :key="`${value}_${key}`">
|
||||
<h4>Identities</h4>
|
||||
<table v-if="result.identities">
|
||||
<tr v-for="(value, key) in Object.entries(result?.identities)" :key="`${value}_${key}`">
|
||||
<td>{{ value[0] }}</td>
|
||||
<td v-if="value[0]!='contact' && value[0]!='pubkey' && value[0]!='software' && value[0]!='version'">{{ value[1] }} </td>
|
||||
<td v-if="value[0]=='contact'"><SafeMail :email="value[1]" /></td>
|
||||
<td v-if="value[0]=='pubkey' || value[0]=='version'"><code>{{ value[1] }}</code></td>
|
||||
<td v-if="value[0]=='software'"><a href="{{ value[1] }}">{{ value[1] }}</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<td><code>{{ value[1] }}</code></td>
|
||||
</tr>
|
||||
<tr v-if="Object.entries(result.identities).length==0">
|
||||
Relay does not provide NIP-05 support and has not registered an administrator key.
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h4>Identities</h4>
|
||||
<table v-if="result.identities">
|
||||
<div style="display: none">{{result}}</div> <!-- ? -->
|
||||
</column>
|
||||
<column :xs="12" :md="6" :lg="6" class="title-card">
|
||||
|
||||
<tr v-for="(value, key) in Object.entries(result?.identities)" :key="`${value}_${key}`">
|
||||
<h4>GEO {{geo?.countryCode ? getFlag() : ''}}</h4>
|
||||
<table v-if="geo[relay]">
|
||||
<tr v-for="(value, key) in Object.entries(geo[relay])" :key="`${value}_${key}`">
|
||||
<td>{{ value[0] }}</td>
|
||||
<td>{{ value[1] }} </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<td>{{ value[0] }}</td>
|
||||
<td><code>{{ value[1] }}</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
</column>
|
||||
<column :xs="12" :md="6" :lg="6" class="title-card">
|
||||
<h4>DNS</h4>
|
||||
<table v-if="geo[relay]">
|
||||
<tr v-for="(value, key) in Object.entries(geo[relay].dns)" :key="`${value}_${key}`">
|
||||
<td>{{ value[0] }}</td>
|
||||
<td>{{ value[1] }} </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div style="display: none">{{result}}</div> <!-- ? -->
|
||||
</column>
|
||||
</row>
|
||||
|
||||
<row container :gutter="12">
|
||||
<column :xs="12" :md="6" :lg="6" class="title-card">
|
||||
|
||||
<h4>GEO {{geo?.countryCode ? getFlag() : ''}}</h4>
|
||||
<table v-if="geo[relay]">
|
||||
<tr v-for="(value, key) in Object.entries(geo[relay])" :key="`${value}_${key}`">
|
||||
<td>{{ value[0] }}</td>
|
||||
<td>{{ value[1] }} </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</column>
|
||||
<column :xs="12" :md="6" :lg="6" class="title-card">
|
||||
<h4>DNS</h4>
|
||||
<table v-if="geo[relay]">
|
||||
<tr v-for="(value, key) in Object.entries(geo[relay].dns)" :key="`${value}_${key}`">
|
||||
<td>{{ value[0] }}</td>
|
||||
<td>{{ value[1] }} </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div style="display: none">{{result}}</div> <!-- ? -->
|
||||
|
||||
</column>
|
||||
<div style="display: none">{{result}}</div> <!-- ? -->
|
||||
|
||||
</column>
|
||||
</row>
|
||||
|
||||
|
||||
<RefreshComponent
|
||||
:relay="relay"
|
||||
/>
|
||||
<span class="credit"><a href="http://sandwich.farm">Another 🥪 by sandwich.farm</a>, built with <a href="https://github.com/jb55/nostr-js">nostr-js</a> and <a href="https://github.com/dskvr/nostr-relay-inspector">nostr-relay-inspector</a>, inspired by <a href="https://github.com/fiatjaf/nostr-relay-registry">nostr-relay-registry</a></span>
|
||||
|
||||
</div>
|
||||
@@ -116,25 +124,43 @@ import { useStorage } from "vue3-storage";
|
||||
|
||||
import LeafletSingleComponent from '../components/LeafletSingleComponent.vue'
|
||||
import NavComponent from '../components/NavComponent.vue'
|
||||
import RefreshComponent from '../components/RefreshComponent.vue'
|
||||
|
||||
import { Row, Column } from 'vue-grid-responsive';
|
||||
import SafeMail from "@2alheure/vue-safe-mail";
|
||||
import emoji from 'node-emoji';
|
||||
import { countryCodeEmoji } from 'country-code-emoji';
|
||||
|
||||
import { Inspector, InspectorObservation } from 'nostr-relay-inspector'
|
||||
// import { Inspector, InspectorObservation } from '../../lib/nostr-relay-inspector'
|
||||
// import { Inspector, InspectorObservation } from '../../lib/nostr-relay-inspector'
|
||||
import sharedMethods from '../shared'
|
||||
|
||||
import { version } from '../../package.json'
|
||||
import { relays } from '../../relays.yaml'
|
||||
import { geo } from '../../geo.yaml'
|
||||
import { messages as RELAY_MESSAGES, codes as RELAY_CODES } from '../../codes.yaml'
|
||||
|
||||
const localMethods = {
|
||||
relayUrl() {
|
||||
// We will see what `params` is shortly
|
||||
return `wss://${this.$route.params.relayUrl}`
|
||||
},
|
||||
|
||||
badgeLink(nip){
|
||||
return `https://img.shields.io/static/v1?style=for-the-badge&label=NIP&message=${this.nipSignature(nip)}&color=black`
|
||||
},
|
||||
|
||||
badgeCheck(which){
|
||||
return `https://img.shields.io/static/v1?style=for-the-badge&label=&message=${which}&color=${this.result?.check?.[which] ? 'green' : 'red'}`
|
||||
},
|
||||
|
||||
import crypto from "crypto"
|
||||
nipSignature(key){
|
||||
return key.toString().length == 1 ? `0${key}` : key
|
||||
},
|
||||
|
||||
nipFormatted(key){
|
||||
return `NIP-${this.nipSignature(key)}`
|
||||
},
|
||||
|
||||
nipLink(key){
|
||||
return `https://github.com/nostr-protocol/nips/blob/master/${this.nipSignature(key)}.md`
|
||||
},
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
title: "nostr.watch registry & network status",
|
||||
@@ -145,6 +171,7 @@ export default defineComponent({
|
||||
LeafletSingleComponent,
|
||||
NavComponent,
|
||||
SafeMail,
|
||||
RefreshComponent,
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -173,215 +200,21 @@ export default defineComponent({
|
||||
|
||||
this.storage = useStorage()
|
||||
this.lastUpdate = this.storage.getStorageSync('lastUpdate')
|
||||
this.preferences = this.storage.getStorageSync('preferences')
|
||||
this.result = this.storage.getStorageSync(this.relay)
|
||||
|
||||
if(this.isExpired())
|
||||
this.check(this.relay)
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
||||
},
|
||||
computed: {},
|
||||
|
||||
updated() {
|
||||
Object.keys(this.timeouts).forEach(timeout => clearTimeout(this.timeouts[timeout]))
|
||||
Object.keys(this.intervals).forEach(interval => clearInterval(this.intervals[interval]))
|
||||
},
|
||||
|
||||
methods: {
|
||||
isExpired(){
|
||||
return typeof this.lastUpdate === 'undefined' || Date.now() - this.lastUpdate > this.preferences.cacheExpiration
|
||||
},
|
||||
|
||||
saveState(relay){
|
||||
this.storage
|
||||
.setStorage({
|
||||
key: relay,
|
||||
data: this.result
|
||||
})
|
||||
.then(successCallback => {
|
||||
console.log(successCallback.errMsg);
|
||||
})
|
||||
.catch(failCallback => {
|
||||
console.log(failCallback.errMsg);
|
||||
})
|
||||
|
||||
this.storage
|
||||
.setStorage({
|
||||
key: "lastUpdate",
|
||||
data: Date.now()
|
||||
})
|
||||
.then(successCallback => {
|
||||
console.log(successCallback.errMsg);
|
||||
this.lastUpdate = Date.now()
|
||||
})
|
||||
.catch(failCallback => {
|
||||
console.log(failCallback.errMsg);
|
||||
})
|
||||
},
|
||||
relayUrl() {
|
||||
// We will see what `params` is shortly
|
||||
return `wss://${this.$route.params.relayUrl}`
|
||||
},
|
||||
async check(relay){
|
||||
//const self = this
|
||||
/* return new Promise(function(resolve, reject) { */
|
||||
/* let nip = new Array(99).fill(false);
|
||||
nip[5] = true
|
||||
nip[11] = true */
|
||||
|
||||
const opts = {
|
||||
checkLatency: true,
|
||||
checkNips: true,
|
||||
/* checkNip: nip, */
|
||||
/* debug: true */
|
||||
}
|
||||
|
||||
let inspect = new Inspector(relay, opts)
|
||||
.on('run', (result) => {
|
||||
result.aggregate = 'processing'
|
||||
})
|
||||
.on('open', (e, result) => {
|
||||
this.result = result
|
||||
this.result.checkClass = {read: null, write: null, connect: null}
|
||||
this.setResultClass('connect')
|
||||
})
|
||||
.on('complete', (instance) => {
|
||||
this.result = instance.result
|
||||
this.messages[this.relay] = instance.inbox
|
||||
|
||||
/* this.setFlag(relay) */
|
||||
this.setAggregateResult()
|
||||
/* this.adjustResult(relay) */
|
||||
this.setResultClass('read')
|
||||
this.setResultClass('write')
|
||||
this.saveState(relay)
|
||||
})
|
||||
.on('notice', (notice) => {
|
||||
const hash = this.sha1(notice)
|
||||
let message_obj = RELAY_MESSAGES[hash]
|
||||
let code_obj = RELAY_CODES[message_obj.code]
|
||||
|
||||
let response_obj = {...message_obj, ...code_obj}
|
||||
|
||||
this.result.observations.push( new InspectorObservation('notice', response_obj.code, response_obj.description, response_obj.relates_to) )
|
||||
})
|
||||
.on('close', (msg) => {
|
||||
console.warn("CAUTION", msg)
|
||||
})
|
||||
.on('error', (err) => {
|
||||
console.error("ERROR", err)
|
||||
})
|
||||
.run()
|
||||
|
||||
return inspect;
|
||||
/* }) */
|
||||
|
||||
},
|
||||
setResultClass (key) {
|
||||
let result = this.result?.check?.[key] === true
|
||||
? 'success'
|
||||
: this.result?.check?.[key] === false
|
||||
? 'failure'
|
||||
: 'pending'
|
||||
this.result.checkClass[key] = result
|
||||
},
|
||||
getLoadingClass () {
|
||||
return this.result?.state == 'complete' ? "relay loaded" : "relay"
|
||||
},
|
||||
generateKey (url, key) {
|
||||
return `${url}_${key}`
|
||||
},
|
||||
|
||||
getFlag () {
|
||||
return this.geo?.countryCode ? countryCodeEmoji(this.geo.countryCode) : emoji.get('shrug');
|
||||
},
|
||||
|
||||
setCheck (bool) {
|
||||
return bool ? '✅ ' : ''
|
||||
},
|
||||
|
||||
badgeLink(nip){
|
||||
return `https://img.shields.io/static/v1?style=for-the-badge&label=NIP&message=${this.nipSignature(nip)}&color=black`
|
||||
},
|
||||
|
||||
badgeCheck(which){
|
||||
return `https://img.shields.io/static/v1?style=for-the-badge&label=&message=${which}&color=${this.result?.check?.[which] ? 'green' : 'red'}`
|
||||
},
|
||||
|
||||
setCross (bool) {
|
||||
return !bool ? '❌' : ''
|
||||
},
|
||||
setCaution (bool) {
|
||||
return !bool ? '⚠️' : ''
|
||||
},
|
||||
identityList () {
|
||||
let string = '',
|
||||
extraString = '',
|
||||
users = Object.entries(this.result.identities),
|
||||
count = 0
|
||||
|
||||
if(this.result.identities) {
|
||||
if(this.result.identities.serverAdmin) {
|
||||
string = `Relay has registered an administrator pubkey: ${this.result.identities.serverAdmin}. `
|
||||
extraString = "Additionally, "
|
||||
}
|
||||
|
||||
const total = users.filter(([key]) => key!='serverAdmin').length,
|
||||
isOne = total==1
|
||||
|
||||
if(total) {
|
||||
string = `${string}${extraString}Relay domain contains NIP-05 verification data for:`
|
||||
users.forEach( ([key]) => {
|
||||
if(key == "serverAdmin") return
|
||||
count++
|
||||
string = `${string} ${(count==total && !isOne) ? 'and' : ''} @${key}${(count!=total && !isOne) ? ', ' : ''}`
|
||||
})
|
||||
}
|
||||
}
|
||||
return string
|
||||
},
|
||||
nipSignature(key){
|
||||
return key.toString().length == 1 ? `0${key}` : key
|
||||
},
|
||||
nipFormatted(key){
|
||||
return `NIP-${this.nipSignature(key)}`
|
||||
},
|
||||
nipLink(key){
|
||||
return `https://github.com/nostr-protocol/nips/blob/master/${this.nipSignature(key)}.md`
|
||||
},
|
||||
async copy(text) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch(err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
|
||||
setAggregateResult () {
|
||||
if(!this.result) return
|
||||
|
||||
let aggregateTally = 0
|
||||
aggregateTally += this.result?.check.connect ? 1 : 0
|
||||
aggregateTally += this.result?.check.read ? 1 : 0
|
||||
aggregateTally += this.result?.check.write ? 1 : 0
|
||||
if (aggregateTally == 3) {
|
||||
this.result.aggregate = 'public'
|
||||
}
|
||||
else if (aggregateTally == 0) {
|
||||
this.result.aggregate = 'offline'
|
||||
}
|
||||
else {
|
||||
this.result.aggregate = 'restricted'
|
||||
}
|
||||
},
|
||||
|
||||
sha1 (message) {
|
||||
const hash = crypto.createHash('sha1').update(JSON.stringify(message)).digest('hex')
|
||||
return hash
|
||||
},
|
||||
|
||||
},
|
||||
methods: Object.assign(localMethods, sharedMethods),
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -4,19 +4,22 @@ import { messages as RELAY_MESSAGES, codes as RELAY_CODES } from '../codes.yaml'
|
||||
import crypto from "crypto"
|
||||
|
||||
export default {
|
||||
invalidate: function(force){
|
||||
invalidate: async function(force, single){
|
||||
if(!this.isExpired() && !force)
|
||||
return
|
||||
|
||||
this.relays.forEach(async relay => {
|
||||
await this.check(relay)
|
||||
this.relays[relay] = this.getState(relay)
|
||||
this.messages[relay] = this.getState(`${relay}_inbox`)
|
||||
})
|
||||
|
||||
// if(this.preferences.refresh)
|
||||
// this.timeouts.invalidate = setTimeout(()=> this.invalidate(), 1000)
|
||||
|
||||
if(single) {
|
||||
await this.check(single)
|
||||
this.relays[single] = this.getState(single)
|
||||
this.messages[single] = this.getState(`${single}_inbox`)
|
||||
}
|
||||
else {
|
||||
this.relays.forEach(async relay => {
|
||||
await this.check(relay)
|
||||
this.relays[relay] = this.getState(relay)
|
||||
this.messages[relay] = this.getState(`${relay}_inbox`)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
isExpired: function(){
|
||||
|
||||
Reference in New Issue
Block a user