|
|
@ -1,7 +1,7 @@ |
|
|
|
<template> |
|
|
|
<div> |
|
|
|
<div class="text-h5 text-bold q-py-md q-px-sm full-width flex row justify-start"> |
|
|
|
<h1>Nostr Relay Registry</h1> |
|
|
|
<h1>Nostr Relay Status <sup>alpha</sup></h1> |
|
|
|
<span>Next ping in {{ nextPing }} seconds</span> | |
|
|
|
<span v-if="relays.filter((url) => status[url] && !status[url].complete).length > 0">Processing {{relays.filter((url) => status[url].complete).length}}/{{relays.length}}</span> |
|
|
|
</div> |
|
|
@ -10,39 +10,40 @@ |
|
|
|
<column :xs="12" :md="12" :lg="6"> |
|
|
|
<div> |
|
|
|
<h2><span class="indicator badge readwrite">{{ query('public').length }}</span>Public</h2> |
|
|
|
<table class="online" v-if="query('public').length > 0"> |
|
|
|
<table class="online public" v-if="query('public').length > 0"> |
|
|
|
<tr> |
|
|
|
<th></th> |
|
|
|
<th></th> |
|
|
|
<th>ℹ️</th> |
|
|
|
<th>🔌</th> |
|
|
|
<th>👁️🗨️</th> |
|
|
|
<th>✏️</th> |
|
|
|
<th><span class="verified-shape-wrapper"><span class="shape verified"></span></span></th> |
|
|
|
<th>🌎</th> |
|
|
|
<!-- <td>wl</td> |
|
|
|
<td>nip-05><td> --> |
|
|
|
<th>⌛️</th> |
|
|
|
<th>ℹ️</th> |
|
|
|
<th>NIP-15</th> |
|
|
|
<th>NIP-20</th> |
|
|
|
<th>FILTER: LIMIT</th> |
|
|
|
</tr> |
|
|
|
<tr v-for="relay in query('public')" :key="{relay}" :class="getLoadingClass(relay)"> |
|
|
|
<td :key="generateKey(relay, 'aggregate')"><span :class="getAggregateStatusClass(relay)"></span></td> |
|
|
|
|
|
|
|
<td class="left-align relay-url" @click="copy(relay)">{{ relay }}</td> |
|
|
|
<td> |
|
|
|
<ul v-if="Object.keys(status[relay].notes).length"> |
|
|
|
<li v-tooltip:left.tooltip="key" v-for="(message, key) in status[relay].notes" :key="generateKey(relay, key)">✉️</li> |
|
|
|
</ul> |
|
|
|
</td> |
|
|
|
<td :key="generateKey(relay, 'didConnect')"><span :class="getStatusClass(relay, 'didConnect')"></span></td> |
|
|
|
<td :key="generateKey(relay, 'didRead')"><span :class="getStatusClass(relay, 'didRead')"></span></td> |
|
|
|
<td :key="generateKey(relay, 'didWrite')"><span :class="getStatusClass(relay, 'didWrite')"></span></td> |
|
|
|
<td></td> |
|
|
|
<td>{{status[relay].flag}}</td> |
|
|
|
<td><span v-if="status[relay].didConnect">{{ status[relay].latency }}<span v-if="status[relay].latency">ms</span></span></td> |
|
|
|
<td> |
|
|
|
<Popper v-if="Object.keys(status[relay].messages).length"> |
|
|
|
{{ status[relay].type }} |
|
|
|
<button @mouseover="showPopper">log</button> |
|
|
|
<template #content> |
|
|
|
<ul> |
|
|
|
<li v-for="(message, key) in status[relay].messages" :key="generateKey(relay, key)">{{key}}</li> |
|
|
|
</ul> |
|
|
|
</template> |
|
|
|
</Popper> |
|
|
|
</td> |
|
|
|
<td>{{ setCheck(status[relay].didNip15) }}</td> |
|
|
|
<td>{{ setCheck(status[relay].didNip20) }}</td> |
|
|
|
<td>{{ setCaution(status[relay].didSubscribeFilterLimit) }}</td> |
|
|
|
</tr> |
|
|
|
</table> |
|
|
|
</div> |
|
|
@ -71,14 +72,9 @@ |
|
|
|
<td>{{status[relay].flag}}</td> |
|
|
|
<td><span v-if="status[relay].didConnect">{{ status[relay].latency }}<span v-if="status[relay].latency">ms</span></span></td> |
|
|
|
<td> |
|
|
|
<Popper v-if="Object.keys(status[relay].messages).length"> |
|
|
|
<button @mouseover="showPopper">log</button> |
|
|
|
<template #content> |
|
|
|
<ul> |
|
|
|
<li v-for="(message, key) in status[relay].messages" :key="generateKey(relay, key)">{{key}}</li> |
|
|
|
</ul> |
|
|
|
</template> |
|
|
|
</Popper> |
|
|
|
<ul v-if="Object.keys(status[relay].notes).length"> |
|
|
|
<li v-tooltip:left.tooltip="key" v-for="(message, key) in status[relay].notes" :key="generateKey(relay, key)">✉️</li> |
|
|
|
</ul> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
</table> |
|
|
@ -91,7 +87,7 @@ |
|
|
|
<th>🔌</th> |
|
|
|
<th>👁️🗨️</th> |
|
|
|
<th>✏️</th> |
|
|
|
<th>msg</th> |
|
|
|
<th>ℹ️</th> |
|
|
|
</tr> |
|
|
|
<tr v-for="relay in query('offline')" :key="{relay}" :class="getLoadingClass(relay)"> |
|
|
|
<td :key="generateKey(relay, 'aggregate')"><span :class="getAggregateStatusClass(relay)"></span></td> |
|
|
@ -100,14 +96,9 @@ |
|
|
|
<td :key="generateKey(relay, 'didRead')"><span :class="getStatusClass(relay, 'didRead')"></span></td> |
|
|
|
<td :key="generateKey(relay, 'didWrite')"><span :class="getStatusClass(relay, 'didWrite')"></span></td> |
|
|
|
<td> |
|
|
|
<Popper v-if="Object.keys(status[relay].messages).length"> |
|
|
|
<button>log</button> |
|
|
|
<template #content> |
|
|
|
<ul> |
|
|
|
<li v-for="(message, key) in status[relay].messages" :key="generateKey(relay, key)">{{key}}</li> |
|
|
|
</ul> |
|
|
|
</template> |
|
|
|
</Popper> |
|
|
|
<ul v-if="Object.keys(status[relay].notes).length"> |
|
|
|
<li v-tooltip:left.tooltip="key" v-for="(message, key) in status[relay].notes" :key="generateKey(relay, key)">✉️</li> |
|
|
|
</ul> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
</table> |
|
|
@ -116,7 +107,7 @@ |
|
|
|
</row> |
|
|
|
|
|
|
|
<!-- <h2>Processing</h2> |
|
|
|
<table v-if="relays.filter((url) => !status[url].complete).length > 0"> |
|
|
|
<table v-if="relays.filter((url) => status[url] && !status[url].complete).length > 0"> |
|
|
|
<tr> |
|
|
|
<th></th> |
|
|
|
</tr> |
|
|
@ -125,12 +116,20 @@ |
|
|
|
</tr> |
|
|
|
</table> |
|
|
|
<a href="./relays/">JSON API</a> --> |
|
|
|
<a class="credit" href="http://sandwich.farm">Another 🥪 by sandwich.farm</a> |
|
|
|
|
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
/* eslint-disable */ |
|
|
|
import { defineComponent} from 'vue' |
|
|
|
import TooltipComponent from './TooltipComponent.vue' |
|
|
|
|
|
|
|
// import nip04 from 'nostr-tools/nip04' |
|
|
|
// import nip05 from '../../node_modules/nostr-tools/nip05' |
|
|
|
// import nip06 from 'nostr-tools/nip06' |
|
|
|
|
|
|
|
// import { relayConnect } from 'nostr-tools/relay' |
|
|
|
import { RelayPool, Relay } from 'nostr' |
|
|
|
|
|
|
@ -152,7 +151,7 @@ export default defineComponent({ |
|
|
|
components: { |
|
|
|
Row, |
|
|
|
Column, |
|
|
|
Popper |
|
|
|
TooltipComponent |
|
|
|
}, |
|
|
|
|
|
|
|
data() { |
|
|
@ -164,11 +163,156 @@ export default defineComponent({ |
|
|
|
connections: {}, |
|
|
|
latency: {}, |
|
|
|
pool: null, |
|
|
|
timeouts: {}, |
|
|
|
nips: {}, |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
mounted() { |
|
|
|
this.relays.forEach(async url => { |
|
|
|
this.status[url] = {} |
|
|
|
await this.testRelay(url) |
|
|
|
}) |
|
|
|
|
|
|
|
let latencyIntVal |
|
|
|
let counterIntVal |
|
|
|
|
|
|
|
// eslint-disable-next-line |
|
|
|
let latencyTimeout = setTimeout(() => { |
|
|
|
this.testRelayLatency() |
|
|
|
// eslint-disable-next-line |
|
|
|
latencyIntVal = setInterval(() => { this.testRelayLatency() }, refreshMillis) |
|
|
|
// eslint-disable-next-line |
|
|
|
latencyIntVal = setInterval(() => { this.nextPing = Math.round((this.lastPing + refreshMillis - Date.now())/1000)}, 1000) |
|
|
|
}, 10000) |
|
|
|
}, |
|
|
|
|
|
|
|
methods: { |
|
|
|
|
|
|
|
hardFail(url) { |
|
|
|
if(!this.status[url]) this.status[url] = {} |
|
|
|
this.status[url].didConnect = false |
|
|
|
this.status[url].didRead = false |
|
|
|
this.status[url].didWrite = false |
|
|
|
this.tryComplete(url) |
|
|
|
if(this.connections[url].close) this.connections[url].close() |
|
|
|
}, |
|
|
|
|
|
|
|
async testRelay (url) { |
|
|
|
this.lastPing = Date.now() |
|
|
|
this.latency[url] = {} |
|
|
|
this.timeouts[url] = {} |
|
|
|
this.status[url].notes = {} |
|
|
|
this.status[url].state = 'pending' |
|
|
|
this.nips[url] = new Array(99).fill(null); |
|
|
|
this.status[url].readEventCount = 0 |
|
|
|
this.status[url].writeEventCount = 0 |
|
|
|
this.status[url].latencyEventCount = 0 |
|
|
|
this.status[url].didNip15 = false |
|
|
|
this.status[url].didNip20 = false |
|
|
|
|
|
|
|
this.timeouts[url].didConnect = setTimeout(() => { |
|
|
|
console.log(url, "TIMEOUT") |
|
|
|
if(Object.keys(this.status[url].notes).length == 0) this.status[url].notes['Reason: Timeout'] = {} |
|
|
|
this.hardFail(url) |
|
|
|
}, 20000) |
|
|
|
|
|
|
|
let relay = Relay(url, {reconnect: false}) |
|
|
|
relay.on('open', e => { |
|
|
|
console.log(url, "OPEN") |
|
|
|
clearTimeout(this.timeouts[url].didConnect) |
|
|
|
this.status[url].didConnect = true |
|
|
|
this.testRead(url, "testRead") |
|
|
|
this.testWrite(url, "testWrite") |
|
|
|
this.tryComplete(url) |
|
|
|
console.log(url, "did connect", this.status[url].didConnect) |
|
|
|
}) |
|
|
|
relay.on('eose', e => { |
|
|
|
//console.log('EOSE', e) |
|
|
|
// relay.close() |
|
|
|
this.tryComplete(url) |
|
|
|
this.status[url].didNip15 = true |
|
|
|
}) |
|
|
|
relay.on('error', (e) => { |
|
|
|
//console.log('ERROR', e) |
|
|
|
clearTimeout(this.timeouts[url].didConnect) |
|
|
|
this.status[url].notes['Reason: Error'] = {} |
|
|
|
this.hardFail(url) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('ok', () => { |
|
|
|
this.status[url].didNip20 = true |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('close', (e) => { |
|
|
|
console.log('close', e) |
|
|
|
// console.dir(arguments) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('other', (e) => { |
|
|
|
// console.log('OTHER!!!!', e) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('event', (sub_id, ev) => { |
|
|
|
// console.log('event', sub_id, ev) |
|
|
|
if(sub_id == this.getID(url, "testRead")) { |
|
|
|
// console.log("SUCCESS:", "READ") |
|
|
|
this.status[url].readEventCount++ |
|
|
|
this.status[url].didRead = true |
|
|
|
clearTimeout(this.timeouts[url].testRead) |
|
|
|
this.connections[url].unsubscribe(sub_id) |
|
|
|
// this.tryComplete(url) |
|
|
|
this.tryComplete(url) |
|
|
|
} |
|
|
|
if(sub_id == this.getID(url, "testWrite")) { |
|
|
|
if(this.status[url].writeEventCount < 1) { |
|
|
|
// console.log("SUCCESS:", "WRITE") |
|
|
|
this.status[url].didWrite = true |
|
|
|
console.log(ev) |
|
|
|
// this.tryComplete(url) |
|
|
|
//console.log(url, this.timeouts[url].testWrite) |
|
|
|
clearTimeout(this.timeouts[url].testWrite) |
|
|
|
this.tryComplete(url) |
|
|
|
} |
|
|
|
this.status[url].writeEventCount++ |
|
|
|
} |
|
|
|
if(sub_id == this.getID(url, "testLatency")) { |
|
|
|
if(this.status[url].latencyEventCount < 1) { |
|
|
|
console.log(url, "SUCCESS:", "test latency") |
|
|
|
clearTimeout(this.timeouts[url].testLatency) |
|
|
|
console.log(this.latency[url].start, this.latency[url].final) |
|
|
|
this.latency[url].final = Date.now() - this.latency[url].start |
|
|
|
this.setLatency(url) |
|
|
|
} |
|
|
|
this.status[url].latencyEventCount++ |
|
|
|
// this.tryComplete(url) |
|
|
|
//console.log(url, this.timeouts[url].testRead) |
|
|
|
} |
|
|
|
// relay.unsubscribe(sub_id) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('message', (message) => { |
|
|
|
// console.log('message', message) |
|
|
|
// console.dir(arguments) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('notice', (message) => { |
|
|
|
const hash = this.sha1(message) |
|
|
|
let message_obj = RELAY_MESSAGES[hash] |
|
|
|
let code_obj = RELAY_CODES[message_obj.code] |
|
|
|
|
|
|
|
message_obj.type = code_obj.type |
|
|
|
message_obj.hash = hash |
|
|
|
this.status[url].notes[code_obj.description] = message_obj |
|
|
|
// this.adjustStatus(url, hash) |
|
|
|
}) |
|
|
|
this.connections[url] = relay |
|
|
|
await this.getIP(url) |
|
|
|
await this.setGeo(url) |
|
|
|
this.setFlag(url) |
|
|
|
// this.setNip05(url) |
|
|
|
}, |
|
|
|
|
|
|
|
// query (group, filterType) { |
|
|
|
query (group) { |
|
|
|
let unordered, |
|
|
@ -214,10 +358,10 @@ export default defineComponent({ |
|
|
|
|
|
|
|
getStatusClass (url, key) { |
|
|
|
let status = this.status?.[url]?.[key] === true |
|
|
|
? 'green' |
|
|
|
? 'success' |
|
|
|
: this.status?.[url]?.[key] === false |
|
|
|
? 'red' |
|
|
|
: 'silver' |
|
|
|
? 'failure' |
|
|
|
: 'pending' |
|
|
|
return `indicator ${status}` |
|
|
|
}, |
|
|
|
|
|
|
@ -225,6 +369,14 @@ export default defineComponent({ |
|
|
|
return this.status?.[url]?.complete ? "relay loaded" : "relay" |
|
|
|
}, |
|
|
|
|
|
|
|
// setNip05(url){ |
|
|
|
// const data = nip05(url.replace('wss://', '')) |
|
|
|
// if(data.length) { |
|
|
|
// this.nips[url][5] = data |
|
|
|
// this.status[url].nip05 = true |
|
|
|
// } |
|
|
|
// }, |
|
|
|
|
|
|
|
setAggregateStatus (url) { |
|
|
|
let aggregateTally = 0 |
|
|
|
aggregateTally += this.status?.[url]?.didConnect ? 1 : 0 |
|
|
@ -249,123 +401,43 @@ export default defineComponent({ |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
setComplete (url) { |
|
|
|
tryComplete (url) { |
|
|
|
let connect = typeof this.status?.[url]?.didConnect !== 'undefined', |
|
|
|
read = typeof this.status?.[url]?.didRead !== 'undefined', |
|
|
|
write = typeof this.status?.[url]?.didWrite !== 'undefined' |
|
|
|
|
|
|
|
// console.log(connect, read, write) |
|
|
|
|
|
|
|
this.setAggregateStatus(url) |
|
|
|
console.log(url, 'trying complete', connect, read, write) |
|
|
|
|
|
|
|
if(connect && read && write) { |
|
|
|
console.log(url, 'did complete') |
|
|
|
this.setAggregateStatus(url) |
|
|
|
this.adjustStatus(url) |
|
|
|
this.status[url].complete = true |
|
|
|
this.connections[url].close() |
|
|
|
this.status[url].testing = false |
|
|
|
if(this.status[url].readEventCount > 1) { |
|
|
|
this.status[url].didSubscribeFilterLimit = false |
|
|
|
} else { |
|
|
|
this.status[url].didSubscribeFilterLimit = true |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
generateKey (url, key) { |
|
|
|
return `${url}_${key}` |
|
|
|
}, |
|
|
|
|
|
|
|
testConnect (url) { |
|
|
|
// console.log(url, "CONNECT", "TEST") |
|
|
|
// const self = this |
|
|
|
// this.connections[url] = Relay(url) |
|
|
|
// console.log(this.connections[url]) |
|
|
|
// this.connections[url] |
|
|
|
// .on('open', (e) => { |
|
|
|
// console.log('open', e) |
|
|
|
// self.testWrite(url) |
|
|
|
// self.testRead(url) |
|
|
|
// }) |
|
|
|
// .on('error', (e) => { |
|
|
|
// console.log('error', e) |
|
|
|
// }) |
|
|
|
// |
|
|
|
// .on('message', (message) => { |
|
|
|
// console.log('message', message) |
|
|
|
// |
|
|
|
// // console.log(url, "CONNECT", "SUCCESS") |
|
|
|
// // const hash = this.sha1(message) |
|
|
|
// // let message_obj = RELAY_MESSAGES[hash] |
|
|
|
// // let code_obj = RELAY_CODES[message_obj.code] |
|
|
|
// // |
|
|
|
// // message_obj.type = code_obj.type |
|
|
|
// // this.status[url].messages[message] = message_obj |
|
|
|
// // this.adjustStatus(url, hash) |
|
|
|
// }) |
|
|
|
// .on('event', (relay, sub_id, ev) => { |
|
|
|
// console.log('event', relay, sub_id, ev) |
|
|
|
// }) |
|
|
|
// .on('notice', (message) => { |
|
|
|
// console.log('notice', message) |
|
|
|
// }) |
|
|
|
// .on('close', (e) => { |
|
|
|
// console.log('close', e) |
|
|
|
// }) |
|
|
|
|
|
|
|
|
|
|
|
// // () => {}, |
|
|
|
// (message) => { |
|
|
|
// |
|
|
|
// |
|
|
|
// console.log(hash) |
|
|
|
// console.dir(message_obj) |
|
|
|
// console.dir(code_obj) |
|
|
|
// |
|
|
|
// |
|
|
|
// // console.log("RECIEVED MESSAGE!") |
|
|
|
// // console.dir(this.status[url].messages) |
|
|
|
// }, |
|
|
|
// () => { |
|
|
|
// console.log(url, "CONNECT", "FAILURE") |
|
|
|
// this.status[url].didConnect = false |
|
|
|
// this.status[url].didRead = false |
|
|
|
// this.status[url].didWrite = false |
|
|
|
// this.setComplete(url) |
|
|
|
// } |
|
|
|
// ) |
|
|
|
// this.status[url].didConnect = true |
|
|
|
async testRead (url, id, benchmark) { |
|
|
|
const subid = this.getID(url, id) |
|
|
|
if(benchmark) this.latency[url].start = Date.now() |
|
|
|
if(benchmark) console.log(url, subid, this.latency[url].start) |
|
|
|
this.connections[url].subscribe(subid, {limit: 1, kinds:[1]}) |
|
|
|
this.timeouts[url][id] = setTimeout(() => { |
|
|
|
if(!benchmark) this.status[url].didRead = false |
|
|
|
this.tryComplete(url) |
|
|
|
}, 3000) |
|
|
|
}, |
|
|
|
|
|
|
|
async testRead (url) { |
|
|
|
// console.log(url, "READ", "TEST") |
|
|
|
this.connections[url].subscribe(this.getID(url, "read"), {limit: 1, kinds:[1]}) |
|
|
|
// console.dir(this.connections[url]) |
|
|
|
// // console.log(this.connections[url]['get status']()) |
|
|
|
// console.log(url, "READ", "TEST") |
|
|
|
// let start |
|
|
|
// start = Date.now(); |
|
|
|
// |
|
|
|
// |
|
|
|
// let {unsub} = await this.connections[url].sub( |
|
|
|
// { |
|
|
|
// cb: () => { |
|
|
|
// console.log(url, "READ", "SUCCESS") |
|
|
|
// this.status[url].didRead = true |
|
|
|
// this.setComplete(url) |
|
|
|
// this.latency[url].read = Date.now() - start; |
|
|
|
// unsub() |
|
|
|
// clearTimeout(willUnsub) |
|
|
|
// }, |
|
|
|
// filter: { |
|
|
|
// ids: [ |
|
|
|
// '41ce9bc50da77dda5542f020370ecc2b056d8f2be93c1cedf1bf57efcab095b0' |
|
|
|
// ] |
|
|
|
// } |
|
|
|
// }, |
|
|
|
// 'nostr-registry' |
|
|
|
// ) |
|
|
|
// let willUnsub = setTimeout(() => { |
|
|
|
// unsub() |
|
|
|
// console.log(url, "READ", "FAILURE") |
|
|
|
// if(!this.status[url].maybe_public) this.status[url].didRead = false |
|
|
|
// this.setComplete(url) |
|
|
|
// }, 10000) |
|
|
|
}, |
|
|
|
|
|
|
|
async testWrite (url) { |
|
|
|
async testWrite (url, id, benchmark) { |
|
|
|
// console.log(url, "WRITE", "TEST") |
|
|
|
const message = { |
|
|
|
id: '41ce9bc50da77dda5542f020370ecc2b056d8f2be93c1cedf1bf57efcab095b0', |
|
|
|
pubkey: |
|
|
@ -377,97 +449,39 @@ export default defineComponent({ |
|
|
|
sig: '08e6303565e9282f32bed41eee4136f45418f366c0ec489ef4f90d13de1b3b9fb45e14c74f926441f8155236fb2f6fef5b48a5c52b19298a0585a2c06afe39ed' |
|
|
|
} |
|
|
|
this.connections[url].send(["EVENT", message]) |
|
|
|
this.connections[url].subscribe(this.getID(url, "write"), {limit: 1, kinds:[1], ids:['41ce9bc50da77dda5542f020370ecc2b056d8f2be93c1cedf1bf57efcab095b0']}) |
|
|
|
this.connections[url].subscribe(this.getID(url, id), {limit: 1, kinds:[1], ids:['41ce9bc50da77dda5542f020370ecc2b056d8f2be93c1cedf1bf57efcab095b0']}) |
|
|
|
this.timeouts[url][id] = setTimeout(() => { |
|
|
|
console.log(url, "did write", id, false) |
|
|
|
if(!benchmark) this.status[url].didWrite = false |
|
|
|
this.tryComplete(url) |
|
|
|
}, 10000) |
|
|
|
}, |
|
|
|
|
|
|
|
getID(url, keyword) { |
|
|
|
return `${keyword}_${url}` |
|
|
|
}, |
|
|
|
|
|
|
|
async testRelay (url) { |
|
|
|
this.lastPing = Date.now() |
|
|
|
this.latency[url] = {} |
|
|
|
this.status[url].messages = {} |
|
|
|
|
|
|
|
let relay |
|
|
|
|
|
|
|
relay = Relay(url) |
|
|
|
relay.on('open', e => { |
|
|
|
// console.log(url, "OPEN") |
|
|
|
this.status[url].didConnect = true |
|
|
|
this.testRead(url) |
|
|
|
this.testWrite(url) |
|
|
|
this.setComplete(url) |
|
|
|
}) |
|
|
|
relay.on('eose', e => { |
|
|
|
// relay.close() |
|
|
|
}) |
|
|
|
relay.on('ok', () => { |
|
|
|
// console.log('ok') |
|
|
|
// console.dir(arguments) |
|
|
|
}) |
|
|
|
relay.on('error', (e, b) => { |
|
|
|
// console.log(b, e) |
|
|
|
this.status[url].didConnect = false |
|
|
|
}) |
|
|
|
relay.on('close', (e) => { |
|
|
|
// console.log('close', e) |
|
|
|
// console.dir(arguments) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('other', (e) => { |
|
|
|
// console.log('OTHER!!!!', e) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('event', (sub_id, ev) => { |
|
|
|
// console.log('event', sub_id, ev) |
|
|
|
if(sub_id == this.getID(url, "read")) { |
|
|
|
// console.log("SUCCESS:", "READ") |
|
|
|
this.status[url].didRead = true |
|
|
|
this.setComplete(url) |
|
|
|
} |
|
|
|
if(sub_id == this.getID(url, "write")) { |
|
|
|
// console.log("SUCCESS:", "WRITE") |
|
|
|
this.status[url].didWrite = true |
|
|
|
this.setComplete(url) |
|
|
|
} |
|
|
|
// relay.unsubscribe(sub_id) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('message', (message) => { |
|
|
|
// console.log('message', message) |
|
|
|
// console.dir(arguments) |
|
|
|
}) |
|
|
|
|
|
|
|
relay.on('notice', (message) => { |
|
|
|
console.log('notice', message) |
|
|
|
// console.dir(arguments) |
|
|
|
}) |
|
|
|
|
|
|
|
this.connections[url] = relay |
|
|
|
|
|
|
|
this.setLatency(url) |
|
|
|
// await this.getIP(url) |
|
|
|
// await this.setGeo(url) |
|
|
|
this.setFlag(url) |
|
|
|
}, |
|
|
|
|
|
|
|
isOnion(url){ |
|
|
|
return onionRegex().test(url) |
|
|
|
}, |
|
|
|
|
|
|
|
setLatency(url) { |
|
|
|
this.status[url].latency = this.latency[url].read |
|
|
|
// console.log(this.status[url].didConnect === true, this.status[url]. latency,this.latency[url].final) |
|
|
|
if (this.status[url].didConnect === true) this.status[url].latency = this.latency[url].final |
|
|
|
// console.log(this.status[url].didConnect === true, this.status[url]. latency,this.latency[url].final) |
|
|
|
console.log("latency",this.latency[url]) |
|
|
|
}, |
|
|
|
|
|
|
|
testRelayLatency(){ |
|
|
|
// console.log('testing latency') |
|
|
|
console.log('testing latency') |
|
|
|
this.relays.forEach(url => { |
|
|
|
// this.testWrite(url, true) |
|
|
|
this.testRead(url, true) |
|
|
|
this.setLatency(url) |
|
|
|
console.log(url, 'did read', this.status[url].didRead) |
|
|
|
if(this.status[url].didRead) { |
|
|
|
console.log(url, 'testing read') |
|
|
|
this.testRead(url, "testLatency", true) |
|
|
|
} |
|
|
|
this.lastPing = Date.now() |
|
|
|
}) |
|
|
|
this.lastPing = Date.now() |
|
|
|
}, |
|
|
|
|
|
|
|
async getIP(url){ |
|
|
@ -491,49 +505,42 @@ export default defineComponent({ |
|
|
|
this.status[url].flag = this.status[url].geo?.countryCode ? countryCodeEmoji(this.status[url].geo.countryCode) : emoji.get('shrug'); |
|
|
|
}, |
|
|
|
|
|
|
|
adjustStatus (url, hash) { |
|
|
|
let code = RELAY_MESSAGES[hash].code, |
|
|
|
type = RELAY_CODES[code].type |
|
|
|
|
|
|
|
this.status[url][type] = code |
|
|
|
if (type == "maybe_public") { |
|
|
|
this.status[url].didWrite = true |
|
|
|
this.status[url].didRead = true |
|
|
|
} |
|
|
|
if (type == "write_restricted") { |
|
|
|
this.status[url].didWrite = false |
|
|
|
} |
|
|
|
setCheck (bool) { |
|
|
|
return bool ? '✅ ' : '' |
|
|
|
}, |
|
|
|
|
|
|
|
setCross (bool) { |
|
|
|
return !bool ? '❌' : '' |
|
|
|
}, |
|
|
|
|
|
|
|
sha1 (message) { |
|
|
|
const hash = crypto.createHash('sha1').update(JSON.stringify(message)).digest('hex') |
|
|
|
// console.log(message, ':', hash) |
|
|
|
return hash |
|
|
|
setCaution (bool) { |
|
|
|
return !bool ? '⚠️' : '' |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mounted() { |
|
|
|
this.relays.forEach(async url => { |
|
|
|
this.status[url] = {} //statusInterface |
|
|
|
if (this.isOnion(url)) { |
|
|
|
url = `${url}.to` //add proxy |
|
|
|
} |
|
|
|
await this.testRelay(url) |
|
|
|
}) |
|
|
|
adjustStatus (url) { |
|
|
|
Object.entries(this.status[url].notes).forEach( ([key, value]) => { |
|
|
|
if(!value.hasOwnProperty("hash")) return |
|
|
|
let code = RELAY_MESSAGES[value.hash].code, |
|
|
|
type = RELAY_CODES[code].type |
|
|
|
|
|
|
|
// // eslint-disable-next-line |
|
|
|
// let latencyTimeout = setTimeout(() => { this.testRelayLatency() }, 10000) |
|
|
|
// |
|
|
|
// // eslint-disable-next-line |
|
|
|
// let latencyIntVal = setInterval(() => { this.testRelayLatency() }, refreshMillis) |
|
|
|
// // eslint-disable-next-line |
|
|
|
// let counterIntVal = setInterval(() => { |
|
|
|
// this.nextPing = Math.round((this.lastPing + refreshMillis - Date.now())/1000) |
|
|
|
// }, 1000) |
|
|
|
this.status[url][type] = code |
|
|
|
if (type == "maybe_public") { |
|
|
|
this.status[url].didWrite = false |
|
|
|
this.status[url].aggregate = 'public' |
|
|
|
} |
|
|
|
if (type == "write_restricted") { |
|
|
|
this.status[url].didWrite = false |
|
|
|
} |
|
|
|
}) |
|
|
|
}, |
|
|
|
|
|
|
|
sha1 (message) { |
|
|
|
const hash = crypto.createHash('sha1').update(JSON.stringify(message)).digest('hex') |
|
|
|
// console.log(message, ':', hash) |
|
|
|
return hash |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
}) |
|
|
@ -589,7 +596,8 @@ tr.relay.loaded td { |
|
|
|
} |
|
|
|
|
|
|
|
.badge.write-only, |
|
|
|
.badge.read-only { |
|
|
|
.badge.read-only, |
|
|
|
table.online.public .indicator.failure { |
|
|
|
background-color:orange !important; |
|
|
|
} |
|
|
|
|
|
|
@ -599,22 +607,22 @@ tr.relay.loaded td { |
|
|
|
border-style: solid; |
|
|
|
} |
|
|
|
|
|
|
|
.indicator.silver { |
|
|
|
.indicator.pernding { |
|
|
|
background-color: #c0c0c0; |
|
|
|
border-color: rgba(55,55,55,0.5); |
|
|
|
} |
|
|
|
|
|
|
|
.indicator.green { |
|
|
|
.indicator.success { |
|
|
|
background-color: green; |
|
|
|
border-color: rgba(0,255,0,0.5); |
|
|
|
} |
|
|
|
|
|
|
|
.indicator.red { |
|
|
|
.indicator.failure { |
|
|
|
background-color: red; |
|
|
|
border-color: rgba(255,0,0,0.5); |
|
|
|
} |
|
|
|
|
|
|
|
.indicator.orange { |
|
|
|
.indicator.caution { |
|
|
|
background-color: orange; |
|
|
|
border-color: rgba(255, 191, 0,0.5); |
|
|
|
} |
|
|
@ -678,4 +686,50 @@ table.online .relay-url { |
|
|
|
cursor: pointer; |
|
|
|
} |
|
|
|
|
|
|
|
.verified-shape-wrapper { |
|
|
|
display:inline-block; |
|
|
|
width: 16px; |
|
|
|
height: 16px; |
|
|
|
} |
|
|
|
|
|
|
|
.shape.verified { |
|
|
|
background: blue; |
|
|
|
width: 16px; |
|
|
|
height: 16px; |
|
|
|
position: relative; |
|
|
|
top: 5px; |
|
|
|
left:-5px; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
.shape.verified:before, |
|
|
|
.shape.verified:after { |
|
|
|
content: ""; |
|
|
|
position: absolute; |
|
|
|
top: 0; |
|
|
|
left: 0; |
|
|
|
height: 13px; |
|
|
|
width: 13px; |
|
|
|
background: blue; |
|
|
|
} |
|
|
|
.shape.verified:before { |
|
|
|
transform: rotate(30deg); |
|
|
|
} |
|
|
|
.shape.verified:after { |
|
|
|
transform: rotate(75deg); |
|
|
|
} |
|
|
|
|
|
|
|
sup { |
|
|
|
color: #c0c0c0; |
|
|
|
font-size:15px; |
|
|
|
} |
|
|
|
|
|
|
|
.credit { |
|
|
|
display:inline-block; |
|
|
|
text-decoration:none; |
|
|
|
color:#333; |
|
|
|
text-transform: uppercase; |
|
|
|
font-size:12px; |
|
|
|
margin-top:25px; |
|
|
|
} |
|
|
|
|
|
|
|
</style> |
|
|
|