message.go raw
1 package marmot
2
3 import (
4 "fmt"
5 "time"
6
7 "next.orly.dev/pkg/nostr/encoders/event"
8 "next.orly.dev/pkg/nostr/encoders/hex"
9 "next.orly.dev/pkg/nostr/encoders/tag"
10 "next.orly.dev/pkg/nostr/interfaces/signer"
11 )
12
13 // MessageToEvent creates a kind 445 event carrying an MLS-encrypted
14 // application message for a group.
15 func MessageToEvent(groupID, ciphertext []byte, sign signer.I) (*event.E, error) {
16 ev := event.New()
17 ev.CreatedAt = time.Now().Unix()
18 ev.Kind = KindGroupMessage
19 ev.Content = ciphertext
20 ev.Tags = tag.NewS(
21 tag.NewFromAny("g", hex.Enc(groupID)),
22 )
23 if err := ev.Sign(sign); err != nil {
24 return nil, fmt.Errorf("sign group message: %w", err)
25 }
26 return ev, nil
27 }
28
29 // EventToMessage extracts the group ID and MLS ciphertext from a kind 445 event.
30 func EventToMessage(ev *event.E) (groupID, ciphertext []byte, err error) {
31 if ev.Kind != KindGroupMessage {
32 return nil, nil, fmt.Errorf("expected kind %d, got %d", KindGroupMessage, ev.Kind)
33 }
34
35 gTag := ev.Tags.GetFirst([]byte("g"))
36 if gTag == nil {
37 return nil, nil, fmt.Errorf("missing 'g' tag (group ID)")
38 }
39 groupID, err = hex.Dec(string(gTag.Value()))
40 if err != nil {
41 return nil, nil, fmt.Errorf("decode group ID: %w", err)
42 }
43 return groupID, ev.Content, nil
44 }
45