diff --git a/go.mod b/go.mod index fbd39ee..fd27fcf 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ toolchain go1.23.4 require ( github.com/bep/debounce v1.2.1 github.com/btcsuite/btcd/btcec/v2 v2.3.4 + github.com/bytedance/sonic v1.13.1 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/fatih/color v1.16.0 @@ -14,10 +15,11 @@ require ( github.com/fiatjaf/khatru v0.16.0 github.com/hanwen/go-fuse/v2 v2.7.2 github.com/json-iterator/go v1.1.12 + github.com/liamg/magic v0.0.1 github.com/mailru/easyjson v0.9.0 github.com/mark3labs/mcp-go v0.8.3 github.com/markusmobius/go-dateparser v1.2.3 - github.com/nbd-wtf/go-nostr v0.51.0 + github.com/nbd-wtf/go-nostr v0.51.1 github.com/urfave/cli/v3 v3.0.0-beta1 golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac ) @@ -29,7 +31,6 @@ require ( github.com/btcsuite/btcd v0.24.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect - github.com/bytedance/sonic v1.13.1 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/logex v1.1.10 // indirect diff --git a/go.sum b/go.sum index 0af85cf..aa842ac 100644 --- a/go.sum +++ b/go.sum @@ -96,6 +96,8 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -127,6 +129,8 @@ github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQe github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/liamg/magic v0.0.1 h1:Ru22ElY+sCh6RvRTWjQzKKCxsEco8hE0co8n1qe7TBM= +github.com/liamg/magic v0.0.1/go.mod h1:yQkOmZZI52EA+SQ2xyHpVw8fNvTBruF873Y+Vt6S+fk= github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= @@ -147,8 +151,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.51.0 h1:Z6gir3lQmlbQGYkccEPbvHlfCydMWXD6bIqukR4DZqU= -github.com/nbd-wtf/go-nostr v0.51.0/go.mod h1:9PcGOZ+e1VOaLvcK0peT4dbip+/eS+eTWXR3HuexQrA= +github.com/nbd-wtf/go-nostr v0.51.1 h1:SKnvWRbcDAoNibMYWrNbG4V1VQzQUc9YWltUJsrSDbw= +github.com/nbd-wtf/go-nostr v0.51.1/go.mod h1:9PcGOZ+e1VOaLvcK0peT4dbip+/eS+eTWXR3HuexQrA= 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= @@ -258,4 +262,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/nostrfs/npubdir.go b/nostrfs/npubdir.go index f2a0509..8a20d06 100644 --- a/nostrfs/npubdir.go +++ b/nostrfs/npubdir.go @@ -1,13 +1,18 @@ package nostrfs import ( + "bytes" "context" + "io" + "net/http" "sync/atomic" "syscall" + "time" "github.com/bytedance/sonic" "github.com/hanwen/go-fuse/v2/fs" "github.com/hanwen/go-fuse/v2/fuse" + "github.com/liamg/magic" "github.com/nbd-wtf/go-nostr" sdk "github.com/nbd-wtf/go-nostr/sdk" ) @@ -42,26 +47,60 @@ func CreateNpubDir( fs.StableAttr{}, ), true) - h.AddChild( - "metadata.json", - h.NewPersistentInode( - ctx, - &AsyncFile{ - ctx: ctx, - load: func() ([]byte, nostr.Timestamp) { - pm := sys.FetchProfileMetadata(ctx, pointer.PublicKey) - jsonb, _ := sonic.ConfigFastest.MarshalIndent(pm, "", " ") - var ts nostr.Timestamp - if pm.Event != nil { - ts = pm.Event.CreatedAt - } - return jsonb, ts + go func() { + pm := sys.FetchProfileMetadata(ctx, pointer.PublicKey) + if pm.Event == nil { + return + } + + metadataj, _ := sonic.ConfigFastest.MarshalIndent(pm, "", " ") + h.AddChild( + "metadata.json", + h.NewPersistentInode( + ctx, + &fs.MemRegularFile{ + Data: metadataj, + Attr: fuse.Attr{ + Mtime: uint64(pm.Event.CreatedAt), + Mode: 0444, + }, }, - }, - fs.StableAttr{}, - ), - true, - ) + fs.StableAttr{}, + ), + true, + ) + + ctx, cancel := context.WithTimeout(ctx, time.Second*20) + defer cancel() + r, err := http.NewRequestWithContext(ctx, "GET", pm.Picture, nil) + if err == nil { + resp, err := http.DefaultClient.Do(r) + if err == nil { + defer resp.Body.Close() + if resp.StatusCode < 300 { + b := &bytes.Buffer{} + io.Copy(b, resp.Body) + + ext := "png" + if ft, err := magic.Lookup(b.Bytes()); err == nil { + ext = ft.Extension + } + + h.AddChild("picture."+ext, h.NewPersistentInode( + ctx, + &fs.MemRegularFile{ + Data: b.Bytes(), + Attr: fuse.Attr{ + Mtime: uint64(pm.Event.CreatedAt), + Mode: 0444, + }, + }, + fs.StableAttr{}, + ), true) + } + } + } + }() h.AddChild( "notes", @@ -193,7 +232,11 @@ func CreateNpubDir( paginate: false, relays: relays, create: func(ctx context.Context, n *ViewDir, event *nostr.Event) (string, *fs.Inode) { - return event.Tags.GetD(), CreateEntityDir(ctx, n, n.wd, ".md", event) + d := event.Tags.GetD() + if d == "" { + d = "_" + } + return d, CreateEntityDir(ctx, n, n.wd, ".md", event) }, }, fs.StableAttr{Mode: syscall.S_IFDIR}, @@ -216,7 +259,11 @@ func CreateNpubDir( paginate: false, relays: relays, create: func(ctx context.Context, n *ViewDir, event *nostr.Event) (string, *fs.Inode) { - return event.Tags.GetD(), CreateEntityDir(ctx, n, n.wd, ".adoc", event) + d := event.Tags.GetD() + if d == "" { + d = "_" + } + return d, CreateEntityDir(ctx, n, n.wd, ".adoc", event) }, }, fs.StableAttr{Mode: syscall.S_IFDIR},