mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-21 19:30:47 +02:00
Saves a copy of the NIP65 and NIP17 relay lists locally
This commit is contained in:
@@ -42,6 +42,8 @@ import com.vitorpamplona.quartz.encoders.Nip47WalletConnect
|
||||
import com.vitorpamplona.quartz.encoders.hexToByteArray
|
||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||
import com.vitorpamplona.quartz.encoders.toNpub
|
||||
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
||||
import com.vitorpamplona.quartz.events.ChatMessageRelayListEvent
|
||||
import com.vitorpamplona.quartz.events.ContactListEvent
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.LnZapEvent
|
||||
@@ -90,6 +92,8 @@ private object PrefKeys {
|
||||
const val DEFAULT_DISCOVERY_FOLLOW_LIST = "defaultDiscoveryFollowList"
|
||||
const val ZAP_PAYMENT_REQUEST_SERVER = "zapPaymentServer"
|
||||
const val LATEST_CONTACT_LIST = "latestContactList"
|
||||
const val LATEST_DM_RELAY_LIST = "latestDMRelayList"
|
||||
const val LATEST_NIP65_RELAY_LIST = "latestNIP65RelayList"
|
||||
const val HIDE_DELETE_REQUEST_DIALOG = "hide_delete_request_dialog"
|
||||
const val HIDE_BLOCK_ALERT_DIALOG = "hide_block_alert_dialog"
|
||||
const val HIDE_NIP_17_WARNING_DIALOG = "hide_nip24_warning_dialog" // delete later
|
||||
@@ -311,10 +315,33 @@ object LocalPreferences {
|
||||
PrefKeys.ZAP_PAYMENT_REQUEST_SERVER,
|
||||
Event.mapper.writeValueAsString(account.zapPaymentRequest),
|
||||
)
|
||||
putString(
|
||||
PrefKeys.LATEST_CONTACT_LIST,
|
||||
Event.mapper.writeValueAsString(account.backupContactList),
|
||||
)
|
||||
if (account.backupContactList != null) {
|
||||
putString(
|
||||
PrefKeys.LATEST_CONTACT_LIST,
|
||||
Event.mapper.writeValueAsString(account.backupContactList),
|
||||
)
|
||||
} else {
|
||||
remove(PrefKeys.LATEST_CONTACT_LIST)
|
||||
}
|
||||
|
||||
if (account.backupDMRelayList != null) {
|
||||
putString(
|
||||
PrefKeys.LATEST_DM_RELAY_LIST,
|
||||
Event.mapper.writeValueAsString(account.backupDMRelayList),
|
||||
)
|
||||
} else {
|
||||
remove(PrefKeys.LATEST_DM_RELAY_LIST)
|
||||
}
|
||||
|
||||
if (account.backupNIP65RelayList != null) {
|
||||
putString(
|
||||
PrefKeys.LATEST_NIP65_RELAY_LIST,
|
||||
Event.mapper.writeValueAsString(account.backupNIP65RelayList),
|
||||
)
|
||||
} else {
|
||||
remove(PrefKeys.LATEST_NIP65_RELAY_LIST)
|
||||
}
|
||||
|
||||
putBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, account.hideDeleteRequestDialog)
|
||||
putBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, account.hideNIP17WarningDialog)
|
||||
putBoolean(PrefKeys.HIDE_BLOCK_ALERT_DIALOG, account.hideBlockAlertDialog)
|
||||
@@ -471,8 +498,8 @@ object LocalPreferences {
|
||||
val latestContactList =
|
||||
try {
|
||||
getString(PrefKeys.LATEST_CONTACT_LIST, null)?.let {
|
||||
println("Decoding Contact List: " + it)
|
||||
if (it != null) {
|
||||
if (it != "null") {
|
||||
println("Decoding Contact List: $it")
|
||||
Event.fromJson(it) as ContactListEvent?
|
||||
} else {
|
||||
null
|
||||
@@ -488,6 +515,46 @@ object LocalPreferences {
|
||||
null
|
||||
}
|
||||
|
||||
val latestDmRelayList =
|
||||
try {
|
||||
getString(PrefKeys.LATEST_DM_RELAY_LIST, null)?.let {
|
||||
if (it != "null") {
|
||||
println("Decoding DM Relay List: $it")
|
||||
Event.fromJson(it) as ChatMessageRelayListEvent?
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.w(
|
||||
"LocalPreferences",
|
||||
"Error Decoding DM Relay List ${getString(PrefKeys.LATEST_DM_RELAY_LIST, null)}",
|
||||
e,
|
||||
)
|
||||
null
|
||||
}
|
||||
|
||||
val latestNip65RelayList =
|
||||
try {
|
||||
getString(PrefKeys.LATEST_NIP65_RELAY_LIST, null)?.let {
|
||||
if (it != "null") {
|
||||
println("Decoding NIP65 Relay List: $it")
|
||||
Event.fromJson(it) as AdvertisedRelayListEvent?
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.w(
|
||||
"LocalPreferences",
|
||||
"Error Decoding NIP65 Relay List ${getString(PrefKeys.LATEST_NIP65_RELAY_LIST, null)}",
|
||||
e,
|
||||
)
|
||||
null
|
||||
}
|
||||
|
||||
val pendingAttestations =
|
||||
try {
|
||||
getString(PrefKeys.PENDING_ATTESTATIONS, null)?.let {
|
||||
@@ -502,7 +569,7 @@ object LocalPreferences {
|
||||
if (e is CancellationException) throw e
|
||||
Log.w(
|
||||
"LocalPreferences",
|
||||
"Error Decoding Contact List ${getString(PrefKeys.LATEST_CONTACT_LIST, null)}",
|
||||
"Error Decoding Contact List ${getString(PrefKeys.PENDING_ATTESTATIONS, null)}",
|
||||
e,
|
||||
)
|
||||
null
|
||||
@@ -595,6 +662,8 @@ object LocalPreferences {
|
||||
hideBlockAlertDialog = hideBlockAlertDialog,
|
||||
hideNIP17WarningDialog = hideNIP17WarningDialog,
|
||||
backupContactList = latestContactList,
|
||||
backupNIP65RelayList = latestNip65RelayList,
|
||||
backupDMRelayList = latestDmRelayList,
|
||||
proxy = proxy,
|
||||
proxyPort = proxyPort,
|
||||
showSensitiveContent = MutableStateFlow(showSensitiveContent),
|
||||
|
@@ -116,6 +116,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.combineTransform
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flattenMerge
|
||||
@@ -192,6 +193,8 @@ class Account(
|
||||
var hideBlockAlertDialog: Boolean = false,
|
||||
var hideNIP17WarningDialog: Boolean = false,
|
||||
var backupContactList: ContactListEvent? = null,
|
||||
var backupDMRelayList: ChatMessageRelayListEvent? = null,
|
||||
var backupNIP65RelayList: AdvertisedRelayListEvent? = null,
|
||||
var proxy: Proxy? = null,
|
||||
var proxyPort: Int = 9050,
|
||||
var showSensitiveContent: MutableStateFlow<Boolean?> = MutableStateFlow(null),
|
||||
@@ -269,7 +272,9 @@ class Account(
|
||||
if (mappedRelaySet.none { it.url == newUrl }) {
|
||||
mappedRelaySet = mappedRelaySet +
|
||||
RelaySetupInfo(
|
||||
newUrl, true, true,
|
||||
newUrl,
|
||||
true,
|
||||
true,
|
||||
setOf(
|
||||
FeedType.PRIVATE_DMS,
|
||||
),
|
||||
@@ -294,7 +299,9 @@ class Account(
|
||||
if (mappedRelaySet.none { it.url == newUrl }) {
|
||||
mappedRelaySet = mappedRelaySet +
|
||||
RelaySetupInfo(
|
||||
newUrl, true, false,
|
||||
newUrl,
|
||||
true,
|
||||
false,
|
||||
setOf(
|
||||
FeedType.SEARCH,
|
||||
),
|
||||
@@ -319,9 +326,14 @@ class Account(
|
||||
if (mappedRelaySet.none { it.url == newUrl }) {
|
||||
mappedRelaySet = mappedRelaySet +
|
||||
RelaySetupInfo(
|
||||
newUrl, true, true,
|
||||
newUrl,
|
||||
true,
|
||||
true,
|
||||
setOf(
|
||||
FeedType.FOLLOWS, FeedType.PUBLIC_CHATS, FeedType.GLOBAL, FeedType.PRIVATE_DMS,
|
||||
FeedType.FOLLOWS,
|
||||
FeedType.PUBLIC_CHATS,
|
||||
FeedType.GLOBAL,
|
||||
FeedType.PRIVATE_DMS,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -344,9 +356,14 @@ class Account(
|
||||
if (mappedRelaySet.none { it.url == newUrl }) {
|
||||
mappedRelaySet = mappedRelaySet +
|
||||
RelaySetupInfo(
|
||||
newUrl, true, true,
|
||||
newUrl,
|
||||
true,
|
||||
true,
|
||||
setOf(
|
||||
FeedType.FOLLOWS, FeedType.PUBLIC_CHATS, FeedType.GLOBAL, FeedType.PRIVATE_DMS,
|
||||
FeedType.FOLLOWS,
|
||||
FeedType.PUBLIC_CHATS,
|
||||
FeedType.GLOBAL,
|
||||
FeedType.PRIVATE_DMS,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -363,10 +380,14 @@ class Account(
|
||||
val write = nip65setup.type == AdvertisedRelayListEvent.AdvertisedRelayType.BOTH || nip65setup.type == AdvertisedRelayListEvent.AdvertisedRelayType.READ
|
||||
|
||||
RelaySetupInfo(
|
||||
relay.url, true, relay.write || write,
|
||||
relay.url,
|
||||
true,
|
||||
relay.write || write,
|
||||
relay.feedTypes +
|
||||
setOf(
|
||||
FeedType.FOLLOWS, FeedType.GLOBAL, FeedType.PUBLIC_CHATS,
|
||||
FeedType.FOLLOWS,
|
||||
FeedType.GLOBAL,
|
||||
FeedType.PUBLIC_CHATS,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
@@ -380,9 +401,12 @@ class Account(
|
||||
|
||||
mappedRelaySet = mappedRelaySet +
|
||||
RelaySetupInfo(
|
||||
newNip65Setup.relayUrl, true, write,
|
||||
newNip65Setup.relayUrl,
|
||||
true,
|
||||
write,
|
||||
setOf(
|
||||
FeedType.FOLLOWS, FeedType.PUBLIC_CHATS,
|
||||
FeedType.FOLLOWS,
|
||||
FeedType.PUBLIC_CHATS,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -2635,6 +2659,26 @@ class Account(
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDMRelayList(newDMRelayList: ChatMessageRelayListEvent?) {
|
||||
if (newDMRelayList == null || newDMRelayList.tags.isEmpty()) return
|
||||
|
||||
// Events might be different objects, we have to compare their ids.
|
||||
if (backupDMRelayList?.id != newDMRelayList.id) {
|
||||
backupDMRelayList = newDMRelayList
|
||||
saveable.invalidateData()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNIP65RelayList(newNIP65RelayList: AdvertisedRelayListEvent?) {
|
||||
if (newNIP65RelayList == null || newNIP65RelayList.tags.isEmpty()) return
|
||||
|
||||
// Events might be different objects, we have to compare their ids.
|
||||
if (backupNIP65RelayList?.id != newNIP65RelayList.id) {
|
||||
backupNIP65RelayList = newNIP65RelayList
|
||||
saveable.invalidateData()
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a User's relay list and adds the types of feeds they are active for.
|
||||
fun activeRelays(): Array<RelaySetupInfo>? {
|
||||
val usersRelayList =
|
||||
@@ -2968,8 +3012,32 @@ class Account(
|
||||
suspend fun registerObservers() =
|
||||
withContext(Dispatchers.Main) {
|
||||
// saves contact list for the next time.
|
||||
userProfile().live().follows.observeForever {
|
||||
GlobalScope.launch(Dispatchers.IO) { updateContactListTo(userProfile().latestContactList) }
|
||||
scope.launch {
|
||||
Log.d("AccountRegisterObservers", "Kind 3 Collector Start")
|
||||
userProfile().flow().follows.stateFlow.collect {
|
||||
Log.d("AccountRegisterObservers", "Updating Kind 3 ${userProfile().toBestDisplayName()}")
|
||||
updateContactListTo(userProfile().latestContactList)
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
Log.d("AccountRegisterObservers", "NIP-17 Relay List Collector Start")
|
||||
getDMRelayListFlow().collect {
|
||||
Log.d("AccountRegisterObservers", "Updating DM Relay List for ${userProfile().toBestDisplayName()}")
|
||||
(it.note.event as? ChatMessageRelayListEvent)?.let {
|
||||
updateDMRelayList(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
Log.d("AccountRegisterObservers", "NIP-65 Relay List Collector Start")
|
||||
getNIP65RelayListFlow().collect {
|
||||
Log.d("AccountRegisterObservers", "Updating NIP-65 List for ${userProfile().toBestDisplayName()}")
|
||||
(it.note.event as? AdvertisedRelayListEvent)?.let {
|
||||
updateNIP65RelayList(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// imports transient blocks due to spam.
|
||||
@@ -2990,7 +3058,7 @@ class Account(
|
||||
}
|
||||
|
||||
init {
|
||||
Log.d("Init", "Account")
|
||||
Log.d("Account", "Init")
|
||||
backupContactList?.let {
|
||||
println("Loading saved contacts ${it.toJson()}")
|
||||
|
||||
@@ -2998,6 +3066,16 @@ class Account(
|
||||
GlobalScope.launch(Dispatchers.IO) { LocalCache.consume(it) }
|
||||
}
|
||||
}
|
||||
|
||||
backupDMRelayList?.let {
|
||||
println("Loading DM Relay List ${it.toJson()}")
|
||||
GlobalScope.launch(Dispatchers.IO) { LocalCache.verifyAndConsume(it, null) }
|
||||
}
|
||||
|
||||
backupNIP65RelayList?.let {
|
||||
println("Loading saved contacts ${it.toJson()}")
|
||||
GlobalScope.launch(Dispatchers.IO) { LocalCache.verifyAndConsume(it, null) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user