refactor: simplify NostrClient API for beginner-friendliness
Comprehensive rename of the NostrClient relay infrastructure to use intuitive, self-documenting names instead of protocol-level jargon. Interface/class renames: - INostrClient → NostrClient (interface) - NostrClient → DefaultNostrClient (implementation) - IRequestListener → SubscriptionListener - IRelayClientListener → RelayConnectionListener - IOpenNostrRequest → SubscriptionHandle - NostrClientStaticReq → StaticSubscription - NostrClientDynamicReq → DynamicSubscription Method renames: - openReqSubscription() → subscribe() - close(subId) → unsubscribe(subId) - send() → publish() - queryCount() → count() - subscribe/unsubscribe(listener) → addConnectionListener/removeConnectionListener - renewFilters() → syncFilters() Callback renames: - onEose → onCaughtUp - isLive → isRealTime - onStartReq → onSubscriptionStarted - onCloseReq → onSubscriptionClosed Extension function renames: - query() → fetchAll() - downloadFirstEvent() → fetchFirst() - req() → subscribe() - reqAsFlow() → subscribeAsFlow() - reqUntilEoseAsFlow() → fetchAsFlow() - sendAndWaitForResponse() → publishAndConfirm() - queryCountSuspend() → count() - queryCountMergedHll() → countMerged() - reqBypassingRelayLimits() → fetchAllPages() - updateFilter() → refresh() on SubscriptionHandle https://claude.ai/code/session_01JPcYCcRx5eZN4GvgGxGwbf
This commit is contained in:
+16
-16
@@ -22,12 +22,12 @@ package com.vitorpamplona.quartz.nip01Core.relay.client
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.PoolCounts
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.PoolEventOutbox
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.PoolRequests
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayPool
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.AuthCmd
|
||||
@@ -76,11 +76,11 @@ import kotlinx.coroutines.launch
|
||||
* are connected to all necessary endpoints. It also listens to relay state changes to update
|
||||
* subscriptions and message retries when connections are re-established.
|
||||
*/
|
||||
class NostrClient(
|
||||
class DefaultNostrClient(
|
||||
private val websocketBuilder: WebsocketBuilder,
|
||||
private val parentScope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
|
||||
) : INostrClient,
|
||||
IRelayClientListener,
|
||||
) : NostrClient,
|
||||
RelayConnectionListener,
|
||||
AutoCloseable {
|
||||
private val relayPool: RelayPool = RelayPool(websocketBuilder, this)
|
||||
|
||||
@@ -91,7 +91,7 @@ class NostrClient(
|
||||
private val activeCounts: PoolCounts = PoolCounts()
|
||||
private val eventOutbox: PoolEventOutbox = PoolEventOutbox()
|
||||
|
||||
private var listeners = setOf<IRelayClientListener>()
|
||||
private var listeners = setOf<RelayConnectionListener>()
|
||||
|
||||
// controls the state of the client in such a way that if it is active
|
||||
// new filters will be sent to the relays and a potential reconnect can
|
||||
@@ -164,10 +164,10 @@ class NostrClient(
|
||||
refreshConnection.tryEmit(Reconnect(onlyIfChanged, ignoreRetryDelays))
|
||||
}
|
||||
|
||||
override fun openReqSubscription(
|
||||
override fun subscribe(
|
||||
subId: String,
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
listener: IRequestListener?,
|
||||
listener: SubscriptionListener?,
|
||||
) {
|
||||
val relaysToUpdate = activeRequests.addOrUpdate(subId, filters, listener)
|
||||
|
||||
@@ -188,7 +188,7 @@ class NostrClient(
|
||||
}
|
||||
}
|
||||
|
||||
override fun queryCount(
|
||||
override fun count(
|
||||
subId: String,
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
) {
|
||||
@@ -208,7 +208,7 @@ class NostrClient(
|
||||
}
|
||||
}
|
||||
|
||||
override fun send(
|
||||
override fun publish(
|
||||
event: Event,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
) {
|
||||
@@ -222,7 +222,7 @@ class NostrClient(
|
||||
}
|
||||
}
|
||||
|
||||
override fun close(subId: String) {
|
||||
override fun unsubscribe(subId: String) {
|
||||
val relaysToUpdateReqs = activeRequests.remove(subId)
|
||||
val relaysToUpdateCounts = activeCounts.remove(subId)
|
||||
|
||||
@@ -232,7 +232,7 @@ class NostrClient(
|
||||
}
|
||||
}
|
||||
|
||||
override fun renewFilters(relay: IRelayClient) {
|
||||
override fun syncFilters(relay: IRelayClient) {
|
||||
if (isActive) {
|
||||
scope.launch {
|
||||
activeRequests.syncState(relay.url, relay::sendOrConnectAndSync)
|
||||
@@ -259,7 +259,7 @@ class NostrClient(
|
||||
pingMillis: Int,
|
||||
compressed: Boolean,
|
||||
) {
|
||||
renewFilters(relay)
|
||||
syncFilters(relay)
|
||||
listeners.forEach { it.onConnected(relay, pingMillis, compressed) }
|
||||
}
|
||||
|
||||
@@ -308,13 +308,13 @@ class NostrClient(
|
||||
listeners.forEach { it.onCannotConnect(relay, errorMessage) }
|
||||
}
|
||||
|
||||
override fun subscribe(listener: IRelayClientListener) {
|
||||
override fun addConnectionListener(listener: RelayConnectionListener) {
|
||||
listeners = listeners.plus(listener)
|
||||
}
|
||||
|
||||
fun isSubscribed(listener: IRelayClientListener): Boolean = listeners.contains(listener)
|
||||
fun hasConnectionListener(listener: RelayConnectionListener): Boolean = listeners.contains(listener)
|
||||
|
||||
override fun unsubscribe(listener: IRelayClientListener) {
|
||||
override fun removeConnectionListener(listener: RelayConnectionListener) {
|
||||
listeners = listeners.minus(listener)
|
||||
}
|
||||
|
||||
+20
-20
@@ -22,8 +22,8 @@ package com.vitorpamplona.quartz.nip01Core.relay.client
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
@@ -31,7 +31,7 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
interface INostrClient : AutoCloseable {
|
||||
interface NostrClient : AutoCloseable {
|
||||
fun connectedRelaysFlow(): StateFlow<Set<NormalizedRelayUrl>>
|
||||
|
||||
fun availableRelaysFlow(): StateFlow<Set<NormalizedRelayUrl>>
|
||||
@@ -52,29 +52,29 @@ interface INostrClient : AutoCloseable {
|
||||
* This is called every time the relay connects
|
||||
* and when auth is successful
|
||||
*/
|
||||
fun renewFilters(relay: IRelayClient)
|
||||
fun syncFilters(relay: IRelayClient)
|
||||
|
||||
fun openReqSubscription(
|
||||
fun subscribe(
|
||||
subId: String = newSubId(),
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
listener: IRequestListener? = null,
|
||||
listener: SubscriptionListener? = null,
|
||||
)
|
||||
|
||||
fun queryCount(
|
||||
fun count(
|
||||
subId: String = newSubId(),
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
)
|
||||
|
||||
fun close(subId: String)
|
||||
fun unsubscribe(subId: String)
|
||||
|
||||
fun send(
|
||||
fun publish(
|
||||
event: Event,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
)
|
||||
|
||||
fun subscribe(listener: IRelayClientListener)
|
||||
fun addConnectionListener(listener: RelayConnectionListener)
|
||||
|
||||
fun unsubscribe(listener: IRelayClientListener)
|
||||
fun removeConnectionListener(listener: RelayConnectionListener)
|
||||
|
||||
fun getReqFiltersOrNull(subId: String): Map<NormalizedRelayUrl, List<Filter>>?
|
||||
|
||||
@@ -87,7 +87,7 @@ interface INostrClient : AutoCloseable {
|
||||
fun activeOutboxCache(url: NormalizedRelayUrl): Set<HexKey>
|
||||
}
|
||||
|
||||
class EmptyNostrClient : INostrClient {
|
||||
class EmptyNostrClient : NostrClient {
|
||||
override fun connectedRelaysFlow() = MutableStateFlow(emptySet<NormalizedRelayUrl>())
|
||||
|
||||
override fun availableRelaysFlow() = MutableStateFlow(emptySet<NormalizedRelayUrl>())
|
||||
@@ -103,29 +103,29 @@ class EmptyNostrClient : INostrClient {
|
||||
|
||||
override fun isActive() = false
|
||||
|
||||
override fun renewFilters(relay: IRelayClient) { }
|
||||
override fun syncFilters(relay: IRelayClient) { }
|
||||
|
||||
override fun openReqSubscription(
|
||||
override fun subscribe(
|
||||
subId: String,
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
listener: IRequestListener?,
|
||||
listener: SubscriptionListener?,
|
||||
) { }
|
||||
|
||||
override fun queryCount(
|
||||
override fun count(
|
||||
subId: String,
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
) { }
|
||||
|
||||
override fun close(subId: String) { }
|
||||
override fun unsubscribe(subId: String) { }
|
||||
|
||||
override fun send(
|
||||
override fun publish(
|
||||
event: Event,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
) { }
|
||||
|
||||
override fun subscribe(listener: IRelayClientListener) {}
|
||||
override fun addConnectionListener(listener: RelayConnectionListener) {}
|
||||
|
||||
override fun unsubscribe(listener: IRelayClientListener) {}
|
||||
override fun removeConnectionListener(listener: RelayConnectionListener) {}
|
||||
|
||||
override fun getReqFiltersOrNull(subId: String): Map<NormalizedRelayUrl, List<Filter>>? = null
|
||||
|
||||
+6
-6
@@ -21,8 +21,8 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EventMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
@@ -32,11 +32,11 @@ import com.vitorpamplona.quartz.utils.Log
|
||||
* Listens to NostrClient's onEvent messages for caching purposes.
|
||||
*/
|
||||
class EventCollector(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
val onEvent: (event: Event, relay: IRelayClient) -> Unit,
|
||||
) {
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -50,12 +50,12 @@ class EventCollector(
|
||||
|
||||
init {
|
||||
Log.d("EventCollector", "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d("EventCollector", "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+16
-16
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.CountMessage
|
||||
@@ -43,7 +43,7 @@ import kotlinx.coroutines.withTimeoutOrNull
|
||||
* @param timeoutMs How long to wait for a response (default 15 s).
|
||||
* @return The [CountResult], or `null` on timeout.
|
||||
*/
|
||||
suspend fun INostrClient.queryCountSuspend(
|
||||
suspend fun NostrClient.count(
|
||||
relay: NormalizedRelayUrl,
|
||||
filter: Filter,
|
||||
timeoutMs: Long = 15_000,
|
||||
@@ -52,7 +52,7 @@ suspend fun INostrClient.queryCountSuspend(
|
||||
val resultChannel = Channel<CountResult>(UNLIMITED)
|
||||
|
||||
val listener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -64,18 +64,18 @@ suspend fun INostrClient.queryCountSuspend(
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(listener)
|
||||
addConnectionListener(listener)
|
||||
|
||||
val result =
|
||||
try {
|
||||
queryCount(subId = subId, filters = mapOf(relay to listOf(filter)))
|
||||
count(subId = subId, filters = mapOf(relay to listOf(filter)))
|
||||
|
||||
withTimeoutOrNull(timeoutMs) {
|
||||
resultChannel.receive()
|
||||
}
|
||||
} finally {
|
||||
close(subId)
|
||||
unsubscribe(listener)
|
||||
unsubscribe(subId)
|
||||
removeConnectionListener(listener)
|
||||
}
|
||||
|
||||
resultChannel.close()
|
||||
@@ -92,7 +92,7 @@ suspend fun INostrClient.queryCountSuspend(
|
||||
* @param timeoutMs How long to wait for all responses (default 15 s).
|
||||
* @return Map of relay -> [CountResult] for every relay that responded in time.
|
||||
*/
|
||||
suspend fun INostrClient.queryCountSuspend(
|
||||
suspend fun NostrClient.count(
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
timeoutMs: Long = 15_000,
|
||||
): Map<NormalizedRelayUrl, CountResult> {
|
||||
@@ -102,7 +102,7 @@ suspend fun INostrClient.queryCountSuspend(
|
||||
val resultChannel = Channel<Pair<NormalizedRelayUrl, CountResult>>(UNLIMITED)
|
||||
|
||||
val listener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -115,12 +115,12 @@ suspend fun INostrClient.queryCountSuspend(
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(listener)
|
||||
addConnectionListener(listener)
|
||||
|
||||
filters.forEach { (relay, filterList) ->
|
||||
val subId = newSubId()
|
||||
subIdToRelay[subId] = relay
|
||||
queryCount(subId = subId, filters = mapOf(relay to filterList))
|
||||
count(subId = subId, filters = mapOf(relay to filterList))
|
||||
}
|
||||
|
||||
val results = mutableMapOf<NormalizedRelayUrl, CountResult>()
|
||||
@@ -132,8 +132,8 @@ suspend fun INostrClient.queryCountSuspend(
|
||||
}
|
||||
}
|
||||
|
||||
subIdToRelay.keys.forEach { close(it) }
|
||||
unsubscribe(listener)
|
||||
subIdToRelay.keys.forEach { unsubscribe(it) }
|
||||
removeConnectionListener(listener)
|
||||
resultChannel.close()
|
||||
|
||||
return results
|
||||
@@ -155,7 +155,7 @@ suspend fun INostrClient.queryCountSuspend(
|
||||
* @param timeoutMs How long to wait for all responses (default 15 s).
|
||||
* @return A merged [CountResult], or `null` if no relay responded.
|
||||
*/
|
||||
suspend fun INostrClient.queryCountMergedHll(
|
||||
suspend fun NostrClient.countMerged(
|
||||
relays: List<NormalizedRelayUrl>,
|
||||
filter: Filter,
|
||||
timeoutMs: Long = 15_000,
|
||||
@@ -163,7 +163,7 @@ suspend fun INostrClient.queryCountMergedHll(
|
||||
if (relays.isEmpty()) return null
|
||||
|
||||
val results =
|
||||
queryCountSuspend(
|
||||
count(
|
||||
filters = relays.associateWith { listOf(filter) },
|
||||
timeoutMs = timeoutMs,
|
||||
)
|
||||
|
||||
+20
-20
@@ -22,8 +22,8 @@ package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -31,45 +31,45 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
|
||||
suspend fun INostrClient.query(
|
||||
suspend fun NostrClient.fetchAll(
|
||||
relay: String,
|
||||
filter: Filter,
|
||||
timeoutMs: Long = 30_000L,
|
||||
) = query(newSubId(), mapOf(RelayUrlNormalizer.normalize(relay) to listOf(filter)), timeoutMs)
|
||||
) = fetchAll(newSubId(), mapOf(RelayUrlNormalizer.normalize(relay) to listOf(filter)), timeoutMs)
|
||||
|
||||
suspend fun INostrClient.query(
|
||||
suspend fun NostrClient.fetchAll(
|
||||
relay: String,
|
||||
filters: List<Filter>,
|
||||
timeoutMs: Long = 30_000L,
|
||||
) = query(newSubId(), mapOf(RelayUrlNormalizer.normalize(relay) to filters), timeoutMs)
|
||||
) = fetchAll(newSubId(), mapOf(RelayUrlNormalizer.normalize(relay) to filters), timeoutMs)
|
||||
|
||||
suspend fun INostrClient.query(
|
||||
suspend fun NostrClient.fetchAll(
|
||||
subscriptionId: String = newSubId(),
|
||||
relay: String,
|
||||
filters: List<Filter>,
|
||||
timeoutMs: Long = 30_000L,
|
||||
) = query(subscriptionId, mapOf(RelayUrlNormalizer.normalize(relay) to filters), timeoutMs)
|
||||
) = fetchAll(subscriptionId, mapOf(RelayUrlNormalizer.normalize(relay) to filters), timeoutMs)
|
||||
|
||||
suspend fun INostrClient.query(
|
||||
suspend fun NostrClient.fetchAll(
|
||||
relay: NormalizedRelayUrl,
|
||||
filter: Filter,
|
||||
timeoutMs: Long = 30_000L,
|
||||
) = query(newSubId(), mapOf(relay to listOf(filter)), timeoutMs)
|
||||
) = fetchAll(newSubId(), mapOf(relay to listOf(filter)), timeoutMs)
|
||||
|
||||
suspend fun INostrClient.query(
|
||||
suspend fun NostrClient.fetchAll(
|
||||
relay: NormalizedRelayUrl,
|
||||
filters: List<Filter>,
|
||||
timeoutMs: Long = 30_000L,
|
||||
) = query(newSubId(), mapOf(relay to filters), timeoutMs)
|
||||
) = fetchAll(newSubId(), mapOf(relay to filters), timeoutMs)
|
||||
|
||||
suspend fun INostrClient.query(
|
||||
suspend fun NostrClient.fetchAll(
|
||||
subscriptionId: String = newSubId(),
|
||||
relay: NormalizedRelayUrl,
|
||||
filters: List<Filter>,
|
||||
timeoutMs: Long = 30_000L,
|
||||
) = query(subscriptionId, mapOf(relay to filters), timeoutMs)
|
||||
) = fetchAll(subscriptionId, mapOf(relay to filters), timeoutMs)
|
||||
|
||||
suspend fun INostrClient.query(
|
||||
suspend fun NostrClient.fetchAll(
|
||||
subscriptionId: String = newSubId(),
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
timeoutMs: Long = 30_000L,
|
||||
@@ -82,10 +82,10 @@ suspend fun INostrClient.query(
|
||||
val remaining = filters.keys.toMutableSet()
|
||||
|
||||
val listener =
|
||||
object : IRequestListener {
|
||||
object : SubscriptionListener {
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -110,7 +110,7 @@ suspend fun INostrClient.query(
|
||||
doneChannel.trySend(relay)
|
||||
}
|
||||
|
||||
override fun onEose(
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -119,7 +119,7 @@ suspend fun INostrClient.query(
|
||||
}
|
||||
|
||||
try {
|
||||
openReqSubscription(subscriptionId, filters, listener)
|
||||
subscribe(subscriptionId, filters, listener)
|
||||
|
||||
withTimeoutOrNull(timeoutMs) {
|
||||
while (remaining.isNotEmpty()) {
|
||||
@@ -128,7 +128,7 @@ suspend fun INostrClient.query(
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
close(subscriptionId)
|
||||
unsubscribe(subscriptionId)
|
||||
doneChannel.close()
|
||||
}
|
||||
|
||||
+11
-11
@@ -21,8 +21,8 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -51,7 +51,7 @@ import kotlin.math.min
|
||||
* @param onEvent Called for every event received (in page order, after each EOSE).
|
||||
* @return Total number of events received across all pages.
|
||||
*/
|
||||
suspend fun INostrClient.reqBypassingRelayLimits(
|
||||
suspend fun NostrClient.fetchAllPages(
|
||||
relay: NormalizedRelayUrl,
|
||||
filters: List<Filter>,
|
||||
timeoutMs: Long = 30_000L,
|
||||
@@ -95,10 +95,10 @@ suspend fun INostrClient.reqBypassingRelayLimits(
|
||||
|
||||
try {
|
||||
val listener =
|
||||
object : IRequestListener {
|
||||
object : SubscriptionListener {
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -120,7 +120,7 @@ suspend fun INostrClient.reqBypassingRelayLimits(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEose(
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -144,16 +144,16 @@ suspend fun INostrClient.reqBypassingRelayLimits(
|
||||
}
|
||||
}
|
||||
|
||||
openReqSubscription(subId, mapOf(relay to remainingFilters), listener)
|
||||
subscribe(subId, mapOf(relay to remainingFilters), listener)
|
||||
|
||||
withTimeoutOrNull(timeoutMs) {
|
||||
doneChannel.receive()
|
||||
}
|
||||
|
||||
close(subId)
|
||||
unsubscribe(subId)
|
||||
doneChannel.close()
|
||||
} finally {
|
||||
close(subId)
|
||||
unsubscribe(subId)
|
||||
doneChannel.close()
|
||||
}
|
||||
|
||||
@@ -168,14 +168,14 @@ suspend fun INostrClient.reqBypassingRelayLimits(
|
||||
return totalEvents
|
||||
}
|
||||
|
||||
suspend fun INostrClient.reqBypassingRelayLimits(
|
||||
suspend fun NostrClient.fetchAllPages(
|
||||
relay: String,
|
||||
filters: List<Filter>,
|
||||
timeoutMs: Long = 30_000L,
|
||||
onNewPage: ((Long) -> Unit)? = null,
|
||||
onEvent: (Event) -> Unit,
|
||||
): Int =
|
||||
reqBypassingRelayLimits(
|
||||
fetchAllPages(
|
||||
relay = RelayUrlNormalizer.normalize(relay),
|
||||
filters = filters,
|
||||
timeoutMs = timeoutMs,
|
||||
+20
-20
@@ -21,8 +21,8 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -31,49 +31,49 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
|
||||
suspend fun INostrClient.downloadFirstEvent(
|
||||
suspend fun NostrClient.fetchFirst(
|
||||
relay: String,
|
||||
filter: Filter,
|
||||
) = downloadFirstEvent(newSubId(), mapOf(RelayUrlNormalizer.normalize(relay) to listOf(filter)))
|
||||
) = fetchFirst(newSubId(), mapOf(RelayUrlNormalizer.normalize(relay) to listOf(filter)))
|
||||
|
||||
suspend fun INostrClient.downloadFirstEvent(
|
||||
suspend fun NostrClient.fetchFirst(
|
||||
relay: String,
|
||||
filters: List<Filter>,
|
||||
) = downloadFirstEvent(newSubId(), mapOf(RelayUrlNormalizer.normalize(relay) to filters))
|
||||
) = fetchFirst(newSubId(), mapOf(RelayUrlNormalizer.normalize(relay) to filters))
|
||||
|
||||
suspend fun INostrClient.downloadFirstEvent(
|
||||
suspend fun NostrClient.fetchFirst(
|
||||
subscriptionId: String = newSubId(),
|
||||
relay: String,
|
||||
filters: List<Filter>,
|
||||
) = downloadFirstEvent(subscriptionId, mapOf(RelayUrlNormalizer.normalize(relay) to filters))
|
||||
) = fetchFirst(subscriptionId, mapOf(RelayUrlNormalizer.normalize(relay) to filters))
|
||||
|
||||
suspend fun INostrClient.downloadFirstEvent(
|
||||
suspend fun NostrClient.fetchFirst(
|
||||
relay: NormalizedRelayUrl,
|
||||
filter: Filter,
|
||||
) = downloadFirstEvent(newSubId(), mapOf(relay to listOf(filter)))
|
||||
) = fetchFirst(newSubId(), mapOf(relay to listOf(filter)))
|
||||
|
||||
suspend fun INostrClient.downloadFirstEvent(
|
||||
suspend fun NostrClient.fetchFirst(
|
||||
relay: NormalizedRelayUrl,
|
||||
filters: List<Filter>,
|
||||
) = downloadFirstEvent(newSubId(), mapOf(relay to filters))
|
||||
) = fetchFirst(newSubId(), mapOf(relay to filters))
|
||||
|
||||
suspend fun INostrClient.downloadFirstEvent(
|
||||
suspend fun NostrClient.fetchFirst(
|
||||
subscriptionId: String = newSubId(),
|
||||
relay: NormalizedRelayUrl,
|
||||
filters: List<Filter>,
|
||||
) = downloadFirstEvent(subscriptionId, mapOf(relay to filters))
|
||||
) = fetchFirst(subscriptionId, mapOf(relay to filters))
|
||||
|
||||
suspend fun INostrClient.downloadFirstEvent(
|
||||
suspend fun NostrClient.fetchFirst(
|
||||
subscriptionId: String = newSubId(),
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
): Event? {
|
||||
val resultChannel = Channel<Event?>(UNLIMITED)
|
||||
|
||||
val listener =
|
||||
object : IRequestListener {
|
||||
object : SubscriptionListener {
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -96,7 +96,7 @@ suspend fun INostrClient.downloadFirstEvent(
|
||||
resultChannel.trySend(null)
|
||||
}
|
||||
|
||||
override fun onEose(
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -106,13 +106,13 @@ suspend fun INostrClient.downloadFirstEvent(
|
||||
|
||||
val result =
|
||||
try {
|
||||
openReqSubscription(subscriptionId, filters, listener)
|
||||
subscribe(subscriptionId, filters, listener)
|
||||
|
||||
withTimeoutOrNull(30000) {
|
||||
resultChannel.receive()
|
||||
}
|
||||
} finally {
|
||||
close(subscriptionId)
|
||||
unsubscribe(subscriptionId)
|
||||
}
|
||||
|
||||
resultChannel.close()
|
||||
+14
-14
@@ -21,8 +21,8 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.OkMessage
|
||||
@@ -41,42 +41,42 @@ class Result(
|
||||
)
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
suspend fun INostrClient.sendAndWaitForResponse(
|
||||
suspend fun NostrClient.publishAndConfirm(
|
||||
event: Event,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
timeoutInSeconds: Long = 15,
|
||||
): Boolean = sendAndWaitForResponseDetailed(event, relayList, timeoutInSeconds).any { it.value }
|
||||
): Boolean = publishAndConfirmDetailed(event, relayList, timeoutInSeconds).any { it.value }
|
||||
|
||||
/**
|
||||
* Sends an event to the given relays and waits for OK responses.
|
||||
* Returns per-relay results: relay URL -> accepted (true/false).
|
||||
*/
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
suspend fun INostrClient.sendAndWaitForResponseDetailed(
|
||||
suspend fun NostrClient.publishAndConfirmDetailed(
|
||||
event: Event,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
timeoutInSeconds: Long = 15,
|
||||
): Map<NormalizedRelayUrl, Boolean> {
|
||||
val resultChannel = Channel<Result>(UNLIMITED)
|
||||
|
||||
Log.d("sendAndWaitForResponse", "Waiting for ${relayList.size} responses")
|
||||
Log.d("publishAndConfirm", "Waiting for ${relayList.size} responses")
|
||||
|
||||
val subscription =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onCannotConnect(
|
||||
relay: IRelayClient,
|
||||
errorMessage: String,
|
||||
) {
|
||||
if (relay.url in relayList) {
|
||||
resultChannel.trySend(Result(relay.url, false))
|
||||
Log.d("sendAndWaitForResponse", "Error from relay ${relay.url}: $errorMessage")
|
||||
Log.d("publishAndConfirm", "Error from relay ${relay.url}: $errorMessage")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDisconnected(relay: IRelayClient) {
|
||||
if (relay.url in relayList) {
|
||||
resultChannel.trySend(Result(relay.url, false))
|
||||
Log.d("sendAndWaitForResponse", "Disconnected from relay ${relay.url}")
|
||||
Log.d("publishAndConfirm", "Disconnected from relay ${relay.url}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ suspend fun INostrClient.sendAndWaitForResponseDetailed(
|
||||
is OkMessage -> {
|
||||
if (msg.eventId == event.id) {
|
||||
resultChannel.trySend(Result(relay.url, msg.success))
|
||||
Log.d("sendAndWaitForResponse", "onSendResponse Received response for ${msg.eventId} from relay ${relay.url} message ${msg.message} success ${msg.success}")
|
||||
Log.d("publishAndConfirm", "onSendResponse Received response for ${msg.eventId} from relay ${relay.url} message ${msg.message} success ${msg.success}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ suspend fun INostrClient.sendAndWaitForResponseDetailed(
|
||||
|
||||
val receivedResults =
|
||||
try {
|
||||
subscribe(subscription)
|
||||
addConnectionListener(subscription)
|
||||
|
||||
// subscribe before sending the result.
|
||||
val resultSubscription =
|
||||
@@ -123,20 +123,20 @@ suspend fun INostrClient.sendAndWaitForResponseDetailed(
|
||||
receivedResults
|
||||
}
|
||||
|
||||
send(event, relayList)
|
||||
publish(event, relayList)
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
resultSubscription.await()
|
||||
} finally {
|
||||
unsubscribe(subscription)
|
||||
removeConnectionListener(subscription)
|
||||
}
|
||||
|
||||
// Clean up the channel
|
||||
resultChannel.close()
|
||||
|
||||
Log.d("sendAndWaitForResponse", "Finished with ${receivedResults.size} results")
|
||||
Log.d("publishAndConfirm", "Finished with ${receivedResults.size} results")
|
||||
|
||||
return receivedResults
|
||||
}
|
||||
+6
-6
@@ -21,8 +21,8 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.OkMessage
|
||||
@@ -32,11 +32,11 @@ import com.vitorpamplona.quartz.utils.Log
|
||||
* Listens to NostrClient's onEvent messages for caching purposes.
|
||||
*/
|
||||
class RelayInsertConfirmationCollector(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
val onRelayReceived: (eventId: HexKey, relay: IRelayClient) -> Unit,
|
||||
) {
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -50,12 +50,12 @@ class RelayInsertConfirmationCollector(
|
||||
|
||||
init {
|
||||
Log.d("RelayInsertConfirmationCollector", "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d("RelayInsertConfirmationCollector", "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.AuthMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.ClosedMessage
|
||||
@@ -41,14 +41,14 @@ import com.vitorpamplona.quartz.utils.Log
|
||||
* Listens to NostrClient's onNotify messages from the relay
|
||||
*/
|
||||
class RelayLogger(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
val debugSending: Boolean = false,
|
||||
val debugReceiving: Boolean = false,
|
||||
) {
|
||||
fun logTag(url: NormalizedRelayUrl) = "Relay ${url.displayUrl()}"
|
||||
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -110,12 +110,12 @@ class RelayLogger(
|
||||
|
||||
init {
|
||||
Log.d("RelayLogger", "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d("RelayLogger", "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.NotifyMessage
|
||||
@@ -31,7 +31,7 @@ import com.vitorpamplona.quartz.utils.Log
|
||||
* Listens to NostrClient's onNotify messages from the relay
|
||||
*/
|
||||
class RelayNotifier(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
val notify: (message: String, relay: IRelayClient) -> Unit,
|
||||
) {
|
||||
companion object {
|
||||
@@ -39,7 +39,7 @@ class RelayNotifier(
|
||||
}
|
||||
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -54,12 +54,12 @@ class RelayNotifier(
|
||||
|
||||
init {
|
||||
Log.d(TAG, "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d(TAG, "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.accessories
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
@@ -30,7 +30,7 @@ import com.vitorpamplona.quartz.utils.Log
|
||||
* Listens to NostrClient's onNotify messages from the relay
|
||||
*/
|
||||
class RelayOfflineTracker(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
) {
|
||||
companion object {
|
||||
const val TAG = "RelayOfflineTracker"
|
||||
@@ -39,7 +39,7 @@ class RelayOfflineTracker(
|
||||
var cannotConnectRelays = setOf<NormalizedRelayUrl>()
|
||||
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onConnected(
|
||||
relay: IRelayClient,
|
||||
pingMillis: Int,
|
||||
@@ -58,12 +58,12 @@ class RelayOfflineTracker(
|
||||
|
||||
init {
|
||||
Log.d(TAG, "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d(TAG, "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.auth
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.AuthMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
@@ -46,14 +46,14 @@ object EmptyIAuthStatus : IAuthStatus {
|
||||
}
|
||||
|
||||
class RelayAuthenticator(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
val scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
|
||||
val signWithAllLoggedInUsers: suspend (EventTemplate<RelayAuthEvent>) -> List<RelayAuthEvent>,
|
||||
) : IAuthStatus {
|
||||
private val authStatus = mutableMapOf<NormalizedRelayUrl, RelayAuthStatus>()
|
||||
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -95,7 +95,7 @@ class RelayAuthenticator(
|
||||
) {
|
||||
// if this is the OK of an auth event, renew all subscriptions and resend all outgoing events.
|
||||
if (authStatus[relay.url]?.checkAuthResults(msg.eventId, msg.success) == true) {
|
||||
client.renewFilters(relay)
|
||||
client.syncFilters(relay)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,12 +103,12 @@ class RelayAuthenticator(
|
||||
|
||||
init {
|
||||
Log.d("RelayAuthenticator", "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d("RelayAuthenticator", "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.counts
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.ClosedMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.CountMessage
|
||||
@@ -33,14 +33,14 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
|
||||
class RelayActiveCountStates(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
) {
|
||||
private var queryStates = mutableMapOf<NormalizedRelayUrl, CountQueryState<String>>()
|
||||
|
||||
fun subGetOrCreate(relay: NormalizedRelayUrl): CountQueryState<String> = queryStates[relay] ?: CountQueryState<String>().also { queryStates.put(relay, it) }
|
||||
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onConnecting(relay: IRelayClient) {
|
||||
queryStates.put(relay.url, CountQueryState())
|
||||
}
|
||||
@@ -75,12 +75,12 @@ class RelayActiveCountStates(
|
||||
|
||||
init {
|
||||
Log.d("RelaySubStateMachine", "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d("RelaySubStateMachine", "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -24,9 +24,9 @@ import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.Command
|
||||
|
||||
open class RedirectRelayClientListener(
|
||||
val listener: IRelayClientListener,
|
||||
) : IRelayClientListener {
|
||||
open class RedirectConnectionListener(
|
||||
val listener: RelayConnectionListener,
|
||||
) : RelayConnectionListener {
|
||||
override fun onConnecting(relay: IRelayClient) {
|
||||
listener.onConnecting(relay)
|
||||
}
|
||||
+2
-2
@@ -24,7 +24,7 @@ import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.Command
|
||||
|
||||
interface IRelayClientListener {
|
||||
interface RelayConnectionListener {
|
||||
fun onConnecting(relay: IRelayClient) {}
|
||||
|
||||
/**
|
||||
@@ -72,4 +72,4 @@ interface IRelayClientListener {
|
||||
) {}
|
||||
}
|
||||
|
||||
object EmptyClientListener : IRelayClientListener
|
||||
object EmptyConnectionListener : RelayConnectionListener
|
||||
+9
-9
@@ -20,9 +20,9 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.pool
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.ReqSubStatus
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.RequestSubscriptionState
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.ClosedMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EoseMessage
|
||||
@@ -51,7 +51,7 @@ class PoolRequests {
|
||||
* to what the app whants to do.
|
||||
*/
|
||||
private val desiredSubs = LargeCache<String, Map<NormalizedRelayUrl, List<Filter>>>()
|
||||
private val desiredSubListeners = LargeCache<String, IRequestListener>()
|
||||
private val desiredSubListeners = LargeCache<String, SubscriptionListener>()
|
||||
val desiredRelays = MutableStateFlow(setOf<NormalizedRelayUrl>())
|
||||
|
||||
/**
|
||||
@@ -101,7 +101,7 @@ class PoolRequests {
|
||||
fun addOrUpdate(
|
||||
subId: String,
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
listener: IRequestListener?,
|
||||
listener: SubscriptionListener?,
|
||||
): Set<NormalizedRelayUrl> {
|
||||
// saves old relays
|
||||
val oldRelays = desiredSubs.get(subId)?.keys ?: emptySet()
|
||||
@@ -165,15 +165,15 @@ class PoolRequests {
|
||||
when (cmd) {
|
||||
is ReqCmd -> {
|
||||
subState(cmd.subId).onOpenReq(relay, cmd.filters)
|
||||
desiredSubListeners.get(cmd.subId)?.onStartReq(
|
||||
desiredSubListeners.get(cmd.subId)?.onSubscriptionStarted(
|
||||
relay = relay.url,
|
||||
forFilters = cmd.filters,
|
||||
)
|
||||
}
|
||||
|
||||
is CloseCmd -> {
|
||||
subState(cmd.subId).onCloseReq(relay)
|
||||
desiredSubListeners.get(cmd.subId)?.onCloseReq(
|
||||
subState(cmd.subId).onSubscriptionClosed(relay)
|
||||
desiredSubListeners.get(cmd.subId)?.onSubscriptionClosed(
|
||||
relay = relay.url,
|
||||
)
|
||||
}
|
||||
@@ -193,7 +193,7 @@ class PoolRequests {
|
||||
state?.onNewEvent(relay.url)
|
||||
desiredSubListeners.get(msg.subId)?.onEvent(
|
||||
event = msg.event,
|
||||
isLive = state?.currentState(relay.url) == ReqSubStatus.LIVE,
|
||||
isRealTime = state?.currentState(relay.url) == ReqSubStatus.LIVE,
|
||||
relay = relay.url,
|
||||
forFilters = state?.lastKnownFilterStates(relay.url),
|
||||
)
|
||||
@@ -201,8 +201,8 @@ class PoolRequests {
|
||||
|
||||
is EoseMessage -> {
|
||||
val state = relayState.get(msg.subId)
|
||||
state?.onEose(relay.url)
|
||||
desiredSubListeners.get(msg.subId)?.onEose(
|
||||
state?.onCaughtUp(relay.url)
|
||||
desiredSubListeners.get(msg.subId)?.onCaughtUp(
|
||||
relay = relay.url,
|
||||
forFilters = state?.lastKnownFilterStates(relay.url),
|
||||
)
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.pool
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.EmptyClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.EmptyConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.basic.BasicRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
@@ -56,8 +56,8 @@ import kotlinx.coroutines.flow.update
|
||||
*/
|
||||
class RelayPool(
|
||||
val websocketBuilder: WebsocketBuilder,
|
||||
val listener: IRelayClientListener = EmptyClientListener,
|
||||
) : IRelayClientListener {
|
||||
val listener: RelayConnectionListener = EmptyConnectionListener,
|
||||
) : RelayConnectionListener {
|
||||
private val relays = LargeCache<NormalizedRelayUrl, IRelayClient>()
|
||||
|
||||
private val _connectedRelays = MutableStateFlow<Set<NormalizedRelayUrl>>(emptySet())
|
||||
|
||||
+11
-11
@@ -21,22 +21,22 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.reqs
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
|
||||
class NostrClientDynamicReq(
|
||||
val client: INostrClient,
|
||||
class DynamicSubscription(
|
||||
val client: NostrClient,
|
||||
val filter: () -> Map<NormalizedRelayUrl, List<Filter>>,
|
||||
val onEvent: (event: Event) -> Unit = {},
|
||||
) : IRequestListener,
|
||||
IOpenNostrRequest {
|
||||
) : SubscriptionListener,
|
||||
SubscriptionHandle {
|
||||
val subId = RandomInstance.randomChars(10)
|
||||
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -47,16 +47,16 @@ class NostrClientDynamicReq(
|
||||
* Creates or Updates the filter with relays. This method should be called
|
||||
* everytime the filter changes.
|
||||
*/
|
||||
override fun updateFilter() = client.openReqSubscription(subId, filter(), this)
|
||||
override fun refresh() = client.subscribe(subId, filter(), this)
|
||||
|
||||
override fun close() = client.close(subId)
|
||||
override fun close() = client.unsubscribe(subId)
|
||||
|
||||
init {
|
||||
updateFilter()
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
fun INostrClient.req(
|
||||
fun NostrClient.subscribe(
|
||||
filters: () -> Map<NormalizedRelayUrl, List<Filter>>,
|
||||
onEvent: (event: Event) -> Unit = {},
|
||||
): IOpenNostrRequest = NostrClientDynamicReq(this, filters, onEvent)
|
||||
): SubscriptionHandle = DynamicSubscription(this, filters, onEvent)
|
||||
+13
-13
@@ -22,7 +22,7 @@ package com.vitorpamplona.quartz.nip01Core.relay.client.reqs
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||
@@ -37,22 +37,22 @@ import kotlinx.coroutines.flow.callbackFlow
|
||||
* 3. Closes the flow (completes) when the relay sends EOSE,
|
||||
* cancelling the subscription automatically via [awaitClose].
|
||||
*/
|
||||
fun INostrClient.reqUntilEoseAsFlow(
|
||||
fun NostrClient.fetchAsFlow(
|
||||
relay: String,
|
||||
filters: List<Filter>,
|
||||
) = reqUntilEoseAsFlow(RelayUrlNormalizer.normalize(relay), filters)
|
||||
) = fetchAsFlow(RelayUrlNormalizer.normalize(relay), filters)
|
||||
|
||||
fun INostrClient.reqUntilEoseAsFlow(
|
||||
fun NostrClient.fetchAsFlow(
|
||||
relay: String,
|
||||
filter: Filter,
|
||||
) = reqUntilEoseAsFlow(RelayUrlNormalizer.normalize(relay), listOf(filter))
|
||||
) = fetchAsFlow(RelayUrlNormalizer.normalize(relay), listOf(filter))
|
||||
|
||||
fun INostrClient.reqUntilEoseAsFlow(
|
||||
fun NostrClient.fetchAsFlow(
|
||||
relay: NormalizedRelayUrl,
|
||||
filter: Filter,
|
||||
) = reqUntilEoseAsFlow(relay, listOf(filter))
|
||||
) = fetchAsFlow(relay, listOf(filter))
|
||||
|
||||
fun INostrClient.reqUntilEoseAsFlow(
|
||||
fun NostrClient.fetchAsFlow(
|
||||
relay: NormalizedRelayUrl,
|
||||
filters: List<Filter>,
|
||||
): Flow<List<Event>> =
|
||||
@@ -62,10 +62,10 @@ fun INostrClient.reqUntilEoseAsFlow(
|
||||
var currentEvents = listOf<Event>()
|
||||
|
||||
val listener =
|
||||
object : IRequestListener {
|
||||
object : SubscriptionListener {
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -76,7 +76,7 @@ fun INostrClient.reqUntilEoseAsFlow(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEose(
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -84,9 +84,9 @@ fun INostrClient.reqUntilEoseAsFlow(
|
||||
}
|
||||
}
|
||||
|
||||
openReqSubscription(subId, mapOf(relay to filters), listener)
|
||||
subscribe(subId, mapOf(relay to filters), listener)
|
||||
|
||||
awaitClose {
|
||||
close(subId)
|
||||
unsubscribe(subId)
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -22,7 +22,7 @@ package com.vitorpamplona.quartz.nip01Core.relay.client.reqs
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||
@@ -42,22 +42,22 @@ import kotlinx.coroutines.flow.callbackFlow
|
||||
* - They will be ignored if they are already in the list.
|
||||
* - They will be added to the beginning of the list if they are new.
|
||||
*/
|
||||
fun INostrClient.reqAsFlow(
|
||||
fun NostrClient.subscribeAsFlow(
|
||||
relay: String,
|
||||
filters: List<Filter>,
|
||||
) = reqAsFlow(RelayUrlNormalizer.normalize(relay), filters)
|
||||
) = subscribeAsFlow(RelayUrlNormalizer.normalize(relay), filters)
|
||||
|
||||
fun INostrClient.reqAsFlow(
|
||||
fun NostrClient.subscribeAsFlow(
|
||||
relay: String,
|
||||
filter: Filter,
|
||||
) = reqAsFlow(RelayUrlNormalizer.normalize(relay), listOf(filter))
|
||||
) = subscribeAsFlow(RelayUrlNormalizer.normalize(relay), listOf(filter))
|
||||
|
||||
fun INostrClient.reqAsFlow(
|
||||
fun NostrClient.subscribeAsFlow(
|
||||
relay: NormalizedRelayUrl,
|
||||
filter: Filter,
|
||||
) = reqAsFlow(relay, listOf(filter))
|
||||
) = subscribeAsFlow(relay, listOf(filter))
|
||||
|
||||
fun INostrClient.reqAsFlow(
|
||||
fun NostrClient.subscribeAsFlow(
|
||||
relay: NormalizedRelayUrl,
|
||||
filters: List<Filter>,
|
||||
): Flow<List<Event>> =
|
||||
@@ -68,10 +68,10 @@ fun INostrClient.reqAsFlow(
|
||||
var currentEvents = listOf<Event>()
|
||||
|
||||
val listener =
|
||||
object : IRequestListener {
|
||||
object : SubscriptionListener {
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -90,7 +90,7 @@ fun INostrClient.reqAsFlow(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEose(
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -98,9 +98,9 @@ fun INostrClient.reqAsFlow(
|
||||
}
|
||||
}
|
||||
|
||||
openReqSubscription(subId, mapOf(relay to filters), listener)
|
||||
subscribe(subId, mapOf(relay to filters), listener)
|
||||
|
||||
awaitClose {
|
||||
close(subId)
|
||||
unsubscribe(subId)
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.reqs
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.ClosedMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EoseMessage
|
||||
@@ -34,14 +34,14 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
|
||||
class RelayActiveRequestStates(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
) {
|
||||
private var subStates = mutableMapOf<NormalizedRelayUrl, RequestSubscriptionState<String>>()
|
||||
|
||||
fun subGetOrCreate(relay: NormalizedRelayUrl): RequestSubscriptionState<String> = subStates[relay] ?: RequestSubscriptionState<String>().also { subStates.put(relay, it) }
|
||||
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onConnecting(relay: IRelayClient) {
|
||||
subStates[relay.url] = RequestSubscriptionState()
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class RelayActiveRequestStates(
|
||||
) {
|
||||
when (msg) {
|
||||
is EventMessage -> subGetOrCreate(relay.url).onNewEvent(msg.subId)
|
||||
is EoseMessage -> subGetOrCreate(relay.url).onEose(msg.subId)
|
||||
is EoseMessage -> subGetOrCreate(relay.url).onCaughtUp(msg.subId)
|
||||
is ClosedMessage -> subGetOrCreate(relay.url).onClosed(msg.subId)
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ class RelayActiveRequestStates(
|
||||
) {
|
||||
when (cmd) {
|
||||
is ReqCmd -> subGetOrCreate(relay.url).onOpenReq(cmd.subId, cmd.filters)
|
||||
is CloseCmd -> subGetOrCreate(relay.url).onCloseReq(cmd.subId)
|
||||
is CloseCmd -> subGetOrCreate(relay.url).onSubscriptionClosed(cmd.subId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,12 +77,12 @@ class RelayActiveRequestStates(
|
||||
|
||||
init {
|
||||
Log.d("RelaySubStateMachine", "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d("RelaySubStateMachine", "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ class RequestSubscriptionState<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fun onEose(reference: T) {
|
||||
fun onCaughtUp(reference: T) {
|
||||
subStates[reference] = ReqSubStatus.LIVE
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ class RequestSubscriptionState<T> {
|
||||
lastKnownFilterStates[reference] = filters
|
||||
}
|
||||
|
||||
fun onCloseReq(reference: T) {
|
||||
fun onSubscriptionClosed(reference: T) {
|
||||
subStates[reference] = ReqSubStatus.CLOSED
|
||||
filterStates.remove(reference)
|
||||
}
|
||||
|
||||
+21
-21
@@ -21,23 +21,23 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.reqs
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
|
||||
class NostrClientStaticReq(
|
||||
val client: INostrClient,
|
||||
class StaticSubscription(
|
||||
val client: NostrClient,
|
||||
val filter: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
val onEvent: (event: Event) -> Unit = {},
|
||||
) : IRequestListener,
|
||||
IOpenNostrRequest {
|
||||
) : SubscriptionListener,
|
||||
SubscriptionHandle {
|
||||
val subId = RandomInstance.randomChars(10)
|
||||
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -48,50 +48,50 @@ class NostrClientStaticReq(
|
||||
* Creates or Updates the filter with relays. This method should be called
|
||||
* everytime the filter changes.
|
||||
*/
|
||||
override fun updateFilter() = client.openReqSubscription(subId, filter, this)
|
||||
override fun refresh() = client.subscribe(subId, filter, this)
|
||||
|
||||
override fun close() = client.close(subId)
|
||||
override fun close() = client.unsubscribe(subId)
|
||||
|
||||
init {
|
||||
updateFilter()
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
fun INostrClient.req(
|
||||
fun NostrClient.subscribe(
|
||||
relay: NormalizedRelayUrl,
|
||||
filters: List<Filter>,
|
||||
onEvent: (event: Event) -> Unit = {},
|
||||
): IOpenNostrRequest = NostrClientStaticReq(this, mapOf(relay to filters), onEvent)
|
||||
): SubscriptionHandle = StaticSubscription(this, mapOf(relay to filters), onEvent)
|
||||
|
||||
fun INostrClient.req(
|
||||
fun NostrClient.subscribe(
|
||||
relay: NormalizedRelayUrl,
|
||||
filter: Filter,
|
||||
onEvent: (event: Event) -> Unit = {},
|
||||
): IOpenNostrRequest = NostrClientStaticReq(this, mapOf(relay to listOf(filter)), onEvent)
|
||||
): SubscriptionHandle = StaticSubscription(this, mapOf(relay to listOf(filter)), onEvent)
|
||||
|
||||
fun INostrClient.req(
|
||||
fun NostrClient.subscribe(
|
||||
relays: List<NormalizedRelayUrl>,
|
||||
filters: List<Filter>,
|
||||
onEvent: (event: Event) -> Unit = {},
|
||||
): IOpenNostrRequest = NostrClientStaticReq(this, relays.associateWith { filters }, onEvent)
|
||||
): SubscriptionHandle = StaticSubscription(this, relays.associateWith { filters }, onEvent)
|
||||
|
||||
fun INostrClient.req(
|
||||
fun NostrClient.subscribe(
|
||||
relays: List<NormalizedRelayUrl>,
|
||||
filter: Filter,
|
||||
onEvent: (event: Event) -> Unit = {},
|
||||
): IOpenNostrRequest = NostrClientStaticReq(this, relays.associateWith { listOf(filter) }, onEvent)
|
||||
): SubscriptionHandle = StaticSubscription(this, relays.associateWith { listOf(filter) }, onEvent)
|
||||
|
||||
// -----------------------------------
|
||||
// Helper methods with relay as string
|
||||
// -----------------------------------
|
||||
fun INostrClient.req(
|
||||
fun NostrClient.subscribe(
|
||||
relay: String,
|
||||
filters: List<Filter>,
|
||||
onEvent: (event: Event) -> Unit = {},
|
||||
): IOpenNostrRequest = NostrClientStaticReq(this, mapOf(RelayUrlNormalizer.normalize(relay) to filters), onEvent)
|
||||
): SubscriptionHandle = StaticSubscription(this, mapOf(RelayUrlNormalizer.normalize(relay) to filters), onEvent)
|
||||
|
||||
fun INostrClient.req(
|
||||
fun NostrClient.subscribe(
|
||||
relay: String,
|
||||
filter: Filter,
|
||||
onEvent: (event: Event) -> Unit = {},
|
||||
): IOpenNostrRequest = NostrClientStaticReq(this, mapOf(RelayUrlNormalizer.normalize(relay) to listOf(filter)), onEvent)
|
||||
): SubscriptionHandle = StaticSubscription(this, mapOf(RelayUrlNormalizer.normalize(relay) to listOf(filter)), onEvent)
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.reqs
|
||||
|
||||
interface IOpenNostrRequest {
|
||||
fun updateFilter()
|
||||
interface SubscriptionHandle {
|
||||
fun refresh()
|
||||
|
||||
fun close()
|
||||
}
|
||||
+5
-5
@@ -24,15 +24,15 @@ import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
|
||||
interface IRequestListener {
|
||||
fun onEose(
|
||||
interface SubscriptionListener {
|
||||
fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {}
|
||||
|
||||
fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {}
|
||||
@@ -49,10 +49,10 @@ interface IRequestListener {
|
||||
forFilters: List<Filter>?,
|
||||
) {}
|
||||
|
||||
fun onStartReq(
|
||||
fun onSubscriptionStarted(
|
||||
relay: String,
|
||||
forFilters: List<Filter>,
|
||||
) {}
|
||||
|
||||
fun onCloseReq(relay: String) {}
|
||||
fun onSubscriptionClosed(relay: String) {}
|
||||
}
|
||||
+6
-6
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.reqs.stats
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EventMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
@@ -31,12 +31,12 @@ import com.vitorpamplona.quartz.utils.Log
|
||||
* Listens to NostrClient's onNotify messages from the relay
|
||||
*/
|
||||
class RelayReqStats(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
) {
|
||||
private val stats = ReqStatsRepository()
|
||||
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -56,12 +56,12 @@ class RelayReqStats(
|
||||
|
||||
init {
|
||||
Log.d("RelaySubStats", "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d("RelaySubStats", "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.single.basic
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.OptimizedJsonMapper
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.basic.BasicRelayClient.Companion.DELAY_TO_RECONNECT_IN_SECS
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.Command
|
||||
@@ -55,7 +55,7 @@ import kotlin.coroutines.cancellation.CancellationException
|
||||
open class BasicRelayClient(
|
||||
override val url: NormalizedRelayUrl,
|
||||
val socketBuilder: WebsocketBuilder,
|
||||
val listener: IRelayClientListener,
|
||||
val listener: RelayConnectionListener,
|
||||
) : IRelayClient {
|
||||
companion object {
|
||||
// minimum wait time to reconnect: 1 second
|
||||
|
||||
+7
-7
@@ -22,9 +22,9 @@ package com.vitorpamplona.quartz.nip01Core.relay.client.single.standalone
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.EmptyClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RedirectRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.EmptyConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RedirectConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.basic.BasicRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
@@ -46,7 +46,7 @@ import com.vitorpamplona.quartz.utils.cache.LargeCache
|
||||
class StandaloneRelayClient(
|
||||
url: NormalizedRelayUrl,
|
||||
socketBuilder: WebsocketBuilder,
|
||||
listener: IRelayClientListener = EmptyClientListener,
|
||||
listener: RelayConnectionListener = EmptyConnectionListener,
|
||||
) {
|
||||
private val outbox = LargeCache<HexKey, Event>()
|
||||
private val reqs = LargeCache<String, List<Filter>>()
|
||||
@@ -56,14 +56,14 @@ class StandaloneRelayClient(
|
||||
BasicRelayClient(
|
||||
url,
|
||||
socketBuilder,
|
||||
object : RedirectRelayClientListener(listener) {
|
||||
object : RedirectConnectionListener(listener) {
|
||||
override fun onConnected(
|
||||
relay: IRelayClient,
|
||||
pingMillis: Int,
|
||||
compressed: Boolean,
|
||||
) {
|
||||
super.onConnected(relay, pingMillis, compressed)
|
||||
renewFilters()
|
||||
syncFilters()
|
||||
}
|
||||
|
||||
override fun onIncomingMessage(
|
||||
@@ -83,7 +83,7 @@ class StandaloneRelayClient(
|
||||
},
|
||||
)
|
||||
|
||||
fun renewFilters() {
|
||||
fun syncFilters() {
|
||||
outbox.forEach { id, event ->
|
||||
client.sendOrConnectAndSync(EventCmd(event))
|
||||
}
|
||||
|
||||
+6
-6
@@ -21,8 +21,8 @@
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.stats
|
||||
|
||||
import androidx.collection.LruCache
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.ClosedMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
@@ -35,7 +35,7 @@ import com.vitorpamplona.quartz.utils.Log
|
||||
import com.vitorpamplona.quartz.utils.bytesUsedInMemory
|
||||
|
||||
class RelayStats(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
) {
|
||||
private val innerCache =
|
||||
object : LruCache<NormalizedRelayUrl, RelayStat>(1000) {
|
||||
@@ -47,7 +47,7 @@ class RelayStats(
|
||||
fun get(url: NormalizedRelayUrl): RelayStat = innerCache[url] ?: throw IllegalArgumentException("Should never happen")
|
||||
|
||||
private val clientListener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onConnecting(relay: IRelayClient) {
|
||||
super.onConnecting(relay)
|
||||
with(get(relay.url)) {
|
||||
@@ -116,12 +116,12 @@ class RelayStats(
|
||||
|
||||
init {
|
||||
Log.d("RelayStats", "Init, Subscribe")
|
||||
client.subscribe(clientListener)
|
||||
client.addConnectionListener(clientListener)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// makes sure to run
|
||||
Log.d("RelayStats", "Destroy, Unsubscribe")
|
||||
client.unsubscribe(clientListener)
|
||||
client.removeConnectionListener(clientListener)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,14 +20,14 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.subscriptions
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
|
||||
data class Subscription(
|
||||
val id: String = newSubId(),
|
||||
val listener: IRequestListener,
|
||||
val listener: SubscriptionListener,
|
||||
) {
|
||||
private var currentVersion: Map<NormalizedRelayUrl, List<Filter>>? = null // Inactive when null
|
||||
|
||||
|
||||
+9
-9
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay.client.subscriptions
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.utils.cache.LargeCache
|
||||
@@ -45,7 +45,7 @@ import com.vitorpamplona.quartz.utils.cache.LargeCache
|
||||
* - Dismiss subscriptions with [dismissSubscription].
|
||||
*/
|
||||
class SubscriptionController(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
) {
|
||||
private val subscriptions = LargeCache<String, Subscription>()
|
||||
|
||||
@@ -53,7 +53,7 @@ class SubscriptionController(
|
||||
|
||||
fun requestNewSubscription(
|
||||
subId: String,
|
||||
listener: IRequestListener,
|
||||
listener: SubscriptionListener,
|
||||
): Subscription = Subscription(subId, listener).also { subscriptions.put(it.id, it) }
|
||||
|
||||
fun dismissSubscription(subId: String) = getSub(subId)?.let { dismissSubscription(it) }
|
||||
@@ -61,7 +61,7 @@ class SubscriptionController(
|
||||
fun dismissSubscription(subscription: Subscription) {
|
||||
subscription.reset()
|
||||
subscriptions.remove(subscription.id)
|
||||
client.close(subscription.id)
|
||||
client.unsubscribe(subscription.id)
|
||||
}
|
||||
|
||||
fun updateRelays() {
|
||||
@@ -77,23 +77,23 @@ class SubscriptionController(
|
||||
|
||||
fun updateRelaysIfNeeded(
|
||||
subId: String,
|
||||
listener: IRequestListener,
|
||||
listener: SubscriptionListener,
|
||||
newFilters: Map<NormalizedRelayUrl, List<Filter>>?,
|
||||
oldFilters: Map<NormalizedRelayUrl, List<Filter>>?,
|
||||
) {
|
||||
if (oldFilters != null) {
|
||||
if (newFilters == null) {
|
||||
// was active and is not active anymore, just close.
|
||||
client.close(subId)
|
||||
client.unsubscribe(subId)
|
||||
} else {
|
||||
client.openReqSubscription(subId, newFilters, listener)
|
||||
client.subscribe(subId, newFilters, listener)
|
||||
}
|
||||
} else {
|
||||
if (newFilters == null) {
|
||||
// was not active and is still not active, does nothing
|
||||
} else {
|
||||
// was not active and becomes active, sends the entire filter.
|
||||
client.openReqSubscription(subId, newFilters, listener)
|
||||
client.subscribe(subId, newFilters, listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -54,13 +54,13 @@ class LiveEventStore(
|
||||
suspend fun query(
|
||||
filters: List<Filter>,
|
||||
onEach: (Event) -> Unit,
|
||||
onEose: () -> Unit,
|
||||
onCaughtUp: () -> Unit,
|
||||
) {
|
||||
// 1. Replay stored events matching filters.
|
||||
store.query(filters, onEach)
|
||||
|
||||
// 2. Signal end of stored events.
|
||||
onEose()
|
||||
onCaughtUp()
|
||||
|
||||
// 3. Stream live events until cancelled.
|
||||
newEventStream.collect { newEvent ->
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ class RelaySession(
|
||||
send(EventMessage(cmd.subId, event))
|
||||
}
|
||||
},
|
||||
onEose = { send(EoseMessage(cmd.subId)) },
|
||||
onCaughtUp = { send(EoseMessage(cmd.subId)) },
|
||||
)
|
||||
} catch (_: kotlinx.coroutines.CancellationException) {
|
||||
// Subscription was closed – this is expected.
|
||||
|
||||
+15
-12
@@ -22,8 +22,8 @@ package com.vitorpamplona.quartz.nip46RemoteSigner.signer
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.req
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.StaticSubscription
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||
@@ -52,7 +52,7 @@ class NostrSignerRemote(
|
||||
val signer: NostrSignerInternal,
|
||||
val remotePubkey: HexKey,
|
||||
val relays: Set<NormalizedRelayUrl>,
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
val permissions: String? = null,
|
||||
val secret: String? = null,
|
||||
) : NostrSigner(signer.pubKey) {
|
||||
@@ -67,13 +67,16 @@ class NostrSignerRemote(
|
||||
)
|
||||
|
||||
val subscription =
|
||||
client.req(
|
||||
relays = relays.toList(),
|
||||
filter =
|
||||
Filter(
|
||||
kinds = listOf(NostrConnectEvent.KIND),
|
||||
tags = mapOf("p" to listOf(signer.pubKey)),
|
||||
),
|
||||
StaticSubscription(
|
||||
client,
|
||||
relays.associateWith {
|
||||
listOf(
|
||||
Filter(
|
||||
kinds = listOf(NostrConnectEvent.KIND),
|
||||
tags = mapOf("p" to listOf(signer.pubKey)),
|
||||
),
|
||||
)
|
||||
},
|
||||
) { event ->
|
||||
if (event is NostrConnectEvent) {
|
||||
scope.launch {
|
||||
@@ -83,7 +86,7 @@ class NostrSignerRemote(
|
||||
}
|
||||
|
||||
fun openSubscription() {
|
||||
subscription.updateFilter()
|
||||
subscription.refresh()
|
||||
}
|
||||
|
||||
fun closeSubscription() {
|
||||
@@ -293,7 +296,7 @@ class NostrSignerRemote(
|
||||
fun fromBunkerUri(
|
||||
bunkerUri: String,
|
||||
signer: NostrSignerInternal,
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
permissions: String? = null,
|
||||
): NostrSignerRemote {
|
||||
if (!bunkerUri.startsWith("bunker://")) throw Exception("Invalid bunker uri")
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@
|
||||
package com.vitorpamplona.quartz.nip46RemoteSigner.signer
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.OptimizedJsonMapper
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
||||
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerRequest
|
||||
@@ -34,7 +34,7 @@ import kotlin.coroutines.resume
|
||||
|
||||
class RemoteSignerManager(
|
||||
val timeout: Long = 30000,
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
val signer: NostrSignerInternal,
|
||||
val remoteKey: String,
|
||||
val relayList: Set<NormalizedRelayUrl>,
|
||||
@@ -77,7 +77,7 @@ class RemoteSignerManager(
|
||||
|
||||
awaitingRequests.put(request.id, continuation)
|
||||
|
||||
client.send(event, relayList = relayList)
|
||||
client.publish(event, relayList = relayList)
|
||||
}
|
||||
|
||||
return when (result) {
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@
|
||||
package com.vitorpamplona.quartz.nip77Negentropy
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.Message
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
@@ -58,7 +58,7 @@ interface INegentropyListener {
|
||||
/**
|
||||
* Manages NIP-77 negentropy sync sessions across multiple relays.
|
||||
*
|
||||
* This class acts as a [IRelayClientListener] that intercepts NEG-MSG and NEG-ERR
|
||||
* This class acts as a [RelayConnectionListener] that intercepts NEG-MSG and NEG-ERR
|
||||
* messages and drives the reconciliation protocol. It maintains active sessions
|
||||
* per relay and subscription ID.
|
||||
*
|
||||
@@ -69,7 +69,7 @@ interface INegentropyListener {
|
||||
*/
|
||||
class NegentropyManager(
|
||||
private val listener: INegentropyListener,
|
||||
) : IRelayClientListener {
|
||||
) : RelayConnectionListener {
|
||||
private val activeSessions = mutableMapOf<String, Pair<NormalizedRelayUrl, NegentropySession>>()
|
||||
|
||||
fun startSync(
|
||||
|
||||
+14
-14
@@ -22,9 +22,9 @@ package com.vitorpamplona.quartz.nip46RemoteSigner.signer
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -37,10 +37,10 @@ import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* INostrClient that records openReqSubscription calls for verification.
|
||||
* NostrClient that records subscribe calls for verification.
|
||||
* Used instead of mockk since commonTest doesn't have mockk.
|
||||
*/
|
||||
private class TrackingNostrClient : INostrClient {
|
||||
private class TrackingNostrClient : NostrClient {
|
||||
data class SubscriptionRecord(
|
||||
val subId: String,
|
||||
val filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
@@ -64,33 +64,33 @@ private class TrackingNostrClient : INostrClient {
|
||||
|
||||
override fun isActive() = false
|
||||
|
||||
override fun renewFilters(relay: IRelayClient) {}
|
||||
override fun syncFilters(relay: IRelayClient) {}
|
||||
|
||||
override fun openReqSubscription(
|
||||
override fun subscribe(
|
||||
subId: String,
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
listener: IRequestListener?,
|
||||
listener: SubscriptionListener?,
|
||||
) {
|
||||
subscriptions.add(SubscriptionRecord(subId, filters))
|
||||
}
|
||||
|
||||
override fun queryCount(
|
||||
override fun count(
|
||||
subId: String,
|
||||
filters: Map<NormalizedRelayUrl, List<Filter>>,
|
||||
) {}
|
||||
|
||||
override fun close(subId: String) {}
|
||||
override fun unsubscribe(subId: String) {}
|
||||
|
||||
override fun send(
|
||||
override fun publish(
|
||||
event: Event,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
) {
|
||||
sentEvents.add(event to relayList)
|
||||
}
|
||||
|
||||
override fun subscribe(listener: IRelayClientListener) {}
|
||||
override fun addConnectionListener(listener: RelayConnectionListener) {}
|
||||
|
||||
override fun unsubscribe(listener: IRelayClientListener) {}
|
||||
override fun removeConnectionListener(listener: RelayConnectionListener) {}
|
||||
|
||||
override fun getReqFiltersOrNull(subId: String): Map<NormalizedRelayUrl, List<Filter>>? = null
|
||||
|
||||
@@ -120,7 +120,7 @@ class NostrSignerRemoteIsolationTest {
|
||||
val trackingClient = TrackingNostrClient()
|
||||
val ephemeralSigner = NostrSignerInternal(KeyPair())
|
||||
|
||||
// Construction triggers client.req() which calls openReqSubscription
|
||||
// Construction triggers client.subscribe() which calls subscribe
|
||||
NostrSignerRemote(
|
||||
signer = ephemeralSigner,
|
||||
remotePubkey = validHex,
|
||||
|
||||
+4
-5
@@ -19,10 +19,9 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.downloadFirstEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.fetchFirst
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -37,10 +36,10 @@ class NostrClientFirstEventTest : BaseNostrClientTest() {
|
||||
fun testDownloadFirstEvent() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val event =
|
||||
client.downloadFirstEvent(
|
||||
client.fetchFirst(
|
||||
relay = "wss://nos.lol",
|
||||
filter =
|
||||
Filter(
|
||||
|
||||
+8
-9
@@ -19,11 +19,10 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||
@@ -43,24 +42,24 @@ class NostrClientManualSubTest : BaseNostrClientTest() {
|
||||
fun testEoseAfter100Events() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val resultChannel = Channel<String>(UNLIMITED)
|
||||
val events = mutableListOf<String>()
|
||||
val mySubId = "test-sub-id-1"
|
||||
|
||||
val listener =
|
||||
object : IRequestListener {
|
||||
object : SubscriptionListener {
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
resultChannel.trySend(event.id)
|
||||
}
|
||||
|
||||
override fun onEose(
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -79,7 +78,7 @@ class NostrClientManualSubTest : BaseNostrClientTest() {
|
||||
),
|
||||
)
|
||||
|
||||
client.openReqSubscription(mySubId, filters, listener)
|
||||
client.subscribe(mySubId, filters, listener)
|
||||
|
||||
withTimeoutOrNull(10000) {
|
||||
while (events.size < 101) {
|
||||
@@ -90,7 +89,7 @@ class NostrClientManualSubTest : BaseNostrClientTest() {
|
||||
|
||||
resultChannel.close()
|
||||
|
||||
client.close(mySubId)
|
||||
client.unsubscribe(mySubId)
|
||||
client.disconnect()
|
||||
|
||||
appScope.cancel()
|
||||
|
||||
+16
-18
@@ -19,9 +19,8 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.queryCountSuspend
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.count
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.normalizeRelayUrl
|
||||
import junit.framework.TestCase.assertTrue
|
||||
@@ -43,9 +42,9 @@ class NostrClientQueryCountTest : BaseNostrClientTest() {
|
||||
fun testQueryCountSuspend() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val result = client.queryCountSuspend(relay = fiatjaf, filter = metadata)
|
||||
val result = client.count(fiatjaf, metadata)
|
||||
|
||||
assertTrue((result?.count ?: 0) > 1)
|
||||
|
||||
@@ -57,9 +56,9 @@ class NostrClientQueryCountTest : BaseNostrClientTest() {
|
||||
fun testQueryCountSuspendAllEvents() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val result = client.queryCountSuspend(relay = fiatjaf, filter = Filter())
|
||||
val result = client.count(fiatjaf, Filter())
|
||||
|
||||
assertTrue((result?.count ?: 0) > 1)
|
||||
|
||||
@@ -71,20 +70,19 @@ class NostrClientQueryCountTest : BaseNostrClientTest() {
|
||||
fun testQueryCountSuspendMultipleRelays() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val result =
|
||||
client.queryCountSuspend(
|
||||
filters =
|
||||
mapOf(
|
||||
fiatjaf to listOf(metadata, outboxRelays),
|
||||
utxo to listOf(metadata, outboxRelays),
|
||||
),
|
||||
val results =
|
||||
client.count(
|
||||
mapOf(
|
||||
fiatjaf to listOf(metadata, outboxRelays),
|
||||
utxo to listOf(metadata, outboxRelays),
|
||||
),
|
||||
)
|
||||
|
||||
result.forEach { url, result ->
|
||||
println("${url.url}: ${result.count}")
|
||||
assertTrue(result.count > 1)
|
||||
results.forEach { (url, countResult) ->
|
||||
println("${url.url}: ${countResult.count}")
|
||||
assertTrue(countResult.count > 1)
|
||||
}
|
||||
|
||||
client.disconnect()
|
||||
|
||||
+10
-11
@@ -19,10 +19,9 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.RelayConnectionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EoseMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.commands.toClient.EventMessage
|
||||
@@ -49,14 +48,14 @@ class NostrClientRepeatSubTest : BaseNostrClientTest() {
|
||||
fun testRepeatSubEvents() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val resultChannel = Channel<String>(UNLIMITED)
|
||||
val events = mutableListOf<String>()
|
||||
val mySubId = "test-sub-id-2"
|
||||
|
||||
val listener =
|
||||
object : IRelayClientListener {
|
||||
object : RelayConnectionListener {
|
||||
override fun onIncomingMessage(
|
||||
relay: IRelayClient,
|
||||
msgStr: String,
|
||||
@@ -79,7 +78,7 @@ class NostrClientRepeatSubTest : BaseNostrClientTest() {
|
||||
}
|
||||
}
|
||||
|
||||
client.subscribe(listener)
|
||||
client.addConnectionListener(listener)
|
||||
|
||||
val filters =
|
||||
mapOf(
|
||||
@@ -121,10 +120,10 @@ class NostrClientRepeatSubTest : BaseNostrClientTest() {
|
||||
Log.d("Test", "Processing message ${events.size}")
|
||||
// simulates an update in the middle of the sub
|
||||
if (events.size == 1) {
|
||||
client.openReqSubscription(mySubId, filtersShouldIgnore)
|
||||
client.subscribe(mySubId, filtersShouldIgnore)
|
||||
}
|
||||
if (events.size == 5) {
|
||||
client.openReqSubscription(mySubId, filtersShouldSendAfterEOSE)
|
||||
client.subscribe(mySubId, filtersShouldSendAfterEOSE)
|
||||
}
|
||||
events.add(resultChannel.receive())
|
||||
}
|
||||
@@ -132,12 +131,12 @@ class NostrClientRepeatSubTest : BaseNostrClientTest() {
|
||||
}
|
||||
|
||||
launch {
|
||||
client.openReqSubscription(mySubId, filters)
|
||||
client.subscribe(mySubId, filters)
|
||||
}
|
||||
}
|
||||
|
||||
client.close(mySubId)
|
||||
client.unsubscribe(listener)
|
||||
client.unsubscribe(mySubId)
|
||||
client.removeConnectionListener(listener)
|
||||
client.disconnect()
|
||||
|
||||
appScope.cancel()
|
||||
|
||||
+6
-7
@@ -19,11 +19,10 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.reqBypassingRelayLimits
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.fetchAllPages
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -40,13 +39,13 @@ class NostrClientReqBypassingRelayLimitsTest : BaseNostrClientTest() {
|
||||
fun testDownloadFromRelayReturnsMetadataEvents() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val events = mutableListOf<Event>()
|
||||
|
||||
// nos.lol returns only 500 events per req
|
||||
val totalFound =
|
||||
client.reqBypassingRelayLimits(
|
||||
client.fetchAllPages(
|
||||
relay = "wss://nos.lol",
|
||||
filters =
|
||||
listOf(
|
||||
@@ -74,14 +73,14 @@ class NostrClientReqBypassingRelayLimitsTest : BaseNostrClientTest() {
|
||||
fun testDownloadFromRelayReturnsMetadataAndContactListEvents() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val metadataEvents = mutableListOf<Event>()
|
||||
val contactListEvents = mutableListOf<Event>()
|
||||
|
||||
// nos.lol returns only 500 events per req
|
||||
val totalFound =
|
||||
client.reqBypassingRelayLimits(
|
||||
client.fetchAllPages(
|
||||
relay = "wss://nos.lol",
|
||||
filters =
|
||||
listOf(
|
||||
|
||||
+5
-6
@@ -19,10 +19,9 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.sendAndWaitForResponse
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.publishAndConfirm
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.normalizeRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
@@ -39,20 +38,20 @@ class NostrClientSendAndWaitTest : BaseNostrClientTest() {
|
||||
fun testSendAndWaitForResponse() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val randomSigner = NostrSignerInternal(KeyPair())
|
||||
|
||||
val event = randomSigner.sign(TextNoteEvent.build("Hello World"))
|
||||
|
||||
val resultDamus =
|
||||
client.sendAndWaitForResponse(
|
||||
client.publishAndConfirm(
|
||||
event = event,
|
||||
relayList = setOf("wss://nostr.bitcoiner.social".normalizeRelayUrl()),
|
||||
)
|
||||
|
||||
val resultNos =
|
||||
client.sendAndWaitForResponse(
|
||||
client.publishAndConfirm(
|
||||
event = event,
|
||||
relayList = setOf("wss://nos.lol".normalizeRelayUrl()),
|
||||
)
|
||||
|
||||
+6
-7
@@ -19,11 +19,10 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.reqAsFlow
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.subscribeAsFlow
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -50,10 +49,10 @@ class NostrClientSubscriptionAsFlowTest : BaseNostrClientTest() {
|
||||
fun testNostrClientSubscriptionAsFlow() =
|
||||
runTest {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val flow =
|
||||
client.reqAsFlow(
|
||||
client.subscribeAsFlow(
|
||||
relay = "wss://nos.lol",
|
||||
filter =
|
||||
Filter(
|
||||
@@ -89,10 +88,10 @@ class NostrClientSubscriptionAsFlowTest : BaseNostrClientTest() {
|
||||
fun testNostrClientSubscriptionAsFlowDebouncing() =
|
||||
runTest {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val flow =
|
||||
client.reqAsFlow(
|
||||
client.subscribeAsFlow(
|
||||
relay = "wss://nos.lol",
|
||||
filter =
|
||||
Filter(
|
||||
|
||||
+15
-11
@@ -19,12 +19,12 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.req
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.StaticSubscription
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@@ -41,19 +41,23 @@ class NostrClientSubscriptionTest : BaseNostrClientTest() {
|
||||
fun testNostrClientSubscription() =
|
||||
runBlocking {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val resultChannel = Channel<Event>(UNLIMITED)
|
||||
val events = mutableSetOf<Event>()
|
||||
|
||||
val sub =
|
||||
client.req(
|
||||
relay = "wss://nos.lol",
|
||||
filter =
|
||||
Filter(
|
||||
kinds = listOf(MetadataEvent.KIND),
|
||||
limit = 100,
|
||||
),
|
||||
StaticSubscription(
|
||||
client,
|
||||
mapOf(
|
||||
RelayUrlNormalizer.normalize("wss://nos.lol") to
|
||||
listOf(
|
||||
Filter(
|
||||
kinds = listOf(MetadataEvent.KIND),
|
||||
limit = 100,
|
||||
),
|
||||
),
|
||||
),
|
||||
) { event ->
|
||||
assertEquals(MetadataEvent.KIND, event.kind)
|
||||
resultChannel.trySend(event)
|
||||
|
||||
+6
-7
@@ -19,11 +19,10 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.reqUntilEoseAsFlow
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.DefaultNostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.fetchAsFlow
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -50,10 +49,10 @@ class NostrClientSubscriptionUntilEoseAsFlowTest : BaseNostrClientTest() {
|
||||
fun testNostrClientSubscriptionUntilEoseAsFlow() =
|
||||
runTest {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val flow =
|
||||
client.reqUntilEoseAsFlow(
|
||||
client.fetchAsFlow(
|
||||
relay = "wss://nos.lol",
|
||||
filter =
|
||||
Filter(
|
||||
@@ -89,10 +88,10 @@ class NostrClientSubscriptionUntilEoseAsFlowTest : BaseNostrClientTest() {
|
||||
fun testNostrClientSubscriptionUntilEoseAsFlowDebouncing() =
|
||||
runTest {
|
||||
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
val client = NostrClient(socketBuilder, appScope)
|
||||
val client = DefaultNostrClient(socketBuilder, appScope)
|
||||
|
||||
val flow =
|
||||
client.reqUntilEoseAsFlow(
|
||||
client.fetchAsFlow(
|
||||
relay = "wss://nos.lol",
|
||||
filter =
|
||||
Filter(
|
||||
|
||||
Reference in New Issue
Block a user