nak outbox

This commit is contained in:
fiatjaf
2025-01-18 18:33:42 -03:00
parent a3ef9b45de
commit 5509095277
6 changed files with 148 additions and 14 deletions

View File

@@ -8,11 +8,12 @@ import (
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip05"
"github.com/nbd-wtf/go-nostr/nip19"
"github.com/nbd-wtf/go-nostr/sdk/hints"
)
var fetch = &cli.Command{
Name: "fetch",
Usage: "fetches events related to the given nip19 or nip05 code from the included relay hints or the author's NIP-65 relays.",
Usage: "fetches events related to the given nip19 or nip05 code from the included relay hints or the author's outbox relays.",
Description: `example usage:
nak fetch nevent1qqsxrwm0hd3s3fddh4jc2574z3xzufq6qwuyz2rvv3n087zvym3dpaqprpmhxue69uhhqatzd35kxtnjv4kxz7tfdenju6t0xpnej4
echo npub1h8spmtw9m2huyv6v2j2qd5zv956z2zdugl6mgx02f2upffwpm3nqv0j4ps | nak fetch --relay wss://relay.nostr.band`,
@@ -90,8 +91,11 @@ var fetch = &cli.Command{
}
if authorHint != "" {
relays := sys.FetchOutboxRelays(ctx, authorHint, 3)
for _, url := range relays {
sys.Hints.Save(authorHint, nostr.NormalizeURL(url), hints.LastInHint, nostr.Now())
}
for _, url := range sys.FetchOutboxRelays(ctx, authorHint, 3) {
relays = append(relays, url)
}
}

2
go.mod
View File

@@ -14,7 +14,7 @@ require (
github.com/json-iterator/go v1.1.12
github.com/mailru/easyjson v0.9.0
github.com/markusmobius/go-dateparser v1.2.3
github.com/nbd-wtf/go-nostr v0.47.3
github.com/nbd-wtf/go-nostr v0.48.0
)
require (

4
go.sum
View File

@@ -117,8 +117,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nbd-wtf/go-nostr v0.47.3 h1:KM86+0rLa8jPvt11akST1T0ffhrs6KpzvJ2CLYo765c=
github.com/nbd-wtf/go-nostr v0.47.3/go.mod h1:O6n8bv+KktkEs+4svL7KN/OSnOWB5LzcZbuKjxnpRD0=
github.com/nbd-wtf/go-nostr v0.48.0 h1:GYu6k6wRzSxYpra4pzMRk3R8xdUW8fac+trQtt6YD0o=
github.com/nbd-wtf/go-nostr v0.48.0/go.mod h1:O6n8bv+KktkEs+4svL7KN/OSnOWB5LzcZbuKjxnpRD0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

View File

@@ -19,18 +19,15 @@ import (
"github.com/nbd-wtf/go-nostr/sdk"
)
var sys = sdk.NewSystem()
var sys *sdk.System
var (
hintsFilePath string
hintsFileExists bool
)
var json = jsoniter.ConfigFastest
func init() {
sys.Pool = nostr.NewSimplePool(context.Background(),
nostr.WithRelayOptions(
nostr.WithRequestHeader(http.Header{textproto.CanonicalMIMEHeaderKey("user-agent"): {"nak/b"}}),
),
)
}
const (
LINE_PROCESSING_ERROR = iota
)

65
main.go
View File

@@ -2,9 +2,15 @@ package main
import (
"context"
"net/http"
"net/textproto"
"os"
"path/filepath"
"github.com/fiatjaf/cli/v3"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/sdk"
"github.com/nbd-wtf/go-nostr/sdk/hints/memoryh"
)
var version string = "debug"
@@ -30,9 +36,15 @@ var app = &cli.Command{
serve,
encrypt,
decrypt,
outbox,
},
Version: version,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config-path",
Hidden: true,
Persistent: true,
},
&cli.BoolFlag{
Name: "quiet",
Usage: "do not print logs and info messages to stderr, use -qq to also not print anything to stdout",
@@ -50,6 +62,59 @@ var app = &cli.Command{
},
},
},
Before: func(ctx context.Context, c *cli.Command) error {
configPath := c.String("config-path")
if configPath == "" {
if home, err := os.UserHomeDir(); err == nil {
configPath = filepath.Join(home, ".config/nak")
}
}
if configPath != "" {
hintsFilePath = filepath.Join(configPath, "outbox/hints.db")
}
if hintsFilePath != "" {
if _, err := os.Stat(hintsFilePath); !os.IsNotExist(err) {
hintsFileExists = true
}
}
if hintsFilePath != "" {
if data, err := os.ReadFile(hintsFilePath); err == nil {
hintsdb := memoryh.NewHintDB()
if err := json.Unmarshal(data, &hintsdb); err == nil {
sys = sdk.NewSystem(
sdk.WithHintsDB(hintsdb),
)
goto systemOperational
}
}
}
sys = sdk.NewSystem()
systemOperational:
sys.Pool = nostr.NewSimplePool(context.Background(),
nostr.WithAuthorKindQueryMiddleware(sys.TrackQueryAttempts),
nostr.WithEventMiddleware(sys.TrackEventHints),
nostr.WithRelayOptions(
nostr.WithRequestHeader(http.Header{textproto.CanonicalMIMEHeaderKey("user-agent"): {"nak/b"}}),
),
)
return nil
},
After: func(ctx context.Context, c *cli.Command) error {
// save hints database on exit
if hintsFileExists {
data, err := json.Marshal(sys.Hints)
if err != nil {
return err
}
return os.WriteFile(hintsFilePath, data, 0644)
}
return nil
},
}
func main() {

68
outbox.go Normal file
View File

@@ -0,0 +1,68 @@
package main
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/fiatjaf/cli/v3"
"github.com/nbd-wtf/go-nostr"
)
var outbox = &cli.Command{
Name: "outbox",
Usage: "manage outbox relay hints database",
DisableSliceFlagSeparator: true,
Commands: []*cli.Command{
{
Name: "init",
Usage: "initialize the outbox hints database",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) error {
if hintsFileExists {
return nil
}
if hintsFilePath == "" {
return fmt.Errorf("couldn't find a place to store the hints, pass --config-path to fix.")
}
if err := os.MkdirAll(filepath.Dir(hintsFilePath), 0777); err == nil {
if err := os.WriteFile(hintsFilePath, []byte("{}"), 0644); err != nil {
return fmt.Errorf("failed to create hints database: %w", err)
}
}
log("initialized hints database at %s\n", hintsFilePath)
return nil
},
},
{
Name: "list",
Usage: "list outbox relays for a given pubkey",
ArgsUsage: "<pubkey>",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) error {
if !hintsFileExists {
log("running with temporary fragile data.\n")
log("call `nak outbox init` to setup persistence.\n")
}
if c.Args().Len() != 1 {
return fmt.Errorf("expected exactly one argument (pubkey)")
}
pubkey := c.Args().First()
if !nostr.IsValidPublicKey(pubkey) {
return fmt.Errorf("invalid public key: %s", pubkey)
}
for _, relay := range sys.FetchOutboxRelays(ctx, pubkey, 6) {
stdout(relay)
}
return nil
},
},
},
}