1 package nostr
2 3 // Tag is a single NIP-01 tag: a non-empty JSON array of strings whose first
4 // element names the tag.
5 type Tag []string
6 7 // Tags is the ordered tag list of an event.
8 type Tags []Tag
9 10 // Name returns the tag name, or "" for an empty tag.
11 func (t Tag) Name() string {
12 if len(t) == 0 {
13 return ""
14 }
15 return t[0]
16 }
17 18 // Value returns the first value (index 1) of the tag, or "".
19 func (t Tag) Value() string {
20 if len(t) < 2 {
21 return ""
22 }
23 return t[1]
24 }
25 26 // First returns the value of the first tag with the given name.
27 func (ts Tags) First(name string) (string, bool) {
28 for _, t := range ts {
29 if t.Name() == name {
30 return t.Value(), true
31 }
32 }
33 return "", false
34 }
35 36 // Values returns every value of every tag with the given name.
37 func (ts Tags) Values(name string) []string {
38 var out []string
39 for _, t := range ts {
40 if t.Name() == name && len(t) >= 2 {
41 out = append(out, t[1])
42 }
43 }
44 return out
45 }
46 47 // Has reports whether a tag with the given name and value exists.
48 func (ts Tags) Has(name, value string) bool {
49 for _, t := range ts {
50 if t.Name() == name && t.Value() == value {
51 return true
52 }
53 }
54 return false
55 }
56 57 // HasName reports whether any tag with the given name exists.
58 func (ts Tags) HasName(name string) bool {
59 for _, t := range ts {
60 if t.Name() == name {
61 return true
62 }
63 }
64 return false
65 }
66 67 // DTag returns the first "d" tag value, or "".
68 func (e *Event) DTag() string {
69 v, _ := e.Tags.First("d")
70 return v
71 }
72 73 // AppendJSON appends the tag list as a JSON array.
74 func (ts Tags) AppendJSON(dst []byte) []byte {
75 dst = append(dst, '[')
76 for i, t := range ts {
77 if i > 0 {
78 dst = append(dst, ',')
79 }
80 dst = t.AppendJSON(dst)
81 }
82 return append(dst, ']')
83 }
84 85 // AppendJSON appends one tag as a JSON array of strings.
86 func (t Tag) AppendJSON(dst []byte) []byte {
87 dst = append(dst, '[')
88 for i, s := range t {
89 if i > 0 {
90 dst = append(dst, ',')
91 }
92 dst = AppendJSONString(dst, s)
93 }
94 return append(dst, ']')
95 }
96 97 // IndexableTags calls fn for every single-letter tag that the store indexes.
98 // NIP-01 only defines filters for single-letter tag names; multi-letter tags
99 // are not indexed.
100 func (ts Tags) IndexableTags(fn func(name string, value string)) {
101 for _, t := range ts {
102 if len(t) < 2 {
103 continue
104 }
105 if len(t[0]) != 1 {
106 continue
107 }
108 fn(t[0], t[1])
109 }
110 }
111