Merge pull request #2494 from vitorpamplona/claude/clubhouse-event-listing-Kta46
Add MoQ-transport client and audio rooms support
This commit is contained in:
+26
@@ -31,8 +31,10 @@ import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
||||
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingRoomEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.tags.MeetingSpaceTag
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.presence.tags.HandRaisedTag
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.presence.tags.MutedTag
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
@Immutable
|
||||
@@ -53,6 +55,8 @@ class MeetingRoomPresenceEvent(
|
||||
|
||||
fun handRaised() = tags.firstNotNullOfOrNull(HandRaisedTag::parse)
|
||||
|
||||
fun muted() = tags.firstNotNullOfOrNull(MutedTag::parse)
|
||||
|
||||
companion object Companion {
|
||||
const val KIND = 10312
|
||||
const val ALT = "Room Presence tag"
|
||||
@@ -78,5 +82,27 @@ class MeetingRoomPresenceEvent(
|
||||
}
|
||||
initializer()
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience builder when the parent is a kind 30312 [MeetingSpaceEvent]
|
||||
* (Clubhouse-style audio room). Mirrors the [MeetingRoomEvent] overload so
|
||||
* a participant can publish presence + hand-raise + mute against an audio
|
||||
* room without adapting to the meeting-room (kind 30313) variant.
|
||||
*/
|
||||
fun build(
|
||||
root: MeetingSpaceEvent,
|
||||
handRaised: Boolean? = null,
|
||||
muted: Boolean? = null,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
initializer: TagArrayBuilder<MeetingRoomPresenceEvent>.() -> Unit = {},
|
||||
) = eventTemplate(KIND, "", createdAt) {
|
||||
alt(root.room() ?: ALT)
|
||||
|
||||
roomMeeting(MeetingSpaceTag(root.address(), root.relays().firstOrNull()))
|
||||
|
||||
handRaised?.let { handRaised(it) }
|
||||
muted?.let { muted(it) }
|
||||
initializer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -26,9 +26,12 @@ import com.vitorpamplona.quartz.nip01Core.tags.aTag.toATag
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingRoomEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.tags.MeetingSpaceTag
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.presence.tags.HandRaisedTag
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.presence.tags.MutedTag
|
||||
|
||||
fun TagArrayBuilder<MeetingRoomPresenceEvent>.roomMeeting(rep: MeetingSpaceTag) = addUnique(rep.toTagArray())
|
||||
|
||||
fun TagArrayBuilder<MeetingRoomPresenceEvent>.roomMeeting(rep: EventHintBundle<MeetingRoomEvent>) = addUnique(rep.toATag().toATagArray())
|
||||
|
||||
fun TagArrayBuilder<MeetingRoomPresenceEvent>.handRaised(raised: Boolean) = addUnique(HandRaisedTag.assemble(raised))
|
||||
|
||||
fun TagArrayBuilder<MeetingRoomPresenceEvent>.muted(muted: Boolean) = addUnique(MutedTag.assemble(muted))
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip53LiveActivities.presence.tags
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||
import com.vitorpamplona.quartz.utils.ensure
|
||||
|
||||
/**
|
||||
* Mute flag for kind 10312 presence events used by Clubhouse-style audio
|
||||
* rooms (e.g. nostrnests/nests). Carried alongside the optional `hand` tag so
|
||||
* other clients can render the speaker as muted without waiting for the audio
|
||||
* transport to drop frames.
|
||||
*/
|
||||
class MutedTag {
|
||||
companion object Companion {
|
||||
const val TAG_NAME = "muted"
|
||||
|
||||
fun parse(tag: Array<String>): Boolean? {
|
||||
ensure(tag.has(1)) { return null }
|
||||
ensure(tag[0] == TAG_NAME) { return null }
|
||||
ensure(tag[1].isNotEmpty()) { return null }
|
||||
return tag[1] == "1"
|
||||
}
|
||||
|
||||
fun assemble(muted: Boolean) = arrayOf(TAG_NAME, if (muted) "1" else "0")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user