mirror of
https://github.com/fiatjaf/vnak.git
synced 2026-07-22 07:48:24 +00:00
many fixes.
This commit is contained in:
19
auth.go
Normal file
19
auth.go
Normal file
@@ -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")
|
||||
}
|
||||
4
event.go
4
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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
19
justfile
19
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
|
||||
|
||||
14
main.go
14
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,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
5
paste.go
5
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())
|
||||
|
||||
66
req.go
66
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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user