#asknostr I wanted to build a thing to check an npubs first note, kinda like to see how long I've been using nostr, but it doesn't work for everyone I try. What's the right way to do this?
Running it here:
https://notecheck.bspr.UK
Code made by a robot:
❯ cat server.js 10:16:39const express = require("express");
const { nip19 } = require("nostr-tools");
const { SimplePool, useWebSocketImplementation } = require("nostr-tools/pool");
const WebSocket = require("ws");
useWebSocketImplementation(WebSocket);
const app = express();
const PORT = 4747;
app.use(express.urlencoded({ extended: true }));
// Convert npub to hex
function npubToHex(npub) {
const { type, data } = nip19.decode(npub);
if (type !== "npub") throw new Error("Invalid npub");
return data;
}
// Expanded default relay list
const defaultRelays = [
"wss://relay.damus.io",
"wss://nos.lol",
"wss://nostr.wine",
"wss://relay.nostr.band",
"wss://nostr.bitcoiner.social",
"wss://nostr.oxtr.dev",
"wss://soloco.nl",
"wss://nostr.einundzwanzig.space",
"wss://relay.nostr.net",
"wss://offchain.pub",
"wss://relay.snort.social",
"wss://eden.nostr.land",
"wss://nostr.mom",
"wss://relay.nostrview.com",
"wss://nostr.plebchain.org",
"wss://nostr.21sats.net"
];
// Get oldest kind 1 (note) timestamp from multiple relays
async function getFirstNoteTimestamp(pubkeyHex, extraRelays = []) {
const relays = [...defaultRelays, ...extraRelays];
const pool = new SimplePool();
let oldestTimestamp = Infinity;
const promises = relays.map(url => {
return new Promise((resolve) => {
const sub = pool.subscribe(
[url],
{ kinds: [1], authors: [pubkeyHex] },
{
onevent(event) {
if (event.created_at < oldestTimestamp) {
oldestTimestamp = event.created_at;
}
},
oneose() {
resolve();
}
}
);
// Safety timeout per relay
setTimeout(() => {
sub?.close();
resolve();
}, 12000);
});
});
await Promise.all(promises);
pool.close(relays);
return oldestTimestamp === Infinity ? null : oldestTimestamp;
}
// Home page
app.get("/", (req, res) => {
res.send(renderPage());
});
// Handle form submission
app.post("/", async (req, res) => {
const npub = req.body.npub;
const extraRelays = req.body.extraRelays
? req.body.extraRelays.split(/\s+/).filter(Boolean)
: [];
let message;
try {
const pubkeyHex = npubToHex(npub);
const ts = await getFirstNoteTimestamp(pubkeyHex, extraRelays);
if (ts) {
const timestampStr = new Date(ts * 1000).toUTCString();
message = `First Note: ${timestampStr}`;
} else {
message = "No notes found for this npub.";
}
} catch (err) {
message = `Error: ${err.message}`;
}
res.send(renderPage(npub, message, extraRelays));
});
// Render HTML page
function renderPage(npub = "", message = "", extraRelays = []) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Nostr First Note Finder</title>
<style>
body {
background-color: #000;
color: #ffb700;
font-family: 'Courier New', monospace;
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem;
min-height: 100vh;
}
h1 { margin-bottom: 1.5rem; }
input, textarea, button {
background: #111;
color: #ffb700;
border: 1px solid #ffb700;
padding: 0.5rem 1rem;
font-family: monospace;
font-size: 1rem;
margin: 0.5rem 0;
}
textarea {
width: 100%;
max-width: 500px;
height: 3rem;
display: ${extraRelays.length ? "block" : "none"};
}
button:hover { background: #222; cursor: pointer; }
.output {
margin-top: 1.5rem;
background: #111;
padding: 1rem;
border: 1px solid #ffb700;
width: 100%;
max-width: 500px;
text-align: center;
word-break: break-word;
}
</style>
</head>
<body>
<h1>Nostr First Note Finder</h1>
<form method="POST" action="/">
<input name="npub" placeholder="Enter npub" required value="${npub}" />
<button type="button" onclick="document.getElementById('extraRelays').style.display='block'; this.style.display='none';">Add Relay</button>
<textarea id="extraRelays" name="extraRelays" placeholder="Optional: extra relays, space-separated">${extraRelays.join(" ")}</textarea>
<button type="submit">Find First Note</button>
</form>
${message ? `<div class="output">${message}</div>` : ""}
</body>
</html>
`;
}
app.listen(PORT, () => {
console.log(`Server running at
http://localhost:${PORT}`);
});