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