Last active
May 6, 2023 22:04
-
-
Save melvincarvalho/8732a03c42d245c70abb59fac0b90dc8 to your computer and use it in GitHub Desktop.
phone.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
import fastify from 'fastify' | |
import fastifyWebsocket from '@fastify/websocket' | |
import { validateEvent, verifySignature } from 'nostr-tools' | |
const port = process.argv[2] || 3000 | |
const events = [] | |
const subscribers = new Map() | |
const fi = fastify() | |
fi.register(fastifyWebsocket) | |
fi.register(async function (fastify) { | |
fastify.get('/', { websocket: true }, async (con, req) => { | |
console.log('ws connection started') | |
const { socket } = con | |
console.log('ws connection established') | |
const eventPassesFilter = (event, filter) => { | |
const { types, kind, from, to } = filter | |
if (types && !types.includes(event.type)) { | |
return false | |
} | |
if (kind && event.kind !== kind) { | |
return false | |
} | |
if (from && event.from !== from) { | |
return false | |
} | |
if (to && event.to !== to) { | |
return false | |
} | |
return true | |
} | |
socket.on('message', async message => { | |
message = message?.toString() | |
console.log('received message', message) | |
const [type, value, ...rest] = JSON.parse(message) | |
switch (type) { | |
case 'EVENT': | |
const ok = validateEvent(value) | |
const veryOk = verifySignature(value) | |
console.log('ok', ok, veryOk) | |
if (ok && veryOk) { // Validate the event using nostr-tools | |
events.push(value) | |
console.log('event ok') | |
subscribers.forEach((filters, subscriber) => { | |
filters.forEach(filter => { | |
if (eventPassesFilter(value, filter)) { | |
subscriber.send(JSON.stringify(['EVENT', filter.subscription_id, value])) | |
} | |
}) | |
}) | |
socket.send(`["OK", ${value.id}, true, ""]`) | |
} else { | |
socket.send('["NOTICE", "Invalid event"]') | |
} | |
break | |
case 'REQ': | |
console.log('REQ') | |
const subscription_id = value | |
const filters = rest.map(filter => ({ ...filter, subscription_id })) | |
subscribers.set(socket, filters) | |
filters.forEach(filter => { | |
events.filter(event => eventPassesFilter(event, filter)) | |
.forEach(event => socket.send(JSON.stringify(['EVENT', filter.subscription_id, event]))) | |
}) | |
socket.send(JSON.stringify(['EOSE', subscription_id])) | |
break | |
case 'CLOSE': | |
const sub_id = value | |
if (subscribers.has(socket)) { | |
const updatedFilters = subscribers.get(socket).filter(filter => filter.subscription_id !== sub_id) | |
if (updatedFilters.length === 0) { | |
subscribers.delete(socket) | |
} else { | |
subscribers.set(socket, updatedFilters) | |
} | |
} | |
break | |
default: | |
socket.send('["NOTICE", "Unrecognized event"]') | |
console.log('Unrecognized event') | |
// ... | |
} | |
}) | |
// ... | |
}) | |
}) | |
fi.listen({ port }, err => { | |
if (err) throw err | |
console.log(`listening on ${port}`) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment