- Waits for the broadcasting to finish.

- Adds a way to load the backup file and just broadcast
- Displays number of downloads and accepted uploads
This commit is contained in:
Vitor Pamplona 2023-08-03 18:57:56 -04:00
parent f89a4886a4
commit 04463e1a2c
4 changed files with 161 additions and 35 deletions

View File

@ -50,7 +50,7 @@
<form> <form>
<div> <div>
<form> <form>
<div class="space-between"> <div class="space-between-small">
<p> <p>
<input <input
type="text" type="text"
@ -62,6 +62,28 @@
required /> required />
</p> </p>
</div> </div>
<div class="space-between-small">
<div class="space-between">
<b>OR</b>
</div>
</div>
<div class="space-between">
<div class="space-between">
<p>
<input type="file" id="file-selector">
</p>
<script>
var fileName = ""
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
fileName = event.target.files[0];
$('#fetch-and-broadcast').css('display', 'none')
$('#just-broadcast').css('display', 'inline-block')
});
</script>
</div>
</div>
</form> </form>
</div> </div>
@ -82,13 +104,19 @@
color: #999; color: #999;
} }
</style> </style>
<p> <p>
<button <button
id="fetch-and-broadcast" id="fetch-and-broadcast"
onclick="fetchAndBroadcast(); return false;"> onclick="fetchAndBroadcast(); return false;">
Backup & Broadcast Backup & Broadcast
</button> </button>
<button
id="just-broadcast"
onclick="justBroadcast(fileName); return false;"
style="display: none">
Broadcast from File
</button>
<button <button
id="get-from-extension" id="get-from-extension"
onclick="getFromExtension(); return false;" onclick="getFromExtension(); return false;"

View File

@ -22,6 +22,7 @@ const fetchAndBroadcast = async () => {
if (!pubkey) return if (!pubkey) return
// disable button (will be re-enable at the end of the process) // disable button (will be re-enable at the end of the process)
$('#fetch-and-broadcast').prop('disabled', true) $('#fetch-and-broadcast').prop('disabled', true)
$('#just-broadcast').prop('disabled', true)
// inform user that app is fetching from relays // inform user that app is fetching from relays
$('#fetching-status').text(txt.fetching) $('#fetching-status').text(txt.fetching)
// show and update fetching progress bar // show and update fetching progress bar
@ -82,3 +83,71 @@ if (window.nostr) {
$('#fetch-and-broadcast').css('display', 'none') $('#fetch-and-broadcast').css('display', 'none')
$('#get-from-extension').css('display', '') $('#get-from-extension').css('display', '')
} }
// button click handler
const justBroadcast = async (fileName) => {
const reader = new FileReader();
reader.addEventListener('load', (event) => {
var data = JSON.parse(event.target.result.substring(13))
broadcast(data)
});
reader.readAsText(fileName)
}
const broadcast = async (data) => {
console.log(data)
// reset UI
$('#fetching-status').html('')
$('#fetching-progress').css('visibility', 'hidden')
$('#fetching-progress').val(0)
$('#file-download').html('')
$('#events-found').text('')
$('#broadcasting-status').html('')
$('#broadcasting-progress').css('visibility', 'hidden')
$('#broadcasting-progress').val(0)
// messages to show to user
const checkMark = '&#10003;'
const txt = {
broadcasting: 'Broadcasting to relays... ',
fetching: 'Loading from file... ',
download: `Downloading Backup file... ${checkMark}`,
}
// disable button (will be re-enable at the end of the process)
$('#fetch-and-broadcast').prop('disabled', true)
$('#just-broadcast').prop('disabled', true)
// show and update fetching progress bar
$('#fetching-progress').css('visibility', 'visible')
$('#fetching-progress').prop('max', relays.length)
// inform user fetching is done
$('#fetching-status').html(txt.fetching + checkMark)
$('#fetching-progress').val(relays.length)
const latestKind3 = data.filter((it) => it.kind == 3)[0]
const myRelaySet = JSON.parse(latestKind3.content)
relays = Object.keys(myRelaySet).filter(url => myRelaySet[url].write).map(url => url)
$('#checking-relays-header-box').css('display', 'none')
$('#checking-relays-box').css('display', 'none')
// inform user that app is broadcasting events to relays
$('#broadcasting-status').html(txt.broadcasting)
// show and update broadcasting progress bar
$('#broadcasting-progress').css('visibility', 'visible')
$('#broadcasting-progress').prop('max', relays.length)
$('#checking-relays-header-box').css('display', 'flex')
$('#checking-relays-box').css('display', 'flex')
$('#checking-relays-header').text("Broadcasting to Relays:")
await broadcastEvents(data)
// inform user that broadcasting is done
$('#broadcasting-status').html(txt.broadcasting + checkMark)
$('#broadcasting-progress').val(relays.length)
// re-enable broadcast button
$('#fetch-and-broadcast').prop('disabled', false)
}

View File

@ -47,10 +47,26 @@ function hexToBytes(hex) {
tempLink.click() tempLink.click()
} }
const updateRelayStatus = (relayStatus) => { const updateRelayStatus = (relay, status, addToCount, relayStatusAndCount) => {
if (Object.keys(relayStatus).length > 0) { if (relayStatusAndCount[relay] == undefined) {
let newText = Object.keys(relayStatus).map( relayStatusAndCount[relay] = {}
it => it.replace("wss://", "").replace("ws://", "") + ": " + relayStatus[it] }
if (status)
relayStatusAndCount[relay].status = status
if (relayStatusAndCount[relay].count != undefined)
relayStatusAndCount[relay].count = relayStatusAndCount[relay].count + addToCount
else
relayStatusAndCount[relay].count = addToCount
displayRelayStatus(relayStatusAndCount)
}
const displayRelayStatus = (relayStatusAndCount) => {
if (Object.keys(relayStatusAndCount).length > 0) {
let newText = Object.keys(relayStatusAndCount).map(
it => it.replace("wss://", "").replace("ws://", "") + ": " + relayStatusAndCount[it].status + " (" + relayStatusAndCount[it].count + ")"
).join("<br />") ).join("<br />")
$('#checking-relays').html(newText) $('#checking-relays').html(newText)
} else { } else {
@ -63,8 +79,7 @@ function hexToBytes(hex) {
const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) => const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
try { try {
relayStatus[relay] = "Starting" updateRelayStatus(relay, "Starting", 0, relayStatus)
updateRelayStatus(relayStatus)
// open websocket // open websocket
const ws = new WebSocket(relay) const ws = new WebSocket(relay)
@ -84,8 +99,7 @@ function hexToBytes(hex) {
ws.close() ws.close()
reject('timeout') reject('timeout')
}, 10_000) }, 10_000)
relayStatus[relay] = "Downloading" updateRelayStatus(relay, "Downloading", 0, relayStatus)
updateRelayStatus(relayStatus)
ws.send(JSON.stringify(['REQ', subsId].concat(filters))) ws.send(JSON.stringify(['REQ', subsId].concat(filters)))
} }
@ -108,35 +122,34 @@ function hexToBytes(hex) {
return return
} }
updateRelayStatus(relay, undefined, 1, relayStatus)
// prevent duplicated events // prevent duplicated events
if (events[id]) return if (events[id]) return
else events[id] = data else events[id] = data
// show how many events were found until this moment // show how many events were found until this moment
$('#events-found').text(`${Object.keys(events).length} events found`) $('#events-found').text(`${Object.keys(events).length} events found`)
} }
// end of subscription messages // end of subscription messages
if (msgType === 'EOSE' && subscriptionId === subsId) { if (msgType === 'EOSE' && subscriptionId === subsId) {
relayStatus[relay] = "Done" updateRelayStatus(relay, "Done", 0, relayStatus)
updateRelayStatus(relayStatus)
ws.close() ws.close()
resolve() resolve()
} }
} }
ws.onerror = (err) => { ws.onerror = (err) => {
relayStatus[relay] = "Done" updateRelayStatus(relay, "Done", 0, relayStatus)
updateRelayStatus(relayStatus)
ws.close() ws.close()
reject(err) reject(err)
} }
ws.onclose = (socket, event) => { ws.onclose = (socket, event) => {
relayStatus[relay] = "Done" updateRelayStatus(relay, "Done", 0, relayStatus)
updateRelayStatus(relayStatus)
resolve() resolve()
} }
} catch (exception) { } catch (exception) {
console.log(exception) console.log(exception)
relayStatus[relay] = "Error" updateRelayStatus(relay, "Error", 0, relayStatus)
updateRelayStatus(relayStatus)
try { try {
ws.close() ws.close()
} catch (exception) { } catch (exception) {
@ -159,7 +172,7 @@ function hexToBytes(hex) {
$('#fetching-progress').val(relays.length - fetchFunctions.length) $('#fetching-progress').val(relays.length - fetchFunctions.length)
await Promise.allSettled( relaysForThisRound.map((relay) => fetchFromRelay(relay, filters, pubkey, events, relayStatus)) ) await Promise.allSettled( relaysForThisRound.map((relay) => fetchFromRelay(relay, filters, pubkey, events, relayStatus)) )
} }
updateRelayStatus({}) displayRelayStatus({})
// return data as an array of events // return data as an array of events
return Object.keys(events).map((id) => events[id]) return Object.keys(events).map((id) => events[id])
@ -171,8 +184,7 @@ function hexToBytes(hex) {
try { try {
const ws = new WebSocket(relay) const ws = new WebSocket(relay)
relayStatus[relay] = "Starting" updateRelayStatus(relay, "Starting", 0, relayStatus)
updateRelayStatus(relayStatus)
// prevent hanging forever // prevent hanging forever
let myTimeout = setTimeout(() => { let myTimeout = setTimeout(() => {
@ -182,37 +194,49 @@ function hexToBytes(hex) {
// fetch events from relay // fetch events from relay
ws.onopen = () => { ws.onopen = () => {
relayStatus[relay] = "Sending" updateRelayStatus(relay, "Sending", 0, relayStatus)
updateRelayStatus(relayStatus)
for (evnt of data) { for (evnt of data) {
clearTimeout(myTimeout) clearTimeout(myTimeout)
myTimeout = setTimeout(() => { myTimeout = setTimeout(() => {
ws.close() ws.close()
reject('timeout') reject('timeout')
}, 5_000) }, 10_000)
ws.send(JSON.stringify(['EVENT', evnt])) ws.send(JSON.stringify(['EVENT', evnt]))
} }
relayStatus[relay] = "Done" }
updateRelayStatus(relayStatus) // Listen for messages
ws.close() ws.onmessage = (event) => {
resolve(`done for ${relay}`) clearTimeout(myTimeout)
myTimeout = setTimeout(() => {
ws.close()
reject('timeout')
}, 10_000)
const [msgType, subscriptionId, inserted] = JSON.parse(event.data)
// event messages
// end of subscription messages
if (msgType === 'OK') {
if (inserted == true) {
updateRelayStatus(relay, undefined, 1, relayStatus)
} else {
console.log(event.data)
}
}
} }
ws.onerror = (err) => { ws.onerror = (err) => {
relayStatus[relay] = "Error" updateRelayStatus(relay, "Error", 0, relayStatus)
updateRelayStatus(relayStatus)
console.log("Error", err) console.log("Error", err)
ws.close() ws.close()
reject(err) reject(err)
} }
ws.onclose = (socket, event) => { ws.onclose = (socket, event) => {
relayStatus[relay] = "Done" updateRelayStatus(relay, "Done", 0, relayStatus)
updateRelayStatus(relayStatus)
resolve() resolve()
} }
} catch (exception) { } catch (exception) {
relayStatus[relay] = "Error" console.log(exception)
updateRelayStatus(relayStatus) updateRelayStatus(relay, "Error", 0, relayStatus)
try { try {
ws.close() ws.close()
} catch (exception) { } catch (exception) {
@ -232,5 +256,5 @@ function hexToBytes(hex) {
await Promise.allSettled( relaysForThisRound.map((relay) => sendToRelay(relay, data, relayStatus)) ) await Promise.allSettled( relaysForThisRound.map((relay) => sendToRelay(relay, data, relayStatus)) )
} }
updateRelayStatus(relayStatus) displayRelayStatus(relayStatus)
} }

View File

@ -150,6 +150,11 @@ a {
margin-bottom: 10px; margin-bottom: 10px;
} }
.space-between-small {
display: flex;
justify-content: center;
}
h2 { h2 {
font-family: Arial,Helvetica Neue,Helvetica,sans-serif; font-family: Arial,Helvetica Neue,Helvetica,sans-serif;
font-size: 1em; font-size: 1em;