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