tags.go raw

   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