- Re-normalizes all relays urls before connecting to reduce duplications
- Normalizes all new relays in the edit screens.
This commit is contained in:
@@ -47,6 +47,7 @@ import com.vitorpamplona.quartz.crypto.KeyPair
|
|||||||
import com.vitorpamplona.quartz.encoders.ATag
|
import com.vitorpamplona.quartz.encoders.ATag
|
||||||
import com.vitorpamplona.quartz.encoders.HexKey
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
import com.vitorpamplona.quartz.encoders.Nip47WalletConnect
|
import com.vitorpamplona.quartz.encoders.Nip47WalletConnect
|
||||||
|
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
|
||||||
import com.vitorpamplona.quartz.encoders.hexToByteArray
|
import com.vitorpamplona.quartz.encoders.hexToByteArray
|
||||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||||
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
||||||
@@ -238,10 +239,16 @@ class Account(
|
|||||||
userProfile().flow().relays.stateFlow,
|
userProfile().flow().relays.stateFlow,
|
||||||
) { nip65RelayList, dmRelayList, searchRelayList, privateOutBox, userProfile ->
|
) { nip65RelayList, dmRelayList, searchRelayList, privateOutBox, userProfile ->
|
||||||
val baseRelaySet = activeRelays() ?: convertLocalRelays()
|
val baseRelaySet = activeRelays() ?: convertLocalRelays()
|
||||||
val newDMRelaySet = (dmRelayList.note.event as? ChatMessageRelayListEvent)?.relays()?.toSet() ?: emptySet()
|
val newDMRelaySet = (dmRelayList.note.event as? ChatMessageRelayListEvent)?.relays()?.map { RelayUrlFormatter.normalize(it) }?.toSet() ?: emptySet()
|
||||||
val searchRelaySet = (searchRelayList.note.event as? SearchRelayListEvent)?.relays()?.toSet() ?: Constants.defaultSearchRelaySet
|
val searchRelaySet = (searchRelayList.note.event as? SearchRelayListEvent)?.relays()?.map { RelayUrlFormatter.normalize(it) }?.toSet() ?: Constants.defaultSearchRelaySet
|
||||||
val nip65RelaySet = (nip65RelayList.note.event as? AdvertisedRelayListEvent)?.relays()
|
val nip65RelaySet =
|
||||||
val privateOutboxRelaySet = (privateOutBox.note.event as? PrivateOutboxRelayListEvent)?.relays() ?: emptySet()
|
(nip65RelayList.note.event as? AdvertisedRelayListEvent)?.relays()?.map {
|
||||||
|
AdvertisedRelayListEvent.AdvertisedRelayInfo(
|
||||||
|
RelayUrlFormatter.normalize(it.relayUrl),
|
||||||
|
it.type,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val privateOutboxRelaySet = (privateOutBox.note.event as? PrivateOutboxRelayListEvent)?.relays()?.map { RelayUrlFormatter.normalize(it) }?.toSet() ?: emptySet()
|
||||||
|
|
||||||
// ------
|
// ------
|
||||||
// DMs
|
// DMs
|
||||||
@@ -2596,22 +2603,24 @@ class Account(
|
|||||||
fun activeRelays(): Array<Relay>? {
|
fun activeRelays(): Array<Relay>? {
|
||||||
val usersRelayList =
|
val usersRelayList =
|
||||||
userProfile().latestContactList?.relays()?.map {
|
userProfile().latestContactList?.relays()?.map {
|
||||||
|
val url = RelayUrlFormatter.normalize(it.key)
|
||||||
|
|
||||||
val localFeedTypes =
|
val localFeedTypes =
|
||||||
localRelays.firstOrNull { localRelay -> localRelay.url == it.key }?.feedTypes
|
localRelays.firstOrNull { localRelay -> RelayUrlFormatter.normalize(localRelay.url) == url }?.feedTypes
|
||||||
?: Constants.defaultRelays
|
?: Constants.defaultRelays
|
||||||
.filter { defaultRelay -> defaultRelay.url == it.key }
|
.filter { defaultRelay -> defaultRelay.url == url }
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
?.feedTypes
|
?.feedTypes
|
||||||
?: FeedType.values().toSet()
|
?: FeedType.values().toSet()
|
||||||
|
|
||||||
Relay(it.key, it.value.read, it.value.write, localFeedTypes)
|
Relay(url, it.value.read, it.value.write, localFeedTypes)
|
||||||
} ?: return null
|
} ?: return null
|
||||||
|
|
||||||
return usersRelayList.toTypedArray()
|
return usersRelayList.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertLocalRelays(): Array<Relay> {
|
fun convertLocalRelays(): Array<Relay> {
|
||||||
return localRelays.map { Relay(it.url, it.read, it.write, it.feedTypes) }.toTypedArray()
|
return localRelays.map { Relay(RelayUrlFormatter.normalize(it.url), it.read, it.write, it.feedTypes) }.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun activeGlobalRelays(): Array<String> {
|
fun activeGlobalRelays(): Array<String> {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package com.vitorpamplona.amethyst.service.relays
|
package com.vitorpamplona.amethyst.service.relays
|
||||||
|
|
||||||
import com.vitorpamplona.amethyst.model.RelaySetupInfo
|
import com.vitorpamplona.amethyst.model.RelaySetupInfo
|
||||||
|
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
val activeTypes = setOf(FeedType.FOLLOWS, FeedType.PRIVATE_DMS)
|
val activeTypes = setOf(FeedType.FOLLOWS, FeedType.PRIVATE_DMS)
|
||||||
@@ -36,21 +37,26 @@ object Constants {
|
|||||||
val defaultRelays =
|
val defaultRelays =
|
||||||
arrayOf(
|
arrayOf(
|
||||||
// Free relays for only DMs, Chats and Follows due to the amount of spam
|
// Free relays for only DMs, Chats and Follows due to the amount of spam
|
||||||
RelaySetupInfo("wss://nostr.bitcoiner.social", read = true, write = true, feedTypes = activeTypesChats),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://nostr.bitcoiner.social"), read = true, write = true, feedTypes = activeTypesChats),
|
||||||
RelaySetupInfo("wss://relay.nostr.bg", read = true, write = true, feedTypes = activeTypesChats),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://relay.nostr.bg"), read = true, write = true, feedTypes = activeTypesChats),
|
||||||
RelaySetupInfo("wss://nostr.oxtr.dev", read = true, write = true, feedTypes = activeTypesChats),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://nostr.oxtr.dev"), read = true, write = true, feedTypes = activeTypesChats),
|
||||||
RelaySetupInfo("wss://nostr.fmt.wiz.biz", read = true, write = false, feedTypes = activeTypesChats),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://nostr.fmt.wiz.biz"), read = true, write = false, feedTypes = activeTypesChats),
|
||||||
RelaySetupInfo("wss://relay.damus.io", read = true, write = true, feedTypes = activeTypes),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://relay.damus.io"), read = true, write = true, feedTypes = activeTypes),
|
||||||
// Global
|
// Global
|
||||||
RelaySetupInfo("wss://nostr.mom", read = true, write = true, feedTypes = activeTypesGlobalChats),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://nostr.mom"), read = true, write = true, feedTypes = activeTypesGlobalChats),
|
||||||
RelaySetupInfo("wss://nos.lol", read = true, write = true, feedTypes = activeTypesGlobalChats),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://nos.lol"), read = true, write = true, feedTypes = activeTypesGlobalChats),
|
||||||
// Paid relays
|
// Paid relays
|
||||||
RelaySetupInfo("wss://nostr.wine", read = true, write = false, feedTypes = activeTypesGlobalChats),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://nostr.wine"), read = true, write = false, feedTypes = activeTypesGlobalChats),
|
||||||
// Supporting NIP-50
|
// Supporting NIP-50
|
||||||
RelaySetupInfo("wss://relay.nostr.band", read = true, write = false, feedTypes = activeTypesSearch),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://relay.nostr.band"), read = true, write = false, feedTypes = activeTypesSearch),
|
||||||
RelaySetupInfo("wss://nostr.wine", read = true, write = false, feedTypes = activeTypesSearch),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://nostr.wine"), read = true, write = false, feedTypes = activeTypesSearch),
|
||||||
RelaySetupInfo("wss://relay.noswhere.com", read = true, write = false, feedTypes = activeTypesSearch),
|
RelaySetupInfo(RelayUrlFormatter.normalize("wss://relay.noswhere.com"), read = true, write = false, feedTypes = activeTypesSearch),
|
||||||
)
|
)
|
||||||
|
|
||||||
val defaultSearchRelaySet = setOf("wss://relay.nostr.band", "wss://nostr.wine", "wss://relay.noswhere.com")
|
val defaultSearchRelaySet =
|
||||||
|
setOf(
|
||||||
|
RelayUrlFormatter.normalize("wss://relay.nostr.band"),
|
||||||
|
RelayUrlFormatter.normalize("wss://nostr.wine"),
|
||||||
|
RelayUrlFormatter.normalize("wss://relay.noswhere.com"),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -25,6 +25,7 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import com.vitorpamplona.amethyst.model.Account
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayStats
|
import com.vitorpamplona.amethyst.service.relays.RelayStats
|
||||||
|
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
@@ -79,7 +80,7 @@ abstract class BasicRelaySetupInfoModel : ViewModel() {
|
|||||||
|
|
||||||
relayList.map { relayUrl ->
|
relayList.map { relayUrl ->
|
||||||
BasicRelaySetupInfo(
|
BasicRelaySetupInfo(
|
||||||
relayUrl,
|
RelayUrlFormatter.normalize(relayUrl),
|
||||||
RelayStats.get(relayUrl),
|
RelayStats.get(relayUrl),
|
||||||
)
|
)
|
||||||
}.distinctBy { it.url }.sortedBy { it.relayStat.receivedBytes }.reversed()
|
}.distinctBy { it.url }.sortedBy { it.relayStat.receivedBytes }.reversed()
|
||||||
|
|||||||
+4
-3
@@ -28,6 +28,7 @@ import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
|||||||
import com.vitorpamplona.amethyst.service.relays.Constants
|
import com.vitorpamplona.amethyst.service.relays.Constants
|
||||||
import com.vitorpamplona.amethyst.service.relays.FeedType
|
import com.vitorpamplona.amethyst.service.relays.FeedType
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayStats
|
import com.vitorpamplona.amethyst.service.relays.RelayStats
|
||||||
|
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@@ -101,7 +102,7 @@ class Kind3RelayListViewModel : ViewModel() {
|
|||||||
?: FeedType.values().toSet().toImmutableSet()
|
?: FeedType.values().toSet().toImmutableSet()
|
||||||
|
|
||||||
Kind3BasicRelaySetupInfo(
|
Kind3BasicRelaySetupInfo(
|
||||||
url = it.key,
|
url = RelayUrlFormatter.normalize(it.key),
|
||||||
read = it.value.read,
|
read = it.value.read,
|
||||||
write = it.value.write,
|
write = it.value.write,
|
||||||
feedTypes = localInfoFeedTypes,
|
feedTypes = localInfoFeedTypes,
|
||||||
@@ -115,7 +116,7 @@ class Kind3RelayListViewModel : ViewModel() {
|
|||||||
account.localRelays
|
account.localRelays
|
||||||
.map {
|
.map {
|
||||||
Kind3BasicRelaySetupInfo(
|
Kind3BasicRelaySetupInfo(
|
||||||
url = it.url,
|
url = RelayUrlFormatter.normalize(it.url),
|
||||||
read = it.read,
|
read = it.read,
|
||||||
write = it.write,
|
write = it.write,
|
||||||
feedTypes = it.feedTypes,
|
feedTypes = it.feedTypes,
|
||||||
@@ -135,7 +136,7 @@ class Kind3RelayListViewModel : ViewModel() {
|
|||||||
_relays.update {
|
_relays.update {
|
||||||
defaultRelays.map {
|
defaultRelays.map {
|
||||||
Kind3BasicRelaySetupInfo(
|
Kind3BasicRelaySetupInfo(
|
||||||
url = it.url,
|
url = RelayUrlFormatter.normalize(it.url),
|
||||||
read = it.read,
|
read = it.read,
|
||||||
write = it.write,
|
write = it.write,
|
||||||
feedTypes = it.feedTypes,
|
feedTypes = it.feedTypes,
|
||||||
|
|||||||
+3
-2
@@ -25,6 +25,7 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import com.vitorpamplona.amethyst.model.Account
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayStats
|
import com.vitorpamplona.amethyst.service.relays.RelayStats
|
||||||
|
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
|
||||||
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@@ -106,7 +107,7 @@ class Nip65RelayListViewModel : ViewModel() {
|
|||||||
|
|
||||||
relayList.map { relayUrl ->
|
relayList.map { relayUrl ->
|
||||||
BasicRelaySetupInfo(
|
BasicRelaySetupInfo(
|
||||||
relayUrl,
|
RelayUrlFormatter.normalize(relayUrl),
|
||||||
RelayStats.get(relayUrl),
|
RelayStats.get(relayUrl),
|
||||||
)
|
)
|
||||||
}.distinctBy { it.url }.sortedBy { it.relayStat.receivedBytes }.reversed()
|
}.distinctBy { it.url }.sortedBy { it.relayStat.receivedBytes }.reversed()
|
||||||
@@ -117,7 +118,7 @@ class Nip65RelayListViewModel : ViewModel() {
|
|||||||
|
|
||||||
relayList.map { relayUrl ->
|
relayList.map { relayUrl ->
|
||||||
BasicRelaySetupInfo(
|
BasicRelaySetupInfo(
|
||||||
relayUrl,
|
RelayUrlFormatter.normalize(relayUrl),
|
||||||
RelayStats.get(relayUrl),
|
RelayStats.get(relayUrl),
|
||||||
)
|
)
|
||||||
}.distinctBy { it.url }.sortedBy { it.relayStat.receivedBytes }.reversed()
|
}.distinctBy { it.url }.sortedBy { it.relayStat.receivedBytes }.reversed()
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
import com.vitorpamplona.quartz.encoders.Nip47WalletConnect
|
import com.vitorpamplona.quartz.encoders.Nip47WalletConnect
|
||||||
|
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
|
||||||
import com.vitorpamplona.quartz.encoders.decodePrivateKeyAsHexOrNull
|
import com.vitorpamplona.quartz.encoders.decodePrivateKeyAsHexOrNull
|
||||||
import com.vitorpamplona.quartz.encoders.decodePublicKey
|
import com.vitorpamplona.quartz.encoders.decodePublicKey
|
||||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||||
@@ -166,18 +167,12 @@ class UpdateZapAmountViewModel(val account: Account) : ViewModel() {
|
|||||||
val relayUrl =
|
val relayUrl =
|
||||||
walletConnectRelay.text
|
walletConnectRelay.text
|
||||||
.ifBlank { null }
|
.ifBlank { null }
|
||||||
?.let {
|
?.let { RelayUrlFormatter.normalize(it) }
|
||||||
var addedWSS =
|
|
||||||
if (!it.startsWith("wss://") && !it.startsWith("ws://")) "wss://$it" else it
|
|
||||||
if (addedWSS.endsWith("/")) addedWSS = addedWSS.dropLast(1)
|
|
||||||
|
|
||||||
addedWSS
|
|
||||||
}
|
|
||||||
|
|
||||||
val privKeyHex = walletConnectSecret.text.ifBlank { null }?.let { decodePrivateKeyAsHexOrNull(it) }
|
val privKeyHex = walletConnectSecret.text.ifBlank { null }?.let { decodePrivateKeyAsHexOrNull(it) }
|
||||||
|
|
||||||
if (pubkeyHex != null) {
|
if (pubkeyHex != null) {
|
||||||
account?.changeZapPaymentRequest(
|
account.changeZapPaymentRequest(
|
||||||
Nip47WalletConnect.Nip47URI(
|
Nip47WalletConnect.Nip47URI(
|
||||||
pubkeyHex,
|
pubkeyHex,
|
||||||
relayUrl,
|
relayUrl,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ mockk = "1.13.11"
|
|||||||
navigationCompose = "2.7.7"
|
navigationCompose = "2.7.7"
|
||||||
okhttp = "5.0.0-alpha.14"
|
okhttp = "5.0.0-alpha.14"
|
||||||
runner = "1.5.2"
|
runner = "1.5.2"
|
||||||
|
rfc3986 = "0.1.0"
|
||||||
secp256k1KmpJniAndroid = "0.15.0"
|
secp256k1KmpJniAndroid = "0.15.0"
|
||||||
securityCryptoKtx = "1.1.0-alpha06"
|
securityCryptoKtx = "1.1.0-alpha06"
|
||||||
spotless = "6.25.0"
|
spotless = "6.25.0"
|
||||||
@@ -100,6 +101,7 @@ markdown-ui = { group = "com.github.vitorpamplona.compose-richtext", name = "ric
|
|||||||
markdown-ui-material3 = { group = "com.github.vitorpamplona.compose-richtext", name = "richtext-ui-material3", version.ref = "markdown" }
|
markdown-ui-material3 = { group = "com.github.vitorpamplona.compose-richtext", name = "richtext-ui-material3", version.ref = "markdown" }
|
||||||
mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" }
|
mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" }
|
||||||
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
|
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
|
||||||
|
rfc3986-normalizer = { group = "org.czeal", name = "rfc3986", version.ref = "rfc3986" }
|
||||||
secp256k1-kmp-jni-android = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-android", version.ref = "secp256k1KmpJniAndroid" }
|
secp256k1-kmp-jni-android = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-android", version.ref = "secp256k1KmpJniAndroid" }
|
||||||
trbl-blurhash = { group = "io.trbl", name = "blurhash", version.ref = "blurhash" }
|
trbl-blurhash = { group = "io.trbl", name = "blurhash", version.ref = "blurhash" }
|
||||||
unifiedpush = { group = "com.github.UnifiedPush", name = "android-connector", version.ref = "unifiedpush" }
|
unifiedpush = { group = "com.github.UnifiedPush", name = "android-connector", version.ref = "unifiedpush" }
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ dependencies {
|
|||||||
// Parses URLs from Text:
|
// Parses URLs from Text:
|
||||||
api libs.url.detector
|
api libs.url.detector
|
||||||
|
|
||||||
|
// Parses URLs from Text:
|
||||||
|
api libs.rfc3986.normalizer
|
||||||
|
|
||||||
testImplementation libs.junit
|
testImplementation libs.junit
|
||||||
androidTestImplementation platform(libs.androidx.compose.bom)
|
androidTestImplementation platform(libs.androidx.compose.bom)
|
||||||
androidTestImplementation libs.androidx.junit
|
androidTestImplementation libs.androidx.junit
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.encoders
|
package com.vitorpamplona.quartz.encoders
|
||||||
|
|
||||||
|
import org.czeal.rfc3986.URIReference
|
||||||
|
|
||||||
class RelayUrlFormatter {
|
class RelayUrlFormatter {
|
||||||
companion object {
|
companion object {
|
||||||
fun displayUrl(url: String): String {
|
fun displayUrl(url: String): String {
|
||||||
@@ -27,20 +29,22 @@ class RelayUrlFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun normalize(url: String): String {
|
fun normalize(url: String): String {
|
||||||
var newUrl =
|
val newUrl =
|
||||||
if (!url.startsWith("wss://") && !url.startsWith("ws://")) {
|
if (!url.startsWith("wss://") && !url.startsWith("ws://")) {
|
||||||
if (url.endsWith(".onion") || url.endsWith(".onion/")) {
|
if (url.endsWith(".onion") || url.endsWith(".onion/")) {
|
||||||
"ws://$url"
|
"ws://${url.trim()}"
|
||||||
} else {
|
} else {
|
||||||
"wss://$url"
|
"wss://${url.trim()}"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
url
|
url.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.endsWith("/")) newUrl = newUrl.dropLast(1)
|
return try {
|
||||||
|
URIReference.parse(newUrl).normalize().toString()
|
||||||
return newUrl
|
} catch (e: Exception) {
|
||||||
|
newUrl
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getHttpsUrl(dirtyUrl: String): String {
|
fun getHttpsUrl(dirtyUrl: String): String {
|
||||||
|
|||||||
Reference in New Issue
Block a user