From a4bae38f68f9441c42bedf4ee58ca23d8273f3f7 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sun, 29 Dec 2024 14:07:19 -0300 Subject: [PATCH] add nip92 imeta parsing helper. --- nip92/imeta.go | 73 ++++++++++++++++++++++++++++++++ nip92/imeta_test.go | 100 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 nip92/imeta.go create mode 100644 nip92/imeta_test.go diff --git a/nip92/imeta.go b/nip92/imeta.go new file mode 100644 index 0000000..af2471e --- /dev/null +++ b/nip92/imeta.go @@ -0,0 +1,73 @@ +package nip92 + +import ( + "strconv" + "strings" + + "github.com/nbd-wtf/go-nostr" +) + +type IMeta []IMetaEntry + +func (imeta IMeta) Get(url string) (IMetaEntry, bool) { + for _, entry := range imeta { + if entry.URL == url { + return entry, true + } + } + return IMetaEntry{}, false +} + +type IMetaEntry struct { + URL string + Blurhash string + Width int + Height int + Alt string +} + +func ParseTags(tags nostr.Tags) IMeta { + var imeta IMeta + for i, tag := range tags { + if len(tag) > 2 && tag[0] == "imeta" { + entry := IMetaEntry{} + for _, item := range tag[1:] { + div := strings.Index(item, " ") + switch item[0:div] { + case "url": + entry.URL = item[div+1:] + case "alt": + entry.Alt = item[div+1:] + case "blurhash": + entry.Blurhash = item[div+1:] + case "dim": + xySplit := strings.Index(item[div+1:], "x") + if xySplit == -1 { + // if any tag is wrong them we don't trust this guy anyway + return nil + } + + x, err := strconv.Atoi(item[div+1 : div+1+xySplit]) + if err != nil { + return nil + } + entry.Width = x + + y, err := strconv.Atoi(item[div+1+xySplit+1:]) + if err != nil { + return nil + } + entry.Height = y + } + } + + if imeta == nil { + imeta = make(IMeta, 1, len(tags)-i) + imeta[0] = entry + } else { + imeta = append(imeta, entry) + } + } + } + return imeta +} diff --git a/nip92/imeta_test.go b/nip92/imeta_test.go new file mode 100644 index 0000000..e400748 --- /dev/null +++ b/nip92/imeta_test.go @@ -0,0 +1,100 @@ +package nip92 + +import ( + "testing" + + "github.com/nbd-wtf/go-nostr" + "github.com/stretchr/testify/require" +) + +func TestIMetaParsing(t *testing.T) { + for i, tcase := range []struct { + expected IMeta + tags nostr.Tags + }{ + { + expected: nil, + tags: nostr.Tags{}, + }, + { + expected: nil, + tags: nostr.Tags{{"t", "nothing"}}, + }, + { + expected: nil, + tags: nostr.Tags{{"imeta", "nothing"}}, + }, + { + expected: nil, + tags: nostr.Tags{ + { + "imeta", + "url https://i.nostr.build/yhsyFkwxWlw7odSB.gif", + "blurhash eDG*7p~AE34;E29x^ij?EMWBEMIWI;IpbI0g0gn+%1oyNGEMM|%1n%", + "dim 225x191", + }, + { + "imeta", + "blurhash qwkueh", + "dim oxo", + }, + }, + }, + { + expected: IMeta{ + { + URL: "https://i.nostr.build/yhsyFkwxWlw7odSB.gif", + Blurhash: "eDG*7p~AE34;E29x^ij?EMWBEMIWI;IpbI0g0gn+%1oyNGEMM|%1n%", + Width: 225, + Height: 191, + }, + }, + tags: nostr.Tags{ + { + "imeta", + "url https://i.nostr.build/yhsyFkwxWlw7odSB.gif", + "blurhash eDG*7p~AE34;E29x^ij?EMWBEMIWI;IpbI0g0gn+%1oyNGEMM|%1n%", + "dim 225x191", + }, + }, + }, + { + expected: IMeta{ + { + URL: "https://image.nostr.build/94060676611fe7fca86588068d3f140607eda443f6d66d6b9754e93b0b8439ac.jpg", + Blurhash: "eQF?RxZ}nNo~fk*0s6Z~kYem0iacsRkEsl9eW;oHkDoIxbtSobRkRi", + Width: 3024, + Height: 3024, + }, + { + URL: "https://image.nostr.build/9bc3998f79c401bc9d3b3b74c1cbff0a3225f754194b94a6f5750ca6ea492846.jpg", + Blurhash: "#2Ss1[RO%MIUx]R*-;WUtR0Kt6njof-;xu-pofxt4-M{yExt%2s.xaV[jF4TM|?bt6tmt6tRaybI0KtS=wRkWYWAtRjYt7tR%M?vNerWRjIBV@RjIAxYIpRP_3NGaKWXRj", + Width: 1920, + Height: 1494, + Alt: "Verifiable file url", + }, + }, + tags: nostr.Tags{ + { + "imeta", + "url https://image.nostr.build/94060676611fe7fca86588068d3f140607eda443f6d66d6b9754e93b0b8439ac.jpg", + "blurhash eQF?RxZ}nNo~fk*0s6Z~kYem0iacsRkEsl9eW;oHkDoIxbtSobRkRi", + "dim 3024x3024", + }, + { + "imeta", + "url https://image.nostr.build/9bc3998f79c401bc9d3b3b74c1cbff0a3225f754194b94a6f5750ca6ea492846.jpg", + "m image/jpeg", + "alt Verifiable file url", + "x 80a8f087f6c45ec7fb9e8839e5af095df9b439a0836cdf70a244086b6b2c1a88", + "size 121397", + "dim 1920x1494", + "blurhash #2Ss1[RO%MIUx]R*-;WUtR0Kt6njof-;xu-pofxt4-M{yExt%2s.xaV[jF4TM|?bt6tmt6tRaybI0KtS=wRkWYWAtRjYt7tR%M?vNerWRjIBV@RjIAxYIpRP_3NGaKWXRj", + "ox 9bc3998f79c401bc9d3b3b74c1cbff0a3225f754194b94a6f5750ca6ea492846", + }, + }, + }, + } { + require.Equal(t, tcase.expected, ParseTags(tcase.tags), "case %d", i) + } +}