diff --git a/nip29/group.go b/nip29/group.go index 1a4acdf..5c260e2 100644 --- a/nip29/group.go +++ b/nip29/group.go @@ -42,8 +42,18 @@ type Group struct { Picture string About string Members map[nostr.PubKey][]*Role + + // indicates that only members can read group messages Private bool - Closed bool + + // indicates that only members can write messages to the group + Restricted bool + + // indicates that relays should hide group metadata from non-members + Hidden bool + + // indicates that join requests are ignored unless they include an invite code + Closed bool Roles []*Role InviteCodes []string @@ -56,11 +66,19 @@ type Group struct { func (group Group) String() string { maybePrivate := "" + maybeRestricted := "" + maybeHidden := "" maybeClosed := "" if group.Private { maybePrivate = " private" } + if group.Restricted { + maybeRestricted = " restricted" + } + if group.Hidden { + maybeHidden = " hidden" + } if group.Closed { maybeClosed = " closed" } @@ -83,10 +101,12 @@ func (group Group) String() string { i++ } - return fmt.Sprintf(``, + return fmt.Sprintf(``, group.Address, group.Name, maybePrivate, + maybeRestricted, + maybeHidden, maybeClosed, group.Picture, group.About, @@ -143,13 +163,15 @@ func (group Group) ToMetadataEvent() nostr.Event { // status if group.Private { evt.Tags = append(evt.Tags, nostr.Tag{"private"}) - } else { - evt.Tags = append(evt.Tags, nostr.Tag{"public"}) + } + if group.Restricted { + evt.Tags = append(evt.Tags, nostr.Tag{"restricted"}) + } + if group.Hidden { + evt.Tags = append(evt.Tags, nostr.Tag{"hidden"}) } if group.Closed { evt.Tags = append(evt.Tags, nostr.Tag{"closed"}) - } else { - evt.Tags = append(evt.Tags, nostr.Tag{"open"}) } return evt @@ -238,6 +260,12 @@ func (group *Group) MergeInMetadataEvent(evt *nostr.Event) error { if tag := evt.Tags.Find("private"); tag != nil { group.Private = true } + if tag := evt.Tags.Find("restricted"); tag != nil { + group.Restricted = true + } + if tag := evt.Tags.Find("hidden"); tag != nil { + group.Hidden = true + } if tag := evt.Tags.Find("closed"); tag != nil { group.Closed = true } diff --git a/nip29/moderation_actions.go b/nip29/moderation_actions.go index 7c66069..df8ec67 100644 --- a/nip29/moderation_actions.go +++ b/nip29/moderation_actions.go @@ -92,20 +92,11 @@ var moderationActionFactories = map[nostr.Kind]func(nostr.Event) (Action, error) } y := true - n := false - - if evt.Tags.Has("public") { - edit.PrivateValue = &n - ok = true - } else if evt.Tags.Has("private") { + if evt.Tags.Has("private") { edit.PrivateValue = &y ok = true } - - if evt.Tags.Has("open") { - edit.ClosedValue = &n - ok = true - } else if evt.Tags.Has("closed") { + if evt.Tags.Has("closed") { edit.ClosedValue = &y ok = true } @@ -205,12 +196,14 @@ func (a RemoveUser) Apply(group *Group) { } type EditMetadata struct { - NameValue *string - PictureValue *string - AboutValue *string - PrivateValue *bool - ClosedValue *bool - When nostr.Timestamp + NameValue *string + PictureValue *string + AboutValue *string + PrivateValue *bool + RestrictedValue *bool + HiddenValue *bool + ClosedValue *bool + When nostr.Timestamp } func (_ EditMetadata) Name() string { return "edit-metadata" } @@ -228,6 +221,12 @@ func (a EditMetadata) Apply(group *Group) { if a.PrivateValue != nil { group.Private = *a.PrivateValue } + if a.RestrictedValue != nil { + group.Restricted = *a.RestrictedValue + } + if a.HiddenValue != nil { + group.Hidden = *a.HiddenValue + } if a.ClosedValue != nil { group.Closed = *a.ClosedValue } @@ -254,6 +253,8 @@ func (a DeleteGroup) Apply(group *Group) { group.Members = make(map[nostr.PubKey][]*Role) group.Closed = true group.Private = true + group.Restricted = true + group.Hidden = true group.Name = "[deleted]" group.About = "" group.Picture = "" diff --git a/nip29/nip29_test.go b/nip29/nip29_test.go index 6e4ec4e..5889baa 100644 --- a/nip29/nip29_test.go +++ b/nip29/nip29_test.go @@ -3,6 +3,7 @@ package nip29 import ( "testing" + "fiatjaf.com/nostr" "github.com/stretchr/testify/require" ) @@ -31,37 +32,28 @@ func TestGroupEventBackAndForth(t *testing.T) { require.True(t, hasPrivate, "translation of group1 to metadata event failed: %s", meta1) group2, _ := NewGroup("groups.com'abc") - group2.Members[ALICE] = []*Role{{Name: "nada"}} - group2.Members[BOB] = []*Role{{Name: "nada"}} - group2.Members[CAROL] = nil - group2.Members[DEREK] = nil + alicePub, _ := nostr.PubKeyFromHex(ALICE) + group2.Members[alicePub] = []*Role{{Name: "nada"}} admins2 := group2.ToAdminsEvent() require.Equal(t, "abc", admins2.Tags.GetD(), "translation of group2 to admins event failed") - require.Equal(t, 3, len(admins2.Tags), "translation of group2 to admins event failed") + require.Equal(t, 2, len(admins2.Tags), "translation of group2 to admins event failed") require.True(t, admins2.Tags.FindWithValue("p", ALICE)[2] == "nada", "translation of group2 to admins event failed") - require.True(t, admins2.Tags.FindWithValue("p", BOB)[2] == "nada", "translation of group2 to admins event failed") members2 := group2.ToMembersEvent() - require.Equal(t, "abc", members2.Tags.GetD(), "translation of group2 to members2 event failed") - require.Equal(t, 5, len(members2.Tags), "translation of group2 to members2 event failed") + require.Equal(t, 2, len(members2.Tags), "translation of group2 to members2 event failed") require.NotNil(t, members2.Tags.FindWithValue("p", ALICE), "translation of group2 to members2 event failed") - require.NotNil(t, members2.Tags.FindWithValue("p", BOB), "translation of group2 to members2 event failed") - require.NotNil(t, members2.Tags.FindWithValue("p", CAROL), "translation of group2 to members2 event failed") - require.NotNil(t, members2.Tags.FindWithValue("p", DEREK), "translation of group2 to members2 event failed") - group1.MergeInMembersEvent(members2) - require.Equal(t, 4, len(group1.Members), "merge of members2 into group1 failed") - require.Len(t, group1.Members[ALICE], 0, "merge of members2 into group1 failed") - require.Len(t, group1.Members[DEREK], 0, "merge of members2 into group1 failed") + group1.MergeInMembersEvent(&members2) + require.Equal(t, 1, len(group1.Members), "merge of members2 into group1 failed") + require.Len(t, group1.Members[alicePub], 0, "merge of members2 into group1 failed") - group1.MergeInAdminsEvent(admins2) - require.Equal(t, 4, len(group1.Members), "merge of admins2 into group1 failed") + group1.MergeInAdminsEvent(&admins2) + require.Equal(t, 1, len(group1.Members), "merge of admins2 into group1 failed") - require.Equal(t, "nada", group1.Members[ALICE][0].Name, "merge of admins2 into group1 failed") - require.Len(t, group1.Members[DEREK], 0, "merge of admins2 into group1 failed") + require.Equal(t, "nada", group1.Members[alicePub][0].Name, "merge of admins2 into group1 failed") - group2.MergeInMetadataEvent(meta1) + group2.MergeInMetadataEvent(&meta1) require.Equal(t, "banana", group2.Name, "merge of meta1 into group2 failed") require.Equal(t, "abc", group2.Address.ID, "merge of meta1 into group2 failed") }