From 7dd973ae010e3bde60550d312a515c49f8ed3004 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Thu, 8 Jan 2026 18:58:01 -0300 Subject: [PATCH] many fixes. --- auth.go | 19 ++++++++++++++++ event.go | 4 ++-- helpers.go | 9 ++++++-- justfile | 19 +++++++++------- main.go | 14 +++--------- paste.go | 5 ++++- req.go | 66 +++++++++++++++++++++++++----------------------------- 7 files changed, 77 insertions(+), 59 deletions(-) create mode 100644 auth.go diff --git a/auth.go b/auth.go new file mode 100644 index 0000000..fd94fb6 --- /dev/null +++ b/auth.go @@ -0,0 +1,19 @@ +package main + +import ( + "context" + "fmt" + + "fiatjaf.com/nostr" +) + +func signAuthEvent(ctx context.Context, evt *nostr.Event) error { + if currentKeyer != nil { + err := currentKeyer.SignEvent(ctx, evt) + if err != nil { + return fmt.Errorf("failed to sign auth event: %w", err) + } + return nil + } + return fmt.Errorf("can't sign auth event, no key") +} diff --git a/event.go b/event.go index 7980c86..ddd45c4 100644 --- a/event.go +++ b/event.go @@ -337,8 +337,8 @@ func (event *eventVars) populate(evt nostr.Event) { // tags // clear all tag items and rows - for _, hbox := range event.tagRowHBoxes { - for _, item := range event.tagRows[len(event.tagRows)-1] { + for i, hbox := range event.tagRowHBoxes { + for _, item := range event.tagRows[i] { hbox.RemoveWidget(item.QWidget) item.DeleteLater() } diff --git a/helpers.go b/helpers.go index cec48c6..ed6d23f 100644 --- a/helpers.go +++ b/helpers.go @@ -2,6 +2,8 @@ package main import ( "context" + "crypto/rand" + "errors" "fmt" "slices" "strings" @@ -14,6 +16,8 @@ import ( "fiatjaf.com/nostr/nip46" ) +var manualCancel = errors.New("canceled") + func handleSecretKeyOrBunker(sec string) (nostr.SecretKey, nostr.Keyer, error) { if strings.HasPrefix(sec, "bunker://") { // it's a bunker @@ -121,9 +125,10 @@ func niceRelayURLs(urls []string) []string { func randString(n int) string { const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" b := make([]byte, n) + randomBytes := make([]byte, n) + rand.Read(randomBytes) for i := range b { - b[i] = letters[time.Now().UnixNano()%int64(len(letters))] - time.Sleep(1 * time.Nanosecond) // ensure different values + b[i] = letters[int(randomBytes[i])%len(letters)] } return string(b) } diff --git a/justfile b/justfile index 38c50dd..ee0a3cc 100644 --- a/justfile +++ b/justfile @@ -1,13 +1,16 @@ +run: + go build && ./vnak + dist: deploy_linux deploy_windows - mkdir -p dist - cd deploy/linux && tar -czvf vnak_linux.tar.gz vnak - mv deploy/linux/vnak_linux.tar.gz dist/ - rm -f deploy/windows/vnak_windows.zip - cd deploy/windows && zip vnak_windows *.exe - mv deploy/windows/vnak_windows.zip dist/ + mkdir -p dist + cd deploy/linux && tar -czvf vnak_linux.tar.gz vnak + mv deploy/linux/vnak_linux.tar.gz dist/ + rm -f deploy/windows/vnak_windows.zip + cd deploy/windows && zip vnak_windows *.exe + mv deploy/windows/vnak_windows.zip dist/ deploy_linux: - go build -ldflags="-s -w" + go build -ldflags="-s -w" deploy_windows: - go build -ldflags="-s -w -H windowsgui" --tags=windowsqtstatic + go build -ldflags="-s -w -H windowsgui" --tags=windowsqtstatic diff --git a/main.go b/main.go index 5c744ed..50848ee 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,6 @@ import ( "context" "encoding/hex" "flag" - "fmt" "net/http" "os" "strings" @@ -51,23 +50,16 @@ func main() { // nostr setup httpHeader := http.Header{} httpHeader.Set("User-Agent", "vnak") + sys.Pool = nostr.NewPool(nostr.PoolOptions{ AuthorKindQueryMiddleware: sys.TrackQueryAttempts, EventMiddleware: sys.TrackEventHintsAndRelays, DuplicateMiddleware: sys.TrackEventRelaysD, PenaltyBox: false, - AuthHandler: func(ctx context.Context, evt *nostr.Event) error { - if currentKeyer != nil { - err := currentKeyer.SignEvent(ctx, evt) - if err != nil { - return fmt.Errorf("failed to sign auth event: %w", err) - } - return nil - } - return fmt.Errorf("can't sign auth event, no key") - }, + AuthRequiredHandler: signAuthEvent, RelayOptions: nostr.RelayOptions{ RequestHeader: httpHeader, + AuthHandler: signAuthEvent, }, }) diff --git a/paste.go b/paste.go index be274ad..0f5f67b 100644 --- a/paste.go +++ b/paste.go @@ -335,7 +335,10 @@ func (p *pasteVars) displayNip05(identifier string) { paste.nip05ctxCancel = cancel defer cancel() pp, err := nip05.QueryIdentifier(nip05ctx, identifier) - if err != nil && err != paste.nip05ctxAbort { + if err != nil { + if err == paste.nip05ctxAbort || context.Cause(nip05ctx) == paste.nip05ctxAbort { + return + } mainthread.Wait(func() { errorLabel := qt.NewQLabel2() errorLabel.SetText("failed to query nip05: " + err.Error()) diff --git a/req.go b/req.go index fa836e7..76f9bf0 100644 --- a/req.go +++ b/req.go @@ -5,6 +5,7 @@ import ( "encoding/json" "strconv" "strings" + "sync/atomic" "time" "fiatjaf.com/nostr" @@ -38,6 +39,8 @@ type reqVars struct { outputEdit *qt.QTextEdit resultsList *qt.QListWidget + + subCancel context.CancelCauseFunc } type reqKindRow struct { @@ -252,7 +255,7 @@ func setupReqTab() *qt.QWidget { buttonsHBox := qt.NewQHBoxLayout2() dlayout.AddLayout(buttonsHBox.QLayout) - editButton := qt.NewQPushButton5("➡️ edit", dialog.QWidget) + editButton := qt.NewQPushButton5("➡️ paste", dialog.QWidget) editButton.OnClicked(func() { paste.inputEdit.SetPlainText(string(pretty)) tabWidget.SetCurrentIndex(tabs.paste) @@ -260,7 +263,7 @@ func setupReqTab() *qt.QWidget { }) buttonsHBox.AddWidget(editButton.QWidget) - publishButton := qt.NewQPushButton5("➡️ publish", dialog.QWidget) + publishButton := qt.NewQPushButton5("➡️ event", dialog.QWidget) publishButton.OnClicked(func() { event.populate(evt) tabWidget.SetCurrentIndex(tabs.event) @@ -373,6 +376,10 @@ func (req *reqVars) updateReq() { } func (req *reqVars) subscribe() { + if req.subCancel != nil { + req.subCancel(manualCancel) + } + // collect relays relays := []string{} for _, edit := range req.relaysEdits { @@ -388,7 +395,9 @@ func (req *reqVars) subscribe() { // subscribe var eoseChan chan struct{} - var eventsChan chan nostr.Event + var eventsChan chan nostr.RelayEvent + ctx, cancel := context.WithCancelCause(ctx) + req.subCancel = cancel if len(relays) == 1 { relay, err := sys.Pool.EnsureRelay(relays[0]) @@ -397,16 +406,6 @@ func (req *reqVars) subscribe() { return } - if currentKeyer != nil { - err = relay.Auth(ctx, func(ctx context.Context, evt *nostr.Event) error { - return currentKeyer.SignEvent(ctx, evt) - }) - if err != nil { - setStatus(tabs.req, "failed to auth to %s: %s", niceRelayURL(relay.URL), err) - return - } - } - setStatus(tabs.req, "subscribed to "+niceRelayURL(relay.URL)) sub, err := relay.Subscribe(ctx, req.filter, nostr.SubscriptionOptions{ Label: "vnak-req-1", @@ -416,7 +415,16 @@ func (req *reqVars) subscribe() { return } - eventsChan = sub.Events + eventsChan := make(chan nostr.RelayEvent) + go func() { + for event := range sub.Events { + eventsChan <- nostr.RelayEvent{ + Event: event, + Relay: relay, + } + } + }() + eoseChan = sub.EndOfStoredEvents go func() { @@ -428,29 +436,18 @@ func (req *reqVars) subscribe() { }() } else { setStatus(tabs.req, "subscribed to "+strings.Join(niceRelayURLs(relays), ", ")) - eoseChan = make(chan struct{}) - eventsChan = make(chan nostr.Event) - - go func() { - for ie := range sys.Pool.SubscribeManyNotifyEOSE(ctx, relays, req.filter, eoseChan, - nostr.SubscriptionOptions{ - Label: "vnak-req", - }, - ) { - eventsChan <- ie.Event - } - }() + eventsChan, eoseChan = sys.Pool.SubscribeManyNotifyEOSE(ctx, relays, req.filter, nostr.SubscriptionOptions{Label: "vnak-req"}) } // collect events - eosed := false + var eosed atomic.Bool go func() { - for event := range eventsChan { - jsonBytes, _ := json.Marshal(event) + for ie := range eventsChan { + jsonBytes, _ := json.Marshal(ie.Event) mainthread.Wait(func() { item := qt.NewQListWidgetItem2(string(jsonBytes)) - if eosed { + if eosed.Load() { req.resultsList.InsertItem(0, item) } else { req.resultsList.AddItemWithItem(item) @@ -462,7 +459,7 @@ func (req *reqVars) subscribe() { go func() { <-eoseChan - eosed = true + eosed.Store(true) }() } @@ -539,7 +536,7 @@ func (req *reqVars) populate(filter nostr.Filter, relays []string) { dt.SetMSecsSinceEpoch(int64(filter.Since) * 1000) req.sinceEdit.SetDateTime(dt) } else { - req.sinceCheck.SetChecked(true) + req.sinceCheck.SetChecked(false) } if filter.Until != 0 { @@ -567,11 +564,10 @@ func (req *reqVars) populate(filter nostr.Filter, relays []string) { relayEdit.DeleteLater() } req.relaysEdits = req.relaysEdits[:0] - for _, relay := range relays { + for i, relay := range relays { req.addRelayEdit() - req.relaysEdits[len(req.relaysEdits)-1].SetText(relay) + req.relaysEdits[i].SetText(relay) } - req.addRelayEdit() // extra empty req.updateReq() }