Skip to content

Latest commit

 

History

History
203 lines (154 loc) · 7.17 KB

BoostZapper.md

File metadata and controls

203 lines (154 loc) · 7.17 KB

BoostZapper

A simple script written in python that will look at responses or references users have made to a post identified by an event id (in hex or bech32 format), and if conditions are met, will attempt to zap the user.

You can define conditions such as

  • minimum length of a response
  • inclusion of key phrases (e.g. including a hashtag or set of words)

Each condition set has an amount of sats that will be zapped if matched

Conditions are processed in order and the first match on a post by a user determines the payment to be made.

A pubkey is only paid once per event being referenced, no matter how many events they publish. Likewise, a lightning address is only paid once. This is intended to reduce or at least somewhat thwart automated responders.

Preparation of Python Environment

To use this script, you'll need to run it with python 3.9 or higher and with the nostr, requests and bech32 packages installed.

First, create a virtual environment (or activate a common one)

python3 -m venv ~/.pyenv/boostzapper
source ~/.pyenv/boostzapper/bin/activate

Then install the dependencies

python3 -m pip install nostr@git+https://github.com/vicariousdrama/python-nostr.git
python3 -m pip install requests
python3 -m pip install bech32

Configuration

A configuration file named config.json is required and takes the following form:

{
    "botPrivateKey": "The hex or nsec of the bot. If not provided a new one is used for each run",
    "relays": [
        ""
    ],
    "referencedEventId": "The hex or bech32 representation of a nostr event id",
    "excludePubkeys": [
        ""
    ],
    "zapMessage": "Thanks for participating!",
    "zapConditions": [
        {
            "requiredPhrase": null,
            "requiredLength": 15,
            "zapAmount": 10
        }
    ],
    "lndServer": {
        "address": "127.0.0.1",
        "port": "10080",
        "macaroon": "020A3B6C....",
        "paymentTimeout": 30,
        "feeLimit": 5
    }
}

For convenience, you can start with the sample-config.json

cp sample-config.json config.json

The botPrivateKey should be configured to use the same identity for the zap request events. An event will get published to the relays specified, so this key could be a personal one, or something dedicated for this purpose. This value may be provided in hex or as a nsec string.

The relays is an array of nostr relays that you want the script to connect to fetch response events. Don't include the wss:// prefix.

The referencedEventId is used for specifying the event id. Ideally this should be the hex id of the nostr note, but many clients only reveal the bech32 nevent string. To facilitate easy copy/pasta, you can paste in event identifiers from clients and the script will normalize as needed to hex format.

The excludePubkeys is as it implies, an array of values that represent pubkeys of any publishers that should be excluded from consideration for zapping. These can be in hex or npub format.

The zapMessage field indicates a standardized message you want to be included as a comment of the zap.

For zapConditions, this is an array of conditions processed from the top down. The first set of conditions that matches an event will be used for determining the amount to be zapped to the user. A zapCondition has the following form

        {
            "requiredPhrase": null,
            "requiredLength": 15,
            "zapAmount": 10
        }

If requiredPhrase is specified as a string (not null), then for this condition to match, the content the user published must contain the phrase indicated. This check is case insensitive. If the value is null, as indicated above, then a specific phrase is not required to be zapped.

The requiredLength should be set to a number. The content that a user posts must be at least this long in length for the condition to match.

All required conditions must be met for the user to be zapped.

The zapAmount is the amount that will be zapped.

Only the first matching zapCondition will be applied to a user, so put the most restrictive condition sets at the top of the array.

The lndServer is used for paying invoices to satisfy the zaps. The configuration of such takes the following form

    "lndServer": {
        "address.comment": "The IP address or FQDN to communicate with the LND server over REST",
        "address": "127.0.0.1",
        "port.comment": "The port the LND server is listening on for REST",
        "port": "10080",
        "macaroon.comment": "Macaroon for LND server in hex format.",
        "macaroon": "0201036C....",
        "paymentTimeout.comment": "Time permitted in seconds to complete a payment or expire it",
        "paymentTimeout": 30,
        "feeLimit.comment": "Fee limit, in sats, allowed for each payment made",
        "feeLimit": 5
    }

The address should be the ip address or fully qualified domain name to communicate with the LND server over REST

The port is that port to connect to.

The macaroon should be provided in hex format.

The permissions needed are

  • lnrpc.Lightning/DecodePayReq
  • routerrpc.Router/SendPaymentV2
  • routerrpc.Router/TrackPaymentV2
  • lnrpc.Lightning/AddInvoice
  • invoicesrpc.Invoices/LookupInvoiceV2

You can bake the macaroon as follows before convertng to hex.

lncli bakemacaroon uri:/lnrpc.Lightning/DecodePayReq uri:/routerrpc.Router/SendPaymentV2 uri:/routerrpc.Router/TrackPaymentV2 uri:/lnrpc.Lightning/AddInvoice uri:/invoicesrpc.Invoices/LookupInvoiceV2 --save_to ${HOME}/BoostZapper.macaroon

cat ${HOME}/BoostZapper.macaroon | xxd -p -c 1000

The paymentTimeout is the number of seconds that should be allowed for the payment to complete routing. This helps avoid unnecessarily long in flights locking up funds.

The feeLimit is the maximum amount of fees, in sats, that you are willing to pay per zap performed, in addition to the amount being zapped.

The LND server needs to be reachable from where the script is run.

Running

Once configured, to run the script simply execute the following which will use the virtual python environment referenced.

change to the folder where boostzapper.py is

~/.pyenv/boostzapper/bin/python boostzapper.py

The console will show output reflecting each event being analyzed.

The following files will be created and updated

  • data/lightningIdcache.json - This file contains a mapping of pubkeys to lightning addresses that is populated by pulling kind0 events for a pubkey. Periodically this file may need to be deleted and rebuilt if users change their addresses

  • data/{eventid}.paid.json - An output file that tracks the pubkeys that were zapped for the event referenced. This tracking prevents paying people twice. It also includes the amount paid, fees paid and other payment metadata

  • data/{eventid}.paidluds.json - An output file that tracks the lightning addresses that were zapped for the event referenced. This tracking prevents paying people twice.

  • data/{eventid}.participants.json - This file includes all pubkeys that created an event referring to the referenced event id, including those that were not zapped either for inelligibility due to the exclusion list, or not having a lightning address setup.