messages.go raw

   1  package net
   2  
   3  import (
   4  	"strconv"
   5  
   6  	"git.smesh.lol/torly/pkg/nostr"
   7  )
   8  
   9  func eventMsg(sub string, data []byte) []byte {
  10  	buf := make([]byte, 0, len(data)+len(sub)+16)
  11  	buf = append(buf, `["EVENT",`...)
  12  	buf = nostr.AppendJSONString(buf, sub)
  13  	buf = append(buf, ',')
  14  	buf = append(buf, data...)
  15  	return append(buf, ']')
  16  }
  17  
  18  func okMsg(id string, good bool, msg string) []byte {
  19  	buf := make([]byte, 0, len(id)+len(msg)+16)
  20  	buf = append(buf, `["OK","`...)
  21  	buf = append(buf, id...)
  22  	buf = append(buf, `",`...)
  23  	if good {
  24  		buf = append(buf, "true"...)
  25  	} else {
  26  		buf = append(buf, "false"...)
  27  	}
  28  	buf = append(buf, ',')
  29  	buf = nostr.AppendJSONString(buf, msg)
  30  	return append(buf, ']')
  31  }
  32  
  33  func eoseMsg(sub string) []byte {
  34  	buf := make([]byte, 0, len(sub)+12)
  35  	buf = append(buf, `["EOSE",`...)
  36  	buf = nostr.AppendJSONString(buf, sub)
  37  	return append(buf, ']')
  38  }
  39  
  40  func noticeMsg(msg string) []byte {
  41  	buf := make([]byte, 0, len(msg)+12)
  42  	buf = append(buf, `["NOTICE",`...)
  43  	buf = nostr.AppendJSONString(buf, msg)
  44  	return append(buf, ']')
  45  }
  46  
  47  func closedMsg(sub, msg string) []byte {
  48  	buf := make([]byte, 0, len(sub)+len(msg)+14)
  49  	buf = append(buf, `["CLOSED",`...)
  50  	buf = nostr.AppendJSONString(buf, sub)
  51  	buf = append(buf, ',')
  52  	buf = nostr.AppendJSONString(buf, msg)
  53  	return append(buf, ']')
  54  }
  55  
  56  func authMsg(challenge string) []byte {
  57  	buf := make([]byte, 0, len(challenge)+12)
  58  	buf = append(buf, `["AUTH",`...)
  59  	buf = nostr.AppendJSONString(buf, challenge)
  60  	return append(buf, ']')
  61  }
  62  
  63  func countMsg(sub string, n int, approximate bool) []byte {
  64  	buf := make([]byte, 0, len(sub)+48)
  65  	buf = append(buf, `["COUNT",`...)
  66  	buf = nostr.AppendJSONString(buf, sub)
  67  	buf = append(buf, `,{"count":`...)
  68  	buf = strconv.AppendInt(buf, int64(n), 10)
  69  	buf = append(buf, `,"approximate":`...)
  70  	if approximate {
  71  		buf = append(buf, "true"...)
  72  	} else {
  73  		buf = append(buf, "false"...)
  74  	}
  75  	return append(buf, `}]`...)
  76  }
  77  
  78  func filterMatches(ev *nostr.Event, f *nostr.Filter) bool {
  79  	if !f.Matches(ev) {
  80  		return false
  81  	}
  82  	if f.Search == "" {
  83  		return true
  84  	}
  85  	want := tokenize(f.Search)
  86  	if len(want) == 0 {
  87  		return true
  88  	}
  89  	have := make(map[string]struct{})
  90  	for w := range tokenize(ev.Content) {
  91  		have[w] = struct{}{}
  92  	}
  93  	for w := range want {
  94  		if _, ok := have[w]; !ok {
  95  			return false
  96  		}
  97  	}
  98  	return true
  99  }
 100  
 101  func tokenize(s string) map[string]struct{} {
 102  	out := make(map[string]struct{})
 103  	var buf []byte
 104  	flush := func() {
 105  		if len(buf) >= 3 {
 106  			out[string(buf)] = struct{}{}
 107  		}
 108  		buf = buf[:0]
 109  	}
 110  	for i := 0; i < len(s); i++ {
 111  		c := s[i]
 112  		switch {
 113  		case c >= 'a' && c <= 'z', c >= '0' && c <= '9':
 114  			buf = append(buf, c)
 115  		case c >= 'A' && c <= 'Z':
 116  			buf = append(buf, c+32)
 117  		default:
 118  			flush()
 119  		}
 120  	}
 121  	flush()
 122  	return out
 123  }
 124