npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nostr-bot-app

v0.1.0

Published

A package for making Nostr bots in a way that can be customized for any use case.

Downloads

14

Readme

Nostr Bot Package

A Nostr bot implementation that can also be customized into various app-like use cases.

Table of contents

Usage

Here is a simple example of a Nostr bot that posts "Hello world" to a relay.

import { EventBuilder, NostrBotApp } from "nostr-bot-app";

const nostrApp = new NostrBotApp({
  privateKey: "<your private key here>",
  relays: ["wss://<your relay url here>"],
});

const newEvent = new EventBuilder({
  pubkey: nostrApp.getPublicKey(),
  content: "Hello world!",
  kind: 1,
});

// Sign the event.
signedEvent = nostrApp.signEvent(newEvent);

// Allow the bot to connect to its relays. Then publish the event.
nostrApp.waitForConnections().then(() => {
  nostrApp.publishSignedEvent(signedEvent.getSignedEventData());
});

Usage as Nostr-based Apps

We can design Nostr bots to function similar to web apps. Instead of https requests and responses, Nostr bots use Nostr events to interact, such as direct messages.

The most obvious advantage of this paradigm is that a Nostr bot automatically knows and trusts the identity of the entity on the other side.

This essentially eliminates the need for the very complicated user authentication processes that are required for web apps.

Drawbacks

At the time or writing this, relays seem to restrict the ways in which bots can receive direct message events for some reason. For instance, many relays require both the sender and recipient to follow each other in order for a bot to recieve message updates. Hence you might need to setup your own dedicated relay in order to receive direct message events to your bot.

Code comparison

The event-callback design of this library is inspired by that of web app libraries. Here is a side by side comparison of a web app and a Nostr bot that function analogously.

import express from "express";

//
//
//

const app = express();

//
//

app.get("/", (req, res) => {
  res.send("Hello there!");
});

//
//
//
//
//
//
//
//

app.listen(3000, () => {
  console.log("Listening.");
});
import {
  NostrBotApp,
  DirectMessageEvent,
  DirectMessageEventBuilder as DMB,
} from "nostr-bot-app";

const nostrApp = new NostrBotApp({
  privateKey: "your private key here",
  relays: ["wss://your-relay-url-here"],
});

nostrApp.onDirectMessageEvent(async function (
  dmObject: DirectMessageEvent,
  botRef: NostrBotApp
) {
  const replyDM = await DMB.createDirectMessageEvent(
    botRef.getPrivateKey(),
    dmObject.pubkey,
    "Hello there!"
  );
  const signedReplyDM = botRef.signEvent(replyDM);
  return signedReplyDM.getSignedEventData();
});

nostrApp.waitForConnections();

//

Callback setters

You can write a custom callback for any message type received from a relay. These message types are described in NIP-01.

1. onEvent

The onEvent method allows you to write a callback for any specific event kind. This is useful to write special handlers for any custom event kinds that you might have.

Below is an implementation that uses onEvent to make a bot that comments under posts.

import { NostrBotApp, GenericEvent, EventBuilder } from "nostr-bot-app";

const commenterBot = new NostrBotApp({
  privateKey: "<commenter_bot_key>",
  relays: ["<your_relay_url>"],
});

// Make the commenterBot respond to events of kind 1 by posting a comment.
commenterBot.onEvent(
  1,
  async (event: GenericEvent, commenterBotRef: NostrBotApp) => {
    const eventData = event.getEventData();

    // Create a new event that will be a comment to this event.
    const commentEvent = new EventBuilder({
      pubkey: commenterBot.getPublicKey(),
      kind: 1,
      content: "I disagree!",
      // You need to reference the id of the event that you are commenting on.
      tags: [["e", eventData.id]],
    });

    const signedEvent = commenterBotRef.signEvent(commentEvent);

    // When using `onEvent`, you are responsible to prepare the event in a Nostr-compabible
    // message format. (Except you don't need to stringify it here; the bot will do that before publishing.)
    const nostrEventMessage = ["EVENT", signedEvent.getSignedEventData()];

    return nostrEventMessage;
  }
);

// Wait for the bot to go online, then subscribe to the pubkey that you want it to comment under.
commenterBot.waitForConnections().then(async () => {
  await commenterBot.subscribeToUser("<pub key to subscribe to>");
});

This package also provides 3 special callback setters that include a special wrappers for each event kind.

onDirectMessageEvent

As the name suggests, this is a specialized callback setter for direct messages (event kind 4). With this setter, your callback can access the decrypted version of the message inside the event parameter. Just use the .decryptedMessage property on the first argument as shown in the example.

In short, it just does the decryption step for you.

onMetadataEvent

This is for event kind 0: author metadata event. This callback setter simply parses the metadata for you, and makes it available in an .authorMetaData property.

onTextNoteEvent

Using this callback is identical with using onEvent with the event kind of 1.

2. onOkResponse

The okResponse is a message sent by relays (not other users) to confirm that your event has been received and processed. This callback setter allows you to write a custom callback for this message. See the example for usage details.