nip29: "hidden" and "private" metadata fields.

https://github.com/nostr-protocol/nips/pull/2106
This commit is contained in:
fiatjaf
2025-11-19 09:19:00 -03:00
parent 5efd8c6485
commit 76abd031d2
3 changed files with 64 additions and 43 deletions

View File

@@ -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(`<Group %s name="%s"%s%s picture="%s" about="%s" members=[%v]>`,
return fmt.Sprintf(`<Group %s name="%s"%s%s%s%s picture="%s" about="%s" members=[%v]>`,
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
}

View File

@@ -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 = ""

View File

@@ -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")
}