package net import ( "strconv" "git.smesh.lol/torly/pkg/nostr" ) func eventMsg(sub string, data []byte) []byte { buf := make([]byte, 0, len(data)+len(sub)+16) buf = append(buf, `["EVENT",`...) buf = nostr.AppendJSONString(buf, sub) buf = append(buf, ',') buf = append(buf, data...) return append(buf, ']') } func okMsg(id string, good bool, msg string) []byte { buf := make([]byte, 0, len(id)+len(msg)+16) buf = append(buf, `["OK","`...) buf = append(buf, id...) buf = append(buf, `",`...) if good { buf = append(buf, "true"...) } else { buf = append(buf, "false"...) } buf = append(buf, ',') buf = nostr.AppendJSONString(buf, msg) return append(buf, ']') } func eoseMsg(sub string) []byte { buf := make([]byte, 0, len(sub)+12) buf = append(buf, `["EOSE",`...) buf = nostr.AppendJSONString(buf, sub) return append(buf, ']') } func noticeMsg(msg string) []byte { buf := make([]byte, 0, len(msg)+12) buf = append(buf, `["NOTICE",`...) buf = nostr.AppendJSONString(buf, msg) return append(buf, ']') } func closedMsg(sub, msg string) []byte { buf := make([]byte, 0, len(sub)+len(msg)+14) buf = append(buf, `["CLOSED",`...) buf = nostr.AppendJSONString(buf, sub) buf = append(buf, ',') buf = nostr.AppendJSONString(buf, msg) return append(buf, ']') } func authMsg(challenge string) []byte { buf := make([]byte, 0, len(challenge)+12) buf = append(buf, `["AUTH",`...) buf = nostr.AppendJSONString(buf, challenge) return append(buf, ']') } func countMsg(sub string, n int, approximate bool) []byte { buf := make([]byte, 0, len(sub)+48) buf = append(buf, `["COUNT",`...) buf = nostr.AppendJSONString(buf, sub) buf = append(buf, `,{"count":`...) buf = strconv.AppendInt(buf, int64(n), 10) buf = append(buf, `,"approximate":`...) if approximate { buf = append(buf, "true"...) } else { buf = append(buf, "false"...) } return append(buf, `}]`...) } func filterMatches(ev *nostr.Event, f *nostr.Filter) bool { if !f.Matches(ev) { return false } if f.Search == "" { return true } want := tokenize(f.Search) if len(want) == 0 { return true } have := make(map[string]struct{}) for w := range tokenize(ev.Content) { have[w] = struct{}{} } for w := range want { if _, ok := have[w]; !ok { return false } } return true } func tokenize(s string) map[string]struct{} { out := make(map[string]struct{}) var buf []byte flush := func() { if len(buf) >= 3 { out[string(buf)] = struct{}{} } buf = buf[:0] } for i := 0; i < len(s); i++ { c := s[i] switch { case c >= 'a' && c <= 'z', c >= '0' && c <= '9': buf = append(buf, c) case c >= 'A' && c <= 'Z': buf = append(buf, c+32) default: flush() } } flush() return out }