noticeenvelope.go raw

   1  // Package noticeenvelope is a codec for the NOTICE envelope, which is used to
   2  // serve (mostly ignored) messages that are supposed to be shown to a user in
   3  // the client.
   4  package noticeenvelope
   5  
   6  import (
   7  	"io"
   8  
   9  	"next.orly.dev/pkg/nostr/encoders/envelopes"
  10  	"next.orly.dev/pkg/nostr/encoders/text"
  11  	"next.orly.dev/pkg/nostr/interfaces/codec"
  12  	"next.orly.dev/pkg/nostr/utils/constraints"
  13  	"next.orly.dev/pkg/lol/chk"
  14  )
  15  
  16  // L is the label associated with this type of codec.Envelope.
  17  const L = "NOTICE"
  18  
  19  // T is a NOTICE envelope, intended to convey information to the user about the
  20  // state of the relay connection. This thing is rarely displayed on clients
  21  // except sometimes in event logs.
  22  type T struct {
  23  	Message []byte
  24  }
  25  
  26  var _ codec.Envelope = (*T)(nil)
  27  
  28  // New creates a new empty NOTICE noticeenvelope.T.
  29  func New() *T { return &T{} }
  30  
  31  // NewFrom creates a new noticeenvelope.T with a provided message.
  32  func NewFrom[V constraints.Bytes](msg V) *T { return &T{Message: []byte(msg)} }
  33  
  34  // Label returns the label of a NOTICE envelope.
  35  func (en *T) Label() string { return L }
  36  
  37  // Write the NOTICE T to a provided io.Writer.
  38  func (en *T) Write(w io.Writer) (err error) {
  39  	_, err = w.Write(en.Marshal(nil))
  40  	return
  41  }
  42  
  43  // Marshal a NOTICE envelope in minified JSON into an noticeenvelope.T,
  44  // appending to a provided destination slice. Note that this ensures correct
  45  // string escaping on the Reason field.
  46  func (en *T) Marshal(dst []byte) (b []byte) {
  47  	var err error
  48  	_ = err
  49  	b = dst
  50  	b = envelopes.Marshal(
  51  		b, L,
  52  		func(bst []byte) (o []byte) {
  53  			o = bst
  54  			o = append(o, '"')
  55  			o = text.NostrEscape(o, en.Message)
  56  			o = append(o, '"')
  57  			return
  58  		},
  59  	)
  60  	return
  61  }
  62  
  63  // Unmarshal a noticeenvelope.T from minified JSON, returning the remainder
  64  // after the end of the envelope. Note that this ensures the Reason string is
  65  // correctly unescaped by NIP-01 escaping rules.
  66  func (en *T) Unmarshal(b []byte) (r []byte, err error) {
  67  	r = b
  68  	if en.Message, r, err = text.UnmarshalQuoted(r); chk.E(err) {
  69  		return
  70  	}
  71  	if r, err = envelopes.SkipToTheEnd(r); chk.E(err) {
  72  		return
  73  	}
  74  	return
  75  }
  76  
  77  // Parse reads a NOTICE envelope in minified JSON into a newly allocated
  78  // noticeenvelope.T.
  79  func Parse(b []byte) (t *T, rem []byte, err error) {
  80  	t = New()
  81  	if rem, err = t.Unmarshal(b); chk.E(err) {
  82  		return
  83  	}
  84  	return
  85  }
  86