mirror of
https://github.com/vitorpamplona/Nostryfied.git
synced 2025-04-19 18:31:17 +00:00
Add files via upload
This commit is contained in:
parent
f1d953d18a
commit
35fa03d445
5
README.md
Normal file
5
README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# nostr-broadcast
|
||||
|
||||
Fetch, backup and broadcast your Nostr events.
|
||||
|
||||
Live at https://nostr-broadcast.pages.dev
|
BIN
img/nostr-broadcast_og.png
Normal file
BIN
img/nostr-broadcast_og.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
BIN
img/nostr-broadcast_twitter.png
Normal file
BIN
img/nostr-broadcast_twitter.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
144
index.html
Normal file
144
index.html
Normal file
@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html>
|
||||
<html data-theme="light" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>NBS</title>
|
||||
<meta name="title" content="Nostr broadcast" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Fetch, backup and broadcast your Nostr events" />
|
||||
|
||||
<!-- Favicon -->
|
||||
<link
|
||||
rel="shortcut icon"
|
||||
href="https://nostr-utils.pages.dev/img/broadcast.png"
|
||||
type="image/x-icon" />
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<!-- Lightning -->
|
||||
<meta name="lightning" content="bordalix@getalby.com" />
|
||||
<!-- PWA -->
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
href="https://nostr-utils.pages.dev/img/broadcast.png" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<main class="container">
|
||||
<div class="header-space">
|
||||
<h1>Nostr Backup Service</h1>
|
||||
</div>
|
||||
<h2>Share all of your events, such as notes &
|
||||
lists of followers/following, with all the major
|
||||
relays and generate a backup filethat can be used
|
||||
to restore your data to any relay of your choice.
|
||||
|
||||
</h2>
|
||||
<div>
|
||||
<form>
|
||||
<div>
|
||||
<form>
|
||||
<div class="space-between">
|
||||
<p>
|
||||
<input
|
||||
type="text"
|
||||
id="pubkey"
|
||||
name="pubkey"
|
||||
onchange="pubkeyOnChange()"
|
||||
placeholder="Public key (npub or hex)"
|
||||
style="width: 180px"
|
||||
required />
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#pubkey {
|
||||
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;
|
||||
}
|
||||
|
||||
#pubkey::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>
|
||||
<button
|
||||
id="fetch-and-broadcast"
|
||||
onclick="fetchAndBroadcast(); return false;">
|
||||
Backup & Broadcast
|
||||
</button>
|
||||
<button
|
||||
id="get-from-extension"
|
||||
onclick="getFromExtension(); return false;"
|
||||
style="display: none">
|
||||
Get from extension
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<p id="fetching-status"></p>
|
||||
<p style="padding-top: 2px">
|
||||
<progress
|
||||
type="range"
|
||||
id="fetching-progress"
|
||||
name="fetching-progress"
|
||||
min="0"
|
||||
max="20"
|
||||
value="0"
|
||||
style="visibility: hidden" />
|
||||
</p>
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<p id="file-download"></p>
|
||||
<p id="events-found"></p>
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<p id="broadcasting-status"></p>
|
||||
<p style="padding-top: 2px">
|
||||
<progress
|
||||
type="range"
|
||||
id="broadcasting-progress"
|
||||
name="broadcasting-progress"
|
||||
min="0"
|
||||
max="20"
|
||||
value="0"
|
||||
style="visibility: hidden" />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<p>Our system is currently working on implementing restoring and
|
||||
automatic daily broadcasting features, which will be available soon."</p>
|
||||
<p>
|
||||
<a href="https://nostr-utils.pages.dev"
|
||||
>learn more</a
|
||||
>
|
||||
</p>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script src="https://bundle.run/buffer@6.0.3"></script>
|
||||
<script src="https://bundle.run/bech32@2.0.0"></script>
|
||||
<script src="https://nostr-utils.pages.dev/js/jquery-3.6.2.min.js"></script>
|
||||
<script src="https://nostr-utils.pages.dev/js/nostr-utils.js"></script>
|
||||
<script src="js/relays.js"></script>
|
||||
<script src="js/nostr-broadcast.js"></script>
|
||||
</body>
|
||||
</html>
|
74
js/nostr-broadcast.js
Normal file
74
js/nostr-broadcast.js
Normal file
@ -0,0 +1,74 @@
|
||||
// button click handler
|
||||
const fetchAndBroadcast = async () => {
|
||||
// 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 = '✓'
|
||||
const txt = {
|
||||
broadcasting: 'Broadcasting to relays... ',
|
||||
fetching: 'Fetching from relays... ',
|
||||
download: `Downloading Backup file... ${checkMark}`,
|
||||
}
|
||||
// parse pubkey ('npub' or hexa)
|
||||
const pubkey = parsePubkey($('#pubkey').val())
|
||||
if (!pubkey) return
|
||||
// disable button (will be re-enable at the end of the process)
|
||||
$('#fetch-and-broadcast').prop('disabled', true)
|
||||
// inform user that app is fetching from relays
|
||||
$('#fetching-status').text(txt.fetching)
|
||||
// show and update fetching progress bar
|
||||
$('#fetching-progress').css('visibility', 'visible')
|
||||
const fetchInterval = setInterval(() => {
|
||||
// update fetching progress bar
|
||||
const currValue = parseInt($('#fetching-progress').val())
|
||||
$('#fetching-progress').val(currValue + 1)
|
||||
}, 1000)
|
||||
// get all events from relays
|
||||
const filter = { authors: [pubkey] }
|
||||
const data = await getEvents(filter)
|
||||
// inform user fetching is done
|
||||
$('#fetching-status').html(txt.fetching + checkMark)
|
||||
clearInterval(fetchInterval)
|
||||
$('#fetching-progress').val(20)
|
||||
// inform user that backup file (js format) is being downloaded
|
||||
$('#file-download').html(txt.download)
|
||||
downloadFile(data, 'nostr-broadcast.js')
|
||||
// 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')
|
||||
const broadcastInterval = setInterval(() => {
|
||||
// update fetching progress bar
|
||||
const currValue = parseInt($('#broadcasting-progress').val())
|
||||
$('#broadcasting-progress').val(currValue + 1)
|
||||
}, 1000)
|
||||
await broadcastEvents(data)
|
||||
// inform user that broadcasting is done
|
||||
$('#broadcasting-status').html(txt.broadcasting + checkMark)
|
||||
clearInterval(broadcastInterval)
|
||||
$('#broadcasting-progress').val(20)
|
||||
// re-enable broadcast button
|
||||
$('#fetch-and-broadcast').prop('disabled', false)
|
||||
}
|
||||
|
||||
const getFromExtension = async () => {
|
||||
const pubkey = await window.nostr.getPublicKey()
|
||||
if (pubkey) $('#pubkey').val(pubkey).change()
|
||||
}
|
||||
|
||||
const pubkeyOnChange = () => {
|
||||
$('#fetch-and-broadcast').css('display', '')
|
||||
$('#get-from-extension').css('display', 'none')
|
||||
}
|
||||
|
||||
if (window.nostr) {
|
||||
$('#fetch-and-broadcast').css('display', 'none')
|
||||
$('#get-from-extension').css('display', '')
|
||||
}
|
46
js/relays.js
Normal file
46
js/relays.js
Normal file
@ -0,0 +1,46 @@
|
||||
// list of paid relays from:
|
||||
// https://thebitcoinmanual.com/articles/paid-nostr-relay/
|
||||
|
||||
const relays = [
|
||||
'wss://atlas.nostr.land', // paid relay 15000 npub12262qa4uhw7u8gdwlgmntqtv7aye8vdcmvszkqwgs0zchel6mz7s6cgrkj
|
||||
'wss://bitcoiner.social', // paid relay 1000 npub1dxs2pygtfxsah77yuncsmu3ttqr274qr5g5zva3c7t5s3jtgy2xszsn4st
|
||||
'wss://brb.io',
|
||||
'wss://eden.nostr.land', // paid relay 5000 npub16k7j4mwsqm8hakjl8x5ycrqmhx89lxkfwz2xxxcw75eav7sd8ztqy2rwdn
|
||||
'wss://expensive-relay.fiatjaf.com',
|
||||
'wss://freedom-relay.herokuapp.com',
|
||||
'wss://nos.lol',
|
||||
'wss://nostr-2.zebedee.cloud',
|
||||
'wss://nostr-pub.wellorder.net',
|
||||
'wss://nostr-relay.alekberg.net',
|
||||
'wss://nostr-relay.freeberty.net',
|
||||
'wss://nostr-relay.wlvs.space',
|
||||
'wss://nostr.bitcoiner.social',
|
||||
'wss://nostr.blocs.fr',
|
||||
'wss://nostr.coollamer.com',
|
||||
'wss://nostr.decentony.com', // paid relay 7000 npub1pp9csm9564ewzer3f63284mrd9u2zssmreq42x4rtt390zmkrj2st4fzpm
|
||||
'wss://nostr.fmt.wiz.biz',
|
||||
'wss://nostr.gives.africa', // paid relay 10000 npub1g8dcep2exsadx9smhdrgwds06pgfc9yyyww6ftdcgnyukcuzk2csqs5jed
|
||||
'wss://nostr.inosta.cc', // paid relay 5000 npub1r34nhc6nqswancymk452f2frgn3ypvu77h4njr67n6ppyuls4ehs44gv0h
|
||||
'wss://nostr.milou.lol', // paid relay 1000 npub1rvg76s0gz535txd9ypg2dfqv0x7a80ar6e096j3v343xdxyrt4ksmkxrck
|
||||
'wss://nostr.onsats.org',
|
||||
'wss://nostr.orangepill.dev',
|
||||
'wss://nostr.plebchain.org', // paid relay 6969 npub1u2tehhr3ye4lv4dc8aen2gkxf6zljdpf356sgfjqfun0wxehvquqgvhuec
|
||||
'wss://nostr.rocks',
|
||||
'wss://nostr.sandwich.farm',
|
||||
'wss://nostr.wine', // paid relay 8888 npub18kzz4lkdtc5n729kvfunxuz287uvu9f64ywhjz43ra482t2y5sks0mx5sz
|
||||
'wss://nostr.zebedee.cloud',
|
||||
'wss://private.red.gb.net', // paid relay 8888 npub1nctdevxxuvth3sx6r0gutv4tmvhwy9syvpkr3gfd5atz67fl97kqyjkuxk
|
||||
'wss://puravida.nostr.land', // paid relay 10000 npub16k7j4mwsqm8hakjl8x5ycrqmhx89lxkfwz2xxxcw75eav7sd8ztqy2rwdn
|
||||
'wss://relay.current.fyi',
|
||||
'wss://relay.damus.io',
|
||||
'wss://relay.nostr.bg',
|
||||
'wss://relay.nostr.com.au', // paid relay 6969 npub1qqqqqrre3jxkuyj3s4m59usdyvm0umgm0lpy6cqjtwpt649sdews5q3hw7
|
||||
'wss://relay.nostr.info',
|
||||
'wss://relay.nostrati.com', // paid relay 2000 npub1qqqqqqqut3z3jeuxu70c85slaqq4f87unr3vymukmnhsdzjahntsfmctgs
|
||||
'wss://relay.nostrich.land', // paid relay 2100 npub1vj0wlergmkcs0sz7hfks2ywj555c2s87f40squ4sqcmqpr7897fqn6mfew
|
||||
'wss://relay.nostriches.org', // paid relay 421 npub1vnmhd287pvxxk5w9mcycf23av24nscwk0da7rrfaa5wq4l8hsehs90ftlv
|
||||
'wss://relay.orangepill.dev', // paid relay 4500 npub16jzr7npgp2a684pasnkhjf9j2e7hc9n0teefskulqmf42cqmt4uqwszk52
|
||||
'wss://relay.snort.social',
|
||||
'wss://relayer.fiatjaf.com',
|
||||
'wss://rsslay.fiatjaf.com',
|
||||
]
|
293
style.css
Normal file
293
style.css
Normal file
@ -0,0 +1,293 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Red+Hat+Text:wght@400;700&display=swap');
|
||||
|
||||
:root{
|
||||
--color: #333;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Red Hat Text', sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
color: var(--color);
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-image: url(https://images.unsplash.com/photo-1519120944692-1a8d8cfc107f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=872&q=80);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
/* this is where the magic happens: */
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
h1 {font-family: "Open Sans", sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 700;
|
||||
font-size: 2rem;
|
||||
|
||||
}
|
||||
.header-space {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 9px;
|
||||
font-family: "Courier", monospace;
|
||||
}
|
||||
|
||||
.box {
|
||||
background-color: #f2f2f2;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
|
||||
progress {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
height: 10px;
|
||||
background-color: #eee;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
progress::-webkit-progress-bar {
|
||||
background-color: #eee;
|
||||
border-radius: 10px;
|
||||
}
|
||||
progress::-webkit-progress-value {
|
||||
background-color: #007bff;
|
||||
border-radius: 10px;
|
||||
animation: loading 2s ease-out infinite;
|
||||
}
|
||||
@keyframes loading {
|
||||
0% {
|
||||
width: 0%;
|
||||
}
|
||||
100% {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
progress {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
height: 10px;
|
||||
background-color: #eee;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
progress::-webkit-progress-bar {
|
||||
background-color: #eee;
|
||||
border-radius: 10px;
|
||||
}
|
||||
progress::-webkit-progress-value {
|
||||
background-color: #007bff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
progress[value="25"]::-webkit-progress-value {
|
||||
background-color: #ffc107;
|
||||
}
|
||||
progress[value="50"]::-webkit-progress-value {
|
||||
background-color: #28a745;
|
||||
}
|
||||
progress[value="75"]::-webkit-progress-value {
|
||||
background-color: #dc3545;
|
||||
}
|
||||
|
||||
|
||||
p {
|
||||
max-width: 52ch;
|
||||
line-height: 1.5;
|
||||
padding: .3em;
|
||||
margin-top: 5px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: .5em 1.5em;
|
||||
background-color: var(--color);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
border-radius: 0.3em;
|
||||
font-weight: 700;
|
||||
letter-spacing: .5px;
|
||||
font-size: .875rem;
|
||||
}
|
||||
|
||||
.blank,
|
||||
.other {
|
||||
width: 100%;
|
||||
min-height: 60vh;
|
||||
background-color: var(--color);
|
||||
}
|
||||
|
||||
.second {
|
||||
background-image:url(https://images.unsplash.com/photo-1514496959998-c01c40915c5f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1740&q=80);
|
||||
background-attachment: fixed;
|
||||
height: 1200px;
|
||||
}
|
||||
|
||||
.second {
|
||||
background-image:url(https://images.unsplash.com/photo-1514496959998-c01c40915c5f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1740&q=80);
|
||||
background-attachment: fixed;
|
||||
height: 1200px;
|
||||
}
|
||||
|
||||
.space-between {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-size: 1em;
|
||||
line-height: 1.5;
|
||||
font-weight: 500; /* Set font-weight to lighter */
|
||||
margin-bottom: 5px;
|
||||
width: 50%; /* set the width of h2 element to 50% of its parent's width */
|
||||
margin: 10 auto; /* set the top and bottom margin to 0, and left and right margin to auto */
|
||||
word-wrap: break-word;
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1080px) { /* apply this style only when the screen width is less than or equal to 600px */
|
||||
h2 {
|
||||
width: 70%; /* set the width of h2 element to 100% of its parent's width */
|
||||
margin: 0; /* set all margins to 0 */
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) { /* apply this style only when the screen width is less than or equal to 600px */
|
||||
h2 {
|
||||
width: 90%; /* set the width of h2 element to 100% of its parent's width */
|
||||
margin: 0; /* set all margins to 0 */
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) { /* apply this style only when the screen width is less than or equal to 600px */
|
||||
h2 {
|
||||
width: 90%; /* set the width of h2 element to 100% of its parent's width */
|
||||
margin: 0; /* set all margins to 0 */
|
||||
}
|
||||
}
|
||||
|
||||
#pubkey {
|
||||
width: 700px !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1080px) {
|
||||
#pubkey {
|
||||
width: 550px !important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
#pubkey {
|
||||
width: 450px !important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
#pubkey {
|
||||
width: 300px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
main div p img {
|
||||
position: relative;
|
||||
top: 6px;
|
||||
height: 1rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
details {
|
||||
background-color: rgba(242, 241, 238, 0.3);
|
||||
border: 1px solid #ccc;
|
||||
padding: 0.5rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
p,
|
||||
li {
|
||||
line-height: 1.33;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-left: -1rem;
|
||||
}
|
||||
|
||||
.box {
|
||||
border: 1px solid #ccc;
|
||||
padding: 0 0.5rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.box-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
font-family: "Courier", monospace;
|
||||
}
|
||||
|
||||
button {
|
||||
appearance: none;
|
||||
background-color: #087bee;
|
||||
border: 1px solid rgba(27, 31, 35, 0.15);
|
||||
border-radius: 6px;
|
||||
box-shadow: rgba(27, 31, 35, 0.04) 0 1px 0, rgba(255, 255, 255, 0.25) 0 1px 0 inset;
|
||||
box-sizing: border-box;
|
||||
color: #f9fafb;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
list-style: none;
|
||||
padding: 6px 16px;
|
||||
position: relative;
|
||||
transition: background-color 0.2s cubic-bezier(0.3, 0, 0.5, 1);
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
touch-action: manipulation;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.gray {
|
||||
background-color: rgba(183, 177, 168, 0.3);
|
||||
}
|
||||
|
||||
.red {
|
||||
background-color: rgba(229, 60, 8, 0.3);
|
||||
}
|
||||
|
||||
.box button {
|
||||
background-color: rgba(0, 0, 0, 0.813);
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
footer p {
|
||||
font-size: 0.8rem;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user