Oddbean new post about | logout
 // 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);