Skip to content

Commit c9f33d5

Browse files
authored
fix: serve real home page instead of redirecting, add templated pages (#409)
1 parent 862cc29 commit c9f33d5

22 files changed

Lines changed: 1645 additions & 184 deletions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"db:migrate": "knex migrate:latest",
4040
"db:migrate:rollback": "knex migrate:rollback",
4141
"db:seed": "knex seed:run",
42-
"pretest:unit": "mkdir -p .test-reports/unit",
42+
"pretest:unit": "node -e \"require('fs').mkdirSync('.test-reports/unit', {recursive: true})\"",
4343
"test:unit": "mocha 'test/**/*.spec.ts'",
4444
"test:unit:watch": "npm run test:unit -- --min --watch --watch-files src/**/*,test/**/*",
4545
"cover:unit": "nyc --report-dir .coverage/unit npm run test:unit",

resources/get-invoice.html

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>Admission Fee Required - {{name}}</title>
7+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
8+
<link rel="stylesheet" href="./css/style.css">
9+
</head>
10+
<body lang="en">
11+
<main class="container">
12+
<form method="post" action="/invoices">
13+
<div class="row">
14+
<div class="col">
15+
<h1 class="mt-4 mb-4 text-center text-nowrap">{{name}}</h1>
16+
</div>
17+
</div>
18+
<div class="row">
19+
<div class="col text-center">
20+
<div class="row">
21+
<div class="d-flex justify-content-center mt-2">
22+
<p class="description-text">
23+
This <a href="https://github.com/nostr-protocol/nostr">Nostr</a> relay <strong>requires</strong> a one-time
24+
admission
25+
fee. <br /> Once payment is complete, you will be able to post and fetch events from this relay.
26+
</p>
27+
</div>
28+
<div class="d-flex justify-content-center mb-1 mt-2">
29+
<p class="description-text">
30+
Provide your Nostr public key to generate a Bitcoin Lightning invoice.
31+
</p>
32+
</div>
33+
</div>
34+
</div>
35+
</div>
36+
<div class="row justify-content-center">
37+
<div class="card col col-md-10 col-lg-6 mb-4">
38+
<div class="card-body">
39+
<div class="d-flex flex-column mb-4">
40+
<label for="pubkey" class="h5">Your Nostr public key</label>
41+
<input type="text" name="pubkey" class="form-control form-control-sm" id="pubkey" placeholder="npub... or hex..." pattern="^([0-9a-f]{64}|npub1[ac-hj-np-z02-9]+)$" required>
42+
<div id="pubkeyAfterHelpBlock" class="form-text">
43+
Hex or npub formats accepted.
44+
</div>
45+
</div>
46+
<div class="form-check">
47+
<input class="form-check-input" type="checkbox" id="tosAccepted" name="tosAccepted" value="yes" required>
48+
<label class="form-check-label" for="tosAccepted">
49+
I have read and agree to the <a href="/terms" class="card-link" target="_blank" rel="noopener noreferrer">Terms of Service</a>
50+
</label>
51+
</div>
52+
</div>
53+
</div>
54+
</div>
55+
<div class="row">
56+
<div class="d-flex justify-content-center mb-3">
57+
<input type="hidden" name="feeSchedule" value="admission" />
58+
<button id="submitBtn" class="btn btn-lg btn-warning" type="submit">Pay {{amount}} sats</button>
59+
</div>
60+
</div>
61+
<div class="row d-none" id="powered-by-zebedee">
62+
<div class="d-flex justify-content-center mb-3 mt-4">
63+
<a href="https://zeb.gg/nostr-zbd-quickstart" target="_blank" rel="noopener noreferrer">
64+
<img class="poweredbyzbd-img" src="https://cdn.zebedee.io/an/nostr/poweredbyzbd.png" />
65+
</a>
66+
</div>
67+
</div>
68+
</form>
69+
</main>
70+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js" integrity="sha384-cuYeSxntonz0PPNlHhBs68uyIAVpIIOZZ5JqeqvYYIcEL727kskC66kF92t6Xl2V" crossorigin="anonymous"></script>
71+
<script nonce="{{nonce}}">
72+
var processor = {{processor_json}}
73+
function attemptGetPubkey() {
74+
const maxRetries = 10
75+
function getPubKey(retries) {
76+
if (window.nostr && typeof window.nostr.getPublicKey === 'function') {
77+
window.nostr.getPublicKey().then((pubkey) => {
78+
console.log(pubkey)
79+
document.getElementById('pubkey').setAttribute('value', pubkey)
80+
}).catch(console.error.bind(console))
81+
} else if (retries > 0) {
82+
setTimeout(() => getPubKey(retries - 1), 100)
83+
}
84+
}
85+
86+
getPubKey(maxRetries)
87+
}
88+
89+
function onLoad() {
90+
setTimeout(attemptGetPubkey, 300)
91+
if (processor === 'zebedee') {
92+
document.getElementById('powered-by-zebedee').classList.remove('d-none')
93+
}
94+
95+
// Check for system preference on load
96+
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
97+
document.body.classList.add('dark-theme');
98+
}
99+
}
100+
window.addEventListener('load', onLoad)
101+
</script>
102+
</body>
103+
</html>

resources/index.html

Lines changed: 55 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -3,161 +3,79 @@
33
<head>
44
<meta charset="utf-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1">
6-
<title>Admission Fee Required - {{name}}</title>
6+
<title>{{name}}</title>
77
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
88
<link rel="stylesheet" href="./css/style.css">
99
</head>
1010
<body lang="en">
1111
<main class="container">
12-
<form method="post" action="/invoices">
13-
<div class="row">
14-
<div class="col">
15-
<h1 class="mt-4 mb-4 text-center text-nowrap">{{name}}</h1>
16-
</div>
12+
<div class="row">
13+
<div class="col">
14+
<h1 class="mt-4 mb-2 text-center text-nowrap">{{name}}</h1>
1715
</div>
18-
<div class="row">
19-
<div class="col text-center">
20-
<div class="row">
21-
<div class="d-flex justify-content-center mt-2">
22-
<p class="description-text">
23-
This <a href="https://github.com/nostr-protocol/nostr">Nostr</a> relay <strong>requires</strong> a one-time
24-
admission
25-
fee. <br /> Once payment is complete, you will be able to post and fetch events from this relay.
26-
</p>
27-
</div>
28-
<div class="d-flex justify-content-center mb-1 mt-2">
29-
<p class="description-text">
30-
Provide your Nostr public key to generate a Bitcoin Lightning invoice.
31-
</p>
32-
</div>
33-
</div>
34-
</div>
16+
</div>
17+
<div class="row">
18+
<div class="col text-center mb-4">
19+
<p class="text-muted">{{description}}</p>
3520
</div>
36-
<div class="row justify-content-center">
37-
<div class="card col col-md-10 col-lg-6 mb-4">
21+
</div>
22+
23+
<div class="row justify-content-center">
24+
<div class="col col-md-10 col-lg-7">
25+
26+
<!-- Nostr relay info card (always shown) -->
27+
<div class="card mb-4">
3828
<div class="card-body">
39-
<div class="d-flex flex-column mb-4">
40-
<label for="pubkey" class="h5">Your Nostr public key</label>
41-
<input type="text" name="pubkey" class="form-control form-control-sm" id="pubkey" placeholder="npub... or hex..." pattern="^([0-9a-f]{64}|npub1[ac-hj-np-z02-9]+)$" required>
42-
<div id="pubkeyAfterHelpBlock" class="form-text">
43-
Hex or npub formats accepted.
44-
</div>
45-
</div>
46-
<div class="form-check">
47-
<input class="form-check-input" type="checkbox" id="tosAccepted" name="tosAccepted" value="yes" required>
48-
<label class="form-check-label" for="tosAccepted">
49-
I have read and agree to the <a href="#" class="card-link" data-bs-toggle="modal" data-bs-target="#tosModal">Terms of Service</a>
50-
</label>
51-
</div>
29+
<h5 class="card-title">Nostr Relay</h5>
30+
<p class="card-text">
31+
This is a <a href="https://github.com/nostr-protocol/nostr" target="_blank" rel="noopener noreferrer">Nostr</a> relay.
32+
To use it, connect with a Nostr client using the address below.
33+
</p>
34+
<p class="card-text">
35+
<strong>Relay address:</strong><br>
36+
<code>{{relay_url}}</code>
37+
</p>
5238
</div>
5339
</div>
54-
</div>
55-
<div class="row">
56-
<div class="d-flex justify-content-center mb-3">
57-
<input type="hidden" name="feeSchedule" value="admission" />
58-
<button id="submitBtn" class="btn btn-lg btn-warning" type="submit">Pay {{amount}} sats</button>
59-
</div>
60-
</div>
61-
<div class="row d-none" id="powered-by-zebedee">
62-
<div class="d-flex justify-content-center mb-3 mt-4">
63-
<a href="https://zeb.gg/nostr-zbd-quickstart" target="_blank">
64-
<img class="poweredbyzbd-img" src="https://cdn.zebedee.io/an/nostr/poweredbyzbd.png" />
65-
</a>
66-
</div>
67-
</div>
68-
</form>
69-
</main>
70-
<div class="modal" id="tosModal" tabindex="-1">
71-
<div class="modal-dialog modal-lg modal-fullscreen-md-down">
72-
<div class="modal-content">
73-
<div class="modal-header">
74-
<h5 class="modal-title">Terms of Service</h5>
75-
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
40+
41+
<!-- Admission fee card (shown only when payments are enabled) -->
42+
<div class="card mb-4 {{payments_section_class}}">
43+
<div class="card-body">
44+
<h5 class="card-title">Admission Required</h5>
45+
<p class="card-text">
46+
This relay requires a one-time admission fee of <strong>{{amount}} sats</strong>
47+
to publish events. Reading events is free.
48+
</p>
49+
<a href="/invoices" class="btn btn-warning">Pay Admission Fee</a>
50+
</div>
7651
</div>
77-
<div class="modal-body">
78-
<p>
79-
These are the terms of service for {{name}}; please read them before using {{name}}.
80-
</p>
81-
<p>
82-
This service (and supporting services) are provided "as is", without warranty of any kind, express or implied, including but
83-
not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement.
84-
</p>
85-
<p>
86-
By connecting to this relay, you agree:
87-
<ul>
88-
<li>To not engage in spam</li>
89-
<li>To not flood</li>
90-
<li>To not expect content moderation</li>
91-
<li>To not misuse or abuse the relay service and other supporting services</li>
92-
<li>To not disseminate illegal content or material</li>
93-
<li>That requests to delete content you published cannot be guaranteed</li>
94-
<li>That this relay has no control over any content published in other relays</li>
95-
<li>That some services, such as but not limited to the privilege to publish content may require payment(s)</li>
96-
<li>That charge backs from payments may result in the termination of the privilege to use the service</li>
97-
<li>That the service might be revoked to you at the operator's sole discretion if found in violation of these terms</li>
98-
<li>That the terms of service may change at any time in the future without explicit notice</li>
99-
<li>To grant us the necessary rights to your content to provide the service to you and to other users for an unlimited time</li>
100-
<li>To use the service in compliance with all laws, rules, and regulations applicable to you</li>
101-
<li>To use the service in good faith and not seek to get the relay operator(s) in trouble</li>
102-
<li>That the service may throttle, rate limit or revoke your access to any content and/or your privilege to publish content for any reason</li>
103-
<li>That the content you publish to this relay will be further broadcasted to any interested client and/or accepting relay</li>
104-
<li>To not infringe on the right of others to publish content to this relay as allowed by the terms of service</li>
105-
<li>That this service is not targeted, nor intended for use by, anyone under the legal age in their respective jurisdiction</li>
106-
<li>To be of legal age or have sufficient legal constent, permission and capacity to use this service</li>
107-
<li>That the service may be temporarily shutdown or permanently terminated at any time and without notice</li>
108-
<li>That the content published by you and other users may be removed at any time and without notice and for any reason</li>
109-
<li>To have your IP address and/or public key collected for the purpose of detecting abuse, spam or misuse</li>
110-
<li>To have your IP address and/or public key in full, truncated, or as a hash digest shared with interested clients and other accepting relays for the sole purpose of reporting abuse, spam or misuse</li>
111-
<li>To cooperate with the relay and its operators for the purpose of combating abuse, spam or misuse of the service</li>
112-
</ul>
113-
<br/>
114-
In addition you understand that:
115-
<ul>
116-
<li>Nostr is a decentralized and distributed network of relays that relays data by users.</li>
117-
<li>Censorship resistance is practiced by posting to multiple relays and running your own private relay.</li>
118-
<li>The responsibility of filtering and moderating is the sole responsibility of the users and not of the relays.</li>
119-
<li>You may be inadvertently exposed to content that you might find triggering, disturbing, distasteful, immoral or against your views.</li>
120-
<li>The relay operator is not liable and has no involvement in the type, quality and legality of the content being produced by users of the relay.</li>
121-
</ul>
122-
</p>
52+
53+
<!-- No-payments message (shown only when payments are disabled) -->
54+
<div class="card mb-4 {{no_payments_section_class}}">
55+
<div class="card-body">
56+
<h5 class="card-title">Open Relay</h5>
57+
<p class="card-text">
58+
This relay is open. Connect with your Nostr client to get started.
59+
</p>
60+
</div>
12361
</div>
124-
<div class="modal-footer">
125-
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
62+
63+
<!-- Legal links -->
64+
<div class="d-flex justify-content-center gap-3 mt-2 mb-5">
65+
<a href="/terms" class="text-muted small">Terms of Service</a>
66+
<span class="text-muted small">·</span>
67+
<a href="/privacy" class="text-muted small">Privacy Policy</a>
12668
</div>
69+
12770
</div>
12871
</div>
129-
</div>
72+
</main>
13073
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js" integrity="sha384-cuYeSxntonz0PPNlHhBs68uyIAVpIIOZZ5JqeqvYYIcEL727kskC66kF92t6Xl2V" crossorigin="anonymous"></script>
13174
<script nonce="{{nonce}}">
132-
var processor = "{{processor}}"
133-
function attemptGetPubkey() {
134-
const maxRetries = 10
135-
function getPubKey(retries) {
136-
if (window.nostr && typeof window.nostr.getPublicKey === 'function') {
137-
window.nostr.getPublicKey().then((pubkey) => {
138-
console.log(pubkey)
139-
document.getElementById('pubkey').setAttribute('value', pubkey)
140-
}).catch(console.error.bind(console))
141-
} else if (retries > 0) {
142-
setTimeout(() => getPubKey(retries - 1), 100)
143-
}
144-
}
145-
146-
getPubKey(maxRetries)
147-
}
148-
149-
function onLoad() {
150-
setTimeout(attemptGetPubkey, 300)
151-
if (processor === 'zebedee') {
152-
document.getElementById('powered-by-zebedee').classList.remove('d-none')
153-
}
154-
155-
// Check for system preference on load
156-
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
157-
document.body.classList.add('dark-theme');
158-
}
75+
// Check for system preference on load
76+
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
77+
document.body.classList.add('dark-theme');
15978
}
160-
window.addEventListener('load', onLoad)
16179
</script>
16280
</body>
16381
</html>

resources/invoices.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ <h2 class="text-danger">Invoice expired!</h2>
7474
<div class="row pending d-none">
7575
<div class="col">
7676
<div class="d-flex justify-content-center mb-3">
77-
<button id="sendPaymentBtn" class="btn btn-lg btn-warning d-none" type="submit">Pay with wallet</button>
77+
<button id="sendPaymentBtn" class="btn btn-lg btn-warning d-none" type="button">Pay with wallet</button>
7878
</div>
7979
</div>
8080
</div>
@@ -88,7 +88,7 @@ <h2 class="text-danger">Invoice expired!</h2>
8888
</div>
8989
<div class="row d-none" id="powered-by-zebedee">
9090
<div class="d-flex justify-content-center mb-3 mt-4">
91-
<a href="https://zeb.gg/nostr-zbd-quickstart" target="_blank">
91+
<a href="https://zeb.gg/nostr-zbd-quickstart" target="_blank" rel="noopener noreferrer">
9292
<img class="poweredbyzbd-img" src="https://cdn.zebedee.io/an/nostr/poweredbyzbd.png" />
9393
</a>
9494
</div>
@@ -152,7 +152,7 @@ <h2 class="text-danger">Invoice expired!</h2>
152152
})
153153
}
154154

155-
fallbackTimeout = setTimeout(getInvoiceStatus, getBackoffTime)
155+
fallbackTimeout = setTimeout(getInvoiceStatus, getBackoffTime())
156156

157157
function connect() {
158158
var socket = new WebSocket(relayUrl)

0 commit comments

Comments
 (0)