From bb4093d834afb0452f63fc18b496bfd29b463927 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Thu, 12 Mar 2026 11:00:01 -0300 Subject: [PATCH] nip29: supported_kinds and transition edit-metadata to be a PUT, not a PATCH. --- nip29/group.go | 23 ++++------- nip29/moderation_actions.go | 82 ++++++++++++++++++++++++++++++++----- 2 files changed, 80 insertions(+), 25 deletions(-) diff --git a/nip29/group.go b/nip29/group.go index fdfd67e..9cc47c3 100644 --- a/nip29/group.go +++ b/nip29/group.go @@ -43,7 +43,7 @@ type Group struct { Picture string About string Members map[nostr.PubKey][]*Role - LiveKitParticipants map[nostr.PubKey]string + LiveKitParticipants []nostr.PubKey // indicates that only members can read group messages Private bool @@ -140,7 +140,7 @@ func NewGroup(gadstr string) (Group, error) { Address: gad, Name: gad.ID, Members: make(map[nostr.PubKey][]*Role), - LiveKitParticipants: make(map[nostr.PubKey]string), + LiveKitParticipants: make([]nostr.PubKey, 0), }, nil } @@ -152,7 +152,7 @@ func NewGroupFromMetadataEvent(relayURL string, evt *nostr.Event) (Group, error) }, Name: evt.Tags.GetD(), Members: make(map[nostr.PubKey][]*Role), - LiveKitParticipants: make(map[nostr.PubKey]string), + LiveKitParticipants: make([]nostr.PubKey, 0), } err := g.MergeInMetadataEvent(evt) @@ -273,13 +273,8 @@ func (group Group) ToLiveKitParticipantsEvent() nostr.Event { } evt.Tags[0] = nostr.Tag{"d", group.Address.ID} - for member, identity := range group.LiveKitParticipants { + for _, member := range group.LiveKitParticipants { tag := nostr.Tag{"participant", member.Hex()} - if identity != "" { - tag = append(tag, identity) - } else { - tag = append(tag, "") - } evt.Tags = append(evt.Tags, tag) } @@ -443,7 +438,7 @@ func (group *Group) MergeInLiveKitParticipantsEvent(evt *nostr.Event) error { } group.LastLiveKitParticipantsUpdate = evt.CreatedAt - group.LiveKitParticipants = make(map[nostr.PubKey]string) + group.LiveKitParticipants = make([]nostr.PubKey, 0, len(evt.Tags)) for _, tag := range evt.Tags { if len(tag) < 2 { continue @@ -456,12 +451,10 @@ func (group *Group) MergeInLiveKitParticipantsEvent(evt *nostr.Event) error { if err != nil { continue } - - identity := "" - if len(tag) >= 3 { - identity = tag[2] + if slices.Contains(group.LiveKitParticipants, member) { + continue } - group.LiveKitParticipants[member] = identity + group.LiveKitParticipants = append(group.LiveKitParticipants, member) } return nil diff --git a/nip29/moderation_actions.go b/nip29/moderation_actions.go index 61c771f..014fbdf 100644 --- a/nip29/moderation_actions.go +++ b/nip29/moderation_actions.go @@ -3,6 +3,7 @@ package nip29 import ( "fmt" "slices" + "strconv" "fiatjaf.com/nostr" ) @@ -81,54 +82,96 @@ var moderationActionFactories = map[nostr.Kind]func(nostr.Event) (Action, error) y := true n := false + hasName := false + + // DEPRECATED: remove all the fields not tagged with Replace = true eventually + // edit-metadata to become a PUT rather than a PATCH + for _, tag := range evt.Tags { if len(tag) >= 1 { switch tag[0] { case "name": if len(tag) >= 2 { edit.NameValue = &tag[1] + if ok { + edit.Replace = true + } ok = true + hasName = true } case "picture": if len(tag) >= 2 { edit.PictureValue = &tag[1] + if hasName { + edit.Replace = true + } ok = true } case "about": if len(tag) >= 2 { edit.AboutValue = &tag[1] + if hasName { + edit.Replace = true + } ok = true } + case "supported_kinds": + kinds := make([]nostr.Kind, 0, len(tag)-1) + for _, kstr := range tag[1:] { + if kind, err := strconv.ParseUint(kstr, 10, 16); err != nil { + return nil, fmt.Errorf("invalid kind: %w", err) + } else { + kinds = append(kinds, nostr.Kind(kind)) + } + } + edit.SupportedKindsValue = &kinds + edit.Replace = true case "closed": edit.ClosedValue = &y + if hasName { + edit.Replace = true + } ok = true case "open": edit.ClosedValue = &n ok = true case "restricted": edit.RestrictedValue = &y + if hasName { + edit.Replace = true + } ok = true case "unrestricted": edit.RestrictedValue = &n ok = true case "hidden": edit.HiddenValue = &y + if hasName { + edit.Replace = true + } ok = true case "visible": edit.HiddenValue = &n ok = true case "private": edit.PrivateValue = &y + if hasName { + edit.Replace = true + } ok = true case "public": edit.PrivateValue = &n ok = true case "livekit": edit.LiveKitValue = &y + edit.Replace = true ok = true case "no-livekit": edit.LiveKitValue = &n ok = true + case "no-text": + edit.SupportedKindsValue = nil + ok = true } } } @@ -237,20 +280,36 @@ func (a RemoveUser) Apply(group *Group) { } type EditMetadata struct { - NameValue *string - PictureValue *string - AboutValue *string - RestrictedValue *bool - ClosedValue *bool - HiddenValue *bool - PrivateValue *bool - LiveKitValue *bool - When nostr.Timestamp + NameValue *string + PictureValue *string + AboutValue *string + RestrictedValue *bool + ClosedValue *bool + HiddenValue *bool + PrivateValue *bool + LiveKitValue *bool + SupportedKindsValue *[]nostr.Kind + + Replace bool + When nostr.Timestamp } func (_ EditMetadata) Name() string { return "edit-metadata" } func (a EditMetadata) Apply(group *Group) { group.LastMetadataUpdate = a.When + + if a.Replace { + group.Name = "" + group.Picture = "" + group.About = "" + group.Restricted = false + group.Closed = false + group.Hidden = false + group.Private = false + group.LiveKit = false + group.SupportedKinds = nil + } + if a.NameValue != nil { group.Name = *a.NameValue } @@ -275,6 +334,9 @@ func (a EditMetadata) Apply(group *Group) { if a.LiveKitValue != nil { group.LiveKit = *a.LiveKitValue } + if a.SupportedKindsValue != nil { + group.SupportedKinds = *a.SupportedKindsValue + } } type CreateGroup struct { @@ -297,7 +359,7 @@ type DeleteGroup struct { func (_ DeleteGroup) Name() string { return "delete-group" } func (a DeleteGroup) Apply(group *Group) { group.Members = make(map[nostr.PubKey][]*Role) - group.LiveKitParticipants = make(map[nostr.PubKey]string) + group.LiveKitParticipants = make([]nostr.PubKey, 0) group.Closed = true group.Private = true group.Restricted = true