mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-05 10:58:23 +00:00
Send feedback to the relays advertised on the Amber repo announcement
The feedback issue was published to a hardcoded nos.lol with a synthetic repository-event hint. sendFeedBack now resolves the developer's NIP-65 relay list first, fetches the NIP-34 repository announcement (kind 30617, d=Amber) from it, and publishes the issue to the relays in its relays tag, using the real announcement as the issue's hint. When either fetch fails it falls back to the previous nos.lol behavior. On Tor both the fetch window (30s -> 60s) and the publish confirmation timeout (15s -> 60s) are widened, since Tor round trips routinely exceed the old limits.
This commit is contained in:
@@ -60,16 +60,20 @@ import com.greenart7c3.nostrsigner.service.ZapstoreUpdater
|
||||
import com.greenart7c3.nostrsigner.service.crashreports.CrashReportCache
|
||||
import com.greenart7c3.nostrsigner.service.crashreports.UnexpectedCrashSaver
|
||||
import com.greenart7c3.nostrsigner.ui.ToastManager
|
||||
import com.vitorpamplona.quartz.nip01Core.crypto.verify
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.fetchFirst
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.publishAndConfirm
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.auth.RelayAuthenticator
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats
|
||||
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.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import java.lang.ref.WeakReference
|
||||
import java.net.InetSocketAddress
|
||||
@@ -782,18 +786,18 @@ class Amber :
|
||||
type: FeedbackType,
|
||||
account: Account,
|
||||
): Boolean {
|
||||
val relays = setOfNotNull(
|
||||
RelayUrlNormalizer.normalizeOrNull("wss://nos.lol/"),
|
||||
)
|
||||
val usingTor = settings.torMode != TorMode.DISABLED
|
||||
// Tor round trips are slow; give the relays time to answer OK before
|
||||
// declaring the publish failed.
|
||||
val publishTimeoutSeconds =
|
||||
if (usingTor) FEEDBACK_TOR_PUBLISH_TIMEOUT_SECONDS else FEEDBACK_PUBLISH_TIMEOUT_SECONDS
|
||||
|
||||
val repositoryEvent = GitRepositoryEvent(
|
||||
"",
|
||||
DEVELOPER_HEX_KEY,
|
||||
TimeUtils.now(),
|
||||
tags = arrayOf(arrayOf("d", "Amber")),
|
||||
"",
|
||||
"",
|
||||
)
|
||||
val repositoryEvent = fetchAmberRepositoryEvent(usingTor) ?: fallbackRepositoryEvent()
|
||||
val relays = repositoryEvent.relays()
|
||||
.mapNotNull { RelayUrlNormalizer.normalizeOrNull(it) }
|
||||
.toSet()
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: setOfNotNull(RelayUrlNormalizer.normalizeOrNull(FEEDBACK_FALLBACK_RELAY))
|
||||
|
||||
val template = GitIssueEvent.build(
|
||||
subject,
|
||||
@@ -810,9 +814,88 @@ class Amber :
|
||||
// This will automatically connect to these relays even if they are not in the list
|
||||
// once the events have been saved, it will disconnect from them unless there are other
|
||||
// filters with them
|
||||
return client.publishAndConfirm(event, relays)
|
||||
return client.publishAndConfirm(event, relays, publishTimeoutSeconds)
|
||||
}
|
||||
|
||||
/**
|
||||
* NIP-34: a repository announcement's `relays` tag lists the relays its
|
||||
* issues live on. The announcement itself is published on the author's own
|
||||
* relays, so resolve those from their NIP-65 relay list first, then ask
|
||||
* for the announcement. Returns null when either step finds nothing.
|
||||
*/
|
||||
private suspend fun fetchAmberRepositoryEvent(usingTor: Boolean): GitRepositoryEvent? {
|
||||
val fetchTimeoutMs = if (usingTor) FEEDBACK_TOR_FETCH_TIMEOUT_MS else FEEDBACK_FETCH_TIMEOUT_MS
|
||||
|
||||
val authorRelays = fetchAuthorRelays(fetchTimeoutMs)
|
||||
val discoveryRelays = (authorRelays + settings.defaultRelays)
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: setOfNotNull(RelayUrlNormalizer.normalizeOrNull(FEEDBACK_FALLBACK_RELAY))
|
||||
|
||||
val event = client.fetchFirst(
|
||||
filters = discoveryRelays.associateWith {
|
||||
listOf(
|
||||
Filter(
|
||||
kinds = listOf(GitRepositoryEvent.KIND),
|
||||
authors = listOf(DEVELOPER_HEX_KEY),
|
||||
tags = mapOf("d" to listOf(AMBER_REPO_IDENTIFIER)),
|
||||
limit = 1,
|
||||
),
|
||||
)
|
||||
},
|
||||
idleTimeoutMs = fetchTimeoutMs,
|
||||
) ?: return null
|
||||
if (!event.verify()) return null
|
||||
|
||||
return GitRepositoryEvent(
|
||||
event.id,
|
||||
event.pubKey,
|
||||
event.createdAt,
|
||||
event.tags,
|
||||
event.content,
|
||||
event.sig,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun fetchAuthorRelays(fetchTimeoutMs: Long): Set<NormalizedRelayUrl> {
|
||||
val discoveryRelays = (settings.defaultProfileRelays + settings.defaultRelays)
|
||||
.toSet()
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: setOfNotNull(RelayUrlNormalizer.normalizeOrNull(FEEDBACK_FALLBACK_RELAY))
|
||||
|
||||
val event = client.fetchFirst(
|
||||
filters = discoveryRelays.associateWith {
|
||||
listOf(
|
||||
Filter(
|
||||
kinds = listOf(AdvertisedRelayListEvent.KIND),
|
||||
authors = listOf(DEVELOPER_HEX_KEY),
|
||||
limit = 1,
|
||||
),
|
||||
)
|
||||
},
|
||||
idleTimeoutMs = fetchTimeoutMs,
|
||||
) ?: return emptySet()
|
||||
if (!event.verify()) return emptySet()
|
||||
|
||||
return AdvertisedRelayListEvent(
|
||||
event.id,
|
||||
event.pubKey,
|
||||
event.createdAt,
|
||||
event.tags,
|
||||
event.content,
|
||||
event.sig,
|
||||
).relaysNorm().toSet()
|
||||
}
|
||||
|
||||
/** Stand-in used for the issue's `a` tag hint when no announcement was found. */
|
||||
private fun fallbackRepositoryEvent(): GitRepositoryEvent = GitRepositoryEvent(
|
||||
"",
|
||||
DEVELOPER_HEX_KEY,
|
||||
TimeUtils.now(),
|
||||
tags = arrayOf(arrayOf("d", AMBER_REPO_IDENTIFIER)),
|
||||
"",
|
||||
"",
|
||||
)
|
||||
|
||||
companion object {
|
||||
var isAppInForeground = false
|
||||
const val TAG = "Amber"
|
||||
@@ -821,6 +904,12 @@ class Amber :
|
||||
private set
|
||||
|
||||
const val DEVELOPER_HEX_KEY = "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19"
|
||||
private const val AMBER_REPO_IDENTIFIER = "Amber"
|
||||
private const val FEEDBACK_FALLBACK_RELAY = "wss://nos.lol/"
|
||||
private const val FEEDBACK_PUBLISH_TIMEOUT_SECONDS = 15L
|
||||
private const val FEEDBACK_TOR_PUBLISH_TIMEOUT_SECONDS = 60L
|
||||
private const val FEEDBACK_FETCH_TIMEOUT_MS = 30_000L
|
||||
private const val FEEDBACK_TOR_FETCH_TIMEOUT_MS = 60_000L
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user