clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

main
tinyrelay / internal / daemon / membership_protocol.go
membership_protocol.go 2.3K
1package daemon23import (4 "context"5 "errors"6 "time"78 "github.com/FelineStateMachine/tinyrelay/internal/event"9 "github.com/FelineStateMachine/tinyrelay/internal/relay"10)1112// nip43Invite returns the relay-signed, ephemeral invite response for a13// kind-28935 request. The response is deliberately generated outside storage14// and is only available to an authenticated member allowed by invite policy.15func (t *Tenant) nip43Invite(ctx context.Context, f event.Filter, s relay.Session) (event.Event, bool, error) {16 if !containsKind(f.Kinds, event.KIND_NIP43_INVITE) {17 return event.Event{}, false, nil18 }19 if f.Limit != nil && *f.Limit <= 0 {20 return event.Event{}, false, nil21 }22 now := time.Now().Unix()23 if !nip43FilterCouldMatch(f, t.records.PublicKey(), now) {24 return event.Event{}, false, nil25 }26 if len(s.PubKeys) == 0 {27 return event.Event{}, false, errors.New("auth-required: NIP-43 invite requests require AUTH")28 }29 invite, err := t.community.IssueNIP43Invite(ctx, s.PubKeys[0])30 if err != nil {31 return event.Event{}, false, err32 }33 response, err := t.records.GenerateEphemeral(ctx, event.KIND_NIP43_INVITE, [][]string{{"-"}, {"claim", invite.Code}}, "", now)34 if err != nil {35 return event.Event{}, false, err36 }37 return response, true, nil38}3940func nip43FilterCouldMatch(f event.Filter, relayPubKey string, now int64) bool {41 if f.IDs != nil || f.Search != "" {42 return false43 }44 if f.Authors != nil && !membershipContainsString(f.Authors, relayPubKey) {45 return false46 }47 if f.Since != nil && now < *f.Since || f.Until != nil && now > *f.Until {48 return false49 }50 for name, values := range f.Tags {51 if name != "claim" || len(values) == 0 {52 return false53 }54 }55 return true56}5758func withoutNIP43Invite(f event.Filter) (event.Filter, bool) {59 if len(f.Kinds) == 0 {60 return f, true61 }62 kinds := make([]int, 0, len(f.Kinds))63 for _, kind := range f.Kinds {64 if kind != event.KIND_NIP43_INVITE {65 kinds = append(kinds, kind)66 }67 }68 if len(kinds) == 0 {69 return event.Filter{}, false70 }71 f.Kinds = kinds72 return f, true73}7475func containsKind(kinds []int, wanted int) bool {76 for _, kind := range kinds {77 if kind == wanted {78 return true79 }80 }81 return false82}8384func membershipContainsString(values []string, wanted string) bool {85 for _, value := range values {86 if value == wanted {87 return true88 }89 }90 return false91}