mirror of
https://github.com/vitorpamplona/Nostryfied.git
synced 2025-07-23 13:45:31 +00:00
adding date range filter
This commit is contained in:
parent
e7ded1e68b
commit
6c97e127bc
111
index.html
111
index.html
@ -39,44 +39,45 @@
|
|||||||
|
|
||||||
<main class="container">
|
<main class="container">
|
||||||
<div class="header-space">
|
<div class="header-space">
|
||||||
<h1>Welcome to Nostryfied</h1>
|
<h1>Backup your Nostr Events</h1>
|
||||||
</div>
|
</div>
|
||||||
<h2><b>Nostryfied</b> offers an <b>Broadcast & Export Service</b> that allows you to <b>Download a
|
|
||||||
Copy of your Data</b> & when you use this service, all of your data will also be <b>Broadcasted to Major Relays</b>
|
|
||||||
on the network. <br><br>This design ensures that the data is <b> Widely Distributed</b>
|
|
||||||
and makes it more <b>Resistant to Censorship.</b>
|
|
||||||
</h2>
|
|
||||||
<div>
|
<div>
|
||||||
<form>
|
<form>
|
||||||
<div>
|
<div>
|
||||||
<form>
|
<form>
|
||||||
<div class="space-between-small">
|
|
||||||
<div class="space-between">
|
|
||||||
<b>From Relays</b>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="space-between-small">
|
<div class="space-between-small">
|
||||||
<p>
|
<p>
|
||||||
|
From relays
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
class="cool-field"
|
||||||
id="relaySet"
|
id="relaySet"
|
||||||
name="relaySet"
|
name="relaySet"
|
||||||
placeholder="Force relays or blank to use your list: wss://nos.lol"
|
placeholder="wss://nos.lol, wss://nostr.mom or leave blank for all"
|
||||||
style="width: 180px"
|
value="wss://nos.lol" />
|
||||||
value="" />
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-between-small-left">
|
||||||
|
<p>
|
||||||
|
Created from
|
||||||
|
<input type="date" class="cool-field" id="startDate" name="startDate" min="2020-01-01" value="2020-01-01" />
|
||||||
|
to
|
||||||
|
<input type="date" class="cool-field" id="endDate" name="endDate" min="2020-01-01" />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-between-small">
|
<div class="space-between-small">
|
||||||
<p>
|
<p>
|
||||||
|
By and about
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="pubkey"
|
id="pubkey"
|
||||||
name="pubkey"
|
name="pubkey"
|
||||||
|
class="cool-field"
|
||||||
onchange="pubkeyOnChange()"
|
onchange="pubkeyOnChange()"
|
||||||
placeholder="Public key (npub or hex)"
|
placeholder="Public key (npub or hex)"
|
||||||
style="width: 180px"
|
value=""
|
||||||
required />
|
required />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -106,35 +107,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#pubkey {
|
.cool-field {
|
||||||
width: 600px; /* change width value */
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
max-width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pubkey::placeholder {
|
.cool-field::placeholder {
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
#relaySet {
|
|
||||||
width: 600px; /* change width value */
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 5px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
max-width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#relaySet::placeholder {
|
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -198,51 +179,6 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="wrapper">
|
|
||||||
<div class="divider div-transparent"></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<a href="https://formfaca.de/sm/t5B7tbyRB"
|
|
||||||
>Auto Backup (Wishlist)</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<div class="wrapper">
|
|
||||||
<div class="divider div-transparent"></div>
|
|
||||||
<h4><b>Why you should Use this backup Service?</b></h1>
|
|
||||||
</div>
|
|
||||||
<h2>
|
|
||||||
Have you been using the new social network Nostr
|
|
||||||
that's <b>free, open, and not controlled</b> by the likes of Big Tech?
|
|
||||||
If so, you might be wondering where your <b>data is stored and
|
|
||||||
how you can get a copy of it.</b> Nostr is designed
|
|
||||||
with a <b>decentralized architecture</b> that stores your data on <b>multiple servers,</b>
|
|
||||||
making it more difficult for any one entity to control or access it. <br><br>
|
|
||||||
<b>Nostryfied</b> provides an <b>Export & Broadcast service</b> that allows you to <b>download a copy of your data,
|
|
||||||
& Broadcast it to all the major relays</b> although please note that this service is not a complete backup and might not
|
|
||||||
include all of your data.
|
|
||||||
</h4>
|
|
||||||
<p>
|
|
||||||
<a href="https://snort.social/p/npub1cmmswlckn82se7f2jeftl6ll4szlc6zzh8hrjyyfm9vm3t2afr7svqlr6f" class="linkbutton">Author</a>
|
|
||||||
<a href="https://snort.social/p/npub1ctpqas992k2ewy72f3qycnfveq8xewgx7kmyy9c8qcf2pjhzn33qauqp94" class="linkbutton">Support</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="wrapper">
|
|
||||||
<div class="divider div-transparent"></div>
|
|
||||||
<h4><b>What is Nostr? How to get started</b></h1>
|
|
||||||
</div>
|
|
||||||
<h2>
|
|
||||||
<b>Notes and Other Stuff Transmitted by Relays</b> Nostr is a <b>relay-based network</b> that broadcasts your messages to multiple servers.
|
|
||||||
This design helps to make the network more <b>resistant to censorship and also ensures
|
|
||||||
that the network is distributed</b>, providing a higher level of <b>availability and reliability.</b> <br><br>
|
|
||||||
<b>NOSTR Lightning integrating</b> By integrating Bitcoin and Lightning into NOSTR, not only do users
|
|
||||||
<b>unlock a decentralized way to transact funds,</b> but relays are also given a way to <b>monetize or control
|
|
||||||
for denial-of-service (DOS) spam attacks.</b>
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
<a href="https://nostr-resources.com/" class="linkbutton">Resources</a>
|
|
||||||
<a href="https://www.austrich.net/nostr/" class="linkbutton">Nostr Tools</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<h5>
|
<h5>
|
||||||
@ -261,5 +197,14 @@
|
|||||||
<script src="js/nostr-utils.js"></script>
|
<script src="js/nostr-utils.js"></script>
|
||||||
<script src="js/relays.js"></script>
|
<script src="js/relays.js"></script>
|
||||||
<script src="js/nostr-broadcast.js"></script>
|
<script src="js/nostr-broadcast.js"></script>
|
||||||
|
<script>
|
||||||
|
Date.prototype.toDateInputValue = (function() {
|
||||||
|
var local = new Date(this);
|
||||||
|
local.setMinutes(this.getMinutes() - this.getTimezoneOffset());
|
||||||
|
return local.toJSON().slice(0,10);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('endDate').value = new Date().toDateInputValue()
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -36,7 +36,19 @@ const fetchAndBroadcast = async () => {
|
|||||||
|
|
||||||
// get all events from relays
|
// get all events from relays
|
||||||
const filters =[{ authors: [pubkey] }, { "#p": [pubkey] }]
|
const filters =[{ authors: [pubkey] }, { "#p": [pubkey] }]
|
||||||
const data = (await getEvents(filters, pubkey, relaySet)).sort((a, b) => b.created_at - a.created_at)
|
|
||||||
|
let date = new Date();
|
||||||
|
let offset = date.getTimezoneOffset() * 60;
|
||||||
|
|
||||||
|
const startDate = Date.parse($('#startDate').val())
|
||||||
|
const endDate = Date.parse($('#endDate').val())
|
||||||
|
|
||||||
|
const addedFilters = {
|
||||||
|
since: Math.floor((startDate - startDate % 864e5) / 1000) + offset, // 0:00
|
||||||
|
until: Math.floor((endDate - endDate % 864e5 + 864e5 - 1) / 1000) + offset // 23:59
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = (await getEvents(filters, addedFilters, pubkey, relaySet)).sort((a, b) => b.created_at - a.created_at)
|
||||||
|
|
||||||
// inform user fetching is done
|
// inform user fetching is done
|
||||||
$('#fetching-status').html(txt.fetching + checkMark)
|
$('#fetching-status').html(txt.fetching + checkMark)
|
||||||
@ -44,15 +56,17 @@ const fetchAndBroadcast = async () => {
|
|||||||
|
|
||||||
const latestKind3 = data.filter((it) => it.kind == 3 && it.pubkey === pubkey)[0]
|
const latestKind3 = data.filter((it) => it.kind == 3 && it.pubkey === pubkey)[0]
|
||||||
|
|
||||||
|
$('#checking-relays-header-box').css('display', 'none')
|
||||||
|
$('#checking-relays-box').css('display', 'none')
|
||||||
|
// inform user that backup file (js format) is being downloaded
|
||||||
|
|
||||||
|
$('#file-download').html(txt.download)
|
||||||
|
downloadFile(data, 'nostr-backup.json')
|
||||||
|
|
||||||
if (latestKind3) {
|
if (latestKind3) {
|
||||||
const myRelaySet = JSON.parse(latestKind3.content)
|
const myRelaySet = JSON.parse(latestKind3.content)
|
||||||
relays = Object.keys(myRelaySet).filter(url => myRelaySet[url].write).map(url => url)
|
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 backup file (js format) is being downloaded
|
|
||||||
$('#file-download').html(txt.download)
|
|
||||||
downloadFile(data, 'nostr-backup.js')
|
|
||||||
// inform user that app is broadcasting events to relays
|
// inform user that app is broadcasting events to relays
|
||||||
$('#broadcasting-status').html(txt.broadcasting)
|
$('#broadcasting-status').html(txt.broadcasting)
|
||||||
// show and update broadcasting progress bar
|
// show and update broadcasting progress bar
|
||||||
|
@ -48,9 +48,9 @@ const parseRelaySet = (commaSeparatedRelayString) => {
|
|||||||
|
|
||||||
// download js file
|
// download js file
|
||||||
const downloadFile = (data, fileName) => {
|
const downloadFile = (data, fileName) => {
|
||||||
const prettyJs = 'const data = ' + JSON.stringify(data, null, 2)
|
const prettyJs = JSON.stringify(data, null, 2)
|
||||||
const tempLink = document.createElement('a')
|
const tempLink = document.createElement('a')
|
||||||
const taBlob = new Blob([prettyJs], { type: 'text/javascript' })
|
const taBlob = new Blob([prettyJs], { type: 'text/json' })
|
||||||
tempLink.setAttribute('href', URL.createObjectURL(taBlob))
|
tempLink.setAttribute('href', URL.createObjectURL(taBlob))
|
||||||
tempLink.setAttribute('download', fileName)
|
tempLink.setAttribute('download', fileName)
|
||||||
tempLink.click()
|
tempLink.click()
|
||||||
@ -120,7 +120,7 @@ const displayRelayStatus = (relayStatusAndCount) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fetch events from relay, returns a promise
|
// fetch events from relay, returns a promise
|
||||||
const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) =>
|
const fetchFromRelay = async (relay, filters, addedFilters, pubkey, events, relayStatus) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
updateRelayStatus(relay, "Starting", 0, undefined, undefined, relayStatus)
|
updateRelayStatus(relay, "Starting", 0, undefined, undefined, relayStatus)
|
||||||
@ -138,13 +138,22 @@ const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) =>
|
|||||||
const subscriptions = Object.fromEntries(filters.map ( (filter, index) => {
|
const subscriptions = Object.fromEntries(filters.map ( (filter, index) => {
|
||||||
let id = "my-sub-"+index
|
let id = "my-sub-"+index
|
||||||
|
|
||||||
|
let myFilter = filter
|
||||||
|
|
||||||
|
if (!myFilter.since && addedFilters.since) {
|
||||||
|
myFilter.since = addedFilters.since
|
||||||
|
}
|
||||||
|
if (!myFilter.until && addedFilters.until) {
|
||||||
|
myFilter.until = addedFilters.until
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
id, {
|
id, {
|
||||||
id: id,
|
id: id,
|
||||||
counter: 0,
|
counter: 0,
|
||||||
lastEvent: null,
|
lastEvent: null,
|
||||||
done: false,
|
done: false,
|
||||||
filter: filter,
|
filter: myFilter,
|
||||||
eventIds: new Set()
|
eventIds: new Set()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -178,6 +187,9 @@ const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) =>
|
|||||||
try {
|
try {
|
||||||
const { id } = data
|
const { id } = data
|
||||||
|
|
||||||
|
if (addedFilters.since && data.created_at < addedFilters.since) return
|
||||||
|
if (addedFilters.until && data.created_at > addedFilters.until) return
|
||||||
|
|
||||||
if (!subscriptions[subscriptionId].lastEvent || data.created_at < subscriptions[subscriptionId].lastEvent.created_at)
|
if (!subscriptions[subscriptionId].lastEvent || data.created_at < subscriptions[subscriptionId].lastEvent.created_at)
|
||||||
subscriptions[subscriptionId].lastEvent = data
|
subscriptions[subscriptionId].lastEvent = data
|
||||||
|
|
||||||
@ -228,7 +240,9 @@ const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) =>
|
|||||||
} else {
|
} else {
|
||||||
//console.log("Limit: ", { ...filters[0], until: lastSub1Event.created_at })
|
//console.log("Limit: ", { ...filters[0], until: lastSub1Event.created_at })
|
||||||
subscriptions[subscriptionId].counter = 0
|
subscriptions[subscriptionId].counter = 0
|
||||||
ws.send(JSON.stringify(['REQ', subscriptions[subscriptionId].id, { ...subscriptions[subscriptionId].filter, until: subscriptions[subscriptionId].lastEvent.created_at } ]))
|
let newFilter = { ...subscriptions[subscriptionId].filter }
|
||||||
|
newFilter.until = subscriptions[subscriptionId].lastEvent.created_at
|
||||||
|
ws.send(JSON.stringify(['REQ', subscriptions[subscriptionId].id, newFilter]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +311,7 @@ const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
// query relays for events published by this pubkey
|
// query relays for events published by this pubkey
|
||||||
const getEvents = async (filters, pubkey, relaySet) => {
|
const getEvents = async (filters, addedFilters, pubkey, relaySet) => {
|
||||||
// events hash
|
// events hash
|
||||||
const events = {}
|
const events = {}
|
||||||
|
|
||||||
@ -309,7 +323,7 @@ const getEvents = async (filters, pubkey, relaySet) => {
|
|||||||
myRelaySet = relays
|
myRelaySet = relays
|
||||||
|
|
||||||
// batch processing of 10 relays
|
// batch processing of 10 relays
|
||||||
await processInPool(myRelaySet, (relay, poolStatus) => fetchFromRelay(relay, filters, pubkey, events, poolStatus), 10, (progress) => $('#fetching-progress').val(progress))
|
await processInPool(myRelaySet, (relay, poolStatus) => fetchFromRelay(relay, filters, addedFilters, pubkey, events, poolStatus), 10, (progress) => $('#fetching-progress').val(progress))
|
||||||
|
|
||||||
displayRelayStatus({})
|
displayRelayStatus({})
|
||||||
|
|
||||||
@ -319,7 +333,7 @@ const getEvents = async (filters, pubkey, relaySet) => {
|
|||||||
|
|
||||||
// broadcast events to list of relays
|
// broadcast events to list of relays
|
||||||
const broadcastEvents = async (data) => {
|
const broadcastEvents = async (data) => {
|
||||||
await processInPool(relays, (relay, poolStatus) => sendToRelay(relay, data, poolStatus), 10, (progress) => $('#broadcasting-progress').val(progress))
|
const poolStatus = await processInPool(relays, (relay, poolStatus) => sendToRelay(relay, data, poolStatus), 10, (progress) => $('#broadcasting-progress').val(progress))
|
||||||
|
|
||||||
displayRelayStatus(relayStatus)
|
displayRelayStatus(relayStatus)
|
||||||
}
|
}
|
||||||
@ -348,6 +362,8 @@ const processInPool = async (items, processItem, poolSize, onProgress) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await Promise.allSettled(Object.values(pool));
|
await Promise.allSettled(Object.values(pool));
|
||||||
|
|
||||||
|
return poolStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendAllEvents = async (relay, data, relayStatus, ws) => {
|
const sendAllEvents = async (relay, data, relayStatus, ws) => {
|
||||||
|
@ -159,6 +159,11 @@ a {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.space-between-small-left {
|
||||||
|
display: flex;
|
||||||
|
justify-content: left;
|
||||||
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-family: Arial,Helvetica Neue,Helvetica,sans-serif;
|
font-family: Arial,Helvetica Neue,Helvetica,sans-serif;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
@ -193,7 +198,7 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pubkey {
|
#pubkey {
|
||||||
width: 600px !important;
|
width: 450px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1080px) {
|
@media screen and (max-width: 1080px) {
|
||||||
@ -215,7 +220,7 @@ h2 {
|
|||||||
|
|
||||||
|
|
||||||
#relaySet {
|
#relaySet {
|
||||||
width: 600px !important;
|
width: 450px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1080px) {
|
@media screen and (max-width: 1080px) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user