From 628db3145120f9aec17d396a22b8fad49148cf67 Mon Sep 17 00:00:00 2001 From: mleku Date: Wed, 10 Jan 2024 11:14:56 +0000 Subject: [PATCH] cleaning up algia --- cmd/algia/config.go | 442 +++++++++++++++++++ cmd/algia/main.go | 411 +---------------- cmd/algia/profile.go | 12 +- cmd/algia/timeline.go | 204 +++++---- cmd/algia/zap.go | 99 +---- cmd/replicatrd/replicatr/broadcasting.go | 2 +- cmd/replicatrd/replicatr/handlefilter.go | 2 +- cmd/replicatrd/replicatr/websockethandler.go | 2 +- pkg/go-nostr/envelope/envelope.go | 2 +- pkg/go-nostr/event/event.go | 17 +- pkg/go-nostr/event/event_test.go | 2 +- pkg/go-nostr/relays/relay.go | 12 +- 12 files changed, 621 insertions(+), 586 deletions(-) create mode 100644 cmd/algia/config.go diff --git a/cmd/algia/config.go b/cmd/algia/config.go new file mode 100644 index 00000000..5dc9732d --- /dev/null +++ b/cmd/algia/config.go @@ -0,0 +1,442 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "sort" + "strings" + "sync" + "time" + + "github.com/Hubmakerlabs/replicatr/pkg/context" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/event" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/filter" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/keys" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip04" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip19" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/relays" + "github.com/fatih/color" +) + +// RelayPerms is +type RelayPerms struct { + Read bool `json:"read"` + Write bool `json:"write"` + Search bool `json:"search"` +} + +// Event is +type Event struct { + Event *event.T `json:"event"` + Profile *Profile `json:"profile"` +} + +// Profile is +type Profile struct { + Website string `json:"website"` + Nip05 string `json:"nip05"` + Picture string `json:"picture"` + Lud16 string `json:"lud16"` + DisplayName string `json:"display_name"` + About string `json:"about"` + Name string `json:"name"` +} + +type Follows map[string]*Profile +type Relays map[string]*RelayPerms +type Emojis map[string]string + +// C is the configuration for the client +type C struct { + Relays `json:"relays"` + Follows `json:"follows"` + PrivateKey string `json:"privatekey"` + Updated time.Time `json:"updated"` + Emojis `json:"emojis"` + NwcURI string `json:"nwc-uri"` + NwcPub string `json:"nwc-pub"` + verbose bool + tempRelay bool + sk string +} + +type RelayIterator func(context.T, *relays.Relay) bool + +type Checklist map[string]struct{} + +var rp = &RelayPerms{Read: true} +var wp = &RelayPerms{Write: true} + +// GetFollows is +func (cfg *C) GetFollows(profile string) (profiles map[string]*Profile, e error) { + var mu sync.Mutex + var pub string + var s any + if _, s, e = nip19.Decode(cfg.PrivateKey); log.Fail(e) { + return nil, e + } + if pub, e = keys.GetPublicKey(s.(string)); log.Fail(e) { + return nil, e + } + // get followers + if (cfg.Updated.Add(3*time.Hour).Before(time.Now()) && !cfg.tempRelay) || + len(cfg.Follows) == 0 { + + mu.Lock() + cfg.Follows = Follows{} + mu.Unlock() + m := Checklist{} + cfg.Do(rp, cfg.aoeu(pub, m, &mu)) + log.D.F("found %d followers\n", len(m)) + if len(m) > 0 { + var follows []string + for k := range m { + follows = append(follows, k) + } + for i := 0; i < len(follows); i += 500 { + // Calculate the end index based on the current index and slice + // length + end := i + 500 + if end > len(follows) { + end = len(follows) + } + // get follower's descriptions + cfg.Do(rp, cfg.PopulateFollows(follows, i, end, &mu)) + } + } + cfg.Updated = time.Now() + if e = cfg.save(profile); log.Fail(e) { + return nil, e + } + } + return cfg.Follows, nil +} +func (cfg *C) aoeu(pub string, m Checklist, mu *sync.Mutex) RelayIterator { + return func(c context.T, rl *relays.Relay) bool { + evs, e := rl.QuerySync(c, filter.T{ + Kinds: []int{event.KindContactList}, + Authors: []string{pub}, + Limit: 1, + }) + if log.Fail(e) { + return true + } + for _, ev := range evs { + var rm Relays + if cfg.tempRelay == false { + if e = json.Unmarshal([]byte(ev.Content), &rm); log.Fail(e) { + continue + } else { + for k, v1 := range cfg.Relays { + if v2, ok := rm[k]; ok { + v2.Search = v1.Search + } + } + cfg.Relays = rm + } + } + for _, tag := range ev.Tags { + if len(tag) >= 2 && tag[0] == "p" { + mu.Lock() + m[tag[1]] = struct{}{} + mu.Unlock() + } + } + } + return true + } +} + +func (cfg *C) PopulateFollows(f []string, i, end int, mu *sync.Mutex) RelayIterator { + return func(c context.T, rl *relays.Relay) bool { + evs, e := rl.QuerySync(c, filter.T{ + Kinds: []int{event.KindProfileMetadata}, + Authors: f[i:end], // Use the updated end index + }) + if log.Fail(e) { + return true + } + for _, ev := range evs { + p := &Profile{} + e = json.Unmarshal([]byte(ev.Content), p) + if e == nil { + mu.Lock() + cfg.Follows[ev.PubKey] = p + mu.Unlock() + } + } + return true + } +} + +// FindRelay is +func (cfg *C) FindRelay(c context.T, r RelayPerms) *relays.Relay { + for k, v := range cfg.Relays { + if r.Write && !v.Write { + continue + } + if !cfg.tempRelay && r.Search && !v.Search { + continue + } + if !r.Write && !v.Read { + continue + } + if cfg.verbose { + fmt.Printf("trying relay: %s\n", k) + } + rl, e := relays.RelayConnect(c, k) + if log.Fail(e) { + continue + } + return rl + } + return nil +} + +// Do is +func (cfg *C) Do(r *RelayPerms, f RelayIterator) { + var wg sync.WaitGroup + c := context.Bg() + for k, v := range cfg.Relays { + if r.Write && !v.Write { + continue + } + if r.Search && !v.Search { + continue + } + if !r.Write && !v.Read { + continue + } + wg.Add(1) + go func(wg *sync.WaitGroup, k string, v *RelayPerms) { + defer wg.Done() + rl, e := relays.RelayConnect(c, k) + if log.Fail(e) { + log.D.Ln(e) + return + } + if !f(c, rl) { + c.Done() + } + log.Fail(rl.Close()) + }(&wg, k, v) + } + wg.Wait() +} + +func (cfg *C) save(profile string) (e error) { + if cfg.tempRelay { + return nil + } + dir, e := configDir() + if log.Fail(e) { + return e + } + dir = filepath.Join(dir, "algia") + + var fp string + if profile == "" { + fp = filepath.Join(dir, "config.json") + } else { + fp = filepath.Join(dir, "config-"+profile+".json") + } + b, e := json.MarshalIndent(&cfg, "", " ") + if log.Fail(e) { + return e + } + return ioutil.WriteFile(fp, b, 0644) +} + +// Decode is +func (cfg *C) Decode(ev *event.T) (e error) { + var sk string + var pub string + if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { + sk = s.(string) + if pub, e = keys.GetPublicKey(s.(string)); log.Fail(e) { + return e + } + } else { + return e + } + tag := ev.Tags.GetFirst([]string{"p"}) + if tag == nil { + return errors.New("is not author") + } + sp := tag.Value() + if sp != pub { + if ev.PubKey != pub { + return errors.New("is not author") + } + } else { + sp = ev.PubKey + } + ss, e := nip04.ComputeSharedSecret(sp, sk) + if log.Fail(e) { + return e + } + content, e := nip04.Decrypt(ev.Content, ss) + if log.Fail(e) { + return e + } + ev.Content = content + return nil +} + +// PrintEvents is +func (cfg *C) PrintEvents(evs []*event.T, f Follows, j, extra bool) { + if j { + if extra { + var events []Event + for _, ev := range evs { + if profile, ok := f[ev.PubKey]; ok { + events = append(events, Event{ + Event: ev, + Profile: profile, + }) + } + } + for _, ev := range events { + log.Fail(json.NewEncoder(os.Stdout).Encode(ev)) + } + } else { + for _, ev := range evs { + log.Fail(json.NewEncoder(os.Stdout).Encode(ev)) + } + } + return + } + + for _, ev := range evs { + profile, ok := f[ev.PubKey] + if ok { + color.Set(color.FgHiRed) + fmt.Print(profile.Name) + } else { + color.Set(color.FgRed) + fmt.Print(ev.PubKey) + } + color.Set(color.Reset) + fmt.Print(": ") + color.Set(color.FgHiBlue) + fmt.Println(ev.PubKey) + color.Set(color.Reset) + fmt.Println(ev.Content) + } +} + +// Events is +func (cfg *C) Events(f filter.T) []*event.T { + var mu sync.Mutex + found := false + var m sync.Map + cfg.Do(rp, func(c context.T, rl *relays.Relay) bool { + mu.Lock() + if found { + mu.Unlock() + return false + } + mu.Unlock() + evs, e := rl.QuerySync(c, f) + if log.Fail(e) { + return true + } + for _, ev := range evs { + if _, ok := m.Load(ev.ID); !ok { + if ev.Kind == event.KindEncryptedDirectMessage { + if e := cfg.Decode(ev); log.Fail(e) { + continue + } + } + m.LoadOrStore(ev.ID, ev) + if len(f.IDs) == 1 { + mu.Lock() + found = true + c.Done() + mu.Unlock() + break + } + } + } + return true + }) + + keys := []string{} + m.Range(func(k, v any) bool { + keys = append(keys, k.(string)) + return true + }) + sort.Slice(keys, func(i, j int) bool { + lhs, ok := m.Load(keys[i]) + if !ok { + return false + } + rhs, ok := m.Load(keys[j]) + if !ok { + return false + } + return lhs.(*event.T).CreatedAt.Time().Before(rhs.(*event.T).CreatedAt.Time()) + }) + var evs []*event.T + for _, key := range keys { + vv, ok := m.Load(key) + if !ok { + continue + } + evs = append(evs, vv.(*event.T)) + } + return evs +} + +// ZapInfo is +func (cfg *C) ZapInfo(pub string) (*Lnurlp, error) { + rl := cfg.FindRelay(context.Bg(), RelayPerms{Read: true}) + if rl == nil { + return nil, errors.New("cannot connect relays") + } + defer rl.Close() + + // get set-metadata + f := filter.T{ + Kinds: []int{event.KindProfileMetadata}, + Authors: []string{pub}, + Limit: 1, + } + + evs := cfg.Events(f) + if len(evs) == 0 { + return nil, errors.New("cannot find user") + } + + var profile Profile + e := json.Unmarshal([]byte(evs[0].Content), &profile) + if log.Fail(e) { + return nil, e + } + + tok := strings.SplitN(profile.Lud16, "@", 2) + if log.Fail(e) { + return nil, e + } + if len(tok) != 2 { + return nil, errors.New("receipt address is not valid") + } + + resp, e := http.Get("https://" + tok[1] + "/.well-known/lnurlp/" + tok[0]) + if log.Fail(e) { + return nil, e + } + defer resp.Body.Close() + + var lp Lnurlp + e = json.NewDecoder(resp.Body).Decode(&lp) + if log.Fail(e) { + return nil, e + } + return &lp, nil +} diff --git a/cmd/algia/main.go b/cmd/algia/main.go index 09fbd0fb..860d3844 100644 --- a/cmd/algia/main.go +++ b/cmd/algia/main.go @@ -2,29 +2,15 @@ package main import ( "encoding/json" - "errors" "fmt" - "io/ioutil" "os" "path/filepath" "runtime" - "sort" "strings" - "sync" - "time" - - "github.com/Hubmakerlabs/replicatr/pkg/context" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/event" - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/filter" - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/keys" - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip04" - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/relays" log2 "github.com/Hubmakerlabs/replicatr/pkg/log" "github.com/urfave/cli/v2" - - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip19" - "github.com/fatih/color" ) var log = log2.GetStd() @@ -35,49 +21,11 @@ const version = "0.0.54" var revision = "HEAD" -// RelayPerms is -type RelayPerms struct { - Read bool `json:"read"` - Write bool `json:"write"` - Search bool `json:"search"` -} - -// Config is -type Config struct { - Relays map[string]RelayPerms `json:"relays"` - Follows map[string]Profile `json:"follows"` - PrivateKey string `json:"privatekey"` - Updated time.Time `json:"updated"` - Emojis map[string]string `json:"emojis"` - NwcURI string `json:"nwc-uri"` - NwcPub string `json:"nwc-pub"` - verbose bool - tempRelay bool - sk string -} - -// Event is -type Event struct { - Event *event.T `json:"event"` - Profile Profile `json:"profile"` -} - -// Profile is -type Profile struct { - Website string `json:"website"` - Nip05 string `json:"nip05"` - Picture string `json:"picture"` - Lud16 string `json:"lud16"` - DisplayName string `json:"display_name"` - About string `json:"about"` - Name string `json:"name"` -} - func configDir() (string, error) { switch runtime.GOOS { case "darwin": dir, e := os.UserHomeDir() - if e != nil { + if log.Fail(e) { return "", e } return filepath.Join(dir, ".config"), nil @@ -86,9 +34,9 @@ func configDir() (string, error) { } } -func loadConfig(profile string) (*Config, error) { +func loadConfig(profile string) (*C, error) { dir, e := configDir() - if e != nil { + if log.Fail(e) { return nil, e } dir = filepath.Join(dir, "algia") @@ -98,32 +46,32 @@ func loadConfig(profile string) (*Config, error) { fp = filepath.Join(dir, "config.json") } else if profile == "?" { names, e := filepath.Glob(filepath.Join(dir, "config-*.json")) - if e != nil { + if log.Fail(e) { return nil, e } - for _, name := range names { - name = filepath.Base(name) - name = strings.TrimLeft(name[6:len(name)-5], "-") - fmt.Println(name) + for _, n := range names { + n = filepath.Base(n) + n = strings.TrimLeft(n[6:len(n)-5], "-") + fmt.Println(n) } os.Exit(0) } else { fp = filepath.Join(dir, "config-"+profile+".json") } - os.MkdirAll(filepath.Dir(fp), 0700) + log.Fail(os.MkdirAll(filepath.Dir(fp), 0700)) - b, e := ioutil.ReadFile(fp) - if e != nil { + b, e := os.ReadFile(fp) + if log.Fail(e) { return nil, e } - var cfg Config + var cfg C e = json.Unmarshal(b, &cfg) - if e != nil { + if log.Fail(e) { return nil, e } if len(cfg.Relays) == 0 { - cfg.Relays = map[string]RelayPerms{} - cfg.Relays["wss://relay.nostr.band"] = RelayPerms{ + cfg.Relays = map[string]*RelayPerms{} + cfg.Relays["wss://relay.nostr.band"] = &RelayPerms{ Read: true, Write: true, Search: true, @@ -132,323 +80,6 @@ func loadConfig(profile string) (*Config, error) { return &cfg, nil } -// GetFollows is -func (cfg *Config) GetFollows(profile string) (map[string]Profile, error) { - var mu sync.Mutex - var pub string - if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { - if pub, e = keys.GetPublicKey(s.(string)); e != nil { - return nil, e - } - } else { - return nil, e - } - - // get followers - if (cfg.Updated.Add(3*time.Hour).Before(time.Now()) && !cfg.tempRelay) || len(cfg.Follows) == 0 { - mu.Lock() - cfg.Follows = map[string]Profile{} - mu.Unlock() - m := map[string]struct{}{} - - cfg.Do(RelayPerms{Read: true}, func(c context.T, rl *relays.Relay) bool { - evs, e := rl.QuerySync(c, filter.T{Kinds: []int{event.KindContactList}, Authors: []string{pub}, Limit: 1}) - if e != nil { - return true - } - for _, ev := range evs { - var rm map[string]RelayPerms - if cfg.tempRelay == false { - if e := json.Unmarshal([]byte(ev.Content), &rm); e == nil { - for k, v1 := range cfg.Relays { - if v2, ok := rm[k]; ok { - v2.Search = v1.Search - } - } - cfg.Relays = rm - } - } - for _, tag := range ev.Tags { - if len(tag) >= 2 && tag[0] == "p" { - mu.Lock() - m[tag[1]] = struct{}{} - mu.Unlock() - } - } - } - return true - }) - if cfg.verbose { - fmt.Printf("found %d followers\n", len(m)) - } - if len(m) > 0 { - follows := []string{} - for k := range m { - follows = append(follows, k) - } - - for i := 0; i < len(follows); i += 500 { - // Calculate the end index based on the current index and slice length - end := i + 500 - if end > len(follows) { - end = len(follows) - } - - // get follower's descriptions - cfg.Do(RelayPerms{Read: true}, func(c context.T, rl *relays.Relay) bool { - evs, e := rl.QuerySync(c, filter.T{ - Kinds: []int{event.KindProfileMetadata}, - Authors: follows[i:end], // Use the updated end index - }) - if e != nil { - return true - } - for _, ev := range evs { - var profile Profile - e := json.Unmarshal([]byte(ev.Content), &profile) - if e == nil { - mu.Lock() - cfg.Follows[ev.PubKey] = profile - mu.Unlock() - } - } - return true - }) - } - } - - cfg.Updated = time.Now() - if e := cfg.save(profile); e != nil { - return nil, e - } - } - return cfg.Follows, nil -} - -// FindRelay is -func (cfg *Config) FindRelay(c context.T, r RelayPerms) *relays.Relay { - for k, v := range cfg.Relays { - if r.Write && !v.Write { - continue - } - if !cfg.tempRelay && r.Search && !v.Search { - continue - } - if !r.Write && !v.Read { - continue - } - if cfg.verbose { - fmt.Printf("trying relay: %s\n", k) - } - rl, e := relays.RelayConnect(c, k) - if e != nil { - if cfg.verbose { - fmt.Fprintln(os.Stderr, e.Error()) - } - continue - } - return rl - } - return nil -} - -// Do is -func (cfg *Config) Do(r RelayPerms, f func(context.T, *relays.Relay) bool) { - var wg sync.WaitGroup - c := context.Bg() - for k, v := range cfg.Relays { - if r.Write && !v.Write { - continue - } - if r.Search && !v.Search { - continue - } - if !r.Write && !v.Read { - continue - } - wg.Add(1) - go func(wg *sync.WaitGroup, k string, v RelayPerms) { - defer wg.Done() - rl, e := relays.RelayConnect(c, k) - if e != nil { - if cfg.verbose { - fmt.Fprintln(os.Stderr, e) - } - return - } - if !f(c, rl) { - c.Done() - } - rl.Close() - }(&wg, k, v) - } - wg.Wait() -} - -func (cfg *Config) save(profile string) (e error) { - if cfg.tempRelay { - return nil - } - dir, e := configDir() - if e != nil { - return e - } - dir = filepath.Join(dir, "algia") - - var fp string - if profile == "" { - fp = filepath.Join(dir, "config.json") - } else { - fp = filepath.Join(dir, "config-"+profile+".json") - } - b, e := json.MarshalIndent(&cfg, "", " ") - if e != nil { - return e - } - return ioutil.WriteFile(fp, b, 0644) -} - -// Decode is -func (cfg *Config) Decode(ev *event.T) (e error) { - var sk string - var pub string - if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { - sk = s.(string) - if pub, e = keys.GetPublicKey(s.(string)); e != nil { - return e - } - } else { - return e - } - tag := ev.Tags.GetFirst([]string{"p"}) - if tag == nil { - return errors.New("is not author") - } - sp := tag.Value() - if sp != pub { - if ev.PubKey != pub { - return errors.New("is not author") - } - } else { - sp = ev.PubKey - } - ss, e := nip04.ComputeSharedSecret(sp, sk) - if e != nil { - return e - } - content, e := nip04.Decrypt(ev.Content, ss) - if e != nil { - return e - } - ev.Content = content - return nil -} - -// PrintEvents is -func (cfg *Config) PrintEvents(evs []*event.T, followsMap map[string]Profile, j, extra bool) { - if j { - if extra { - var events []Event - for _, ev := range evs { - if profile, ok := followsMap[ev.PubKey]; ok { - events = append(events, Event{ - Event: ev, - Profile: profile, - }) - } - } - for _, ev := range events { - json.NewEncoder(os.Stdout).Encode(ev) - } - } else { - for _, ev := range evs { - json.NewEncoder(os.Stdout).Encode(ev) - } - } - return - } - - for _, ev := range evs { - profile, ok := followsMap[ev.PubKey] - if ok { - color.Set(color.FgHiRed) - fmt.Print(profile.Name) - } else { - color.Set(color.FgRed) - fmt.Print(ev.PubKey) - } - color.Set(color.Reset) - fmt.Print(": ") - color.Set(color.FgHiBlue) - fmt.Println(ev.PubKey) - color.Set(color.Reset) - fmt.Println(ev.Content) - } -} - -// Events is -func (cfg *Config) Events(f filter.T) []*event.T { - var mu sync.Mutex - found := false - var m sync.Map - cfg.Do(RelayPerms{Read: true}, func(c context.T, rl *relays.Relay) bool { - mu.Lock() - if found { - mu.Unlock() - return false - } - mu.Unlock() - evs, e := rl.QuerySync(c, f) - if e != nil { - return true - } - for _, ev := range evs { - if _, ok := m.Load(ev.ID); !ok { - if ev.Kind == event.KindEncryptedDirectMessage { - if e := cfg.Decode(ev); e != nil { - continue - } - } - m.LoadOrStore(ev.ID, ev) - if len(f.IDs) == 1 { - mu.Lock() - found = true - c.Done() - mu.Unlock() - break - } - } - } - return true - }) - - keys := []string{} - m.Range(func(k, v any) bool { - keys = append(keys, k.(string)) - return true - }) - sort.Slice(keys, func(i, j int) bool { - lhs, ok := m.Load(keys[i]) - if !ok { - return false - } - rhs, ok := m.Load(keys[j]) - if !ok { - return false - } - return lhs.(*event.T).CreatedAt.Time().Before(rhs.(*event.T).CreatedAt.Time()) - }) - var evs []*event.T - for _, key := range keys { - vv, ok := m.Load(key) - if !ok { - continue - } - evs = append(evs, vv.(*event.T)) - } - return evs -} - func doVersion(cCtx *cli.Context) (e error) { fmt.Println(version) return nil @@ -671,18 +302,21 @@ func main() { } profile := cCtx.String("a") cfg, e := loadConfig(profile) - if e != nil { + if log.Fail(e) { return e } cCtx.App.Metadata = map[string]any{ "config": cfg, } cfg.verbose = cCtx.Bool("V") + if cfg.verbose { + log2.SetLogLevel(log2.Debug) + } relays := cCtx.String("relays") if strings.TrimSpace(relays) != "" { - cfg.Relays = make(map[string]RelayPerms) + cfg.Relays = make(map[string]*RelayPerms) for _, rl := range strings.Split(relays, ",") { - cfg.Relays[rl] = RelayPerms{ + cfg.Relays[rl] = &RelayPerms{ Read: true, Write: true, } @@ -693,8 +327,7 @@ func main() { }, } - if e := app.Run(os.Args); e != nil { - fmt.Fprintln(os.Stderr, e) + if e := app.Run(os.Args); log.Fail(e) { os.Exit(1) } } diff --git a/cmd/algia/profile.go b/cmd/algia/profile.go index 2e14120e..190b2473 100644 --- a/cmd/algia/profile.go +++ b/cmd/algia/profile.go @@ -7,21 +7,19 @@ import ( "os" "github.com/Hubmakerlabs/replicatr/pkg/context" - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/event" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/filter" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/keys" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip19" "github.com/Hubmakerlabs/replicatr/pkg/nostr-sdk" "github.com/urfave/cli/v2" - - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip19" ) func doProfile(cCtx *cli.Context) (e error) { user := cCtx.String("u") j := cCtx.Bool("json") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) rl := cfg.FindRelay(context.Bg(), RelayPerms{Read: true}) if rl == nil { return errors.New("cannot connect relays") @@ -31,7 +29,7 @@ func doProfile(cCtx *cli.Context) (e error) { var pub string if user == "" { if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { - if pub, e = keys.GetPublicKey(s.(string)); e != nil { + if pub, e = keys.GetPublicKey(s.(string)); log.Fail(e) { return e } } else { @@ -63,11 +61,11 @@ func doProfile(cCtx *cli.Context) (e error) { } var profile Profile e = json.Unmarshal([]byte(evs[0].Content), &profile) - if e != nil { + if log.Fail(e) { return e } npub, e := nip19.EncodePublicKey(pub) - if e != nil { + if log.Fail(e) { return e } fmt.Printf("Pubkey: %v\n", npub) diff --git a/cmd/algia/timeline.go b/cmd/algia/timeline.go index 7b8fe6d7..7eba6fda 100644 --- a/cmd/algia/timeline.go +++ b/cmd/algia/timeline.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "regexp" "strings" @@ -32,11 +31,12 @@ import ( func doDMList(cCtx *cli.Context) (e error) { j := cCtx.Bool("json") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) // get followers - followsMap, e := cfg.GetFollows(cCtx.String("a")) - if e != nil { + var followsMap Follows + followsMap, e = cfg.GetFollows(cCtx.String("a")) + if log.Fail(e) { return e } @@ -47,7 +47,7 @@ func doDMList(cCtx *cli.Context) (e error) { } else { return e } - if npub, e = keys.GetPublicKey(sk); e != nil { + if npub, e = keys.GetPublicKey(sk); log.Fail(e) { return e } @@ -62,8 +62,8 @@ func doDMList(cCtx *cli.Context) (e error) { name string pubkey string } - users := []entry{} - m := map[string]struct{}{} + var users []entry + m := Checklist{} for _, ev := range evs { p := ev.Tags.GetFirst([]string{"p"}).Value() if _, ok := m[p]; ok { @@ -107,7 +107,7 @@ func doDMTimeline(cCtx *cli.Context) (e error) { j := cCtx.Bool("json") extra := cCtx.Bool("extra") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) var sk string var npub string @@ -116,7 +116,7 @@ func doDMTimeline(cCtx *cli.Context) (e error) { } else { return e } - if npub, e = keys.GetPublicKey(sk); e != nil { + if npub, e = keys.GetPublicKey(sk); log.Fail(e) { return e } @@ -131,7 +131,7 @@ func doDMTimeline(cCtx *cli.Context) (e error) { } // get followers followsMap, e := cfg.GetFollows(cCtx.String("a")) - if e != nil { + if log.Fail(e) { return e } @@ -156,7 +156,7 @@ func doDMPost(cCtx *cli.Context) (e error) { } sensitive := cCtx.String("sensitive") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { @@ -164,9 +164,9 @@ func doDMPost(cCtx *cli.Context) (e error) { } else { return e } - ev := event.T{} + ev := &event.T{} if npub, e := keys.GetPublicKey(sk); e == nil { - if _, e := nip19.EncodePublicKey(npub); e != nil { + if _, e := nip19.EncodePublicKey(npub); log.Fail(e) { return e } ev.PubKey = npub @@ -175,8 +175,8 @@ func doDMPost(cCtx *cli.Context) (e error) { } if stdin { - b, e := ioutil.ReadAll(os.Stdin) - if e != nil { + b, e := io.ReadAll(os.Stdin) + if log.Fail(e) { return e } ev.Content = string(b) @@ -206,21 +206,21 @@ func doDMPost(cCtx *cli.Context) (e error) { ev.Kind = event.KindEncryptedDirectMessage ss, e := nip04.ComputeSharedSecret(ev.PubKey, sk) - if e != nil { + if log.Fail(e) { return e } ev.Content, e = nip04.Encrypt(ev.Content, ss) - if e != nil { + if log.Fail(e) { return e } - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return e } var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { e := rl.Publish(c, ev) - if e != nil { + if log.Fail(e) { fmt.Fprintln(os.Stderr, rl.URL, e) } else { success.Add(1) @@ -232,7 +232,17 @@ func doDMPost(cCtx *cli.Context) (e error) { } return nil } - +func (cfg *C) publish(ev *event.T, success *atomic.Int64) RelayIterator { + return func(c context.T, rl *relays.Relay) bool { + e := rl.Publish(c, ev) + if log.Fail(e) { + log.D.Ln(rl.URL, e) + } else { + success.Add(1) + } + return true + } +} func doPost(cCtx *cli.Context) (e error) { stdin := cCtx.Bool("stdin") if !stdin && cCtx.Args().Len() == 0 { @@ -241,7 +251,7 @@ func doPost(cCtx *cli.Context) (e error) { sensitive := cCtx.String("sensitive") geohash := cCtx.String("geohash") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { @@ -249,9 +259,9 @@ func doPost(cCtx *cli.Context) (e error) { } else { return e } - ev := event.T{} + ev := &event.T{} if pub, e := keys.GetPublicKey(sk); e == nil { - if _, e := nip19.EncodePublicKey(pub); e != nil { + if _, e := nip19.EncodePublicKey(pub); log.Fail(e) { return e } ev.PubKey = pub @@ -261,7 +271,7 @@ func doPost(cCtx *cli.Context) (e error) { if stdin { b, e := io.ReadAll(os.Stdin) - if e != nil { + if log.Fail(e) { return e } ev.Content = string(b) @@ -320,14 +330,14 @@ func doPost(cCtx *cli.Context) (e error) { ev.CreatedAt = timestamp.Now() ev.Kind = event.KindTextNote - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return e } var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { e := rl.Publish(c, ev) - if e != nil { + if log.Fail(e) { fmt.Fprintln(os.Stderr, rl.URL, e) } else { success.Add(1) @@ -350,7 +360,7 @@ func doReply(cCtx *cli.Context) (e error) { sensitive := cCtx.String("sensitive") geohash := cCtx.String("geohash") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { @@ -358,9 +368,9 @@ func doReply(cCtx *cli.Context) (e error) { } else { return e } - ev := event.T{} + ev := &event.T{} if pub, e := keys.GetPublicKey(sk); e == nil { - if _, e := nip19.EncodePublicKey(pub); e != nil { + if _, e := nip19.EncodePublicKey(pub); log.Fail(e) { return e } ev.PubKey = pub @@ -377,8 +387,8 @@ func doReply(cCtx *cli.Context) (e error) { ev.CreatedAt = timestamp.Now() ev.Kind = event.KindTextNote if stdin { - b, e := ioutil.ReadAll(os.Stdin) - if e != nil { + b, e := io.ReadAll(os.Stdin) + if log.Fail(e) { return e } ev.Content = string(b) @@ -426,17 +436,17 @@ func doReply(cCtx *cli.Context) (e error) { } var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { if !quote { ev.Tags = ev.Tags.AppendUnique(tags.Tag{"e", id, rl.URL, "reply"}) } else { ev.Tags = ev.Tags.AppendUnique(tags.Tag{"e", id, rl.URL, "mention"}) } - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return true } e := rl.Publish(c, ev) - if e != nil { + if log.Fail(e) { fmt.Fprintln(os.Stderr, rl.URL, e) } else { success.Add(1) @@ -452,9 +462,9 @@ func doReply(cCtx *cli.Context) (e error) { func doRepost(cCtx *cli.Context) (e error) { id := cCtx.String("id") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) - ev := event.T{} + ev := &event.T{} var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { sk = s.(string) @@ -462,7 +472,7 @@ func doRepost(cCtx *cli.Context) (e error) { return e } if pub, e := keys.GetPublicKey(sk); e == nil { - if _, e := nip19.EncodePublicKey(pub); e != nil { + if _, e := nip19.EncodePublicKey(pub); log.Fail(e) { return e } ev.PubKey = pub @@ -489,22 +499,22 @@ func doRepost(cCtx *cli.Context) (e error) { first.Store(true) var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { if first.Load() { evs, e := rl.QuerySync(c, f) - if e != nil { + if log.Fail(e) { return true } for _, tmp := range evs { ev.Tags = ev.Tags.AppendUnique(tags.Tag{"p", tmp.ID}) } first.Store(false) - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return true } } e := rl.Publish(c, ev) - if e != nil { + if log.Fail(e) { fmt.Fprintln(os.Stderr, rl.URL, e) } else { success.Add(1) @@ -525,7 +535,7 @@ func doUnrepost(cCtx *cli.Context) (e error) { return fmt.Errorf("failed to parse event from '%s'", id) } - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { @@ -534,7 +544,7 @@ func doUnrepost(cCtx *cli.Context) (e error) { return e } pub, e := keys.GetPublicKey(sk) - if e != nil { + if log.Fail(e) { return e } f := filter.T{ @@ -544,9 +554,9 @@ func doUnrepost(cCtx *cli.Context) (e error) { } var repostID string var mu sync.Mutex - cfg.Do(RelayPerms{Read: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(rp, func(c context.T, rl *relays.Relay) bool { evs, e := rl.QuerySync(c, f) - if e != nil { + if log.Fail(e) { return true } mu.Lock() @@ -557,19 +567,19 @@ func doUnrepost(cCtx *cli.Context) (e error) { return true }) - var ev event.T + ev := &event.T{} ev.Tags = ev.Tags.AppendUnique(tags.Tag{"e", repostID}) ev.CreatedAt = timestamp.Now() ev.Kind = event.KindDeletion - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return e } var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { - e := rl.Publish(c, ev) - if e != nil { - fmt.Fprintln(os.Stderr, rl.URL, e) + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { + e = rl.Publish(c, ev) + if log.Fail(e) { + log.D.Ln(rl.URL, e) } else { success.Add(1) } @@ -584,9 +594,9 @@ func doUnrepost(cCtx *cli.Context) (e error) { func doLike(cCtx *cli.Context) (e error) { id := cCtx.String("id") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) - ev := event.T{} + ev := &event.T{} var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { sk = s.(string) @@ -594,7 +604,7 @@ func doLike(cCtx *cli.Context) (e error) { return e } if pub, e := keys.GetPublicKey(sk); e == nil { - if _, e := nip19.EncodePublicKey(pub); e != nil { + if _, e := nip19.EncodePublicKey(pub); log.Fail(e) { return e } ev.PubKey = pub @@ -632,23 +642,23 @@ func doLike(cCtx *cli.Context) (e error) { first.Store(true) var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { if first.Load() { evs, e := rl.QuerySync(c, f) - if e != nil { + if log.Fail(e) { return true } for _, tmp := range evs { ev.Tags = ev.Tags.AppendUnique(tags.Tag{"p", tmp.ID}) } first.Store(false) - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return true } return true } e := rl.Publish(c, ev) - if e != nil { + if log.Fail(e) { fmt.Fprintln(os.Stderr, rl.URL, e) } else { success.Add(1) @@ -669,7 +679,7 @@ func doUnlike(cCtx *cli.Context) (e error) { return fmt.Errorf("failed to parse event from '%s'", id) } - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { @@ -678,7 +688,7 @@ func doUnlike(cCtx *cli.Context) (e error) { return e } pub, e := keys.GetPublicKey(sk) - if e != nil { + if log.Fail(e) { return e } f := filter.T{ @@ -688,9 +698,9 @@ func doUnlike(cCtx *cli.Context) (e error) { } var likeID string var mu sync.Mutex - cfg.Do(RelayPerms{Read: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(rp, func(c context.T, rl *relays.Relay) bool { evs, e := rl.QuerySync(c, f) - if e != nil { + if log.Fail(e) { return true } mu.Lock() @@ -701,18 +711,18 @@ func doUnlike(cCtx *cli.Context) (e error) { return true }) - var ev event.T + ev := &event.T{} ev.Tags = ev.Tags.AppendUnique(tags.Tag{"e", likeID}) ev.CreatedAt = timestamp.Now() ev.Kind = event.KindDeletion - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return e } var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { e := rl.Publish(c, ev) - if e != nil { + if log.Fail(e) { fmt.Fprintln(os.Stderr, rl.URL, e) } else { success.Add(1) @@ -728,9 +738,9 @@ func doUnlike(cCtx *cli.Context) (e error) { func doDelete(cCtx *cli.Context) (e error) { id := cCtx.String("id") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) - ev := event.T{} + ev := &event.T{} var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { sk = s.(string) @@ -738,7 +748,7 @@ func doDelete(cCtx *cli.Context) (e error) { return e } if pub, e := keys.GetPublicKey(sk); e == nil { - if _, e := nip19.EncodePublicKey(pub); e != nil { + if _, e := nip19.EncodePublicKey(pub); log.Fail(e) { return e } ev.PubKey = pub @@ -754,14 +764,14 @@ func doDelete(cCtx *cli.Context) (e error) { ev.Tags = ev.Tags.AppendUnique(tags.Tag{"e", id}) ev.CreatedAt = timestamp.Now() ev.Kind = event.KindDeletion - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return e } var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { e := rl.Publish(c, ev) - if e != nil { + if log.Fail(e) { fmt.Fprintln(os.Stderr, rl.URL, e) } else { success.Add(1) @@ -779,15 +789,15 @@ func doSearch(cCtx *cli.Context) (e error) { j := cCtx.Bool("json") extra := cCtx.Bool("extra") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) // get followers - var followsMap map[string]Profile + var followsMap Follows if j && !extra { - followsMap = make(map[string]Profile) + followsMap = make(Follows) } else { followsMap, e = cfg.GetFollows(cCtx.String("a")) - if e != nil { + if log.Fail(e) { return e } } @@ -815,12 +825,12 @@ func doStream(cCtx *cli.Context) (e error) { if pattern != "" { var e error re, e = regexp.Compile(pattern) - if e != nil { + if log.Fail(e) { return e } } - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) rl := cfg.FindRelay(context.Bg(), RelayPerms{Read: true}) if rl == nil { @@ -835,7 +845,7 @@ func doStream(cCtx *cli.Context) (e error) { return e } pub, e := keys.GetPublicKey(sk) - if e != nil { + if log.Fail(e) { return e } @@ -843,7 +853,7 @@ func doStream(cCtx *cli.Context) (e error) { var follows []string if f { followsMap, e := cfg.GetFollows(cCtx.String("a")) - if e != nil { + if log.Fail(e) { return e } for k := range followsMap { @@ -861,7 +871,7 @@ func doStream(cCtx *cli.Context) (e error) { } sub, e := rl.Subscribe(context.Bg(), filters.T{ff}) - if e != nil { + if log.Fail(e) { return e } for ev := range sub.Events { @@ -871,17 +881,17 @@ func doStream(cCtx *cli.Context) (e error) { } json.NewEncoder(os.Stdout).Encode(ev) if reply != "" { - var evr event.T + evr := &event.T{} evr.PubKey = pub evr.Content = reply evr.Tags = evr.Tags.AppendUnique(tags.Tag{"e", ev.ID, "", "reply"}) evr.CreatedAt = timestamp.Now() evr.Kind = event.KindTextNote - if e := evr.Sign(sk); e != nil { + if e := evr.Sign(sk); log.Fail(e) { return e } - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { - rl.Publish(c, evr) + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { + log.Fail(rl.Publish(c, evr)) return true }) } @@ -897,11 +907,11 @@ func doTimeline(cCtx *cli.Context) (e error) { j := cCtx.Bool("json") extra := cCtx.Bool("extra") - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) // get followers followsMap, e := cfg.GetFollows(cCtx.String("a")) - if e != nil { + if log.Fail(e) { return e } var follows []string @@ -922,7 +932,7 @@ func doTimeline(cCtx *cli.Context) (e error) { } func postMsg(cCtx *cli.Context, msg string) (e error) { - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { @@ -930,9 +940,9 @@ func postMsg(cCtx *cli.Context, msg string) (e error) { } else { return e } - ev := event.T{} + ev := &event.T{} if pub, e := keys.GetPublicKey(sk); e == nil { - if _, e := nip19.EncodePublicKey(pub); e != nil { + if _, e := nip19.EncodePublicKey(pub); log.Fail(e) { return e } ev.PubKey = pub @@ -944,15 +954,15 @@ func postMsg(cCtx *cli.Context, msg string) (e error) { ev.CreatedAt = timestamp.Now() ev.Kind = event.KindTextNote ev.Tags = tags.Tags{} - if e := ev.Sign(sk); e != nil { + if e := ev.Sign(sk); log.Fail(e) { return e } var success atomic.Int64 - cfg.Do(RelayPerms{Write: true}, func(c context.T, rl *relays.Relay) bool { - e := rl.Publish(c, ev) - if e != nil { - fmt.Fprintln(os.Stderr, rl.URL, e) + cfg.Do(wp, func(c context.T, rl *relays.Relay) bool { + e = rl.Publish(c, ev) + if log.Fail(e) { + log.D.Ln(rl.URL, e) } else { success.Add(1) } diff --git a/cmd/algia/zap.go b/cmd/algia/zap.go index c5fc8373..aa75d7e5 100644 --- a/cmd/algia/zap.go +++ b/cmd/algia/zap.go @@ -7,22 +7,19 @@ import ( "net/http" "net/url" "os" - "strings" "github.com/Hubmakerlabs/replicatr/pkg/context" - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/event" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/filter" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/keys" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip04" + "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip19" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/pointers" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/relays" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/tags" "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/timestamp" "github.com/mdp/qrterminal/v3" "github.com/urfave/cli/v2" - - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip04" - "github.com/Hubmakerlabs/replicatr/pkg/go-nostr/nip19" ) // Lnurlp is @@ -63,42 +60,42 @@ type PayResponse struct { } `json:"result"` } -func pay(cfg *Config, invoice string) (e error) { +func pay(cfg *C, invoice string) (e error) { uri, e := url.Parse(cfg.NwcURI) - if e != nil { + if log.Fail(e) { return e } wallet := uri.Host host := uri.Query().Get("relay") secret := uri.Query().Get("secret") pub, e := keys.GetPublicKey(secret) - if e != nil { + if log.Fail(e) { return e } rl, e := relays.RelayConnect(context.Bg(), host) - if e != nil { + if log.Fail(e) { return e } defer rl.Close() ss, e := nip04.ComputeSharedSecret(wallet, secret) - if e != nil { + if log.Fail(e) { return e } var req PayRequest req.Method = "pay_invoice" req.Params.Invoice = invoice b, e := json.Marshal(req) - if e != nil { + if log.Fail(e) { return e } content, e := nip04.Encrypt(string(b), ss) - if e != nil { + if log.Fail(e) { return e } - ev := event.T{ + ev := &event.T{ PubKey: pub, CreatedAt: timestamp.Now(), Kind: event.KindNWCWalletRequest, @@ -106,7 +103,7 @@ func pay(cfg *Config, invoice string) (e error) { Content: content, } e = ev.Sign(secret) - if e != nil { + if log.Fail(e) { return e } @@ -119,23 +116,23 @@ func pay(cfg *Config, invoice string) (e error) { Limit: 1, }} sub, e := rl.Subscribe(context.Bg(), filters) - if e != nil { + if log.Fail(e) { return e } e = rl.Publish(context.Bg(), ev) - if e != nil { + if log.Fail(e) { return e } er := <-sub.Events content, e = nip04.Decrypt(er.Content, ss) - if e != nil { + if log.Fail(e) { return e } var resp PayResponse e = json.Unmarshal([]byte(content), &resp) - if e != nil { + if log.Fail(e) { return e } if resp.Err != nil { @@ -145,54 +142,6 @@ func pay(cfg *Config, invoice string) (e error) { return nil } -// ZapInfo is -func (cfg *Config) ZapInfo(pub string) (*Lnurlp, error) { - rl := cfg.FindRelay(context.Bg(), RelayPerms{Read: true}) - if rl == nil { - return nil, errors.New("cannot connect relays") - } - defer rl.Close() - - // get set-metadata - f := filter.T{ - Kinds: []int{event.KindProfileMetadata}, - Authors: []string{pub}, - Limit: 1, - } - - evs := cfg.Events(f) - if len(evs) == 0 { - return nil, errors.New("cannot find user") - } - - var profile Profile - e := json.Unmarshal([]byte(evs[0].Content), &profile) - if e != nil { - return nil, e - } - - tok := strings.SplitN(profile.Lud16, "@", 2) - if e != nil { - return nil, e - } - if len(tok) != 2 { - return nil, errors.New("receipt address is not valid") - } - - resp, e := http.Get("https://" + tok[1] + "/.well-known/lnurlp/" + tok[0]) - if e != nil { - return nil, e - } - defer resp.Body.Close() - - var lp Lnurlp - e = json.NewDecoder(resp.Body).Decode(&lp) - if e != nil { - return nil, e - } - return &lp, nil -} - func doZap(cCtx *cli.Context) (e error) { amount := cCtx.Uint64("amount") comment := cCtx.String("comment") @@ -204,7 +153,7 @@ func doZap(cCtx *cli.Context) (e error) { return cli.ShowSubcommandHelp(cCtx) } - cfg := cCtx.App.Metadata["config"].(*Config) + cfg := cCtx.App.Metadata["config"].(*C) var sk string if _, s, e := nip19.Decode(cfg.PrivateKey); e == nil { @@ -218,7 +167,7 @@ func doZap(cCtx *cli.Context) (e error) { zr.Tags = tags.Tags{} if pub, e := keys.GetPublicKey(sk); e == nil { - if _, e := nip19.EncodePublicKey(pub); e != nil { + if _, e := nip19.EncodePublicKey(pub); log.Fail(e) { return e } zr.PubKey = pub @@ -258,20 +207,20 @@ func doZap(cCtx *cli.Context) (e error) { zr.Kind = event.KindZapRequest // 9734 zr.CreatedAt = timestamp.Now() zr.Content = comment - if e := zr.Sign(sk); e != nil { + if e := zr.Sign(sk); log.Fail(e) { return e } b, e := zr.MarshalJSON() - if e != nil { + if log.Fail(e) { return e } zi, e := cfg.ZapInfo(receipt) - if e != nil { + if log.Fail(e) { return e } u, e := url.Parse(zi.Callback) - if e != nil { + if log.Fail(e) { return e } param := url.Values{} @@ -279,14 +228,14 @@ func doZap(cCtx *cli.Context) (e error) { param.Set("nostr", string(b)) u.RawQuery = param.Encode() resp, e := http.Get(u.String()) - if e != nil { + if log.Fail(e) { return e } defer resp.Body.Close() var iv Invoice e = json.NewDecoder(resp.Body).Decode(&iv) - if e != nil { + if log.Fail(e) { return e } @@ -303,7 +252,7 @@ func doZap(cCtx *cli.Context) (e error) { fmt.Println("lightning:" + iv.PR) qrterminal.GenerateWithConfig("lightning:"+iv.PR, config) } else { - pay(cCtx.App.Metadata["config"].(*Config), iv.PR) + pay(cCtx.App.Metadata["config"].(*C), iv.PR) } return nil } diff --git a/cmd/replicatrd/replicatr/broadcasting.go b/cmd/replicatrd/replicatr/broadcasting.go index 32733ff1..85bf94b5 100644 --- a/cmd/replicatrd/replicatr/broadcasting.go +++ b/cmd/replicatrd/replicatr/broadcasting.go @@ -12,7 +12,7 @@ func (rl *Relay) BroadcastEvent(evt *event.T) { if !listener.filters.Match(evt) { return true } - log.E.Chk(ws.WriteJSON(event.Envelope{ + log.E.Chk(ws.WriteJSON(event.E{ SubscriptionID: &id, T: *evt}, )) diff --git a/cmd/replicatrd/replicatr/handlefilter.go b/cmd/replicatrd/replicatr/handlefilter.go index a298eb7e..5c7082e2 100644 --- a/cmd/replicatrd/replicatr/handlefilter.go +++ b/cmd/replicatrd/replicatr/handlefilter.go @@ -51,7 +51,7 @@ func (rl *Relay) handleFilter(c context.T, id string, for _, ovw := range rl.OverwriteResponseEvent { ovw(c, ev) } - rl.E.Chk(ws.WriteJSON(event2.Envelope{ + rl.E.Chk(ws.WriteJSON(event2.E{ SubscriptionID: &id, T: *ev, })) diff --git a/cmd/replicatrd/replicatr/websockethandler.go b/cmd/replicatrd/replicatr/websockethandler.go index 0b6a1f55..d0e5564f 100644 --- a/cmd/replicatrd/replicatr/websockethandler.go +++ b/cmd/replicatrd/replicatr/websockethandler.go @@ -74,7 +74,7 @@ func (rl *Relay) websocketProcessMessages(message []byte, c context.T, ws *WebSo return } switch env := env.(type) { - case *event.Envelope: + case *event.E: // check id hash := sha256.Sum256(env.T.Serialize()) id := hex.Enc(hash[:]) diff --git a/pkg/go-nostr/envelope/envelope.go b/pkg/go-nostr/envelope/envelope.go index ffe40262..fe42dc95 100644 --- a/pkg/go-nostr/envelope/envelope.go +++ b/pkg/go-nostr/envelope/envelope.go @@ -25,7 +25,7 @@ func ParseMessage(message []byte) envelopes.E { var v envelopes.E switch { case bytes.Contains(label, []byte("EVENT")): - v = &event.Envelope{} + v = &event.E{} case bytes.Contains(label, []byte("REQ")): v = &req.Envelope{} case bytes.Contains(label, []byte("COUNT")): diff --git a/pkg/go-nostr/event/event.go b/pkg/go-nostr/event/event.go index e4562e00..ac2f86cc 100644 --- a/pkg/go-nostr/event/event.go +++ b/pkg/go-nostr/event/event.go @@ -148,10 +148,11 @@ func (evt T) CheckSignature() (bool, error) { } // Sign signs an event with a given privateKey. -func (evt *T) Sign(privateKey string, signOpts ...schnorr.SignOption) error { - s, e := hex.Dec(privateKey) +func (evt *T) Sign(sec string, signOpts ...schnorr.SignOption) error { + s, e := hex.Dec(sec) if e != nil { - return fmt.Errorf("Sign called with invalid private key '%s': %w", privateKey, e) + return fmt.Errorf("sign called with invalid private key '%s': %w", + sec, e) } if evt.Tags == nil { @@ -174,16 +175,16 @@ func (evt *T) Sign(privateKey string, signOpts ...schnorr.SignOption) error { return nil } -type Envelope struct { +type E struct { SubscriptionID *string T } -var _ envelopes.E = (*Envelope)(nil) +var _ envelopes.E = (*E)(nil) -func (_ Envelope) Label() string { return "EVENT" } +func (_ E) Label() string { return "EVENT" } -func (v *Envelope) UnmarshalJSON(data []byte) error { +func (v *E) UnmarshalJSON(data []byte) error { r := gjson.ParseBytes(data) arr := r.Array() switch len(arr) { @@ -197,7 +198,7 @@ func (v *Envelope) UnmarshalJSON(data []byte) error { } } -func (v Envelope) MarshalJSON() ([]byte, error) { +func (v E) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} w.RawString(`["EVENT",`) if v.SubscriptionID != nil { diff --git a/pkg/go-nostr/event/event_test.go b/pkg/go-nostr/event/event_test.go index 0e5f8b87..ba7a51af 100644 --- a/pkg/go-nostr/event/event_test.go +++ b/pkg/go-nostr/event/event_test.go @@ -15,7 +15,7 @@ func TestEventEnvelopeEncodingAndDecoding(t *testing.T) { } for _, raw := range eventEnvelopes { - var env Envelope + var env E if e := json.Unmarshal([]byte(raw), &env); e != nil { t.Errorf("failed to parse event envelope json: %v", e) } diff --git a/pkg/go-nostr/relays/relay.go b/pkg/go-nostr/relays/relay.go index 2ef91d18..f07b5131 100644 --- a/pkg/go-nostr/relays/relay.go +++ b/pkg/go-nostr/relays/relay.go @@ -232,17 +232,19 @@ func (r *Relay) Connect(c context.T) error { continue } r.challenge = *env.Challenge - case *event.Envelope: + case *event.E: if env.SubscriptionID == nil { continue } if subscription, ok := r.Subscriptions.Load(*env.SubscriptionID); !ok { - fmt.Printf("{%s} no subscription with id '%s'\n", r.URL, *env.SubscriptionID) + fmt.Printf("{%s} no subscription with id '%s'\n", + r.URL, *env.SubscriptionID) continue } else { // check if the event matches the desired filter, ignore otherwise if !subscription.Filters.Match(&env.T) { - fmt.Printf("{%s} filter does not match: %v ~ %v\n", r.URL, subscription.Filters, env.T) + fmt.Printf("{%s} filter does not match: %v ~ %v\n", + r.URL, subscription.Filters, env.T) continue } @@ -298,8 +300,8 @@ func (r *Relay) Write(msg []byte) <-chan error { } // Publish sends an "EVENT" command to the relay r as in NIP-01 and waits for an OK response. -func (r *Relay) Publish(c context.T, ev event.T) error { - return r.publish(c, ev.ID, &event.Envelope{T: ev}) +func (r *Relay) Publish(c context.T, ev *event.T) error { + return r.publish(c, ev.ID, &event.E{T: *ev}) } // Auth sends an "AUTH" command client->relay as in NIP-42 and waits for an OK response.