nip29: livekit group live participants.

This commit is contained in:
fiatjaf
2026-03-11 16:06:30 -03:00
parent 681bd55e55
commit 3bd059d1f9
4 changed files with 223 additions and 158 deletions
+3
View File
@@ -246,6 +246,8 @@ func (kind Kind) Name() string {
return "SimpleGroupMembers" return "SimpleGroupMembers"
case KindSimpleGroupRoles: case KindSimpleGroupRoles:
return "SimpleGroupRoles" return "SimpleGroupRoles"
case KindSimpleGroupLiveKitParticipants:
return "SimpleGroupLiveKitParticipants"
case KindWikiArticle: case KindWikiArticle:
return "WikiArticle" return "WikiArticle"
case KindRedirects: case KindRedirects:
@@ -396,6 +398,7 @@ const (
KindSimpleGroupAdmins Kind = 39001 KindSimpleGroupAdmins Kind = 39001
KindSimpleGroupMembers Kind = 39002 KindSimpleGroupMembers Kind = 39002
KindSimpleGroupRoles Kind = 39003 KindSimpleGroupRoles Kind = 39003
KindSimpleGroupLiveKitParticipants Kind = 39004
KindWikiArticle Kind = 30818 KindWikiArticle Kind = 30818
KindRedirects Kind = 30819 KindRedirects Kind = 30819
KindFeed Kind = 31890 KindFeed Kind = 31890
+65 -7
View File
@@ -43,6 +43,7 @@ type Group struct {
Picture string Picture string
About string About string
Members map[nostr.PubKey][]*Role Members map[nostr.PubKey][]*Role
LiveKitParticipants map[nostr.PubKey]string
// indicates that only members can read group messages // indicates that only members can read group messages
Private bool Private bool
@@ -57,7 +58,7 @@ type Group struct {
Hidden bool Hidden bool
// indicates that the group supports audio/video live chat // indicates that the group supports audio/video live chat
Livekit bool LiveKit bool
// indicates which event kinds this group supports // indicates which event kinds this group supports
SupportedKinds []nostr.Kind SupportedKinds []nostr.Kind
@@ -69,6 +70,7 @@ type Group struct {
LastAdminsUpdate nostr.Timestamp LastAdminsUpdate nostr.Timestamp
LastMembersUpdate nostr.Timestamp LastMembersUpdate nostr.Timestamp
LastRolesUpdate nostr.Timestamp LastRolesUpdate nostr.Timestamp
LastLiveKitParticipantsUpdate nostr.Timestamp
} }
func (group Group) String() string { func (group Group) String() string {
@@ -90,9 +92,9 @@ func (group Group) String() string {
maybeClosed = " closed" maybeClosed = " closed"
} }
maybeLivekit := "" maybeLiveKit := ""
if group.Livekit { if group.LiveKit {
maybeLivekit = " livekit" maybeLiveKit = " livekit"
} }
members := make([]string, len(group.Members)) members := make([]string, len(group.Members))
@@ -120,7 +122,7 @@ func (group Group) String() string {
maybeRestricted, maybeRestricted,
maybeHidden, maybeHidden,
maybeClosed, maybeClosed,
maybeLivekit, maybeLiveKit,
group.Picture, group.Picture,
group.About, group.About,
strings.Join(members, " "), strings.Join(members, " "),
@@ -138,6 +140,7 @@ func NewGroup(gadstr string) (Group, error) {
Address: gad, Address: gad,
Name: gad.ID, Name: gad.ID,
Members: make(map[nostr.PubKey][]*Role), Members: make(map[nostr.PubKey][]*Role),
LiveKitParticipants: make(map[nostr.PubKey]string),
}, nil }, nil
} }
@@ -149,6 +152,7 @@ func NewGroupFromMetadataEvent(relayURL string, evt *nostr.Event) (Group, error)
}, },
Name: evt.Tags.GetD(), Name: evt.Tags.GetD(),
Members: make(map[nostr.PubKey][]*Role), Members: make(map[nostr.PubKey][]*Role),
LiveKitParticipants: make(map[nostr.PubKey]string),
} }
err := g.MergeInMetadataEvent(evt) err := g.MergeInMetadataEvent(evt)
@@ -186,7 +190,7 @@ func (group Group) ToMetadataEvent() nostr.Event {
if group.Closed { if group.Closed {
evt.Tags = append(evt.Tags, nostr.Tag{"closed"}) evt.Tags = append(evt.Tags, nostr.Tag{"closed"})
} }
if group.Livekit { if group.LiveKit {
evt.Tags = append(evt.Tags, nostr.Tag{"livekit"}) evt.Tags = append(evt.Tags, nostr.Tag{"livekit"})
} }
@@ -261,6 +265,27 @@ func (group Group) ToRolesEvent() nostr.Event {
return evt return evt
} }
func (group Group) ToLiveKitParticipantsEvent() nostr.Event {
evt := nostr.Event{
Kind: nostr.KindSimpleGroupLiveKitParticipants,
CreatedAt: group.LastLiveKitParticipantsUpdate,
Tags: make(nostr.Tags, 1, 1+len(group.LiveKitParticipants)),
}
evt.Tags[0] = nostr.Tag{"d", group.Address.ID}
for member, identity := 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)
}
return evt
}
func (group *Group) MergeInMetadataEvent(evt *nostr.Event) error { func (group *Group) MergeInMetadataEvent(evt *nostr.Event) error {
if evt.Kind != nostr.KindSimpleGroupMetadata { if evt.Kind != nostr.KindSimpleGroupMetadata {
return fmt.Errorf("expected kind %d, got %d", nostr.KindSimpleGroupMetadata, evt.Kind) return fmt.Errorf("expected kind %d, got %d", nostr.KindSimpleGroupMetadata, evt.Kind)
@@ -284,7 +309,7 @@ func (group *Group) MergeInMetadataEvent(evt *nostr.Event) error {
case "hidden": case "hidden":
group.Hidden = true group.Hidden = true
case "livekit": case "livekit":
group.Livekit = true group.LiveKit = true
case "supported_kinds": case "supported_kinds":
kinds := make([]nostr.Kind, 0, len(tag)-1) kinds := make([]nostr.Kind, 0, len(tag)-1)
for _, raw := range tag[1:] { for _, raw := range tag[1:] {
@@ -408,3 +433,36 @@ func (group *Group) MergeInRolesEvent(evt *nostr.Event) error {
return nil return nil
} }
func (group *Group) MergeInLiveKitParticipantsEvent(evt *nostr.Event) error {
if evt.Kind != nostr.KindSimpleGroupLiveKitParticipants {
return fmt.Errorf("expected kind %d, got %d", nostr.KindSimpleGroupLiveKitParticipants, evt.Kind)
}
if evt.CreatedAt < group.LastLiveKitParticipantsUpdate {
return fmt.Errorf("event is older than our last update (%d vs %d)", evt.CreatedAt, group.LastLiveKitParticipantsUpdate)
}
group.LastLiveKitParticipantsUpdate = evt.CreatedAt
group.LiveKitParticipants = make(map[nostr.PubKey]string)
for _, tag := range evt.Tags {
if len(tag) < 2 {
continue
}
if tag[0] != "participant" {
continue
}
member, err := nostr.PubKeyFromHex(tag[1])
if err != nil {
continue
}
identity := ""
if len(tag) >= 3 {
identity = tag[2]
}
group.LiveKitParticipants[member] = identity
}
return nil
}
+9 -6
View File
@@ -124,10 +124,10 @@ var moderationActionFactories = map[nostr.Kind]func(nostr.Event) (Action, error)
edit.PrivateValue = &n edit.PrivateValue = &n
ok = true ok = true
case "livekit": case "livekit":
edit.LivekitValue = &y edit.LiveKitValue = &y
ok = true ok = true
case "no-livekit": case "no-livekit":
edit.LivekitValue = &n edit.LiveKitValue = &n
ok = true ok = true
} }
} }
@@ -244,7 +244,7 @@ type EditMetadata struct {
ClosedValue *bool ClosedValue *bool
HiddenValue *bool HiddenValue *bool
PrivateValue *bool PrivateValue *bool
LivekitValue *bool LiveKitValue *bool
When nostr.Timestamp When nostr.Timestamp
} }
@@ -272,8 +272,8 @@ func (a EditMetadata) Apply(group *Group) {
if a.PrivateValue != nil { if a.PrivateValue != nil {
group.Private = *a.PrivateValue group.Private = *a.PrivateValue
} }
if a.LivekitValue != nil { if a.LiveKitValue != nil {
group.Livekit = *a.LivekitValue group.LiveKit = *a.LiveKitValue
} }
} }
@@ -287,6 +287,7 @@ func (a CreateGroup) Apply(group *Group) {
group.LastMetadataUpdate = a.When group.LastMetadataUpdate = a.When
group.LastAdminsUpdate = a.When group.LastAdminsUpdate = a.When
group.LastMembersUpdate = a.When group.LastMembersUpdate = a.When
group.LastLiveKitParticipantsUpdate = a.When
} }
type DeleteGroup struct { type DeleteGroup struct {
@@ -296,6 +297,7 @@ type DeleteGroup struct {
func (_ DeleteGroup) Name() string { return "delete-group" } func (_ DeleteGroup) Name() string { return "delete-group" }
func (a DeleteGroup) Apply(group *Group) { func (a DeleteGroup) Apply(group *Group) {
group.Members = make(map[nostr.PubKey][]*Role) group.Members = make(map[nostr.PubKey][]*Role)
group.LiveKitParticipants = make(map[nostr.PubKey]string)
group.Closed = true group.Closed = true
group.Private = true group.Private = true
group.Restricted = true group.Restricted = true
@@ -303,10 +305,11 @@ func (a DeleteGroup) Apply(group *Group) {
group.Name = "[deleted]" group.Name = "[deleted]"
group.About = "" group.About = ""
group.Picture = "" group.Picture = ""
group.Livekit = false group.LiveKit = false
group.LastMetadataUpdate = a.When group.LastMetadataUpdate = a.When
group.LastAdminsUpdate = a.When group.LastAdminsUpdate = a.When
group.LastMembersUpdate = a.When group.LastMembersUpdate = a.When
group.LastLiveKitParticipantsUpdate = a.When
} }
type CreateInvite struct { type CreateInvite struct {
+1
View File
@@ -28,6 +28,7 @@ var MetadataEventKinds = KindRange{
nostr.KindSimpleGroupAdmins, nostr.KindSimpleGroupAdmins,
nostr.KindSimpleGroupMembers, nostr.KindSimpleGroupMembers,
nostr.KindSimpleGroupRoles, nostr.KindSimpleGroupRoles,
nostr.KindSimpleGroupLiveKitParticipants,
} }
func (kr KindRange) Includes(kind nostr.Kind) bool { func (kr KindRange) Includes(kind nostr.Kind) bool {