diff --git a/app/build.gradle b/app/build.gradle index ac98d234..5bfb0c04 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,7 +68,10 @@ android { } dependencies { - implementation project(path: ':quartz') + implementation('com.github.vitorpamplona.amethyst:quartz:main-SNAPSHOT') { + exclude group: 'net.java.dev.jna' + } + implementation 'net.java.dev.jna:jna:5.13.0@aar' implementation "androidx.core:core-splashscreen:1.0.1" implementation 'androidx.core:core-ktx:1.10.1' diff --git a/build.gradle b/build.gradle index e83ce30a..9d06c1b0 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,6 @@ buildscript { lifecycle_version = '2.6.1' compose_ui_version = '1.5.0' nav_version = "2.7.0" - core_ktx_version = '1.10.1' } } diff --git a/quartz/.gitignore b/quartz/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/quartz/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/quartz/build.gradle b/quartz/build.gradle deleted file mode 100644 index b3836de7..00000000 --- a/quartz/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'org.jetbrains.kotlin.plugin.serialization' -} - -android { - namespace 'com.vitorpamplona.quartz' - compileSdk 34 - - defaultConfig { - minSdk 26 - targetSdk 34 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = '17' - } -} - -dependencies { - implementation "androidx.core:core-ktx:$core_ktx_version" - - // @Immutable and @Stable - implementation "androidx.compose.runtime:runtime:$compose_ui_version" - - // Bitcoin secp256k1 bindings to Android - api 'fr.acinq.secp256k1:secp256k1-kmp-jni-android:0.10.1' - - // LibSodium for XChaCha encryption - implementation "com.goterl:lazysodium-android:5.1.0@aar" - implementation 'net.java.dev.jna:jna:5.13.0@aar' - - api 'com.fasterxml.jackson.module:jackson-module-kotlin:2.15.2' - - // immutable collections to avoid recomposition - api("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.5") - - // Parses URLs from Text: - api "io.github.url-detector:url-detector:0.1.23" - - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' -} \ No newline at end of file diff --git a/quartz/consumer-rules.pro b/quartz/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/quartz/proguard-rules.pro b/quartz/proguard-rules.pro deleted file mode 100644 index 4727a86b..00000000 --- a/quartz/proguard-rules.pro +++ /dev/null @@ -1,60 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# preserve the line number information for debugging stack traces. --dontobfuscate --keepattributes LocalVariableTable --keepattributes LocalVariableTypeTable --keepattributes *Annotation* --keepattributes SourceFile --keepattributes LineNumberTable --keepattributes Signature --keepattributes Exceptions --keepattributes InnerClasses --keepattributes EnclosingMethod --keepattributes MethodParameters --keepparameternames - --keepdirectories libs - -# Keep all names --keepnames class ** { *; } - -# Keep All enums --keep enum ** { *; } - -# preserve access to native classses --keep class fr.acinq.secp256k1.** { *; } - -# JNA For Libsodium --keep class com.goterl.lazysodium.** { *; } - -# JNA also requires AWT, which Android does not have. So the classes are broken down to filter AWT out --keep class com.sun.jna.ToNativeConverter { *; } --keep class com.sun.jna.NativeMapped { *; } --keep class com.sun.jna.CallbackReference { *; } --keep class com.sun.jna.ptr.IntByReference { *; } --keep class com.sun.jna.NativeLong { *; } --keep class com.sun.jna.Structure { *; } --keep class com.sun.jna.Structure$* { *; } --keep class com.sun.jna.Native$ffi_callback { *; } --keep class * implements com.sun.jna.Structure$* { *; } --keep class * implements com.sun.jna.Native$* { *; } --keep class com.sun.jna.Native { - private static com.sun.jna.NativeMapped fromNative(java.lang.Class, java.lang.Object); - private static com.sun.jna.NativeMapped fromNative(java.lang.reflect.Method, java.lang.Object); - private static java.lang.Class nativeType(java.lang.Class); - private static java.lang.Object toNative(com.sun.jna.ToNativeConverter, java.lang.Object); - private static java.lang.Object fromNative(com.sun.jna.FromNativeConverter, java.lang.Object, java.lang.reflect.Method); -} - -# JSON parsing --keep class com.vitorpamplona.quartz.crypto.** { *; } --keep class com.vitorpamplona.quartz.encoders.** { *; } --keep class com.vitorpamplona.quartz.events.** { *; } --keep class com.vitorpamplona.amethyst.model.** { *; } --keep class com.vitorpamplona.amethyst.service.** { *; } \ No newline at end of file diff --git a/quartz/src/androidTest/assets/nostr_vitor_short.json b/quartz/src/androidTest/assets/nostr_vitor_short.json deleted file mode 100644 index ffb46ce7..00000000 --- a/quartz/src/androidTest/assets/nostr_vitor_short.json +++ /dev/null @@ -1,13261 +0,0 @@ -[ - { - "content": "Do you know which relay has your old info? ", - "created_at": 1690301795, - "id": "fc0e838994bb66a8249aea78e883c6e98f98b93296fb5209e9e9bab54477fe3d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "326a0f267def66d2733ae0d90fcc8cb52de711e5e93561fc90bcd9291f4cad00f135fa65470a52a1dfa3e758595a0057d6c3407f791f052836a263a95fe0f85f", - "tags": [ - [ - "e", - "e414229203fa467f99b4a20f84584e4389b9d22ae7203556d0c0da9012ac321d", - "", - "root" - ], - [ - "e", - "0eb3cb5cc57e25bf08590da5fcd7370b30b74ed2e3fcf4e909d7c03c4d3b7dbc", - "wss://nostr-pub.wellorder.net/", - "reply" - ], - [ - "p", - "eda96cb93aecdd61ade0c1f9d2bfdf95a7e76cf1ca89820c38e6e4cea55c0c05" - ], - [ - "p", - "d9dba0e072bdb353dfb0020de159126af47e69e133ea91bbd48e8bede37320e2" - ], - [ - "p", - "eda96cb93aecdd61ade0c1f9d2bfdf95a7e76cf1ca89820c38e6e4cea55c0c05" - ] - ] - }, - { - "content": "Some relays still have your old profile.\n\nIf you were using a given relay set in the past, changed your profile there (so all of them got updated) then removed a few relays from the list and updated your profile again, the relays you removed did not receive the update. \n\nSo, if apps are using those relays, they get your old version. ", - "created_at": 1690301420, - "id": "4ef323e0e32b6025b5e7c59e78f4ed0145805fbab9b95247357a10379ede375d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "83caf220a6da34754d147f844f1d56ae61020bb14d2bab38b0498b94037c0ee153121f4e0c99e8be353f096cf72bfcaa6a04b5bacda50df06ffb96faa63b3357", - "tags": [ - [ - "e", - "e414229203fa467f99b4a20f84584e4389b9d22ae7203556d0c0da9012ac321d", - "", - "root" - ], - [ - "e", - "e428765c0b240bb6fc8baa027db1252c0a98ca5bb822bd81f763730374a0be0c", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "d9dba0e072bdb353dfb0020de159126af47e69e133ea91bbd48e8bede37320e2" - ], - [ - "p", - "eda96cb93aecdd61ade0c1f9d2bfdf95a7e76cf1ca89820c38e6e4cea55c0c05" - ] - ] - }, - { - "content": "Not that I know of. No bounties as well. \n\nIt doesn't look like people have any interest in this. ", - "created_at": 1690301261, - "id": "d5cce4e3b7a6cf4d2fec27cecb12e8e7f71951fa0fceef56fdf1b834c382843c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a4c39738640bbd6bfd10b949f4f641b964a539977bffe5c4028bb549fba99f32737b2605936979f76745fe3b9db7f1be5b083b0b74b50b8717d3dc5b855ba04c", - "tags": [ - [ - "e", - "5778111b09d78ecec02c9b7f52feccd655b8fbb049c40c380c03eead049bf7ea", - "", - "root" - ], - [ - "e", - "e673f98336da0b6884567adcf72dd6b4d86ab16eb036c1c6d6b859110b9233a6", - "wss://nostr.mom/", - "reply" - ], - [ - "p", - "eff0899a8d3e8ed7d7524b86f5a7077c1ec39ee305c191738b29b0bbfa20fe42" - ], - [ - "p", - "7a7cfab852cd457336ec2126c2bcd8b2c77d569054fae53009d1f4631bfa1448" - ] - ] - }, - { - "content": "qZOB2WyD9zuBMmN1tNBhojLDTNJtmsUOIqg2Ld86lyLioL3UDNiTT7jr1D0UdxVuRuGrwaLG4dKDedXWx3s5Bo2CKDBJ0w6fEE43TCqP88yZMjjDwjqLN+a8O1/aKEgP?iv=rwL3fBSM4pvyyMJZpWVGcQ==", - "created_at": 1690298384, - "id": "48a4acebd543263bd867fa41754dcb443c7816a91cd200dce977dc6e6d269060", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9341cdb84ec7338fcf579abfaa484489aeb8858b97c3c8399d0dd4ee26a7932109b4660f9cca5809b8023a714dc38a15c745a2de51792f3773df10382405ec8c", - "tags": [ - [ - "p", - "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a" - ] - ] - }, - { - "content": "AhyW0o7KjGgdrLZcI866xQ==?iv=oVtmzuGFBaBQ616f1JzXBg==", - "created_at": 1690298365, - "id": "c2763bebb1521a0d34a331785bf6d6a4f267f2fd093e4240cf309aad439efcad", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "834c99b2bdaa2a974b44907c2c8457c7ca63c929bf1f19fad960f8abacfb3f1d9b064c918ed4e7f326c88fa80c8b5d7cd85c8e675fac299206a5b9fa75baedec", - "tags": [ - [ - "p", - "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a" - ] - ] - }, - { - "content": "{\"f412192fdc846952c75058e911d37a7392aa7fd2e727330f4344badc92fb8a22\":1690289907,\"42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5\":1690289924,\"25e5c82273a271cb1a840d0060391a0bf4965cafeb029d5ab55350b418953fbb\":1688330562,\"d9185164dbaf1e36a856b8f8759f8f4fb35942da22bac7afc131c910314b1f6c\":1688750583,\"645681b9d067b1a362c4bee8ddff987d2466d49905c26cb8fec5e6fb73af5c84\":1688750587,\"89d1ce9164f1f172daaa9c784153178cb1dec7912bf55f5dc07e0f1dabe40e6c\":1688750589,\"4ff652622cbe22d93e3a0ce2487e86736a9a209724a7328c59bc29b064a42926\":1688750592,\"460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c\":1688750595,\"9989500413fb756d8437912cc32be0730dbe1bfc6b5d2eef759e1456c239f905\":1688750599,\"97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322\":1688750600,\"339e87a4ad5b32a7fa88c6a56a65a53bcfbea8595a86b5d87201a39b0408c29c\":1688750603,\"975d0ba9c395954e0d06a801aa27bbd7a631d9a9a8a461df191328cd1505419c\":1688750604}", - "created_at": 1690289924, - "id": "63407a41d95e8e78c33b0d88a329331968a1b6a8f0f3c8c5d1a5b0761d2d5923", - "kind": 30078, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "98e4157674a0fb090a91ffeacc8cecfc5f17df26310252b7bce000cf4e7aade32ba3611ad3ab6a9988fe0c0e951f64a1135d9ce0a07de24187b3a8ab2e5276c3", - "tags": [ - [ - "d", - "read-mark-map" - ] - ] - }, - { - "content": "TL4qxgYec/DKRDTc1GIS0utLHiswcT/c03jZvtSimCECbf1LQBKUlmgRUwQJqgAhmrFDjYD88goSVYyR+OkZ/K2mIC3K8sbYrnvkk93KA6k=?iv=Idl20mo4wuDM+NPMfnvayw==", - "created_at": 1690289826, - "id": "8556d3f5a7bb23f79f5749aefc75b4febd17877fd525ff9b5afab65854e17908", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "49edc54a022ece3f2826f347793042745be713bd4841efa1883dfa4fb35281d429aed42d2e1606077c2cb50dab1e9efd41510e16cabde309bcf57381e7926e5a", - "tags": [ - [ - "p", - "ad5eb2f02a967459a97d041a44cac14cdffe0394ca6fae48b7b354eb1c4fae18" - ], - [ - "lamport", - "6360" - ] - ] - }, - { - "content": "UKV5cwhYK7gCH5bnwoAwkQRrqmCMCfJMBeFzZw9qsco=?iv=aiK4ONfev1EUOMrB7cJ8hg==", - "created_at": 1690289810, - "id": "6fb5ba413998496d6efc3ad69e7673d91320327f6a54b3c049695f995d532194", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "aa039c210a32e919d1ccb7dbb4434265aac723f898a1729222cc7eaeee48e49399c92e67528ffd20c1a863783c64bdb1a60e8de56d4de6429f41c0b03993cae0", - "tags": [ - [ - "p", - "ad5eb2f02a967459a97d041a44cac14cdffe0394ca6fae48b7b354eb1c4fae18" - ], - [ - "lamport", - "6359" - ] - ] - }, - { - "content": "Yep. The amount of memory rotating in the background when you scrool is quite large. We are constantly working to reduce it, but a battle ", - "created_at": 1690289456, - "id": "ff08047596ad0eb7be11cdf66789b4982728d3522838aa7c79b0f173d9196e28", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "38c554b203d4128ab15681d149307cadd250a705f43cfe2c49c4bb454c0a82900ca6371aa214ab1e8e58af5bd47438f6d688b519bcd42cb6b23acf083d6893bf", - "tags": [ - [ - "e", - "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271", - "", - "root" - ] - ] - }, - { - "content": "s5pf5nJ1HZSJtnJye6/gZT2H1Ksq0ZOddenz1xOCD76rVJlKpGiXibeIBcGmmJ+M?iv=lgE2cTIHfsdJp2RIFA9kCA==", - "created_at": 1690289261, - "id": "9f48eaddca03a88dd02257a51fffdfc6e58847691e6449b46eda116826d3ee32", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3765866916e6b9ee662b28d81d570265f0e116d5aeab50aad4d2ed503c938a5c4261f6e5712c7dc8e63cc5bfa6f86efad3a0572c285104299fd9945e82555b93", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "uDIFFjFeuxLWlBZ2QBqcxf6GnfFxadrtdwciH7laVOx85iQ9XAOrDbJaOWIllu95KxXuI7SK8bttv66qQjCQ+Q==?iv=47N/FrAOij7INTY45GngLw==", - "created_at": 1690288560, - "id": "29e0784695da2615a4a83a5e55036c9e749cd4cf98324d6b4e49aa20ac3927db", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5ce3335af0da098ae483bfb758ff4c4ac355bf82721cce3587edb9912440044be28651b1a2f72fdcf05561c221c4e1c9f70bce5e4098e6095ca5cffa5a6d0e4f", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "NwfzYhOIbMzbc6dDEbnWWhgPEz89V2smVNkOMdc20k5QKjQWvE83O1UGviFWquSsgGv3GQrqCCi4EW9IQbhXvg==?iv=1xfL0/+De1Tl0PVON5sTMw==", - "created_at": 1690288549, - "id": "294991508f9fe42234c3937d85db77478389a28a2e1c8817c7be7189dd452fdc", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0894f96fb95f158e727189cb3d4e0bdf59b4b4ac065e8972e7b44e94b0816a8330fd8175ee2a52260231fecc81b5429c4a3418f926bc5c548c10e110468d67f2", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Uisi4OKioPOCqI/A0gDNKynLNV+ej0aNCY70P/vjgu21hbMRD1DCw/N7sRO7PeeE?iv=QNIoWu01HPHSdRUdeQYf+w==", - "created_at": 1690288547, - "id": "0600aa6b0e40e5057d6ff85b4d0eefd86bf661a109a0ea5e30a616f8a7509eb9", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e1726e0ca65b41dbd13d6c46248d6beb9f7d28eb8a03a50c6f7ff55cee77c85fc7209a2306fda5b849c5f3127420c862d5849b0c5695d48acbb21c5ac651f8ed", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690288395, - "id": "ac2fb0c9b72a6fefe60262fbce6eb8740380b7f964200cb8efdd2e72fcb1ddb0", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6df6aeef98c21a0508a788cbe6a2a6825e5cc69e57dd843dc6e6d4ce2c28dd042947723fda3d8b24489305d86b1e81f9f66b390d6f7dabf9742cd3775e17e53f", - "tags": [ - [ - "e", - "2cc5b6e012c5a64fcf580fc1b53bed25ed0d7f785fd896744524b1a114dcc86e" - ], - [ - "p", - "c80b5248fbe8f392bc3ba45091fb4e6e2b5872387601bf90f53992366b30d720" - ] - ] - }, - { - "content": "tRYUKww0df3YH/uVQVDVuZMuxAwVlPxkCInhfjLdaJcaLOaP4nanBVJSiN/Mwd4TqDRIiENmB0VFvfICFVuSC9JWVRA5RXKwhNUvJA8lFhqyYZKJ7hu7vIv/pBsYmoodZkmIOm1k62krq6xcnMab9l5AeqgAGyWmPOM0nZM+B5LFp9s5iqc5uly52wpT4HFrbNEO7Tnp7yg5Zzrrl6wwUcmvgMf9ZdJHUusgy0y449WOglVIZI7CouMgjH4tfxbTr7jpZEb+Bl8PPMBRylEV0qniBEd46TAYTHZW7QOJRnSP18vMfESf+kjM9KbiQJhyOY8FKIMJ2/ofUjCiOlWhlME29JykleKz70KmsrJNA0bQH3MfzQ0M9qBdvSdpD0pPIRc9hFmAmPuSOQpb1k/+lF+lcNQc2SPdj3NOS0L6BialMn8fwWtpuBHFtdRJIj5WrHpgnmXxeZ2ES40KZUwA6izlW+YOYI8RtlkqxsrmOWg=?iv=diRnj/9ih+6dFgT9qGMIdg==", - "created_at": 1690287796, - "id": "856d60b6545084c4d8a450d8f079dddcb3bcff54aed5df0d84eb63aec1f9ce6e", - "kind": 30078, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e7e2a040ec7c4fa8a931005b3fb2880c927107de970165d4869a403a2b3fcadd858ca4ddbfe6305d15b208fbafa15f0341217af5cb6f965aa4194c9b8a2c06a3", - "tags": [ - [ - "d", - "coracle/last_checked/v1" - ], - [ - "client", - "coracle" - ] - ] - }, - { - "content": "I am not raising money because I can't make the numbers work for investors. But we do take donations to build the team. :) ", - "created_at": 1690287547, - "id": "8a359c03413c06340f034cde37528c4a0bf49cc2b42e571ee806c86abe93ff1b", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a08449b21dc283a0effc8a0ee4ad3254ed1905e0e5f53963b101a927d05cd8b7b5718d04ec9909e34986d743e5db272b0541b6b86b1749696f22883b2afad7ef", - "tags": [ - [ - "e", - "5778111b09d78ecec02c9b7f52feccd655b8fbb049c40c380c03eead049bf7ea", - "", - "root" - ], - [ - "e", - "4705531ded4c3dff81ff3435c28f2112cc789593fc6afe6d9ad2335b2619245b", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "7a7cfab852cd457336ec2126c2bcd8b2c77d569054fae53009d1f4631bfa1448" - ], - [ - "p", - "7a7cfab852cd457336ec2126c2bcd8b2c77d569054fae53009d1f4631bfa1448" - ] - ] - }, - { - "content": "ohhh good catch. ", - "created_at": 1690287166, - "id": "ffd37a3e6504bb5171ba0c201019628dea6d282b12c71e3a7e35e20ae4de538c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8cbf2035954db635d65b039d549c36f2111a6e8c5c831db5e5a3eed0260009462660e8d0d3923b48141f1b35366854890a3fbda91e1360d242175cecf0a96a7c", - "tags": [ - [ - "e", - "56887d01eebd3727ffc37ca54eb67b6e8427db4b03e7c003683931f5cbde82c2", - "", - "root" - ], - [ - "e", - "8154235a2796bdab6c7c0cc0777a8cc6fb6bdcb19607a5d1f901d02494648743", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93" - ], - [ - "p", - "6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93" - ], - [ - "p", - "de14fe62f97e09429581f9e8fec3170f3ce5e7936a2134bf70c87c5ff229e53a" - ] - ] - }, - { - "content": "We don't have server. The main issue is that now the app uses up to 1GB to keep all the content the app needs. Most old phones will definitely struggle with that level of memory use. ", - "created_at": 1690286996, - "id": "5b3a569ab61dc0d88da2a93564de9da3e6f42c8479bb93a522370501ecd08140", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "515101902a9168031260d2cc889bef1a1e6b4e499397e7cfba08799b7503b81cbf3e4a9147a0cbd4cc9fcc252a66330c428e9a6ae4dd6751c551cf9dc1cd6c5e", - "tags": [ - [ - "e", - "5778111b09d78ecec02c9b7f52feccd655b8fbb049c40c380c03eead049bf7ea", - "", - "reply" - ], - [ - "p", - "7a7cfab852cd457336ec2126c2bcd8b2c77d569054fae53009d1f4631bfa1448" - ] - ] - }, - { - "content": "+", - "created_at": 1690286957, - "id": "0c97361806dd60f9b6f5a0ffaa25da846d5e4d4717287551530b665db9d39302", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3770d5924fb47cbad974ea6be874dab133a90176e3a62502aff7c8a1ad32ed39a29387c88a1270f78a2d25e01cb926f6fde2b0f3a63fc2356b26e5295b03c3ce", - "tags": [ - [ - "e", - "4705531ded4c3dff81ff3435c28f2112cc789593fc6afe6d9ad2335b2619245b" - ], - [ - "p", - "7a7cfab852cd457336ec2126c2bcd8b2c77d569054fae53009d1f4631bfa1448" - ] - ] - }, - { - "content": "I am not sure why you would say so. Any event can be part of a community, including long-form content. ", - "created_at": 1690286892, - "id": "f65330aab9339f7c814b763a571c02a2c00de96e321e803a09e08140ec941138", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5f391228b9a47d83978a304f0505a16b594ffe48fcb872e8bd69489557306b38cf926603f955e0ed742baabf59dcafd2934919cea4c600e285eebf239d42dfc0", - "tags": [ - [ - "e", - "9dd8ff6c397f19373006037c894b02f35da2b69ac12f62ec008889c9571dbd08", - "", - "reply" - ], - [ - "p", - "c80b5248fbe8f392bc3ba45091fb4e6e2b5872387601bf90f53992366b30d720" - ] - ] - }, - { - "content": "Well, Primal and others don't load everything we do. They just offer the main feed. That's the main difference. Amethyst can use up to 1GB of memory in heavy use. Many light compose apps will work just fine. They are definitely heavier than other UI frameworks for 2+year old phones but the issue happens when we try to add the all components we have on the screen. ", - "created_at": 1690286508, - "id": "07bdab60f70082150f6b50c8f9166244f7fefa4087b95409328c595cd17dce53", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "993391d5757ae264346c8db656d4fcfdec396a63c780d012e767a608087a673ceb262b64a9c0bd12ff18140a1d80b79645759e019c13a969e681092e6c0537c2", - "tags": [ - [ - "e", - "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271", - "", - "root" - ] - ] - }, - { - "content": "Probably because your are following a hashtag or a community. Those show up in your feed as well. If so, there is an identifier of the community or hashtag in the first row, together with your name ", - "created_at": 1690285153, - "id": "aae6aa51e943bdd8f9f09b2babbbf02397ca2c7e9c99dfa0042876ded4073ef1", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3b79f668ec10f8fd8d2c7ae7a0a075c57e764440a4d0cb92b8a823941418180af07577f6fd46b9b8459c6cb64151176abea129261af861468fd44ecebc566847", - "tags": [ - [ - "e", - "7e374164ec625c01d4efce693a8d7a13225fd87bbf4a439390fd995ba077b038", - "", - "reply" - ], - [ - "p", - "2ebcd815589195d4fe00e1996323d41c3a455641d3065d7b82e68e574f0c0f48" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690285082, - "id": "6b4c1249dcbebb07e1642ff72384a709ddaace107d98b34ee87028cf2ee151bb", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "71409c88d13a42740a17249bf2a5300c875b7a8fad471fc6097b5de1b9234db339c1f160d4156a661abb871a7e9f97015048735ef44b1af3c95517eaa8b143fc", - "tags": [ - [ - "e", - "69ddeaa2cbbf8954e8bfca9c58354512461de79691e0e57870b40cf13139aefa" - ], - [ - "p", - "e6ce6154325b54e69c9478c46cf1284e093f790e658b6a70f9df6eed275e3444" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690283168, - "id": "1edacc7f9f091e63b8cd59498b98cc28c997b4381a343efbe67b5f0010f594a4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0c20f045b2cf70e5479ae1fea72bd4f766eb3cf5bc62a544466d907c14f212fcac3af581d4440f4c2d99dcb98eadad206e05dfcecc984aa940a133226d2401ff", - "tags": [ - [ - "e", - "6c766ae83204902ae112190f418eafd35fc977f8b64367a13d7a526fc86bbd73" - ], - [ - "p", - "f5f98ba54045a2fa8df2a97c35fc30299b9e0d51a701795c040ca80cedaf39b4" - ] - ] - }, - { - "content": "I am also doing a local database for the app. That will allow us to delete most of the unused local cache. ", - "created_at": 1690283062, - "id": "3a7b49772ed9223c3d5ec1d0aafe05739aca6b4b0a87da760f78d820a678cfef", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "bc768ccf0a6525851f30cd453bf78d1d26658422f56d08ea216132d15b11b773ff30f7612a126f14e16cf03b29b8d34b487a6d59f51802a58ff834af27617a4e", - "tags": [ - [ - "e", - "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271", - "", - "root" - ] - ] - }, - { - "content": "It could be the live data as well. Live data runs on the main thread.vwe could switch to Flow objects, which are heavier, but don't switch to main and back all the time. ", - "created_at": 1690283001, - "id": "cfb933727089ceb7735f9c7794217338f354cdd67421ee4582bbd108b8b875a2", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9c5e74d3ddcdab7244866c27a71c54d78f82a95ddb74764a42a08a18c88299d9eae6c02627a68e8bd66ea867c3425aa4b6d2e272eef28e41883aa6b805b8372f", - "tags": [ - [ - "e", - "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271", - "", - "root" - ] - ] - }, - { - "content": "", - "created_at": 1690252421, - "id": "e17e96546af73ea49281aec14d8833cdc9a6c8758eb499eca64890d5e16dff1f", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "01e3edbdabf4d7612977af8de5afe3f8ee53c0fd63bc211f2b7cae0c9e04af11ef21449a260bb3945e16f6999c1975d87b6f8cd52e74284083a90716ee3814fd", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_902a3245d00d506efc193b25f25f32ee994c365bbd73a515.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "c8d8226166e4c54ed87aa1151229301230a0b9936ada748ce2b02a3a2fc28cbc" - ], - [ - "size", - "844802" - ] - ] - }, - { - "content": "Are you using the latest (10.7)? It's about memory. The app is using up to 1Gb of ram these days. ", - "created_at": 1690251933, - "id": "85094e157439a0ede8ba0354b9be60aabb4d952bc3baa5838c1049f1e1f62b7d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8c43251aeb9eba5bc6a265a8060eb24ac4e699661eec156e33c1cd48678c13442d15ed3f29fdf6d3395317892d11a854853e9529dc0eb4113fd1a23723dbde88", - "tags": [ - [ - "e", - "5778111b09d78ecec02c9b7f52feccd655b8fbb049c40c380c03eead049bf7ea", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "7a7cfab852cd457336ec2126c2bcd8b2c77d569054fae53009d1f4631bfa1448" - ] - ] - }, - { - "content": "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?iv=wDDS+Cbpqw1TX2BT52Qf9Q==", - "created_at": 1690251675, - "id": "fe6e8976ed1f8ae9906457bf5a0f7ce6c2382844872628aed2b1b66eeff79558", - "kind": 30000, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "238d972238ce203e5d6d6e4b6f9d7aa3f815027b0e9adae80ae64ea7d59e6b2df08f4707962303cb9a4eeb19030a468961dec44590892c2af4c7cc5a4b14007a", - "tags": [ - [ - "d", - "mute" - ] - ] - }, - { - "content": "", - "created_at": 1690251675, - "id": "8dc884509db4f009054d39c4fc6873245f6bbdfad7322f4dcce8f9668d1b4be1", - "kind": 1984, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f08f2ad807861b07ae6ca36048250889fa4bd88c5b0d767d6b62ccaabb48e602c5fb86a5cb58e759843abcf23755c99e3fe1709a1c1f86427e540ba684ae835f", - "tags": [ - [ - "p", - "2065474608976bb14e103389871a8a9d2c91ea1a71a49247228d8ed104afb068", - "nudity" - ] - ] - }, - { - "content": "Tell them to wear a contact lens.", - "created_at": 1690248352, - "id": "df011422245d4c13a97f589c45296cdc8e033f778f3ec62a79f1e601a6361796", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "73f25c2c5344fa80aa61af19e32c8675d44c7e9822fdc00b6998c6151aadb23e8ccb9e0c01d2178ebcc98d1c1061e7f520d6246a2c4906e524052d9a6f6f22be", - "tags": [ - [ - "e", - "2a6f72d18ce554ad81a90a552dc2d5e5e1799b3801139a299c567c20bbcaa615", - "", - "reply" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ] - ] - }, - { - "content": "", - "created_at": 1690246668, - "id": "2f7d62cd826a517f6153da75112d62bb4591bd7a9980632f11692653ee176fdd", - "kind": 1984, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "deccb7dd37b7d77db7712d8dfae4742274644bc443064c8c9237ad4d2663f8dda75d670faba06785bce2e4eab532aef3f3a2bae6d4e6d4b3fadf39addfecef50", - "tags": [ - [ - "e", - "db6e3abe953de42ee3e4499c298973d0c957f346e6a56ba9681d881a5a1c10b1", - "nudity" - ], - [ - "p", - "7b2dd801b71077284f0f64333a4a9e7c6a32699b68fec8776f86f90ab497109e", - "nudity" - ] - ] - }, - { - "content": "⚠️", - "created_at": 1690246668, - "id": "10ad1d3b9fae2dbb52b04eeef0ec80f3347f4675c5c2084f752f4eaaaabfe152", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "90be5cc5f4906d57ab629fcd285aa74b6e8bb5d10114e6c6b2f7daecb0b9b7335ac86f9390aa721a0cf3f5d997590a88d7f5c1b193a8e9956e526e80305164db", - "tags": [ - [ - "e", - "db6e3abe953de42ee3e4499c298973d0c957f346e6a56ba9681d881a5a1c10b1" - ], - [ - "p", - "7b2dd801b71077284f0f64333a4a9e7c6a32699b68fec8776f86f90ab497109e" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690244222, - "id": "111997ddef6b12be593cb96068e0d016be081d4a718c5cc2c618d9519f1fce57", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "23e2c107252140431c0c845c38f3cabed50113ab04149d100ff53b8f30f5fa8d991d3f0c59573114577c39d38bb0634dfaf89a5c802fa5304a28131a31de56e4", - "tags": [ - [ - "e", - "3621f31be0bd7c5980c3497fde8f6d1d170641084632a62178439871249ccca8" - ], - [ - "p", - "a85f28306f6739230c0b96483f33fc894058c1f7e2248647c61c7d475d3db7c7" - ] - ] - }, - { - "content": "I wonder if there is a crazy person out there to reuse our jetpack compose ui elements and build a desktop app with it. ", - "created_at": 1690244215, - "id": "bb42bc6543d54910a38cf2a213da81d4d13278d130208dd05e56b16e6a01fc3b", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "814a28dd2fed0807907b63426fe61517f9a18c10dfdad23481919455282e076436c2364b3d1802608e3da96772dba9636c77822b3acdffd3b12b37d8de21e573", - "tags": [ - [ - "e", - "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271", - "", - "root" - ] - ] - }, - { - "content": "Devs and designers welcome. ", - "created_at": 1690242675, - "id": "5885b2edaef4155e17df4e0dc7af9db4121165f0708652955c5d11957c871601", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "888aa55504da091f0d786e330df76b2c29d8349e034dd529aa583fbca266b46d6f163638b1c67384f3568f9406266a37d3b4eb8435e2ba09784914db0ede74b3", - "tags": [ - [ - "e", - "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271", - "", - "root" - ] - ] - }, - { - "content": "FbLT7gYTHET9t9YxQOCC5rVKnX4AgpL0uZscQbjdqdmyK/HpPN3ZFtq2AAUqatmOV7dg2oOIafZ2sTYFSqpnXw==?iv=hvlO/iOLcRyNPebLu91jLw==", - "created_at": 1690242653, - "id": "c2b2c99123f9509df30ad497d5c7497e3dabed7a1f478c015843e4bd8de8772c", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "add8ac7f7ad0ab40dcdd158c2fd33f66f2f0ef113a296ae372a98e997950af6c4027e666243abaab264c86e9a1291999edd152f9bb603131302721d8ba29acb5", - "tags": [ - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ] - ] - }, - { - "content": "ZYM8lrGBHNK4kHXEOVZzN74I1UfT64sIkxDRJWopfnVSr3oxREm2+QAH5JSCzL5kwwLWUMZFueIj9s8178zs2c4onTx7JDc6ByCZGhjbY/gvAo2yK23fChDGdHoQPzqX8p53KTM3a38XHA/sNEO7YvKsoYd94R1Q0UZgQiF7ivVb5QLDFgyTSQVfKiH/ca6I?iv=d2t4j8CP9B8pJ3/cfoT6MQ==", - "created_at": 1690242638, - "id": "3c8f1e613e96ab9dd7b35573dd938cf21877df1dded96de49e74456c39470002", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b6acf30bd79d64fe6056ea864f9e1132daf296626147df9afcd161a9406fd264c3f0106004894dc0f6310da30d76ae7a4804726b1d1d655ba193e008cbdabd06", - "tags": [ - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ] - ] - }, - { - "content": "+vCJukCAGqBNb4lXkeHcUbWo7Co8S3U/1hr8gbWdgx8=?iv=pYsP8v0FjaupHym497BEBw==", - "created_at": 1690242635, - "id": "6bd12d078b1579fb62f3a8bed7bbda20af983dbde9ee36844e11cff195c101b3", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "dd5c8aa6588d26c536d1dbccaf84e1208b18d411b2080c971a5af836e517a97ed20f44638dfe8d6ddc7760c33e95a37ae64da9dace0dac229ef79808564dc9ed", - "tags": [ - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ] - ] - }, - { - "content": "BRZoGneJdOYKd0brs+QhEg==?iv=SbDOAorgoLdzFI1CnvDJfQ==", - "created_at": 1690242630, - "id": "682b4eee106d4dce8e6dac8c736abc9f16762b47934c30b12447299b2cee5387", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1408fa4fc6271e0ed4b90de165db36850ca4d09f9ced27e35179e3360d8180731df2180e07b429f76e1ac977cf4ff981a5220e3fd5fc6bd77c72c20dbb039667", - "tags": [ - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ] - ] - }, - { - "content": "IEyJCe4nxKc3oD9jgM1oORxiGagpXRf+veHnumcq9jN/7Pv+xruUY9rxYmyMbRw3Vm6tgusfzyIeaegKjfzzb0GKOjwkJ0ATdJcbJG8hGWV+2pMbxvRAKVRjy+bI8dvlOVGrhqlF5N97o4jcaTkPbDsBrGXePHXsIJau6O0omYa4sMSH6IIEeO3LHU8Qhgsi?iv=uwKdPGDkXcjSbo54u4xX+Q==", - "created_at": 1690242609, - "id": "7ecc386b5026262c448a0266cbc9fdb0c86bf5894681e48bee04fdf410210bc0", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "87fe2a64db4728b2b7129590bfbb573303a6d825323438fd60d6a6f433a0722045ea04ef3cc8b0bfe36e4650a65875eb1e3d535bfda7b3905471d1a8ecce80e1", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Zzyg37FBq7HsOb9i4CqR0Q==?iv=I+N33Ubcnk2BOzO2wZiYww==", - "created_at": 1690242607, - "id": "dcf996c003eaae0bb47986c539d997bcfa04d4a7b6cea4dd2dbacdfa30fdce92", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c5846d1006c431459e88cb3e50b49697756155c0c54d4a7565005bc7f89acb93d43658322cd5cbc107781df72c768f472c3f47c9cedda26aaa8046cb644e85c4", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "4fH6cWjO2fRxNwnpk/WEfGQV2d4BrdX7ePzU+u0eJYEQ3oQfSND3qqn3L2gM1o9q?iv=Kf5/gUOJ2HKcG3EQbPSjfA==", - "created_at": 1690242606, - "id": "857e84d663936020a3c3dfbf418e7af5ce93fc64f370368694e5e1966e6de565", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "39d1bc609f8b11bfc0aae3f9e65f43de46bab94370a44e23439b12e56b647c79169b789a802bc552e7b70b2790a1194073ba1993e2a7e6494867cfaa720234bf", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "{\"about\":\"Channel for coders and designers to discuss Amethyst development. \",\"name\":\"Amethyst Devs\",\"picture\":\"https://nostr.build/i/7548146ede4c08de8be3e19ee3b2d1e7af90fbef12d2c247f54e8aa23cafe763.jpg\"}", - "created_at": 1690242586, - "id": "89b9c20216de8fa443e1e10d808befd8cd0569f53158796b45202c82e1659b02", - "kind": 41, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "341bb56ae426689fefc6b769d5bc2bd3597b7f84725327e59c775a79c0a5d774e42ebdb9af6562e829f280f5586cb545be4786606c7c9291edf65395ff3c290b", - "tags": [ - [ - "e", - "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271", - "", - "root" - ] - ] - }, - { - "content": "{\"about\":\"Channel for coders and designers to discuss Amethyst development. \",\"name\":\"Amethyst Devs\",\"picture\":\"https://nostr.build/i/7548146ede4c08de8be3e19ee3b2d1e7af90fbef12d2c247f54e8aa23cafe763\"}", - "created_at": 1690242548, - "id": "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271", - "kind": 40, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "edcea8f6515a80792fd9e28842a6ea8c4d0de17788f56c3045198242a6938f3a9d3fed5e24e5e58d516e94fe1041478a6b4074d7c10a887d3db84a6db7000011", - "tags": [] - }, - { - "content": "{\"wss://nostr.oxtr.dev/\":{\"read\":true,\"write\":true},\"wss://filter.nostr.wine/\":{\"read\":true,\"write\":true},\"wss://nos.lol/\":{\"read\":true,\"write\":true},\"wss://relay.damus.io/\":{\"read\":true,\"write\":true},\"wss://nostr.bitcoiner.social/\":{\"read\":true,\"write\":true},\"wss://nostr-pub.wellorder.net/\":{\"read\":true,\"write\":true},\"wss://no.str.cr/\":{\"read\":true,\"write\":true},\"wss://nostr.mom/\":{\"read\":true,\"write\":true},\"wss://relay.nostr.band/\":{\"read\":true,\"write\":false},\"wss://relay.nostr.bg/\":{\"read\":true,\"write\":true},\"wss://relay.nostriches.org/\":{\"read\":true,\"write\":true},\"wss://relay.orangepill.dev/\":{\"read\":true,\"write\":true},\"wss://relay.snort.social/\":{\"read\":true,\"write\":true},\"wss://relay.mostr.pub\":{\"read\":true,\"write\":true},\"wss://relay.nostrati.com/\":{\"read\":true,\"write\":true},\"wss://nostr.inosta.cc/\":{\"read\":true,\"write\":true},\"wss://atlas.nostr.land/\":{\"read\":true,\"write\":true}}", - "created_at": 1690242548, - "id": "4efe027b19cc54a8f4c1ab8cc9f89ae3d88b3d93cfde079d6c8d9804fd6d1ec2", - "kind": 3, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "94eb3d76bf5be95ddb2f88fb9b5130316c8da617a5be637de39d46a81276df5068fc313935b6dfb138a75e28a3c3787faabd9509d503d94770b14aca46ca67a0", - "tags": [ - [ - "p", - "d0a1ffb8761b974cec4a3be8cbcb2e96a7090dcf465ffeac839aa4ca20c9a59e" - ], - [ - "p", - "b7c1a5ef7ccf5cfd5976fba251116ed3f3ae3d3ed175a9ce5e3d33a890b4684b" - ], - [ - "p", - "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6" - ], - [ - "p", - "80482e60178c2ce996da6d67577f56a2b2c47ccb1c84c81f2b7960637cb71b78" - ], - [ - "p", - "bfc6af8244dc2859efdfd0e81a6a79f4ee395bc78acb3202b6f287a1ca3a27b3" - ], - [ - "p", - "b9b0bb9edc3ecf01389c570ea6f44c55a80b9db066d0bca8a22237af185252e6" - ], - [ - "p", - "5b29255d5eaaaeb577552bf0d11030376f477d19a009c5f5a80ddc73d49359f6" - ], - [ - "p", - "4d62dd5e6ac55ae2405940f59f6f030a994ec2b3ecc5556c8dc542cce20e46dd" - ], - [ - "p", - "e75692ec71174e698df1f3d1f5771855bcc4e6e568489d2eaad489d81064ace6" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2" - ], - [ - "p", - "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" - ], - [ - "p", - "8c0da4862130283ff9e67d889df264177a508974e2feb96de139804ea66d6168" - ], - [ - "p", - "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9" - ], - [ - "p", - "35d26e4690cbe1a898af61cc3515661eb5fa763b57bd0b42e45099c8b32fd50f" - ], - [ - "p", - "46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184b16bd8ce4d" - ], - [ - "p", - "52b4a076bcbbbdc3a1aefa3735816cf74993b1b8db202b01c883c58be7fad8bd" - ], - [ - "p", - "3235036bd0957dfb27ccda02d452d7c763be40c91a1ac082ba6983b25238388c" - ], - [ - "p", - "d987084c48390a290f5d2a34603ae64f55137d9b4affced8c0eae030eb222a25" - ], - [ - "p", - "472f440f29ef996e92a186b8d320ff180c855903882e59d50de1b8bd5669301e" - ], - [ - "p", - "e9c0a9c12e3a04edd79afc77d89b6c6413cc942ef9e61c51e51283cbe9db0c8f" - ], - [ - "p", - "b17c59874dc05d7f6ec975bce04770c8b7fa9d37f3ad0096fdb76c9385d68928" - ], - [ - "p", - "e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411" - ], - [ - "p", - "ad46db12ee250a108756ab4f0f3007b04d7e699f45eac3ab696077296219d207" - ], - [ - "p", - "1b11ed41e815234599a52050a6a40c79bdd3bfa3d65e5d4a2c8d626698835d6d" - ], - [ - "p", - "85080d3bad70ccdcd7f74c29a44f55bb85cbcd3dd0cbb957da1d215bdb931204" - ], - [ - "p", - "f728d9e6e7048358e70930f5ca64b097770d989ccd86854fe618eda9c8a38106" - ], - [ - "p", - "83e818dfbeccea56b0f551576b3fd39a7a50e1d8159343500368fa085ccd964b" - ], - [ - "p", - "50d94fc2d8580c682b071a542f8b1e31a200b0508bab95a33bef0855df281d63" - ], - [ - "p", - "c2622c916d9b90e10a81b2ba67b19bdfc5d6be26c25756d1f990d3785ce1361b" - ], - [ - "p", - "eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f" - ], - [ - "p", - "00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "19fefd7f39c96d2ff76f87f7627ae79145bc971d8ab23205005939a5a913bc2f" - ], - [ - "p", - "090254801a7e8e5085b02e711622f0dfa1a85503493af246aa42af08f5e4d2df" - ], - [ - "p", - "58c741aa630c2da35a56a77c1d05381908bd10504fdd2d8b43f725efa6d23196" - ], - [ - "p", - "e41e883f1ef62485a074c1a1fa1d0a092a5d678ad49bedc2f955ab5e305ba94e" - ], - [ - "p", - "84dee6e676e5bb67b4ad4e042cf70cbd8681155db535942fcc6a0533858a7240" - ], - [ - "p", - "645681b9d067b1a362c4bee8ddff987d2466d49905c26cb8fec5e6fb73af5c84" - ], - [ - "p", - "e9e4276490374a0daf7759fd5f475deff6ffb9b0fc5fa98c902b5f4b2fe3bba2" - ], - [ - "p", - "d12feb34b3ee120423b818cd8dda47000639bbec9a6ee6d3317ea886ec5b084f" - ], - [ - "p", - "bf2376e17ba4ec269d10fcc996a4746b451152be9031fa48e74553dde5526bce" - ], - [ - "p", - "1577e4599dd10c863498fe3c20bd82aafaf829a595ce83c5cf8ac3463531b09b" - ], - [ - "p", - "703e26b4f8bc0fa57f99d815dbb75b086012acc24fc557befa310f5aa08d1898" - ], - [ - "p", - "6e1534f56fc9e937e06237c8ba4b5662bcacc4e1a3cfab9c16d89390bec4fca3" - ], - [ - "p", - "4523be58d395b1b196a9b8c82b038b6895cb02b683d0c253a955068dba1facd0" - ], - [ - "p", - "148d1366a5e4672b1321adf00321778f86a2371a4bdbe99133f28df0b3d32fa1" - ], - [ - "p", - "b8e6bf46e109314616fe24e6c7e265791a5f2f4ec95ae8aa15d7107ad250dc63" - ], - [ - "p", - "c73e75dba8adce307479d65575019ef5bee4dc8042dceeded3350ff89e9909f2" - ], - [ - "p", - "ea2e3c814d08a378f8a5b8faecb2884d05855975c5ca4b5c25e2d6f936286f14" - ], - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805" - ], - [ - "p", - "2b1964b885de3fcbb33777874d06b05c254fecd561511622ce86e3d1851949fa" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ], - [ - "p", - "9b0247ea14361a453ea9d77f9fdabc858fac10063424ce0bb3aa560237ededcb" - ], - [ - "p", - "7d95baf9ac8486d06798348e580a944e2110740e88586af731dffebfc1301e68" - ], - [ - "p", - "c7dccba4fe4426a7b1ea239a5637ba40fab9862c8c86b3330fe65e9f667435f6" - ], - [ - "p", - "aef0d6b212827f3ba1de6189613e6d4824f181f567b1205273c16895fdaf0b23" - ], - [ - "p", - "1a1a7ff211f3762d6a5a849e3d29d288fd43b618423c9d030ae7d64b951ea183" - ], - [ - "p", - "546879d1ef626692ca8a54f9943e9629197b97c58ea1b4a3abd6ff968b280d09" - ], - [ - "p", - "2779f3d9f42c7dee17f0e6bcdcf89a8f9d592d19e3b1bbd27ef1cffd1a7f98d1" - ], - [ - "p", - "fdd5e8f6ae0db817be0b71da20498c1806968d8a6459559c249f322fa73464a7" - ], - [ - "p", - "08b80da85ba68ac031885ea555ab42bb42231fde9b690bbd0f48c128dfbf8009" - ], - [ - "p", - "34d2f5274f1958fcd2cb2463dabeaddf8a21f84ace4241da888023bf05cc8095" - ], - [ - "p", - "597b42de56a9e0c19ee2d0cde5797dd58d48ce8dd25c732b4c873af11161f9fd" - ], - [ - "p", - "74dcec31fd3b8cfd960bc5a35ecbeeb8b9cee8eb81f6e8da4c8067553709248d" - ], - [ - "p", - "0000006a13e10fb648049b5e78632a0c2bf09eaf6a9d55d081b82baf86c951be" - ], - [ - "p", - "9c612f8b770f0e3fd35cdac2bc57fcee8561e560504ea25c8b9eff8e03512b3e" - ], - [ - "p", - "4657dfe8965be8980a93072bcfb5e59a65124406db0f819215ee78ba47934b3e" - ], - [ - "p", - "1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ], - [ - "p", - "d0debf9fb12def81f43d7c69429bb784812ac1e4d2d53a202db6aac7ea4b466c" - ], - [ - "p", - "6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93" - ], - [ - "p", - "246716c303cb0df99b45eba30ff058e506bedd4193957df34ba61fb1929dc73a" - ], - [ - "p", - "c5d4815c26e18e2c178133004a6ddba9a96a5f7af795a3ab606d11aa1055146a" - ], - [ - "p", - "df4cafee85f79769545851db202a8856f82dc917548093c760f3094896e987b2" - ], - [ - "p", - "7e2cb3b6793ffb7b38cecb1664c47f6216b4abec00c18a8d1eb9f6dbc0da1e02" - ], - [ - "p", - "dbf3d7c79a92995ccfb135997ac1612f41637c8a805be393204b3d1c2769d127" - ], - [ - "p", - "dd81a8bacbab0b5c3007d1672fb8301383b4e9583d431835985057223eb298a5" - ], - [ - "p", - "330fb1431ff9d8c250706bbcdc016d5495a3f744e047a408173e92ae7ee42dac" - ], - [ - "p", - "b945e8537bfd2ca3d36acc393e6ce948ad08471a44e5bc2f7eb1409cf5046619" - ], - [ - "p", - "8c3b267e9db6b0115498cc3efcd187d1474864940ae8ff977826b9d83d205877" - ], - [ - "p", - "aa9047325603dacd4f8142093567973566de3b1e20a89557b728c3be4c6a844b" - ], - [ - "p", - "25a2192dcf34c3be326988b5c9f942aa96789899d15b59412602854a8723e9e8" - ], - [ - "p", - "c7d32972e398d4d20cd69b1a8451956cc14a2e9065ad1a8fda185c202698937b" - ], - [ - "p", - "045681cf8d47413904ff6429753e6d5a41e05e8d9d50dbd4ec0125380d886f3b" - ], - [ - "p", - "da0cc82154bdf4ce8bf417eaa2d2fa99aa65c96c77867d6656fccdbf8e781b18" - ], - [ - "p", - "9fec72d579baaa772af9e71e638b529215721ace6e0f8320725ecbf9f77f85b1" - ], - [ - "p", - "489ac583fc30cfbee0095dd736ec46468faa8b187e311fda6269c4e18284ed0c" - ], - [ - "p", - "6f32dddf2d54f2c5e64e1570abcb9c7a05e8041bac0ee9f4235f694fccb68b5d" - ], - [ - "p", - "62cef883863022a4f1d60d54857c9d729650702c9fe227b0988c0b6e36c4bcce" - ], - [ - "p", - "eaf27aa104833bcd16f671488b01d65f6da30163b5848aea99677cc947dd00aa" - ], - [ - "p", - "4c8b51820cb56aef2462213fe6927ebb6efda2b94450db5ff8c0b38eec020d89" - ], - [ - "p", - "57c4ec915796158cbe0b7763f6dd0fadcb17495a8fd8db8d27f0122116504232" - ], - [ - "p", - "6e0f5f69570cc2f2565864b0872cfff43219a0b1946e8d46e9d9de1beacb3ab2" - ], - [ - "p", - "58ead82fa15b550094f7f5fe4804e0fe75b779dbef2e9b20511eccd69e6d08f9" - ], - [ - "p", - "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - ], - [ - "p", - "933d97b01272a03d281deaec23d446a3f9c72c8dee83e30081f0db191c7e20e7" - ], - [ - "p", - "b7ed68b062de6b4a12e51fd5285c1e1e0ed0e5128cda93ab11b4150b55ed32fc" - ], - [ - "p", - "8cef25eebe711364a06f2e61251cb3361d05cc75283606bc52d74f674ca0295c" - ], - [ - "p", - "c1fc7771f5fa418fd3ac49221a18f19b42ccb7a663da8f04cbbf6c08c80d20b1" - ], - [ - "p", - "de7ecd1e2976a6adb2ffa5f4db81a7d812c8bb6698aa00dcf1e76adb55efd645" - ], - [ - "p", - "3d842afecd5e293f28b6627933704a3fb8ce153aa91d790ab11f6a752d44a42d" - ], - [ - "p", - "3356de61b39647931ce8b2140b2bab837e0810c0ef515bbe92de0248040b8bdd" - ], - [ - "p", - "7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194" - ], - [ - "p", - "d61f3bc5b3eb4400efdae6169a5c17cabf3246b514361de939ce4a1a0da6ef4a" - ], - [ - "p", - "ff27d01cb1e56fb58580306c7ba76bb037bf211c5b573c56e4e70ca858755af0" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b9003833fabff271d0782e030be61b7ec38ce7d45a1b9a869fbdb34b9e2d2000" - ], - [ - "p", - "958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c" - ], - [ - "p", - "520830c334a3f79f88cac934580d26f91a7832c6b21fb9625690ea2ed81b5626" - ], - [ - "p", - "07ecf9838136fe430fac43fa0860dbc62a0aac0729c5a33df1192ce75e330c9f" - ], - [ - "p", - "b154080cb49639bb079a6a53c1d98e7130eeab3c61aa95dd9e38f9e400027cc7" - ], - [ - "p", - "deba271e547767bd6d8eec75eece5615db317a03b07f459134b03e7236005655" - ], - [ - "p", - "e6a92d8b6c20426f78bba8510ccdc73df5122814a3bac1d553adebac67a92b27" - ], - [ - "p", - "bb1cf5250435ff475cd8b32acb23e3ee7bbe8fc38f6951704b4798513947672c" - ], - [ - "p", - "af9d70407464247d19fd243cf1bee81e6df1e639217dc66366bf37aa42d05d35" - ], - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ], - [ - "p", - "7cb13cde0670e590f02cbe9ea0fcf1e05edbc5cc8a409731fa5436440181cf1d" - ], - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ], - [ - "p", - "ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49" - ], - [ - "p", - "facdaf1ce758bdf04cdf1a1fa32a3564a608d4abc2481a286ffc178f86953ef0" - ], - [ - "p", - "5b0e8da6fdfba663038690b37d216d8345a623cc33e111afd0f738ed7792bc54" - ], - [ - "p", - "17538dc2a62769d09443f18c37cbe358fab5bbf981173542aa7c5ff171ed77c4" - ], - [ - "p", - "1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef" - ], - [ - "p", - "e5308b9c04ec5cc2bae04b5a70a7da79b28501a0676c243375813eb0cf8f4c08" - ], - [ - "p", - "9b99745fa17b337f8a6857f4369a4e844f914bd739c41bfeb939eb0930d41d7b" - ], - [ - "p", - "e5272de914bd301755c439b88e6959a43c9d2664831f093c51e9c799a16a102f" - ], - [ - "p", - "9989500413fb756d8437912cc32be0730dbe1bfc6b5d2eef759e1456c239f905" - ], - [ - "p", - "e7764a227c12ac1ef2db79ae180392c90903b2cec1e37f5c1a4afed38117185e" - ], - [ - "p", - "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a" - ], - [ - "p", - "7f5c2b4e48a0e9feca63a46b13cdb82489f4020398d60a2070a968caa818d75d" - ], - [ - "p", - "1989034e56b8f606c724f45a12ce84a11841621aaf7182a1f6564380b9c4276b" - ], - [ - "p", - "76c71aae3a491f1d9eec47cba17e229cda4113a0bbb6e6ae1776d7643e29cafa" - ], - [ - "p", - "e1ff3bfdd4e40315959b08b4fcc8245eaa514637e1d4ec2ae166b743341be1af" - ], - [ - "p", - "3d2e51508699f98f0f2bdbe7a45b673c687fe6420f466dc296d90b908d51d594" - ], - [ - "p", - "1539b0762732585a92290b32355aee503a3532959657f554b12caa979097421a" - ], - [ - "e", - "42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5" - ], - [ - "e", - "25e5c82273a271cb1a840d0060391a0bf4965cafeb029d5ab55350b418953fbb" - ], - [ - "a", - "34550:f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0:Art" - ], - [ - "a", - "34550:3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24:android" - ], - [ - "t", - "Amethyst" - ], - [ - "e", - "e89d7c2b4e1aa72e41979b5b1acf5dc4aceeaa97d0c40aaeebcde5cd4ff56271" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690242409, - "id": "0e184dda2b69d84cb2e0ae4ee2db7fc936ca33345f2899dea56bed3707161a06", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ad4e6c68c56053aa6c7bf62e379fab9a8bc5379fcb9cd413a32e4ccaae77a4b09b6747588006dc386a091fdc991ba84faae7e7362027f3173511f9c7f3766372", - "tags": [ - [ - "e", - "c37445ad00b5628b11bf4cf91e318f5372ac977d73778e8ee17613d5e357c98d" - ], - [ - "p", - "d2704392769c20d67a153fa77a8557ab071ef27aafc29cf6b46faf582e0595f2" - ] - ] - }, - { - "content": "Check version 10.7. it's using less memory. ", - "created_at": 1690242311, - "id": "7afe29b6be3eab6b18c38ba80db6b2e3e0154c5d62c7d10b96b4a73ae4e543c3", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0cd914ffb217298fd679625ea29319e953a09006bf542270817d563dd294f9eddd432f03e0b702d6ff4664c0110f3c5505b3c07fe7f8a4b1eb5dd283d0a900d9", - "tags": [ - [ - "e", - "df9b11fd6029e3b4c27bfb5cb59aa152442a03d57bc5b759684263864ae729af", - "", - "root" - ], - [ - "e", - "3e646fa6294a2a87e6ccd619c39a50974d6c70216eae79d700bca6c46179a389" - ], - [ - "e", - "f469473308fa5e222d3e5358bdd2eaf6b1c4c135f4ab4bf60dd6cd1c8ebfa7e2" - ], - [ - "e", - "649c1cf41e4c73a75604829b09a3a9f7042a685eaeb747a0158e2c70a6f39cd4", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "43d140f61e46792199dea8a8ab4634dd21f1aedaaa4fbd29add506f8029f1265" - ] - ] - }, - { - "content": "Does your strfry relay implement NIP 50, search? We really need more adoption of search. ", - "created_at": 1690241996, - "id": "0369c6437dcb238de1a62e0dc40432c0c3218774515b85bdde00a33921beac5b", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5f4c9d0efb7f470ef3900e7b4082bb447276b8e33d89b64aecfc6f5580dbd0bc5246fba629504b0cd8f7cdaa1b6d0ed1ffd1ae2d528f101c34b4403942d95541", - "tags": [ - [ - "e", - "296e0cd484e6d03d7e316cf0fb7dee81c159fe09ff9497165f3eaef60b8515d3", - "", - "reply" - ], - [ - "p", - "d2704392769c20d67a153fa77a8557ab071ef27aafc29cf6b46faf582e0595f2" - ] - ] - }, - { - "content": "yWAWxGt2MBu3qv1x45J3CEVpaHvQq1lV7E1BuNGgbLKZ2RYbrC2mNJcmG4TRup0s?iv=sndyUVWm/4nas9Os4pF9Og==", - "created_at": 1690239415, - "id": "257c1c59ed183315bc7e62b01e6bf4c6f60ebd849b410113f235cd332438009d", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "53496c038f4f10700b95c8c665a637522c417bf560624e5ccb814c2d4f36e5f8c7862d70fa3a7c5baf9ec6f38108a327a3966a9f927890c0cb3764df125ed850", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "7PIEPW2iCjCHl16lfM4WwnzZVxdZmAQKwu6iXqRlUQUOs5mTn0CrgPwRUw/kyfRJ?iv=2aJX1EIfi/f0hT+pcBHvrw==", - "created_at": 1690239404, - "id": "222a45a2ff03a0323452d28f264c454c2cc776d0f447c6a3d1cc8a3851d7856d", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "99eb19b3d3548c6e91497aae7c8df7c467e1959c958be85336b6b16e50df644cfad4860c872eeb6fecaf3c816dc4c2961da9944f65b398f4aa8cb0e1c30b99fe", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Play has Google's in-device translations and integrates with Google for the Push notification system. \n\nThe FDroid version does not offer translations or notifications. ", - "created_at": 1690239264, - "id": "4a3236c13d92cc3cae2017b186a114d1bea42452ec0da1d7f7b6c37d691cc5be", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1c820adbaa8f6005e262c05843ae9360928a33f90e313589c98f5818420ac458e49ea1ba1695b3919555e849b949cdd35d4e13889143bf9f5afd0ea16315d601", - "tags": [ - [ - "e", - "19c3f76a4283f23d1f9f422eb114864ff4ccc56d47c6f6e4f8c10d6198bcedce", - "", - "reply" - ], - [ - "p", - "a85f28306f6739230c0b96483f33fc894058c1f7e2248647c61c7d475d3db7c7" - ] - ] - }, - { - "content": "lutGFIB1gMuvUV+eCwKXKNYL7z6TIm2kDAlbYQVPx2GQ38X02lKyoY1n2hFkfEnUPkVhuXzDpduaxSXtvPkyhOPgWksP7H6jeOicnK9hppM=?iv=HME/2DSrRY30pbrUFJKFlg==", - "created_at": 1690238899, - "id": "39b67b4dbc474ea200d367c0c9a61556fa34b6867479ed4fb577f8461611a2eb", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0bd1227154260816c06eee5008a7c9218032b827c2f6d4be9e3428e63b8735f47afce8c5fa6fa4c6c9df572385010dcf5c405a89ebf1776312ff6fbb2d7e4329", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "2/8yfvCiP34LktEny5ATUg==?iv=UmruzcdgxrWaGP0yiKeb8A==", - "created_at": 1690237129, - "id": "b73fd5a3c23b46473847cd3a4b4ce0f1f97d5dc774ad9ace37a99386f84298a4", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2af9b7d79b24f5b53a916f1afe8b56ce9f9370e326b28d5dfdf5120bc0ef325576eb48efb4d108b33f8752effff8331329d704539a616afcc4131d8d33206547", - "tags": [ - [ - "p", - "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a" - ] - ] - }, - { - "content": "Q9dvA4/+KObTdjEDP0rnDA==?iv=xiQVTdvQrHxPo/72WBkT8g==", - "created_at": 1690237059, - "id": "8d9ae6ec863f8e8825b8ef87444cf994127f3f48a379b50ca2a3400cb6c7610a", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9769552001ddc7666d756297d8de7654e202af09fe0e6f2a633affd452abfc04357fe1a6e4a9e265b27c2873a5ef385fef305866bb0c9dd135f775a407b75c67", - "tags": [ - [ - "p", - "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a" - ] - ] - }, - { - "content": "C+LkAFAhExz9RWkcHhP3Eg==?iv=skqU97xEJJAVJfodGfTJlw==", - "created_at": 1690237054, - "id": "a438e87973913596c44ef1fcc3476217af9151c1eb924bcdd2cbc209b0a5746a", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7202d13005954592606d39208c59cc172e870ab5734b17bc3bbf6c46116e1e184cfd524ef76be0d48cead9efb408686080aa758fbc3fe456c02d82c39d1d3dc1", - "tags": [ - [ - "p", - "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a" - ] - ] - }, - { - "content": "bUp6adO8XbYh3Sr1zpH0Tw==?iv=NFUyntsKUNXwb1GCVHrkGA==", - "created_at": 1690237016, - "id": "9f231718910c64f0fd5815ddba10b6f86bacbb554f47e02e66c91527de9a84ff", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8e0a14112190e4dad8552470767e464275b8eb66171a46075aac39601b0b814c0fa64d54ddc24adedca85f6a270b8f69c332f7d4e898b1e136043151d432777e", - "tags": [ - [ - "p", - "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a" - ] - ] - }, - { - "content": "You would write a message and the message would not be able to be decrypted. Message would be lost. ", - "created_at": 1690234459, - "id": "ce6fb302782f0ada5c5b3ffec15a906b81ce681a8ff0bd6eda7ddf5b8a688538", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c62e0d9fbe9cf9d901d50be9a06ba57ad45b12e2de3c11477d71966a402d1e93dcf0c9a06c8b2635ec1445581d3823853a1a9edf60a57a2165532a60965830bf", - "tags": [ - [ - "e", - "025bdab0900f6c0bf2036713aca293e43a743e17108134b82816d2adab53fcb2", - "", - "root" - ], - [ - "e", - "bc4b1cf5a43e096cb581ef42dcf175781b767dad580f4451d61538ef4646c71e" - ], - [ - "e", - "3f1570f86b94170334e666d69d136a2181c3794a15cdb31c64ca2083ac3e653f", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "9110fe860a5e40a41e03d52d306a7b337ecf32d1090812ceaf423ec9b94954c8" - ] - ] - }, - { - "content": "I used android's base64.encode instead of base64.encodeToString function. ", - "created_at": 1690233995, - "id": "bc4b1cf5a43e096cb581ef42dcf175781b767dad580f4451d61538ef4646c71e", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f84634af97f84d1367c715079323912aa1c4e95c075d18891ed5fd26f347fa2c406722be048abc1f3c72a86ea8de970b4afad2ef83752d52eb406729b9a01ea2", - "tags": [ - [ - "e", - "025bdab0900f6c0bf2036713aca293e43a743e17108134b82816d2adab53fcb2", - "", - "root" - ], - [ - "e", - "d86189ed8e68f18a3c2578f30a2c210cc38aef8e2acea0d6161e2db4a83994d9", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "9110fe860a5e40a41e03d52d306a7b337ecf32d1090812ceaf423ec9b94954c8" - ], - [ - "r", - "base64.encode" - ], - [ - "r", - "base64.encodeToString" - ] - ] - }, - { - "content": "Qz4ewQ+n1+swMl4fTB6D5A==?iv=bP1lZMkZaTb+/TvOpcaYOQ==", - "created_at": 1690233455, - "id": "2b9a446fa07a6f76ab0efd6320f86f45c3724a75c1a7127f479a5772c10ec0d8", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "66a171a9de4a483d2f5503eeb559e6c788e14a4e0022e94cf6ac37e1edbe06c291814944b1843a4c9baeb8010c696cecc0076190b22790bbd076e209bd4beb18", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "GFHPMUZu/xt52Emyqe2/yOgPgRyeWFlJrL+1Y0qZu7WZj62+TMnyYzbSh45Er8qiu5HMTd3NBQDGdb7fcpqCvbqYIM9i+GZTaUGLxK4kN0IEx3uToJBURlAsvXQkoBZB3r4hx0nxYpMMvZ6vF0G14A==?iv=HoxnNfugsgE7IR3UsrlW5g==", - "created_at": 1690233445, - "id": "78bad12a81ae89278fe090f75f91c59f179366c7cb2e8f137af78500b69500bb", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "89ffa0617d9dd878a893848d3d2d4a891178d9785cd5b66d1c1b94d5ee1959638224ef5b3ca8a6fdf7fb3d3dd9f802f9c358e513a325abfeaa537ffe6e5e96d6", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "VxwuKCcgYzAgWi2niqNgp5PDat8/kgR5kgj6os7tBTKDJT3/gOqedH8twDrv64BZMZ3LvtdZGlQzLIcgNE7CAg==?iv=o0QVnuaCOW9yrN67IvWZCQ==", - "created_at": 1690233329, - "id": "fa22a5e06437a59b12babf7ca2f213817137741062424da50bab867f668da877", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6b40692264d9b0aac45d8272c44a4bd07bf3623ce9993bf3074892b3c284e90353b4d022ded1537bf4023ec162cdd259fe023a19dab7195504ede33fe2f255a0", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": ":inky:", - "created_at": 1690233253, - "id": "d41516e423d2b7c3f4333c574f4120bc16ff6a820e42e2b946a389269a87267b", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "891aadb039c5e1e887f3c689e274d9b17710d085bebf71e61695020d74ed6950ef65699e7a0477e463b457b2784edfd85047a22d12207c5a60978c5f0e386eff", - "tags": [ - [ - "e", - "7d48910e219b9145d0dc6728032f393dd6ab4fc7cbaa1f230eb0e70b6a88cc44" - ], - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ], - [ - "emoji", - "inky", - "https://yunginter.net/e/invader/inky.png" - ] - ] - }, - { - "content": "gP4BTdaw8HAFyHiTD1l16g==?iv=AsRwobD8FAWgbZI+GS24ow==", - "created_at": 1690233247, - "id": "25fa7b6874d69b4674b5b835bf6e5557d51abe7df38e7f6da991c2179abe7135", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "48ebba404b944c20cb201323d7a729a6482895ae0d05284d752f6d8b22368aca598cd931173cd34b5c31a1182380bf6e33df572608ec32b92720170ff9968609", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "S/toRHn+x4imuEgpE3QBog==?iv=FcftlhIXXfoW8Jt8IAWWfA==", - "created_at": 1690233237, - "id": "a98032bead45c8a3129451dded37a1eac6e01da6504903c93fa0a1b62d59247e", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "4e556f453e9de83f83ef00f4370189735df123e41226f8a33c9927b02739aa5c9a3b2dce93e5cbd698a28192acf77dc80a47f0be880201cc5e50a6ddc80ea80c", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "not really, the F-Droid version does not have any Google framework, so it does not support Notifications and automatic translations. ", - "created_at": 1690233206, - "id": "9c597be469ced87df16e5085a19810af53ad36c5cd6b2d1f0bdbac24b4775e77", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a368541efa152d50641999646842fb571dac8a24b754e71023cb30d33d89d94b87098c408a3a2b8e68521a13a771942d919f1e9fc5e2894c26181333213ae97a", - "tags": [ - [ - "e", - "025bdab0900f6c0bf2036713aca293e43a743e17108134b82816d2adab53fcb2", - "", - "root" - ], - [ - "e", - "3f3832ea69dde0c130aa13be5e9461a48548322be88f9980d68f5bfc0585c4b1", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "a85f28306f6739230c0b96483f33fc894058c1f7e2248647c61c7d475d3db7c7" - ], - [ - "p", - "a85f28306f6739230c0b96483f33fc894058c1f7e2248647c61c7d475d3db7c7" - ] - ] - }, - { - "content": "KdASbRnhHUXkBGGr6cZluHyz26/QGGb37ud5Mi0PXXrfNaqv8SJFDbM0SsspYGfkphxbkm+OBtqQ/uCOT+Kfv6yebKDzZc1OFFqtLFQ6FhnoB3RdB2zlzx5YLeBm2+zi?iv=pFCz97lTnwgdru7KL9vVNg==", - "created_at": 1690233173, - "id": "d4f4bf086674bbc8654ef1cf38d548e067a68fb7988c530c2f5435906c063c35", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6743508bccfdfda8fce6e04e22b39f66ad2a7e80dc884a96b6a5e8e74c3fa31ec3332c6544840816ca43caf2e0ae8aa4f7808c26d788f3943931f99eb7fe0416", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "f2K+pgicmByWLG1+7gJo1+gHYNOWUMZ+JtDF32q/JYI=?iv=2Pq0gyLVHIi8Z74r49cG0A==", - "created_at": 1690233137, - "id": "e4b88e84fcb8678183bce2e37d1cac638f752e07dd8c94a74729f65862de4616", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d61dd8721786c9969e0359a926f736a4fec4a7608c158aaef480fc4326a54541299ab3ef901613498829e7e4701851e43ef454dde8502fa42e2c955cc56c5bc4", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "bz+BVeVRvzE8GMyhbckpyg==?iv=i7V1ONc6Sfrao9ADzYJ0TQ==", - "created_at": 1690233110, - "id": "9c5fbe5cdac9797ad05de2ed9db76a5dcb04bb95bedbce1d46247007bf4c3d68", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "293198a3b3a0c3d9ca30e84b4f03d39e3eb2536e02c91572b41e55c6680d775ba611f1bbf0bde379ebe774f1a752716196ffe4a13c1818f0b5f702f209ba0651", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "+", - "created_at": 1690233094, - "id": "eab230246fad596b82ed49e50eb6c4ca97ad39a63f1170e7b3c630079076b294", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "771b470b3aae05e08353b4259c3b4c0e339dd257759f2ea3b75518237c775b3f15be3d5c188cdc72b78dd666e5e2c0d7a96681973ae7d92c531c2c217c418677", - "tags": [ - [ - "e", - "8e39d79d31dd146b5be3e2cd8fbc54dc7c0e8ddf1936e982cf223ac21045aefd" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ] - ] - }, - { - "content": "0.70.7 if you can use the APK. Otherwise, just wait from the PlayStore/Fdroid/Obtainium. ", - "created_at": 1690232704, - "id": "b6244ed1c0c63352a8df29cb1a689cf8d920681aa29d5b19d6cfb8d43f5b3724", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d2abc85bacebcb5da5ec1c8fd88fcbfcbbf789a6d53afa7d9f3f95ba377a4aa940dcfb4e6286c2eb56cee6bce2a975f2b24a6b7dbcf14fe0c884c7f1fdbbed7b", - "tags": [ - [ - "e", - "025bdab0900f6c0bf2036713aca293e43a743e17108134b82816d2adab53fcb2", - "", - "root" - ], - [ - "e", - "3dd05c239b3eead3467fc3966010c9236722c0dde65a2fef32701ceca6845255", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "a85f28306f6739230c0b96483f33fc894058c1f7e2248647c61c7d475d3db7c7" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690232541, - "id": "98450fc53c6bf56129545c1cfd1710eee3c337381171e996a7c2d827ea1f550d", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f0a92f7211f3806a685412084ca06a8d62605780d509f3f2f1846e2d08c1a19fd2809672a71081839b2d46d8cb9d976a2e3e1437336bc14ab616189b624410af", - "tags": [ - [ - "e", - "0916d8bb10357ef41e467ca5df22f1a5972848b6e37e53deaf776498eb9930e1" - ], - [ - "p", - "444eaf65c2d35511fd0dbdbb0fe3c74139fcd144de00d22d57819ae5fdc76ae8" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690232403, - "id": "f698c1f427edd31e0e568f9799545b441e4d9ba1fd1ae7283eee93ea5b921245", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3f1345b5bea6f2ffe95c042a79e9fbc50cb81cd55e52a822090f465e06bf0e09eba273786a6c6081297e6a82b85d081438621c05ccb76a6c27ba1fd846143fde", - "tags": [ - [ - "e", - "05844e361974d2f429b58f3121098397c14efcf6b5f01cf12792d406c9d94da2" - ], - [ - "p", - "7ab1d3867722b4cbabb6c8503ab3f9265daa4f82e228cefe302621f4e5ee1f1c" - ] - ] - }, - { - "content": "### #Amethyst v0.70.7: Coding is hard. \n\n- Bug fix for the DM encrypting bug\n- Bug fix for the back button going back in the stack instead of leaving the app\n\nDownload:\n- [Play Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.7/amethyst-googleplay-universal-v0.70.7.apk)\n- [F-Droid Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.7/amethyst-fdroid-universal-v0.70.7.apk)", - "created_at": 1690232204, - "id": "025bdab0900f6c0bf2036713aca293e43a743e17108134b82816d2adab53fcb2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8bacaafc49225c0eef14edbafa84cc784973437975f44228742e91293f1c21b413ffb83324a91ab64400193c5765d3bd7d72478b40b912a810303e41941916a1", - "tags": [ - [ - "t", - "amethyst" - ] - ] - }, - { - "content": "A/e5KObtOus9SzOgkNcHMlfQgCLHcWdCivaz3lfPoygriVTNoNDuO1XudVbM7ZY5ChnivB4u6Gj2odhYVTT7hg==?iv=SxkaG4il8/q4Zn2uTtmiDg==", - "created_at": 1690231960, - "id": "fb28220996d832bdf65a884c43c3e0fa1887225543313e7c223af1e18a3863dc", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5a54e12b362c66c3a4a4234d15c5f2a2f988a1786af4c5e171f86eed16a44ba327c80ea43f65c68a80aca17354be9df3a45fe00be09df3180d701164ebe725a9", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "1nx3MjyOTjE9i+BNK/hEZc4/b79lFMz08xElOLD7ogY=?iv=hwTj8iR7LfwqoHtLz3NZmg==", - "created_at": 1690231858, - "id": "f24bc09b4f67ac27baac41681704a97a450895223c2a3a1d2df7d95d28e91261", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "021cc84269b26c4e73ca5614030b49f18bfc58e65a92c3cfec8003d0210a327dd87479d91fe2e470e826368a1103eb05af1c018daca2fb96e2a316c2ef04a317", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "+", - "created_at": 1690231061, - "id": "30c908f6de4b1540adc20dd9ee8c54f954806753041c4e09f1a45475317ae2b4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f4121d7b80ff896340a85fcbf0812b78a7b0bd41d184bedc20d4cc3adeb57068fadc4feb615b25a42288d2ad34c7360de53d67440ca3db8b918091e527175be5", - "tags": [ - [ - "e", - "806bf35434fe8274e3e903ddc2bcbd761edc4cbd895e2a184bd879519b22578a" - ], - [ - "p", - "f1ea91eeab7988ed00e3253d5d50c66837433995348d7d97f968a0ceb81e0929" - ] - ] - }, - { - "content": "Lvf0zVwlwHUtikVDSv1RXA==?iv=uVw4/+FGz10yZRjdp45HCw==", - "created_at": 1690230486, - "id": "1834ceeff3d3c1a81054b9b4fb57f8ad08e277503ea8ca0800a6fea26940562a", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "bf4fbf6bab096234c166c1ffaf220eb91505f27eea0e8ccb4c4b2a87c00fb534f51662669b98664546cbce1324738d2ac227f7c5a035221992ecb4252d1accdd", - "tags": [ - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "73jzDyeieTrjiwJoTnNKZw==?iv=x4Yn/MQpDRXqOFJ8tN47Mg==", - "created_at": 1690230482, - "id": "060df5b6bb4d97478ed9f54bcee5cc1f5abeebf1fbf162f2bd10d46cfb3b7e35", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "01024d0a7c43b80be39140a28d311a66f86ac105cd465efd3f9698b4ff3e1b432924a2385c3aa4d757897e012decdb0e385abf892be4f398778c1f015191848a", - "tags": [ - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "[B@8d25849?iv=[B@9ec054e", - "created_at": 1690230354, - "id": "ce065bfabf37a72ce7ce604c69da4b6e7bf1eb175f1ffa3f256580a47d637c06", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f4558138d334b34b653c44eaa5df46432ce1b5a93b4eed8d67bf09b6ac07824db55c605cc5d177274a4766f05f2a3ad6f10f20a4bfe0b323245dc8b0cc70401c", - "tags": [ - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "ovBLFoTTdd8TOTzjD69NYg==?iv=Q6muB1flX0fXudU7Box7Kw==", - "created_at": 1690230346, - "id": "da53a14a794809086bc065c1cd60e2c0f42a5a94809cd6f60b14b6a2df2022b1", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a0314cef159927d1d2925942595034e2e7a3ee3f1e97161106114f9b40e2e9012bc76c823cd42f3370844b3cd154d6132da0439c9ca2bf94148928ed353a37e5", - "tags": [ - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "client", - "coracle" - ] - ] - }, - { - "content": "Folks we have a new bug when encrypting messages in this version (we updated our crypto tools). \n\nI recommend not updating yet. \n\nnostr:nevent1qqs0lvtq2hfp39hy9krkk8ztc8y8ck5hafs8sexs6umzfe2azz5vjcspz3mhxue69uhhyetvv9ujuerpd46hxtnfdupzq3svyhng9ld8sv44950j957j9vchdktj7cxumsep9mvvjthc2pjuqvzqqqqqqyt233p2", - "created_at": 1690230275, - "id": "bbda567a7e9ada22cff285af2b7af45239a0bb91022355dba78e72a629f18345", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a206a2202235726776f0fe90c52f8d780a6c240ed0cc3a509ac4d444bb97478856f59d497774e5d769077d74deb863ec7278907d507b12d06d16aa8323be7d75", - "tags": [ - [ - "e", - "ffb16055d21896e42d876b1c4bc1c87c5a97ea607864d0d73624e55d10a8c962", - "", - "mention" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "", - "mention" - ] - ] - }, - { - "content": "Tu2w55+Du9shxbY5c/XJTAH7P9gpzolIVU40qRwMZr8K44HlgcZgXUnf+Dpmx7JdFTignWLS0dbc7c3EtV9JfA==?iv=kuysIu6gBOGKjEkgOVQTig==", - "created_at": 1690229940, - "id": "2e9380fa35888db71b7a34f718f3498537d8fa0f908eccc32bcdaaab4e3743f7", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3ae5ad7c3d55d7b6fde18e9f534494724ac7032fc6014d494ba3fec8f70236fcfaf8c50b224490d1ba4339a8498b98cb3bd7f9f9b8b3495580b882b655bb5a9c", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "TCnpqllIWnsFTtu3sjc7OQ==?iv=SGT6iPifAUL6ZaC/lOaDKw==", - "created_at": 1690229836, - "id": "4ac2618bda32746e23dd03d4f4b8b284c86e6f1c1b3729f755ef67c22a2147e5", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "07f8b94b38d9f9c13f2e6b05c62097a7f019fbe62c850d2ea19dc3e42a98952e06a42b922fe8ed14308ef0050cbb64b0dc7562185573ccf12dd18f5b1fa596cf", - "tags": [ - [ - "p", - "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a" - ] - ] - }, - { - "content": "nSTEB5yiTJ4P5rUuIgymnK8WzsU2D474gZuIUMnPpu8Sv/pJjmXqAUSnHvu5xVzC?iv=12q9C6xeozl3+7XGJOA5Vw==", - "created_at": 1690229516, - "id": "049d7746738bcd7e3d08699dfeca3ff343c0e87cd7f120fc88deeba0b7c45900", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e3c2791ab4e94d129a5b639dc95e2cafef1f891435cf994974d153c42e7b0c834f18884f0651d0ba2ec5dd8b309f4374ae402246bd0bb3d078cc5e686a491f75", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "[B@a24d242?iv=[B@ac9d253", - "created_at": 1690229467, - "id": "ca97e741fa2666883892aa47fa6c1afaf5d92e9b7f9b6777227de0ebcf947090", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3f91893f237a82c249d3b950ab64fab6e26906a495e83336b93389a8f88130bf7edc961702b6ce0ef6e4cfd5992551d34c76211f6a974533b43ae24cd0dd2870", - "tags": [ - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "[B@30f641e?iv=[B@b42f4ff", - "created_at": 1690229418, - "id": "cee035666cd2135df68562f2a8841a9a8ee1fcbcacab0e2eb529735155d35809", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "38dcbbb36ff2b9a69292722d136381308f9d1dd71fc20305b6e3544bcaf9a491e78e7c5688eab8efbc306e6feb98fea6b9840bd8387742aeb4c931d099c2ee02", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "### #Amethyst v0.70.6: Slighly more stable\n\n- Fixes a crash when onNewIntent is called before onCreate\n- New Post, Relay Choice: Select/Deselect all options by nostr:npub1w4uswmv6lu9yel005l3qgheysmr7tk9uvwluddznju3nuxalevvs2d0jr5\n- New Post, Relay Choice: Fixes missing switch when url is too long by nostr:npub1w4uswmv6lu9yel005l3qgheysmr7tk9uvwluddznju3nuxalevvs2d0jr5\n- Adds missing OptIn when using GlobalScope by nostr:npub1w4uswmv6lu9yel005l3qgheysmr7tk9uvwluddznju3nuxalevvs2d0jr5\n- Refactors Crypto/Hex/Bech classes and dependencies \n- Simplifies relay connection status\n- Moves to OkHttpClient on URL Preview Queries\n- Moves to OkHttpClient on Image uploads\n- Refactoring of the Connectivity Settings\n- Avoids crossfading animations when loading NIP94 and NIP95 content\n- Moves playback service startup to the IO Thread\n- Activates Strict mode in debug\n- Updates Firebase version\n- Updates Hungarian translations by nostr:npub1ww8kjxz2akn82qptdpl7glywnchhkx3x04hez3d3rye397turrhssenvtp\n\nDownload:\n- [Play Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.6/amethyst-googleplay-universal-v0.70.6.apk)\n- [F-Droid Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.6/amethyst-fdroid-universal-v0.70.6.apk)", - "created_at": 1690229318, - "id": "ffb16055d21896e42d876b1c4bc1c87c5a97ea607864d0d73624e55d10a8c962", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2fe7528a93ac8f89d1d1af8a112e3cab60e616c244b29ac10b87afcd452f7f2e55916381ccfbf24169a0134e7e61e3ca4d39b3fac0acc4d7209edc2d03b4532a", - "tags": [ - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ], - [ - "p", - "738f69184aeda675002b687fe47c8e9e2f7b1a267d6f9145b1193312f97c18ef" - ], - [ - "t", - "amethyst" - ] - ] - }, - { - "content": "f0rxFkXgSlpTYJRIga6xkw==?iv=pkfpyqUbMS9WPb82bwVHBA==", - "created_at": 1690228620, - "id": "8deec47d7370fe50914436b50d46e3e9781bb5a01b9cdf57744e05ea9a44ac81", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "de222d3c13251b4f350050b27599a84577dc45865cafdd1802581eae735291346c4063a57bbb48d136ea307fe2564bdc7a5553d864c8e95bd01622fbed8cb24c", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "5IXoOnU0zP2tbig0jrI/eaMHmHTmqe4G0hMJM4JTvQMfnXV4ARJu7K5X8P0dtIFmuE/LJ/rXjjGe8KK6M1LSIbFoE2u10thYAGCspZTFmqvvaBqtWO1NiRlLoEYHK+h3U0W8VAv+/RsMRjUeEVEoVTeCf6FvLrFZpjL5x4pB2uk=?iv=rvsakuPh8qVCx3bTDHtXEA==", - "created_at": 1690228608, - "id": "b4babfe9e28154ec2c49e4ce6ff357946adc7218d8faef5fdb97a6bcc0aba755", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "69fe9bed3f5bf09a70cebf02f93a8bf7678ff2b6c9f536ee824546fd81d943009a950ff4ecb07f777ed3a09316f7bd8025283d2ab40c7b60b44236a77e5c5237", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "e7YlqY3i9/YsfIv436ynsmIgk69dMdhiNLpU5Im8cv9o5IigoU9O64wUr/8phC38KRCOqL379X03kC7/MkoX1Q==?iv=C4RfGcjbmCwARvXaUJ3Yog==", - "created_at": 1690228538, - "id": "a3078be67b927101c85c94b18d3612186adb9668d40b8883ff3d4c158774cd13", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fb4c05e3a908b05329b306ecc418afd06f745bcf7be1c48e6ebd4940c98787c557d6ffe88b697916879770a3543cf56d2939090d07e00c67f5a1522b0dd1c7ee", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "wFpRKzRmd0CE8Er6sSdFOaW+SLRywldsT9xuc3gyxJ0=?iv=4n0/TMTuAAmzPgZMQLqixg==", - "created_at": 1690228503, - "id": "04fd69bcf970a32314cf0d89075521e349cee6e1138847cd30a91bc24f6359df", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "bc0182f52b3135918c9de527bcb295571970940586b1a563b59edd81e64b9d81b72a67b701f10d3a78ccb4239088d93fb5506e84ddfed0b4fc5df4f7ece6059c", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "G2fjhfEAILx+EERl5rBcT8MiB6OJpJO+YSBVFwl0NHg=?iv=jN2FU7QB9W8RbTfPSMuIGQ==", - "created_at": 1690228433, - "id": "f06da5c6ccebd61777bb9ea7403f8cae990348e04eb533a321e603d986d5f818", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "331f43a63744baaeef49eb46e8308dabe78dd699a81bcd9113724924296352225f0025daa5cf0fe4accf425224f3d817861dfa11425260f47002f8a1ad6b8e40", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "Zv6wgC9t3LH/CepLmgk2W18K+/TJSmVd5spsy0DXu/z9ihTGoyOrUQ36qwVGlXvV3wDsZNSh0GbKmIcqtlBUVrGmbx4xH5/SeT5j4M/VpQXlfK5sH/9YaSi8ljvx8ukKsJoao4abVsfrY88FbnZEhw==?iv=VR7r/xc6QJ2HkDfHLSsqXg==", - "created_at": 1690228423, - "id": "b4b7ec12901324d608dd17692f09c22c6b3e8b34d32cb68159c9871225fbd1e4", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "710df5f81ac0dba5bc27dfa4272e9fa33e5057e1c573ab5a13cc4d3e59eef31aefe5af8368f1d95c33b9bf5aa1363e0c889a45780ddbadd151364b59ea78db71", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "NtMkCfX5hIj1XxHNo4bfPBzMGEBs9fT+OVdIG4wINrRh6HEs4Qz87Bn5bFkagTc6?iv=b/mnWmOf5k2wSImYITU8hA==", - "created_at": 1690228342, - "id": "4a70cb34f63ed31520032823021c713467df32bd648de0989b37f35326ea6f16", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0638f065e9d88fb8f930b2a5f97dd6a8845cfe3f453060d9e5b926d4866735deb1e63ccb04c8c70de43a5e0b41820d87125b15aef716e2167bd52d97e5ad3bd7", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "KsvZMEAGgsnCrhObxHfleeyGrrrUj0+7b6W/dmI7kKbgvZdRrxc+99AtetHSgEPH?iv=8Dzaf+ZPo20rymUi9gLMBQ==", - "created_at": 1690228325, - "id": "aa4fd0a517095fdf6e1805dd65e2933eb9060cd48d1057408cadd8f0bf0b4f75", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "70fca6c5e521629504e3e70eb57fd5dbd41564946bc53ba875ac8f47794b699c3797e4891326777d03451e03623cac3fba5dac221a55a8535f2b2b47496afd96", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ], - [ - "e", - "3b90e6bc6ed1dc8d54cd7d16b31fd55227ea422dd6d3877c6176fa0f1adab26b" - ] - ] - }, - { - "content": "hOoDDnlWlF0POet6CinuxFBVdITw1XpHmXkuFQm/ijXZ5dJO1kVbgcMStOh1ob4/?iv=RxSDrWU5WZL5AAwJpM6/7Q==", - "created_at": 1690228290, - "id": "ea66a129fd8ea1d89ae1edcf883385210b199834b7659f88925772758005111c", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1032781f5e623eaa8a0b936aacf177f86d2620db8bb62a2e80d5d151ee020268b1cdc93f2ac6395175f55ecf62bb75f44c355a05a5a39b4448964c50eab0d2fa", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "OgJTFpAbiLGECgMTDUUqaiE7imMVLEo6xgC+UMXsdkM=?iv=vWJbTiA1NAH88r6W5sAkVg==", - "created_at": 1690228276, - "id": "1b79f0dd1cbfc588c73267a81d7a5fe339116f5b3e7482dc0e888ccb62c49b41", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6e0bf43c28dd4f887c5636d86b78cc6f5ab8b49a78e3c47998303d58e0b4750b7c601a36d77bebf37b0419d85d3b0b492f57f40c9fed6c934c68967acb2ec98d", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "Wa4cXONJIYkjZ7UF1W38RXF8RGOYF1Ga8H2Wu9f2Qm0=?iv=jz9nL8hnlLnyb0nicyHBiQ==", - "created_at": 1690228095, - "id": "071d645bd306db51ca237a9b97978b50553734023bc27866b5e63372e5325edc", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "51208ce6b3fbfd750ea7dec69988b5b1d5d460829dede36e9550f3c38102a275f0fb556879c9137cc0bcbbb2dac53c6f89ea5d72742ed00e715b571ecc502046", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "aP/EaL6KMt0cKss6Ou+Cj8gSeEiLNwz4lxBmo21lLp1Oxrbpyhb7AiPB/yaouzi6L34ERksQXG90Qm0iL6Yxmg==?iv=dJU3gVfMgoeCeTN7FmTL3w==", - "created_at": 1690228088, - "id": "a5464ad10b971eb8f6f5111bda5a64b9d76fad5b4bfdb9f26aa40db369eb56f0", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "59c5f55ff8176d65b6bc2249ab42f73c53700a12aefac764eb34b47ab2c8497b59629a3b1a1f58f662c2e22f9df8407fff59d5765125abb9149235044b7565b3", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "UBrSmGFZyQMMAmYON6Z0ppQTcoU/35ZllF3z69xyc9a1TtJr+vNCA/9+FhZH5ahhIbjTE6ZRjk/d/JGyXbS3gmkVkYK01xGi2kkwVCW6JD0=?iv=05pAWlAlwMAVbWzQOoq7VA==", - "created_at": 1690227805, - "id": "58f3fd95d3afee12a33547c3f793d7a8def09adb3ffb6ef3760d69288c66f56a", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d973fc6baeeeb7af8d476f13482c3d6a1d14e68ebcdbe22be72a31b11d9258e0b5ea46a84f6341028075d2c525d22ba27a3fe5dcf9edc71f9f317c702e9aced1", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "uppuL+KowTG72APQiuYQzEAKl6opOeCI6jaBifrt4BvrJnP0SYvg5JvAyijt6XRmAJs9HjO83GJ8nExLYZsPqA==?iv=CcFmyDxQnHbOUqNJDgbEZw==", - "created_at": 1690227791, - "id": "44e95b224b6998c70fbd3f20bcdd17345fe2fa881e0cdd81c80a10af00e4aaa7", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "368cb4004b40583c3fd71a37de17b4977b7c9d8bbfef8d976e79d090175d173b85b902f514b2ef2123af8c5fa8e71bcac2d43f72d56f3caf12de3775618d8733", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "EaRIVyoO1jSDRUYVqLN8g/yllaPPxFSAnmbTSdtyab6O8Y3YGMkRO0Wg1RRphDRM2nEaTZcngkvg40ayVQzgv1mTqhxkEiWP+YFFLV5H6Xc=?iv=IDdLzaZDUjIXAq4s7YYPpA==", - "created_at": 1690227754, - "id": "276c7ede298ca1a7b642c28e72cc9efe263e656e2e7c12fbe6607b07fe7871cf", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "80997a5c0787a7fa042568bbb43c147117da062fae9801275015a6cc21596b20f6944eb51c34b809890a5d2499bc1916e988d57718e6663c6ce19d7f5127308f", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690227628, - "id": "efef075535252bbeeb40f003ada1a7f295f583a56bb38443778318d17b6a128f", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3f5659f79dd35cb3b5ae418cc62a7e28284cace0ae69b66a2b39e81770e368bf6dca9dfbbacf6522914bccc78610c601d887af774c946ffd1e71f2e57908d783", - "tags": [ - [ - "e", - "23a9662d410b7000b2b387b0fc7edbfe709449e8af56cd88ab0205ace1cd2c74" - ], - [ - "p", - "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - ] - ] - }, - { - "content": "cd7zf88DXaEqGtgPPfoyAL4HcfQy/q6DtAUhhu8MnJSTEHb3CKmN3uMi7EJbWiRM?iv=vgZdKLxwPhshs3Mh4O9C0A==", - "created_at": 1690227507, - "id": "cd53313a1754ba05f4b6ce93adfa39ebd09f3234f978a911fa054272296f0191", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b0ab7330919cb4698aa671989ffe34a4f0864b311d389c9935238fda82ed238f471ab9f211cfcd883866e7aa479778ed6522f32b35a288f9a4caecb469df1e9a", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "we5Ld/YAGVvuGerqzNpvT0+m2DKMxDuuEZsdj+ONxeo2NIzwzP2VfsU6gfu0MBp2?iv=i+YzLjzuAAtDTXNdLEluig==", - "created_at": 1690227490, - "id": "0a7a433e967a942c56c61148603568f473f0a05f7abffda23f493fe5c4dc385c", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "460c4329424abf9fe6ab5dd4af6cedd96aa0d9b7e367159f61562c082d4d893142a6c07dc339ea320eaedf3eeb2641b344f26b7102fe1aa83c900b7163d07d0a", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "+699S2I9lB0O3ivY+8B1btsWTArJsDJJCrBn9FgU5JX/H9emLLrkzql41Q68FLgh?iv=hih4I9oS/uZGPyD1e4nJ/A==", - "created_at": 1690227474, - "id": "30dc3c835502332ea13fc39e86ba050d541408eaaa5aa8e9746cb552dfdad582", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b5b726b12a911c57c390293e71e1af2f7ec22b062d1ca70e9eb3c7d3d6c6d8027269cbd5b3526b7446b4fb9f437e3edfdc1eae09064772144db84311e537691a", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "1UIB/MzWT/7eZpeBwTDiL7rCj4X6zANvyLUjidDqTb5aQknFxJs6y+wMpjwoSiZf085nzV8EGMy0Q40+bZ5RhQ==?iv=V3+jmN+XsSkq5H/koJE+6Q==", - "created_at": 1690227338, - "id": "fcec1f5080b1a3804ddbfd8e8f4511767e866ae5197a541948fef8a48c97ab12", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "38596c01b3657c7fe45b3dc9b4c57e350e865acb0e4551ce38634c52ec7031c4db8d9f9a653072669556788ad0c10d1594cd143a56ded585319a44600b5c03d2", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "3xR4YgFOWvu+mwlBXCHBcxKkbImhQBAwqrt68/YWq9bhCLUnmAb3ug9hIm1vQACw?iv=FjLifC80ldIYZoUhlZUZhA==", - "created_at": 1690227306, - "id": "b98730e230d2e0d2a5989591828bd102b14c5d9daacb8bef89070c63a3c516ca", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f50a1cc8c049b954b51841132ea92e2b913c550bc81a9bfbb5fdc03a2aa018c233e11048db7b45a13826f3a5ddf3f7242f31f5d10aa1bd4e63ed5577c4183fda", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "oC5quZsBkzBT7QbwF8IaboEGgtQkfp9vsJHBhCZC420=?iv=I7afX/EYBNynEoXLx/Gfog==", - "created_at": 1690226941, - "id": "c1dd8bdc3032122a8fdcc7f646e35e499eaec0872f0455f61732e28b268467ed", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "afd4b73d65d83a14af2f8e33795a25c2c736a3241b670852abb254851e99fa2023a9a82c4d53b46af8a0348cad40c29fcc9b295ab01d6e8ebecee711baa12d27", - "tags": [ - [ - "p", - "b1f94c43bcfa4ef78bf24f9792169fd66aa644ff37e588734f1b42df2f319048" - ] - ] - }, - { - "content": "on it... I need to massively reduce the amount of memory we use. ", - "created_at": 1690225524, - "id": "b127a0cf66668468bb6a1bf83ae6837cd394edab9b0c9db875f68a29e7046262", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d956e9f64a6ce9bdb2332ea3c6ac9f2196a848ac011d6898083bf924d7bca3a377469afefd05e4baa8b28270ea6e4189f6109f42c83b05afaf5e265dcda3bfe0", - "tags": [ - [ - "e", - "b346ca28b9063b0d6d9d81715a716ee5472e99e7a0be48d1e53e94dcbcf2e807", - "", - "reply" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690216404, - "id": "cd60ef428467bd132a1c9aad9f99eae847563c8ebc8eec0e41a753e1e060c91d", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1d5354a460dd7e1a29a7e15f783bd456c47f4439679862a799e01c4ffdc6a7054440272d4600ff8410243556e6d653100063c78822057e24cfe402471acb1061", - "tags": [ - [ - "e", - "c7662cbd99c71e97772a6399985b658316a46cba499a1fd8e220e09c915534a3" - ], - [ - "p", - "f5f98ba54045a2fa8df2a97c35fc30299b9e0d51a701795c040ca80cedaf39b4" - ] - ] - }, - { - "content": "+", - "created_at": 1690212757, - "id": "f6a137add3e53b6f5f447ccc35fcf84a0a07e69dd06bd8aaa19d6808c6a20b88", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a370fa9b8e5a070f7cd98c966f91b6c2c763cbfad9412a94d3250e55a7b0efdf2fa1812c57f5d34f699a16d4a598eb9241704b50baf113872de8558722d1994b", - "tags": [ - [ - "e", - "3a9d72b17813409f277e464f823a36d81415bad69dab3efe7851abb848751218" - ], - [ - "p", - "5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78" - ] - ] - }, - { - "content": "People's favorite punch bag. ", - "created_at": 1690212178, - "id": "c380b568b96380709a679b97f1ff03bda1707dbf7c486e2f00610475e1db889b", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "815038531ead8cb887ef5648aa6389dcaa51475a57295f87cfbaea64c69f8975aace31240a926c26b1f650547fe8f08c14e92a82f147e178204e3a13fc5a58b1", - "tags": [ - [ - "e", - "72820a1aa7f666673f7542abb7ab672b330582efda66339ad291189c2710a3fd", - "", - "root" - ], - [ - "e", - "6c78d72cdb718c818f872b463abb331294663b339823388b8284359761581d2d", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "577de06dce160a0379163a4bb7b680be3e0a0e1c68de6e6ba8c01134b44064dd" - ] - ] - }, - { - "content": "We all have multiple identities", - "created_at": 1690210832, - "id": "dc092b256c585056a6cf94f3b1c5a560d5524a7ffba61a85fc84fbc56727edf7", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "05d53d798b60ae9b7970cc027106c04daf72458f42be131d2fbee901b90e74cfd5e6a8962a03f593c5354ef0da5daa436b68e1fd2d7b6f9790dcefed92711009", - "tags": [ - [ - "e", - "ff7c9d42b017c4487ea0608a61b792a5e52e86d5816521ca25cc7da2053aca7f", - "", - "reply" - ], - [ - "p", - "f728d9e6e7048358e70930f5ca64b097770d989ccd86854fe618eda9c8a38106" - ] - ] - }, - { - "content": "Yg/ItlxjLuKDzlhNZxNzxUFW005logbVHbRYOs1iCjc=?iv=VB8/JXO4MSxwX+I8wS43pQ==", - "created_at": 1690208557, - "id": "4efcb194e78ac43494f6f83c4113470880931392bb682bdbaa1dea63b671fc22", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3ad28c322bf12d3fc32d4ce05a42468ff299676b923ab408f9f72d1ec04ebc3565472dc2e998407800584fd92fa4cd22dc1d3db87f3b9b51716daa53a473b236", - "tags": [ - [ - "p", - "f5f98ba54045a2fa8df2a97c35fc30299b9e0d51a701795c040ca80cedaf39b4" - ], - [ - "e", - "eed8c3d0d10c88c26ddf9afdd5f15d407da027fa811b6aa33ed634e81835ed59" - ], - [ - "p", - "f5f98ba54045a2fa8df2a97c35fc30299b9e0d51a701795c040ca80cedaf39b4" - ] - ] - }, - { - "content": "Yep, I just have not had the time to work on it yet. ", - "created_at": 1690208431, - "id": "6c4bd9de4e6142f6aca5107f8f88bc021142f2e70ea25a7d569d38f49934de48", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3688bfafa385f849b731462f1f10324b54f5a08489ed55b6fd1fe52d190d2d4e40426c3ab3bfe79a2c72564df5021aff7e7215f69def3148175f415222add0b7", - "tags": [ - [ - "e", - "1b3d29f67935201aab597b4194a92a56f9d55ae23a24558527454b2284b82f20", - "", - "root" - ], - [ - "e", - "6dadc904610d86e20a7c364bb152237fe0185df7e3ac8ebff5b2f89abe751c04", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "456cfdb590144b9cee34dc09130217a938446b2558f06624f1cf160accd0e57d" - ] - ] - }, - { - "content": "Interesting... is the Community available from the relay set you are using on Amethyst?", - "created_at": 1690208409, - "id": "9adbdee8fce306d17e61e72d0931bd5697da102f95b5d17b0508b3238882e557", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6ead4535864f2f8b092158d16bd2b4811d0819464b0a5d3aa63aa46f482fd1895b142f52a9e0320933f3b72f1e2e31b7ae488eec14e1acaf0440ab9aa083d217", - "tags": [ - [ - "e", - "3eb890730dc61b60344b8b2f832943fcb41faa9288049a3e41c2523f7a84d39c", - "", - "root" - ], - [ - "e", - "3576a8688b06d3e39f107ab0b7da6aefc03a32231223af6a52f5b353711f94a0", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "6bf33edbbfe348c1f04d9b708fd51fb6004485812adab49f1d70ad0b66d7c715" - ], - [ - "p", - "6bf33edbbfe348c1f04d9b708fd51fb6004485812adab49f1d70ad0b66d7c715" - ], - [ - "p", - "efc37e97fa4fad679e464b7a6184009b7cc7605aceb0c5f56b464d2b986a60f0" - ], - [ - "p", - "1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef" - ] - ] - }, - { - "content": "+", - "created_at": 1690201062, - "id": "be0a53286c98adb52eda88de58f83793c159454533a225dfb5f141362d5635ab", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d2ac7b39051870c9cca6086e889f515d0168a0156a1c636a0006c0d549cb5a06a3eac7d3f4661470e51a0692e51e60c9ddc10dd5c43fe89765f565393bd5e50e", - "tags": [ - [ - "e", - "154e8961290541af45697deaf2537663da54456cda58565fe8350e4db201dfa1" - ], - [ - "p", - "1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef" - ] - ] - }, - { - "content": "Hummmm this one? It was the 6th in my feed.\n \nnostr:naddr1qq8yummnw3eyx6rfv9mx2mnwvypzq9eemymaerqvwdc25f6ctyuvzx0zt3qld3zp5hf5cmfc2qlrzdh0qvzqqqyx7cm9ctex\n", - "created_at": 1690198600, - "id": "256b47a26fdd08ce0e2040850d7328a55938c5bdb2eff7598f15779b15ed781c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "cd94f05a2af150bbe32a5297d897eaaf53510b7905a28bff1c4ab581cea8e6701e4646dc6c188ccad884eb5f76ca4a2d9f6d20933b6c3d7dbc30a46638ccdb5f", - "tags": [ - [ - "e", - "3eb890730dc61b60344b8b2f832943fcb41faa9288049a3e41c2523f7a84d39c", - "", - "root" - ], - [ - "e", - "b08691e0f9e4d9254981f1876a430ac9a9f248bf26e54f06109a7002a78a6e91" - ], - [ - "e", - "dabcd7ee3d178ab8efba9949dc273ad96c106e2d2394a986af153ddc17a6390a", - "", - "reply" - ], - [ - "p", - "6bf33edbbfe348c1f04d9b708fd51fb6004485812adab49f1d70ad0b66d7c715" - ], - [ - "p", - "efc37e97fa4fad679e464b7a6184009b7cc7605aceb0c5f56b464d2b986a60f0" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef", - "", - "mention" - ], - [ - "a", - "34550:1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef:NostrChiavenna", - "", - "mention" - ] - ] - }, - { - "content": "👀", - "created_at": 1690198560, - "id": "b24c556f1f979dc09c6720e851c7707ae907ac272a6bdde25d3d48c1df51b800", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "720c6e740aab5bfe7caa84dd8fdc82bac0d6c4666369f79d8217ded86a91c48691cd8ed0ff59d8b63054eb5e6efe72770d42a1186f1052d70522bb27872c990a", - "tags": [ - [ - "e", - "9aa0a176088c0c2b2e7be88c65c49c0872aeeca70602776d915e9d05ff7005d0" - ], - [ - "p", - "1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef" - ], - [ - "a", - "34550:1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef:NostrChiavenna" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690197065, - "id": "2c60ea99918ede4de03f2d193a5bd90eaa27cd3eb77f4248e7545fbf3cd10ca6", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8c520ae3c6846e504aeb7154b11b4f1f74c4408f059f756eeafa0542675c3a8306242ce3b1b10865ef543351f2c85308f9ced483e93bef5036c4bd96fac6b959", - "tags": [ - [ - "e", - "3ba8420929d76e222190d23f28cc8a1871c0a38ee15bcabe749e78e4a3685d54" - ], - [ - "p", - "a9434ee165ed01b286becfc2771ef1705d3537d051b387288898cc00d5c885be" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690196883, - "id": "f40a4a59a641bd45869ff6950d16a03c09c856afd25ea81e84f53ae22014c3f4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "17d0aed9b66ba569d6073a56ce2bcbe82c14e5efc9f0173bbaea699d7b5f4d8b675125d067c36e454015e44a234f7b04e356155de64de5444c74ad1632393f39", - "tags": [ - [ - "e", - "e000d1594ab01fd630fd7d635150fce287ed77a1bcb5087360b0000d016176eb" - ], - [ - "p", - "c43bbb58e2e6bc2f9455758257f6ba5329107bd4e8274068c2936c69d9980b7d" - ] - ] - }, - { - "content": "🫂", - "created_at": 1690196838, - "id": "af60844f79ca0fd418e34883cee61a9cb0cbea8e890ce110267c419ae256fd3a", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d3bae96968d29b6f1ab47e3aa6e482fd825802443e4baf9fd09bd2bf260a346011e6c336589fcbb0ba20b97689f46ca35f6ef9b912c31c2138a6b6a5a2b2161b", - "tags": [ - [ - "e", - "a284954804a64168b23f5e9f179ac5a2dbf8d01812deafff3e3c452adf872f7e" - ], - [ - "p", - "8decf18b154e3c1f8450df95a501581e64dac7ca09bf9a83e95c783b695ab6db" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690168165, - "id": "f505e57ff50b2fa767db7bdfdf4b294ed7f6f8ecc92edbeadb7086335edf8d7b", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1a6789532ec1ae5b91d992f091d88ffb5889e4d1fba76da7bae3a624db24ff6d9176dde9323b78fe517f8c2c1769deb376591ac670eaf65f2355919f8410178e", - "tags": [ - [ - "e", - "ed5c3ff7a4ce9a16367646b9de3b342e06f5ce9cd1db92547d9764d2d54105ef" - ], - [ - "p", - "04ea59bf576b9c41ad8d2137c538d4f499717bb3df14f5a20d9489dcc457774d" - ] - ] - }, - { - "content": "", - "created_at": 1690166988, - "id": "480e76bf0c518a68f30fec75a613f7e93ac3b40567c55c04d3d99c4939dd0fd7", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "80fb0c2cc3ef946a63ee4fc9439ecf6ac68b30bd3bc2021b333cdf456c04f0e71c9767f97777fab6170cbb2a536700c368954363f9510d585bf4a033bbabae71", - "tags": [ - [ - "url", - "https://nostr.build/av/9a5ab1d24c343007c57d1fcc15c0062b8aa10417b9853373b494dc0a4ffe3865.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "9a5ab1d24c343007c57d1fcc15c0062b8aa10417b9853373b494dc0a4ffe3865" - ], - [ - "size", - "378735" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690164742, - "id": "2743a30ac796bca3d84379e02c2c151a683cacd0c95e436c9944c75fccbd1775", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "950321f75b1abce3ae87ed53692cd681f9f75cdee99e2bd3f55c2dddbd5c3b677762c70ad15b1e465588256e2a93cf0a2f9da9fc0118dc62b82e993f31656618", - "tags": [ - [ - "e", - "1e5fa48d69a1f37cf7d5777c664c2db8a305f3348fdc67cd85de66a23dad1e3f" - ], - [ - "p", - "f5f98ba54045a2fa8df2a97c35fc30299b9e0d51a701795c040ca80cedaf39b4" - ] - ] - }, - { - "content": "We might also need an extension to this nip https://github.com/nostr-protocol/nips/blob/master/39.md", - "created_at": 1690164717, - "id": "d03b49913572ef0628c03cf431ac5cc7e05f37c23ab25f418b798be8aa2819a9", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d9f9ab2c46276d1684de49938273d172c58a04352ca3e1b8c6616737d79875925104285d6286c0e1aa5a0dfe2f4cd266ed5d7d3187b229787e6ef2fb7a9cd7b1", - "tags": [ - [ - "e", - "42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5", - "", - "root" - ] - ] - }, - { - "content": "Ohh I see. We might need to find a way to verify that this is the public identity and not one of the links to be kept private to avoid mistakes. ", - "created_at": 1690164593, - "id": "402d8aacbec848091fb77eb84fee6cd7483bb051bbd5bdeac068561d37056752", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3861611c96d4e7d62ec3689c8a3afead9441f4c3f927dac52a381c4322c2747ad84e9294596b687722dd6743e7e22e1aa6d875c867085d6319f4126f1847a469", - "tags": [ - [ - "e", - "42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5", - "", - "root" - ], - [ - "e", - "150fda08135c4a4d05b7b2efc6f41f519696d4543dced36a0b0cd4093575c780" - ], - [ - "p", - "b70bcc7ad2ef996c7939d91653aa1472e0b7b3a741d194fbb26fe8c1786ed4af" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690161505, - "id": "a88d6e1c7b8b9e83839c15f05bd1b9244dd1e1aaf69408fc53088bcf88d938e5", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7bad72a24620794f1a337602c5416d6980420f20aaad77fabafbd03f43391053ace15018cc9044f48bdde6475072a6d6b51b25d10f0cae061504c260f78b06b6", - "tags": [ - [ - "e", - "8e11fddd2171c00c8cc93b5c7a3e1dbc1789cb41e9bbbc9d3cb57bfaa9b193b2" - ], - [ - "p", - "93eb23ad1d9274e3e284babe1d507f2c80d1eac2f3ef54969361a8a1f926cdaf" - ] - ] - }, - { - "content": "I am not sure if that is a good idea. The point of SimpleX is to not associate your chats with an identity. If you place it in your profile, it might break many if not all privacy guarantees. ", - "created_at": 1690161330, - "id": "3fd93179c24eb3122ccb49fac0be6e6eae50f9e091d7b0eedf350407553ee66b", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0ef0f98973d9a18a12a62aa4ef939eb8062dbdf0e63146d5d6fa3b3aceb7ff9c419a48956244b2d06470a3da5c2d35f9417529e9e87a0f6123ad867640743703", - "tags": [ - [ - "e", - "42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5", - "", - "root" - ], - [ - "e", - "8ad94c49e2d56130ff28c11159233d834aa0acffc2c26ebff60d9fb61eca3258" - ], - [ - "p", - "b16a48eed39254385a8754f989045d2b7110e35123ae188e354ab2b3926d925a" - ] - ] - }, - { - "content": "+", - "created_at": 1690154636, - "id": "9fd566b3366e9ed28e0e21bdbb64dfd32d47df582a7e0dc1bdec1658bf698b0a", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "57e6ef3a82458da584a807f665839564e929d309c137c33f30dbbea7396b797fda170328663e1d10eeec65b2d9dea67e428a2414dceef3a3d1da0b3b23487d44", - "tags": [ - [ - "e", - "203ac0002170f40a7204961a2d9f767cd398a86da66d483677ce526e7da523c3" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ] - ] - }, - { - "content": "", - "created_at": 1690147047, - "id": "dcab77b29cb67b63a70a816f489781e662de54c9d7700c326e5eea796ac1e3f8", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "60dcc3d5b4ee38c8f736d5655be8846010b804e59587550f80699eef95a5917ca9cf5f83e8ad60422e0d6b052f9934994e03a6d085a48d9e198fcaf1891fdbb6", - "tags": [ - [ - "url", - "https://nostr.build/av/21267a60f742ee85cda5b6025cc96a56980082d18f299786f60dafd8f1778b2f.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "21267a60f742ee85cda5b6025cc96a56980082d18f299786f60dafd8f1778b2f" - ], - [ - "size", - "6007727" - ] - ] - }, - { - "content": "", - "created_at": 1690146416, - "id": "3873f4f5dbf76a19d6704b05019017f7c42270fc3aa08e3bcf7b263c637d976b", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6b0dcfe92b2984f3f02bf6cc917b5283909dbde0690bc50891805342cdc1e5b987f240f18ebd748152297e06e0d2eba483bdcffcbad6324c6bac2e095584a213", - "tags": [ - [ - "url", - "https://nostr.build/av/0a04db3be1b25964c6b524df3deb0b31d33d8380d5a4a05a1dc66d541f51ca64.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "0a04db3be1b25964c6b524df3deb0b31d33d8380d5a4a05a1dc66d541f51ca64" - ], - [ - "size", - "9910725" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690146413, - "id": "97abf6fc744ca35ac884549ad7bf7ba7607b282047badd8422c4837a14eef612", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6fae6d3f4351602af9b930fae47439d469d5cdce3d73625926a02a94397488ac359012551a2aee439a45a42f993667c69487a20c53fc18fbebbe90cfed00e15a", - "tags": [ - [ - "e", - "2b75ed8899dac01b919a7e6c78803145cb8643a0def9069b0d31d8062810cae2" - ], - [ - "p", - "7538994d9cdbb870be588f44a44a16fe7c2cde7ab203b7dd5fcdef76b8a2ced1" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690146218, - "id": "f75d1da64a3ecdf3fffcffc0e117d86329896647429acde4938d8180e0ee0d4d", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "97f0d2c7ec025279f71b5a25434ef8358bc1f40d05e46b7d69868dd4d521f12beddd77cf3509dc0283b91afd9c103c700c49f10d7421b7ad8f8239a6fad92aaf", - "tags": [ - [ - "e", - "aa79b7a1b2833c8ecde7623691870f290f70cfc7b578a02de9fffcf4b0bd4cfc" - ], - [ - "p", - "693c2832de939b4af8ccd842b17f05df2edd551e59989d3c4ef9a44957b2f1fb" - ] - ] - }, - { - "content": "Hi", - "created_at": 1690145711, - "id": "1fad5cbcb12c2dfc878755e9d36253994d744c3234bb7f126e108681c20dcacb", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7e89e6af46236aa7d6d1ecb3886561e6b3ced76a8eae6dbf21ffca4581a9311dd0affc5ea44f3ff2fd6a10fd8efb9bba5e756ccc0afa8b0994706fa9e84cd2f7", - "tags": [ - [ - "e", - "42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5", - "", - "root" - ], - [ - "e", - "72b24ba015112bd0d9dfe0b19036500113c5727bf509c5f1f6b66a54a0e24f68" - ], - [ - "p", - "93eb23ad1d9274e3e284babe1d507f2c80d1eac2f3ef54969361a8a1f926cdaf" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690145702, - "id": "64cd298c3d576f3e71c3a49eaceac2fbd576ecfacc5b9310fb55f8059da287e4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5bff5e7e5353ff5626db58fb2d0422298a7fa34a3584473f2a07645d103bb1269f4de2e10ba9465557b49e610ee58b5bf2eb86e208e504e849205983b512b912", - "tags": [ - [ - "e", - "72b24ba015112bd0d9dfe0b19036500113c5727bf509c5f1f6b66a54a0e24f68" - ], - [ - "p", - "93eb23ad1d9274e3e284babe1d507f2c80d1eac2f3ef54969361a8a1f926cdaf" - ] - ] - }, - { - "content": "Sorry, is this on Amethyst? When you search for a hashtag, the first reply should be an option to see the hashtag feed. The button is not as clear as I would like, but it is there. \n\nLet me know if it is not showing up for you when you type #word on search. There might be a bug somewhere. ", - "created_at": 1690144629, - "id": "062f556e82c36c6515f86f4e7c27c22fe464f0096aec5a4d10a131ae9abb4547", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b55589ad969ee964ddfdddfcd59bd6ed59c1283f1660b3b8e80b3f66f7f4460783cbb94521145999f3b86df2a43cdfb6b384efc6c8489600dff8d155dcf4c61e", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "508286bb1e1589f1339a50fe488c126287cb7c68a627433253e949b03c2aa9ed", - "wss://filter.nostr.wine/", - "reply" - ], - [ - "p", - "8decf18b154e3c1f8450df95a501581e64dac7ca09bf9a83e95c783b695ab6db" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "t", - "word" - ] - ] - }, - { - "content": "I don't think that is an iOS vs Android thing, it's just the app design style. \n\nOn Amethyst, the notification is supposed to be a glimpse of how your content was received. There is no need to go anywhere else. \n\nI think the idea of meaningful reactions (which doesn't exist on Damus yet) is confusing for those not used to seeing and quickly parsing so many reaction possibilities. The emojis tell you a lot: Those who agree, don't agree, are happy to see the post, or the post left them thinking more about it. We want you to look at it and go: oh cool, I got a few people to laugh at this and two others to think about it. Nice. ", - "created_at": 1690144150, - "id": "e9f43494d02050b4cda38b4618ace86b14ff46d96b816a9434959b9e7699b036", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "bc9e359ecc2d6a09470631bb9f8fb32b608d1f40b16c91d60f4a52529b93efafca74f22224b1d1d621bf1b7c26891e25d37eddf7b3b82118c789a117c07bf3db", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "00d94cc83d7c26eed1a915d4a927e6897627997659144f2bcecf6e761b16f71c", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "693c2832de939b4af8ccd842b17f05df2edd551e59989d3c4ef9a44957b2f1fb" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "Neither in Nostr nor in centralizing apps out there. It's indeed a challenge. \n\nBut we have to embrace it. Or we risk just being another centralization force in the world. :( ", - "created_at": 1690143743, - "id": "e3623f238ba397fd9fb22e4f4a72d159f4cc47feb3663788da9a282d6f1c7a56", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6795f9ce277ef0eeb41be85317d6b68ab8b6ccfe8e1e5decfd2814a134bf5407c3b5c24988e4b151dbcfcdaa53e98809423a1ba085c49cba8285c1292ea64df2", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "3edd892b48748d552d2426ca32e8da671b966bf6476668460d14b91104f4536e", - "wss://relay.damus.io/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "It's better than Twitter's for sure. Especially for complicated reply structures with multiple conversations at once. Twitter's one only works when you are following a single branch of the conversation. It works because it forces you to go into your follows branches and ignore replies at each level. Which is not ideal. \n\nBut the current view needs work. We need to code a way to \"close\" branches so that when they break off and you are in the second branch, you can click to close and see the post the author was replying to. \n\nLots of work yet. ", - "created_at": 1690143600, - "id": "78de29f56dc8981d1c04a08f49dfc0f4aca4fdf6b7380fe53fc06c758543c066", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c6a343af4611e7c0288a040eb91e91fae70dbbddfbc7780d6b311303ef10ef46bd28ece5381bc54c5d9aa905a4af363a43ed4037269c699b4ace98ec1157c31d", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "8300def46c069d0f10fc9e16b6feef71c1c810821e73bf76e8e3984d4531f457", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "I wish we had more forks. The more the merrier. \n\nFunny story: my initial vision for Amethyst was to require every person to fork the repo on GitHub and when they did that, a GitHub action would change Amethyst's name/package id and release the user's own version of the APK, ready to install. One-click deployment type of thing. That was the only way I found to not centralize it on me. \n\nThat's why the app is in my personal repo. I was going to change the app id to people's usernames at every new fork-install. It would have been beautiful. True decentralization. \n\nBut people love to centralize. \n\nThey gave me feedback, I listened to it and decided to ship the app myself in the stores. It's worse, but it got us going. ", - "created_at": 1690143259, - "id": "76688fced94a5746890fcd7c79d23674e7e84e36f29ef3ff75a1f4b7de62b1f2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f1fe4a9f07e4137f4d5f98f570b28054f56d7b84c894c50b0fda60739557cc5246ff09f0d76c0a3cbcc4d733f20b61b87ade4df22e34d53078cb846bd8a167f4", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "999243d5a5643ba565a8f9f295101d66c70050388e68f771f1ed70688de120a8", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "It is the Reddit model. Basically, posts in the same number of lines are replying to the same post. ", - "created_at": 1690142625, - "id": "cc908556894f1207f2b6fa108a61c6b1d6f47a93f56b4cbe430d9f18048eaf15", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "bfb61f208a2a20d8dece7b0e1e1946dbdebad5768c00ad756ab003b08ccdb2425367ede7fbf930c1480f73a569d4d11aaa546f912419f6fb618515d88919e6dd", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "b398f36ea69452fa77c6aa09b2cda032efc3a41a4f826a9bdcbdf935e4507cdc", - "wss://nos.lol/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "nostr:npub149p5act9a5qm9p47elp8w8h3wpwn2d7s2xecw2ygnrxqp4wgsklq9g722q's new icon set for Amethyst is awesome. I am happy to have more help :) ", - "created_at": 1690140751, - "id": "158cd5feb11ec8292d4b9441a0b948dc5d91027b33792990ce33813fa6c39297", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "96731754da8e1be93910fb52675c1aad1b51a7ed2429d534f9f1703856632d61e5e11bc1cba457f153a5ab20a307286e1f96b690f84b469ef3db8fb8f794e662", - "tags": [ - [ - "e", - "5a03b6a7d21f8b76e5ebca4e04cdaaba732a6da4537e7b75d9c57381d84eddc3", - "", - "root" - ], - [ - "e", - "47f1806284a61de31e8cc587a5c66f84fe25b0e6024b40c2851dd1d607aa72d2", - "", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "a9434ee165ed01b286becfc2771ef1705d3537d051b387288898cc00d5c885be", - "", - "mention" - ], - [ - "p", - "5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78" - ] - ] - }, - { - "content": "👀", - "created_at": 1690140234, - "id": "0d4467e19a71a4a5c372a96bbeb23fd46f91ea39230791ecb203852f80094c11", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2ba1790c77db5062ee64b7ec4f8fac7ea5d0cac65eb6f95a828e005d0b9ec6b0da429014c020c9a7243ed1f16414cad16da8a09705d1cd122a0879ec2d2676f2", - "tags": [ - [ - "e", - "d63d391bd694b9e1ec5e2de2210771ba5596ad18bd996a4059466a1c0af2a100" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ] - ] - }, - { - "content": "Then I am just confused why are you comparing this with a notifications screen. ", - "created_at": 1690140198, - "id": "fb72346b3a189ef576609b2b2e5af56f52546722d84094f41733675aa55e4db2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8a7d4b654828e11f8dc94355ecb50b507ee8430599b1187b0ae63b534b5f1b283c74f3b78e641c0301d2bd8c9d58be9e4e276d7be6afbcb0acb4123fec6a0922", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "bbc7290015806dc41ab15d37f8d5b6b66e469371f052abf36738017e4d41db71" - ], - [ - "e", - "d6d3bb1689a95eb9e69e9fe143951c2c2fe402740a4bf35fe5255d86fd9a0227", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "Also, it looks like you are two clicks away from notifications. Is that right? ", - "created_at": 1690139942, - "id": "bbc7290015806dc41ab15d37f8d5b6b66e469371f052abf36738017e4d41db71", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "eb3b73acc14478f87a3dc92f946cf8831a63cc1c647bd7fbe1ff585ae7b0d97f588852ed42e8ff68d22dbd0b866dffc045f50468fe0c054e9c0898f46ee900e8", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "7cbb8c290f9c2722e094cf95af3e51069ef97171300d49d84108f66f53de7558" - ], - [ - "e", - "bdf5ddb752eb601777f835846a60f8e7ea34fe0e807afefa515e700ece0040b0" - ], - [ - "e", - "6ea171a5dc97b971fea2a551cfbd418c308c436f2b851aaab8737367f9196838", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "Why? Did you ask your users to see if this is what they wanted? ", - "created_at": 1690139749, - "id": "6ea171a5dc97b971fea2a551cfbd418c308c436f2b851aaab8737367f9196838", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "060d4e3a9202d09af5388d11c51089677f725845e96d8f2c7d07747a8be73dfcfb33c8836057d099974d9310ee23161eb78ddf3842560fb7040e8a6acbcde8b3", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "7cbb8c290f9c2722e094cf95af3e51069ef97171300d49d84108f66f53de7558" - ], - [ - "e", - "bdf5ddb752eb601777f835846a60f8e7ea34fe0e807afefa515e700ece0040b0", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "It was in the very early days, but we did. \n\nNotifications tab is not the mood for follow and detailed info. This is more for a regular feed, when you are in the \"get more details about this post I just saw mindset\". On notifications, you already recognize most of the faces. \"It's all duplicated\". There is no need to explain or occupy more space than needed.\n\nOrganically, in over 100k downloads, no one has ever asked me to add a button to follow in that page or display the about info, which should speak volumes about the need since it's one of the most used tabs in the app. ", - "created_at": 1690139394, - "id": "e1c04a093203e1a39fa51775e79645d9303330e3d5fc0a6ba4f1ba85568fe260", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9bb5bbe24d10e80f88d117e52c5ec9598a7d45ee6941a0bda09db4aa9efc9ec2623a80fb10453ed7e097284648cf15628d6812a7b41c6613b7772e404cc5e56f", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "27cdfcce9c8f291ea1519567d2d3180a131f3e276801c2b0b208fcec3a4a56de" - ], - [ - "e", - "39a3badfb3a96cbca72aeb6b6319b7ca2b2aafda06c9060158c9c2b56e71dcb9", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "deab79dafa1c2be4b4a6d3aca1357b6caa0b744bf46ad529a5ae464288579e68" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "User's last seen is a very good idea. \n\nnostr:nevent1qqsxnj27sn2xud90fyqre6jgakzxwcu2axnj9kcec9jch66cph5u7uqpz4mhxue69uhhyetvv9ujuerpd46hxtnfduhsygymuzlquexn3g56nnkf5hyw7hv88s4l55mz5j643kjl76du8jacrcpsgqqqqqqsuu0vvw", - "created_at": 1690138954, - "id": "c9ab82b0a6b2ef1adf14106f3c660f9fc06fc063d54fa89c092f64fe24d0193a", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "529d56a80125fa7b0e0ba5d9592bb457473929449c775d5860c142d64c6e08a655381bcae282540ab3198636cbfe9aa5074fd237344e93c38dd087ee9e8c0629", - "tags": [ - [ - "e", - "69c95e84d46e34af49003cea48ed8467638ae9a722db19c1658beb580de9cf70", - "", - "mention" - ], - [ - "p", - "9be0be0e64d38a29a9cec9a5c8ef5d873c2bfa5362a4b558da5ff69bc3cbb81e", - "", - "mention" - ] - ] - }, - { - "content": "Last seen is very cool idea. ", - "created_at": 1690138907, - "id": "6ae05de6606182d1f3f3afec4b42cd0fcd37c4b12b4807f1f1971f16d4a42273", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2c593ad41af45511a937c5f95e50aacd4ff953e1758faa13c96f71a5c68832f08cf513926fe318dcf52bdc55ae28ee3aeb615a3b12aac553474cb4f4406a8396", - "tags": [ - [ - "e", - "69c95e84d46e34af49003cea48ed8467638ae9a722db19c1658beb580de9cf70", - "", - "reply" - ], - [ - "p", - "9be0be0e64d38a29a9cec9a5c8ef5d873c2bfa5362a4b558da5ff69bc3cbb81e" - ] - ] - }, - { - "content": "So, you have to click on each section to see who zapped and each reaction? Sounds like a click too far for me. \n\nAnd why does it display people's about info and follow button? I am not there to follow people. I just want to see how people reacted. \n\nThis is weird. ", - "created_at": 1690138829, - "id": "27cdfcce9c8f291ea1519567d2d3180a131f3e276801c2b0b208fcec3a4a56de", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b9e256fc3ab93ecb522625669dfd5f50bd4468d2c1d0f5328341c559c4d5cb1f44f707bb30949a93fa9d91ac8738786d433f4141e0bd0db625984ab8e6187344", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "546fbf068c293c15c5c48232570d12e81e551891fbc611b1fc186a798ad0dc92" - ], - [ - "e", - "2d59b8711e9aac9f6f6cc1025ce215e744e94979f4af33e7b9a586918e24bd18", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "deab79dafa1c2be4b4a6d3aca1357b6caa0b744bf46ad529a5ae464288579e68" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "Show us how Damus display the same notifications. Now I am curious to see why is it so much better. ", - "created_at": 1690138505, - "id": "7cbb8c290f9c2722e094cf95af3e51069ef97171300d49d84108f66f53de7558", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5cc460d2f1812da1372b2e1e5bb883ea09e14fd7b33c2ce0fb3324e1b77e5f21cf451226465950061ab59d49e7c766f6f9010116dd0a68a2bca796e2f45bfc33", - "tags": [ - [ - "e", - "10d0e4bb3a880b36610703cf2101b8bf49b91ffe3edcbf1002564fc86e6c4913", - "", - "root" - ], - [ - "e", - "1874dc3c39bf3dab4d9fc3b6022ad850ad5a4aa7ef4d40aa24b019f4f1e4b841" - ], - [ - "e", - "f8c6955a54a8f9c254d85c8c28d9dfa22b63d6b98c7903a8e407a20ff1152f18", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136517, - "id": "9f8f3d9d1e5bb57492d8fb2c6a654ec0953515e5ed009f86fedd08fd788cbb70", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "db59f7ddd49bcb186e12483cc07b819c45f8dd0e1719c3a6dad063595eefb7df34c963ccb206cbcabd37041b4df4d6b5fa4013d4b39217d59cb2199e76181e75", - "tags": [ - [ - "e", - "10fe6f028555c905ce355d042b50605f0eb13b925ba4742855537ffb5a50be60" - ], - [ - "p", - "20d29810d6a5f92b045ade02ebbadc9036d741cc686b00415c42b4236fe4ad2f" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136496, - "id": "b30e186018667152d83b1b2a366150907bc4cfc5158c2a74e095fc63eb75cc0c", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "14a4b1db558c64a679e02c944b5d63b7d41df6faba4f02d700d92e742a48a21c241c161415416ced8d5bd3663553b071533cfc2b4dbed88979f07ba41176d22d", - "tags": [ - [ - "e", - "eac398b0b928cb10dc9337df29acf7cdf621ba05a4b300792b8aa4d1125e0c55" - ], - [ - "p", - "18affadacb471657941485d8e3053e2be0daa95aa42f9c6f8680d62c758a9ab3" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136491, - "id": "ee2956b81136a28caf94c12a47a4879a75dc2c204a911ebfbba85243613d4cb7", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7bd2df393c2d65b4240a001c7e67efd7a069f83f50b51f8047bbd3c1c45eea4d1967b066aed45dc3bceeb054df9078d5f451e43427d7063daa1266dbf83b44ea", - "tags": [ - [ - "e", - "df6924922f7fdcf06a802348b28b26cb4eb0eece4d0af995e8c352b6887d04aa" - ], - [ - "p", - "5f2b6a543f5083b79dc22227867507a12a999e365f0af741b1f5852bc1974226" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136489, - "id": "e28b0e4bcf4c16bbc83a7a4d4c4d3ce4159a3798a7ad7a4fb2bb95e5178d0da6", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ca878cea73fb03a532452b6fdedc6cb0ec1a4259d9e5ba428cec6b27d8ce2e09605cb079c5d251a45072544de907eeef01219cde2264a8ee6597c2382cdf3b84", - "tags": [ - [ - "e", - "0127ccbde49aec4c9f88ea5f18c2f442383f403d59ba060142f08535f09ee4f5" - ], - [ - "p", - "18affadacb471657941485d8e3053e2be0daa95aa42f9c6f8680d62c758a9ab3" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136483, - "id": "ceba0d38900e9b7f3ffa6e2935c3e9654aee754f3dd3ad15ff416a061bd6beb1", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "954b2b32fdf7cc393722296b1b5639ef7ba9889a0e850746c8a91f8cb817facb9cf16881f6a1a6f7aa51e924baabf19c796e33eec1dc41c9e30cbc30c9225552", - "tags": [ - [ - "e", - "bff7c2588efc33f94e24ed9e9b9e24e560e5e2c4460cb6bbd6ecbd5cb074528e" - ], - [ - "p", - "18affadacb471657941485d8e3053e2be0daa95aa42f9c6f8680d62c758a9ab3" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136480, - "id": "23751602d5fefff93fdb7d202f5c0ac4b856d93f674ac24db7675693b1e8c33d", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "122735ff28c4bd0e45b43618767c1a12df1d1c22244d78ed24906ccc9f5194da01540386e75dc74775363fa744b4e2ce338857d4f0013876806e5b9c6c5dc5a3", - "tags": [ - [ - "e", - "107fbdd98adbce0798b6858248213be4262ae1301fbac29e2e5ed7b838534b15" - ], - [ - "p", - "18affadacb471657941485d8e3053e2be0daa95aa42f9c6f8680d62c758a9ab3" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136460, - "id": "e1404352314e0ea33f8b70f23a9f833e475bd118b0f49886c0d34b01dca6be80", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "286b6470e0c2a51b07d1c7cf72d919d7e06d0f303ad2d6bf05c2a525e37fa17b6b9c1d05d7c80f49dfa954bc08f51c865a6e3e5b0a5feb184d5f96adec613530", - "tags": [ - [ - "e", - "5fb517843bf3accd6ce60e69d5f7b964323f582238242f6776a58c9daa59a3c5" - ], - [ - "p", - "18affadacb471657941485d8e3053e2be0daa95aa42f9c6f8680d62c758a9ab3" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136457, - "id": "1d8c8f7707f365909ecfffc890bf58ac28489b81f1fb71ceb506b8d9a1417140", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e8a21f42780365e514b9bee4dbf8335722a9520068f312da2b7b8185a8a6041de17e2b631f06edf1aa7959f4436658855688e011b971c2653d83a7f36784d6a6", - "tags": [ - [ - "e", - "28f176f094da6a46ee195eac39ca4154d0d94d86d2e545532f697238f3e52f9f" - ], - [ - "p", - "31da8e96a0d372f657280a3b678c5c8398b053d0891d458b7c8b0a752737a9e0" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690136453, - "id": "f81ec9b259fedf292974205e6d2523cb527f53825e7b16ab794bac30021e5c3c", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f207099dd78a41e9fb3f09359acd0fc37199cac970cbeaa0f96e01d3c6e2d1f444f4dc4c7624e5ebed94ca6e936a7d7c60a5f43a753e822e67d4b04ae709585a", - "tags": [ - [ - "e", - "92e9e94ee0da6fd08c62fc2477a8a2c825fecbf0ad91a2c5d060d2978f20d6cd" - ], - [ - "p", - "4ff36a4d67fa327ef1a686a575d0106b4781600900f68ccb5a40f7e455530baa" - ] - ] - }, - { - "content": "Ohh interesting. Thank you! ", - "created_at": 1690134858, - "id": "20e91ddf23a4b87c138fc41c50bd6baeee6bfa352b2f156a51cb914c29927847", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5cbc7535ec7ebc60a21faa27e3bb61d3ad5b5381270209fc50ba7b709c40df4c02fe5c7865b7881aefd4bafbce90abd24f45d058beeda22d94eb6ebc388a9695", - "tags": [ - [ - "e", - "a08a26900f0c1aedf142e61d122abde0f764ff5fe61cf5660c61547a9ad0f79c", - "", - "root" - ], - [ - "e", - "4e2cc89c76dd14bb69fb38d2c6faec03f85f1ef0ef40227ccbbc3c7b05e6e3e7" - ], - [ - "e", - "56ea1f92baa9008920ab905465776d55cf623539069f406b0cfb057fd5442ef7" - ], - [ - "e", - "1dd32c99b5e875b90617599580270c16e2f7e3be233f029bc73345eb591ba294" - ], - [ - "e", - "3ca18ec56b18d5c17bc31576b80edb9ba355b4cc82dc7fb671effbdf90a79562" - ], - [ - "e", - "682a31ccafec8eb46dc6ae3b8e94471e6d4bf2f98289236e164481f50cd76630", - "", - "reply" - ], - [ - "p", - "ec9bd7465546ba061f5dfde716a4f20f3f27ecc28ca4870775e5e853df11a9d0" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "That is very weird. It should definitely work. I will investigate. ", - "created_at": 1690132862, - "id": "3ca18ec56b18d5c17bc31576b80edb9ba355b4cc82dc7fb671effbdf90a79562", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d35335a2ee1d8b813b5a63bd86716561356de9c0208162927e3efb1ec6cbb89df04d3d7ceada1c71848d7456037999df947e55a17a7083960b362ba252d2b246", - "tags": [ - [ - "e", - "a08a26900f0c1aedf142e61d122abde0f764ff5fe61cf5660c61547a9ad0f79c", - "", - "root" - ], - [ - "e", - "4e2cc89c76dd14bb69fb38d2c6faec03f85f1ef0ef40227ccbbc3c7b05e6e3e7" - ], - [ - "e", - "56ea1f92baa9008920ab905465776d55cf623539069f406b0cfb057fd5442ef7" - ], - [ - "e", - "1dd32c99b5e875b90617599580270c16e2f7e3be233f029bc73345eb591ba294", - "", - "reply" - ], - [ - "p", - "ec9bd7465546ba061f5dfde716a4f20f3f27ecc28ca4870775e5e853df11a9d0" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "Does it stay on after you Mark it all as Read? Sometimes very old messages arrive and they are all the way back in the list, but they are still unseen for that person. ", - "created_at": 1690132343, - "id": "82ed575f4d9bc4f19660e277890c34ff4f0aa0d023b86d91fbb809d3457483e2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5c3e81917835a58561b20a6d559a85530aface929422fca1c06e837975932c33124217e5073a13e251fa8ec8d7aed6ccc5aa3fbadf7f996743a9018f21d275bb", - "tags": [ - [ - "e", - "a08a26900f0c1aedf142e61d122abde0f764ff5fe61cf5660c61547a9ad0f79c", - "", - "root" - ], - [ - "e", - "4e2cc89c76dd14bb69fb38d2c6faec03f85f1ef0ef40227ccbbc3c7b05e6e3e7", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "ec9bd7465546ba061f5dfde716a4f20f3f27ecc28ca4870775e5e853df11a9d0" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ] - ] - }, - { - "content": "Back button? That's new. Any particular place? ", - "created_at": 1690132236, - "id": "56ea1f92baa9008920ab905465776d55cf623539069f406b0cfb057fd5442ef7", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ee7f13431181d04a1c8b0ce211c2ee788c2890a978f35636c8fde70fd1bd56feb16230f40c90eabf1b6ea3016d324d08e09b24e5513dfccc334ff5489e29b217", - "tags": [ - [ - "e", - "a08a26900f0c1aedf142e61d122abde0f764ff5fe61cf5660c61547a9ad0f79c", - "", - "root" - ], - [ - "e", - "4e2cc89c76dd14bb69fb38d2c6faec03f85f1ef0ef40227ccbbc3c7b05e6e3e7", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "ec9bd7465546ba061f5dfde716a4f20f3f27ecc28ca4870775e5e853df11a9d0" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ] - ] - }, - { - "content": "Same risk as using SimpleChat with the same outgoing IP for all contacts, right? The relay can bundle your messages/queues. ", - "created_at": 1690131040, - "id": "5a97c5a5397b6f222d660713269dbd08ef14933f1868d5f20edae897e0be5ac2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "432af5b48d193d0d069dcf2b292edceaba44f0381df378d1e491a9ba5d84a4e0c2d5f755f8a9e8df0c8d55cef22b189014c7a0a138b4119d1a3e9a4b2f814c06", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "1fc5133e2cf877c6dbb2ce5478a5780fb252c77b7683b7871d4944e1f309c82d", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b7ed68b062de6b4a12e51fd5285c1e1e0ed0e5128cda93ab11b4150b55ed32fc" - ] - ] - }, - { - "content": "+", - "created_at": 1690130924, - "id": "ac1fa90872d0848def9120db1cb0ee16fc13e90b4e5725365fea651d7a939737", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d8a4cc59e04de535673bb2eeddd7a65348d8daaf3d5c7c694cf4a0df2f1af7ed7d74f7f0d075264e77144932b9701f7fdc35eb2ef089837c59d2b376e80fb4e5", - "tags": [ - [ - "e", - "1fc5133e2cf877c6dbb2ce5478a5780fb252c77b7683b7871d4944e1f309c82d" - ], - [ - "p", - "b7ed68b062de6b4a12e51fd5285c1e1e0ed0e5128cda93ab11b4150b55ed32fc" - ] - ] - }, - { - "content": "Simplex doesn't want to have a link to a known identity like Nostr would have. ", - "created_at": 1690130888, - "id": "273b7d10c62906e48866911ce18fe3735099bc1f2b352e1c7b8a6f26195d0cf1", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9014e9eef179975957e241cbcab1e9b5ffa04b9a527b3447b67dcc17946a8fab0209c384badb255d9e81c7e22a44c1402f8699d794e4fbdfcec22b0db2acad8e", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "0df509f7198ea50bd1e62d3a63d876f64180ab31752b6271facf16e34a6bbaea" - ], - [ - "e", - "cdefd0a3c55e3fe120d6a4fd93666a04f9a94e3349f47e9ccb39c57696e0af38" - ], - [ - "e", - "a34f5bf152db8de7cd90c7dba18ddb1ce8ca0309b778af5db99dd9e0afd0055b" - ], - [ - "e", - "1c3241c983d9423dd321ed6cacf17012a38b3a637e1d886a19f21f068a6be1a2" - ], - [ - "e", - "26929187391d11f6428433b304a0d19e72c3766a405cb31edf54f5a6b668db6e" - ], - [ - "e", - "f71fdb383382be27b75a45c8d201f43a9086a5704fc948165d428b52f3fec539" - ], - [ - "e", - "5bfcab4ddb3d59528974588f1c16a1e7633d7720e2fe8ed370e856c20b57882a", - "", - "reply" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "c0605aff47b9330575f4865671528832323c6d0a8320a8568c9e044272e266c5" - ] - ] - }, - { - "content": "We can rotate keys, but if you discard them, you won't see the messages address to that key anymore. In all cases, you will need a collection of all your past receiving keys to move to a new phone, for instance. ", - "created_at": 1690130151, - "id": "f71fdb383382be27b75a45c8d201f43a9086a5704fc948165d428b52f3fec539", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ffc4b2fd51e22628d66fdf10f01b93551a6ed69c42f115f9e880858b13445e87a913a569ac1832c6394d9658fd600dafa297c13b9228ae3b9bc06c251f95c7dd", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "0df509f7198ea50bd1e62d3a63d876f64180ab31752b6271facf16e34a6bbaea" - ], - [ - "e", - "cdefd0a3c55e3fe120d6a4fd93666a04f9a94e3349f47e9ccb39c57696e0af38" - ], - [ - "e", - "a34f5bf152db8de7cd90c7dba18ddb1ce8ca0309b778af5db99dd9e0afd0055b" - ], - [ - "e", - "1c3241c983d9423dd321ed6cacf17012a38b3a637e1d886a19f21f068a6be1a2" - ], - [ - "e", - "26929187391d11f6428433b304a0d19e72c3766a405cb31edf54f5a6b668db6e", - "", - "reply" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "Not if you need to save all these keys somewhere (locally or on the cloud) to see the same feed in another client or device. That's what SimpleX does with the local database. Keys don't leak randomly. They leak when you are inserting them in a new device/client or when somebody gets access to it. If you keep your keys and the local db together, the attackers gets both. ", - "created_at": 1690129188, - "id": "1c3241c983d9423dd321ed6cacf17012a38b3a637e1d886a19f21f068a6be1a2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9378974e955039364618a0ad76df16e4c2ba1e18fedbca954896008fcda96ff469886df88c648d5590e99b6849f8d188a959731ecdab7f191554a66696bc2669", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "0df509f7198ea50bd1e62d3a63d876f64180ab31752b6271facf16e34a6bbaea" - ], - [ - "e", - "cdefd0a3c55e3fe120d6a4fd93666a04f9a94e3349f47e9ccb39c57696e0af38" - ], - [ - "e", - "a34f5bf152db8de7cd90c7dba18ddb1ce8ca0309b778af5db99dd9e0afd0055b", - "", - "reply" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "The new idea does use ephemeral keys to send. We could do ephemeral keys to receive as well, but I am not sure if it actually adds much security. ", - "created_at": 1690128558, - "id": "cdefd0a3c55e3fe120d6a4fd93666a04f9a94e3349f47e9ccb39c57696e0af38", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ea935c0dce11832e87a7dee58bead19a6fe74eeaf4dbfda227f82501ba4b8da987eb9644e4fa6feeae8e5da99670878fccea63b351267fa5b732859f121bdc25", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "0df509f7198ea50bd1e62d3a63d876f64180ab31752b6271facf16e34a6bbaea", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ] - ] - }, - { - "content": "I don't see it. As long as there are two clients doing DMs, we are going to have this issue. We only need two good ones that compete well and people will be lost. It gets attenuated when people use a client on the desktop or a tablet and another in the phone. They want to see the same feed in both, at all times. ", - "created_at": 1690128385, - "id": "43baea1d165172f1fb7ece392e3d227921d7a2558e0ae25bc29a39c9889528bb", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6899b4e30252916d97848ea0f26bf89834528e7d1fc47c566c61a16246f32f6041db75a44c62e5fce44f3cae02a70d2ffbab6b58982f649411698f9425a23956", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "cefaf39fa34dbc1e01b28930f269af13d9d77c90b2e121f6166b4a7933c998a2", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ] - ] - }, - { - "content": "SimpleX chat relays do keep your messages for a while just like Nostr does. And the receiver also has a copy of your messages. So, it's not that different than in Nostr (with the new idea, dropping step 4). ", - "created_at": 1690128254, - "id": "ceafe9e1ef47db0d1a62dadcfd38dc621121beb555a5937579832d3dfb5cbcd3", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8d5efb0bbce9a5c0cc7fe2855e2d33747a2c904fa2c37fc2bdefbad2fcb8a196f3a649fb658dc87e8268bdc6c4eebc24638c78149ab0e62f4a8811fabdb910cd", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "f1208fe67ea4647e66f4c1245c42ac8eb15fa94cb635969b025ac5fec07ab0da", - "wss://nostr.mom/", - "reply" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ] - ] - }, - { - "content": "I am not so sure. In practice, the security is as faulty as with Nostr keys. The things that would cause a key leak in Nostr would also cause a chat database leak in SimpleXChat. And since on Nostr, people want their DMs in every client, there will be a lot of export and import happening, which yields bigger chances for leaking the entire thing. ", - "created_at": 1690127530, - "id": "d1d6ae797dd7a9900dc6696e3bebc884f5d06a523d010e6cad62a70aea755589", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9748ea22ea7336a436133085fa8052a1b60f146ef9ef49bb27676d72e55f047165385fc409a3217fbb01f3178a76deb889674d9cf51a9f657a5fe9693a068f65", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "90c441fe992e9277e2b5ab4cb40c249d1d3ca64f41ea4dd33e1e5734cd6bb869", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "c060b31fe2bbb0be4d393bc7c40a80848a25b8f0e0f382cb5b49c37bf7476cb4" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ] - ] - }, - { - "content": "+", - "created_at": 1690126785, - "id": "0601df915b7a6b6e0aec792879ed95a7c05edea54e339bfa330be013cd9087f3", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ffa70983b791fb19bb5a15da05b4e71b6a9d5d65a7df796e1c7d9633187fb1b52000a21d18c8f8d29ec278bab88bf159c24a1620ac0b64cfdd95836951c43cef", - "tags": [ - [ - "e", - "0001d512384cff57a0a051ca705e2913269c8d7ad2563f7717f988acde2e0d71" - ], - [ - "p", - "2ef93f01cd2493e04235a6b87b10d3c4a74e2a7eb7c3caf168268f6af73314b5" - ] - ] - }, - { - "content": "People can opt out of the 4th step if they don't want to recover their own sent messages. \n\nI am not sure if there is a practical solution for the DM history leaking issue. If people want to keep their history between clients, they will keep whatever is needed to recover the history together with the key. Once the key leaks, the rest is also leaked. :( ", - "created_at": 1690125971, - "id": "8e763cfbd52dcae5c9d14e772a36d1114ab129b9d1fee0725387d4979f43af44", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9da781d49e1d952b4f11633bbb67e22d4ecd54460f9d3ff99ce5908b83d49f4d123dd9996a62cc65090279a9c3798bc913d5aeb136d53e9faaa59eb0b2d0c06e", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "ddbaa33cfe39957dfb381ad963d74951902bb907f9c07e167c2e336a27d34e95", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690125054, - "id": "9f7e02cb022e9efab2fde0dd13493ce8c9753c4189be3e057cd3ce88d7a03c93", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "224e654f8599b4f25e53dfb49462a359bcddd37ff5c9e0374e11b538cdef9641e7197babc7984de626577b10940c54ece892f6824ee49548d6e541a756ae5cff", - "tags": [ - [ - "e", - "098f01242f5d18f7dfe622ed292090b7c008c55f8185e5b972cfdbb8df7a4c00" - ], - [ - "p", - "ae39bf0aab59bfb1bacc784bd7b230ce762a671eb33d5c0c586ef7e96c8ae25f" - ] - ] - }, - { - "content": "Yeah, I need to figure out how to use less memory. :( ", - "created_at": 1690125040, - "id": "b735f0cc3f6fc10d2a15bf6da690ffd8f94e1f03cc7ea24869b14b10d7fe8533", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2d709feacb2657707eeb80219d626cc397ddb8815bf5b28aa5592f486d66e45dd2163682cefbf063a263ae4079e0d482c685fbcd2832c0849fed9c310b702aad", - "tags": [ - [ - "e", - "e362d1324f7672556d6e8fdfbac3fc3a26906abb2b32824b43ba1d2fb80305e8", - "", - "root" - ], - [ - "e", - "a122d53b0340257911cc8e2f7d940279dd5e4100a708b70c9b3dd20eced7f18b" - ], - [ - "e", - "a38e734e65750bbdf679e6564f52e49a19ee8424e590319935f05625820c83be" - ], - [ - "e", - "669c66fe822ba472e5b4b603409f9116badf3a1af439de357c9ec159b894dde4", - "", - "reply" - ], - [ - "p", - "269b0b280b99e4724daf5718a6c8e412c59269cc472a70b472b1acf0dec91bca" - ], - [ - "p", - "356875ffd729b06eeb4c1d7a70a1f750045d067774d21c0faffe4af2bf96a2e8" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "Yep, just an extension of that. ", - "created_at": 1690124736, - "id": "8d4bd3ea01e934d6553372da70175e07fb63708e34cd2cd6e99b903d7eecad32", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fabc98d48f0f3a3910418899c1eed968ca9b15f7b2b4cb19c32934fd4ae83cfcfc480e26e074fd091d331ada5dfac6689350921c6df53bfac7a40998ac6dd6cf", - "tags": [ - [ - "e", - "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "", - "root" - ], - [ - "e", - "38a91f7ab267336f20745f74312d4dba3fad6c8a965cd61aa8b294e86e7b4503", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Isn't this better than SimpleX Chat's protocol? \n\n1. There wouldn't even be a queue to correlate messages on. Each message comes from a different random key. \n\n2. Send and receive payloads can be separated in time (the receiver sees the DM immediately, but the sender logs the message, or better, a group of messages, in the future or the past inside Nostr relays).\n\n3. As we add more private event kinds, the anonymity set increases. The public won't even know what is a DM and what's not. \n\n4. Yes, anyone will see that you are receiving \"things\". But GiftWraps can wrap Noise (events that don't mean anything and should be discarded upon receipt). No one will know what's noise and what's an actual DM. \n\nhttps://github.com/nostr-protocol/nips/pull/468#issuecomment-1646858226", - "created_at": 1690124517, - "id": "4591adeb9ecc789599b3f20f51714fbd005c5b38943f91b5ee1174443a63246d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "86eb89acac53fd87f975c1b3799113c9841ee92c0802a15547e9ae6f4914233a95224a1364c087434e758f57190229db17fcc1d8a45951d785824bed063beac3", - "tags": [ - [ - "t", - "issuecomment-1646858226" - ] - ] - }, - { - "content": "Really? Hum.. I don't see any crash reports when writing messages yet. Is there a particular procedure that I can replicate? ", - "created_at": 1690123683, - "id": "a38e734e65750bbdf679e6564f52e49a19ee8424e590319935f05625820c83be", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2bd6a3dc8b8e16a2a3474e59d2b7fb8052dcc374cbaf2cbf387306fb8b482e54f972a29ff2ce8e9fa4acf872334e322dcb0ac02498862c4f96940e28f7e326be", - "tags": [ - [ - "e", - "e362d1324f7672556d6e8fdfbac3fc3a26906abb2b32824b43ba1d2fb80305e8", - "", - "root" - ], - [ - "e", - "a122d53b0340257911cc8e2f7d940279dd5e4100a708b70c9b3dd20eced7f18b", - "wss://relay.orangepill.dev/", - "reply" - ], - [ - "p", - "269b0b280b99e4724daf5718a6c8e412c59269cc472a70b472b1acf0dec91bca" - ], - [ - "p", - "356875ffd729b06eeb4c1d7a70a1f750045d067774d21c0faffe4af2bf96a2e8" - ] - ] - }, - { - "content": "Each page has it's own setting. You need to change it 3 times to get the result you want. ", - "created_at": 1690123610, - "id": "b6fc9e80837196ee50661ec7dccae9e4780efacb2f1c041eebced362819e9066", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d206951c7acd7ccbadad68edeeabdc91952600c8f438055fd57a0d096c2192e73c28fce4b78cca04f04a8b249b762997cb2242c589af79090ac2f4e5e994f99f", - "tags": [ - [ - "e", - "c26effa4ceb95606db038a88d7be714328a4819be98e52fc7536c8deaed67b14", - "", - "reply" - ], - [ - "p", - "ae39bf0aab59bfb1bacc784bd7b230ce762a671eb33d5c0c586ef7e96c8ae25f" - ] - ] - }, - { - "content": "Yep, block is local. Report is when you let everyone know about a person or a note ", - "created_at": 1690115660, - "id": "d35a705e248e0d748938bd403a3041895396babffd227e41eaae2c8006a1929d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "44fb41d3992aeee7343a65c3ef11abbd34b6399c8fc7fe244e2a0f23e928ea78b7c9f68470358f8e165fbda7e68c088b754b2942e19c362c1eb0212df6489977", - "tags": [ - [ - "e", - "c038888ec69c6c8987f5b2dfd224ddb55ca039689b0a20a22287303ef8894f36", - "", - "root" - ], - [ - "e", - "e8091b484dff5afdf25f0f4a4d1199944cb1ee13f3938f78030fccbd6da92a33" - ], - [ - "e", - "806796cf44e651a4f91b9e3f645024a1df19e0fa62aa95db444e15e8939377b0" - ], - [ - "e", - "121b4044bc989a3b0139372d7ccf27890fea3a5b77af370311f778ea57695bf0" - ], - [ - "e", - "ab1d298ae27795f0fea2c9446fabbbc41b2e5b6a127bf4f200598a71295eb569", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "0c9b1e9fef76c88b63f86645dc33bb7777f0259ec41e674b61f4fc553f6db0e0" - ] - ] - }, - { - "content": "Fight free speech with more speech :) ", - "created_at": 1690114179, - "id": "121b4044bc989a3b0139372d7ccf27890fea3a5b77af370311f778ea57695bf0", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "56f0634768de22c8bf3f396e30f3249ed6a3f6d68be81ba9c61f82d77b92699f58320a0f59be3c69aad77b81287af066211ac43f298942940fa2846fcf412671", - "tags": [ - [ - "e", - "c038888ec69c6c8987f5b2dfd224ddb55ca039689b0a20a22287303ef8894f36", - "", - "root" - ], - [ - "e", - "e8091b484dff5afdf25f0f4a4d1199944cb1ee13f3938f78030fccbd6da92a33" - ], - [ - "e", - "806796cf44e651a4f91b9e3f645024a1df19e0fa62aa95db444e15e8939377b0", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "0c9b1e9fef76c88b63f86645dc33bb7777f0259ec41e674b61f4fc553f6db0e0" - ] - ] - }, - { - "content": "", - "created_at": 1690113754, - "id": "dc34c01e8f71b64c206ed9ef324beed9b233a298f8df3227702b0ed2907603fc", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "789c4078488b2eecde89c63d63ce93f8a6803cc704728465d3ab4657128474de9b17cb12eb8b8dcf03cd0659c1d34e248829ab3f6358f079baf3d71817a1aae4", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_d829c52bb54e2125989bc4c7876c2523f0c7945e20ed1f59.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "a61a285079ad066ed4a31e6dc59bbd6e187c32225c66895342f7ee6b82121a5f" - ], - [ - "size", - "2054861" - ] - ] - }, - { - "content": "Him: I don't fall for placebos. \nAlso him: \nhttps://nostr.build/av/6a92ccde091c71316a28f8652a40147a82d7e573076414095cac12b9d2a3b1aa.mp4", - "created_at": 1690113542, - "id": "ad1d69d0565ca03d3329fa91e93e7d5e7ec21df3d8729ab8b8696379f04605ed", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "95758a89bbc4251e022aef31d0e5f98b342e26f20889e836e39ac59ea8f02131897053ecf4b9e2cdde66ff78dbfd209afd35f0dec754e0f6707a1a9974e7d1a3", - "tags": [ - [ - "r", - "https://nostr.build/av/6a92ccde091c71316a28f8652a40147a82d7e573076414095cac12b9d2a3b1aa.mp4" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690112771, - "id": "6b5de9eaa52f1c889dd1c49b44696a53709d119784f3b8859b27b350d75df2e4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3e79410fae3b7223997edc61a6da17df8ec3978723a2931680d8636b64e7cb9ed420d0ec275aecd2f7733df56978166ae568076f106b1cc1ac81ed01c0236950", - "tags": [ - [ - "e", - "ad079dc69fee2dd362bf444404e71b71a4709b790bdf7cc45c4a38b95c9b87c2" - ], - [ - "p", - "ee6b33fc72adf103af33ce25a018179e4458e79d1e898bbe8d460eaa7818bb90" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690112700, - "id": "ed1aab29b697e44b5a6237e7859df7e8217b8d2f42627be6745a7031774e6939", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6cdb924b825c5982738b2bf16090f49356fd76eedd098c8153f6071164cc8d8c53956d385f8fd7f7f1e26cb5f35ac3f07f27f3128dd122efbcba58bcc4c061a9", - "tags": [ - [ - "e", - "b69250498d25feb15d65e2e8270154a65cc241593be32cce4efd299c78619e99" - ], - [ - "p", - "a12fb7fe051724a34ef3409ebcdb377b9d1157a79b7a2fcd8d008995f190d9fe" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690112681, - "id": "0bebf55a12f843aa3fbdac0481db0939a5926561f1d76a0a3c7ce3d8cb3cafde", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "952547cddc189995dc5aa3b2b34e4c21d540d7cb3203eee559419feaf7f97b4415f00a51dcbb8a719ae7b8d3de87990ccb6448622a64489142cdd5dae0bf6577", - "tags": [ - [ - "e", - "b5a56ca5ca5535609b08a9d1f7985cdc0c96d7ecf5fad484145ad0b1060575ae" - ], - [ - "p", - "be0435d2baff7c44dcf0c38ff53a26720f2729660141a5dbc0dbcc25d0cc619d" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690112674, - "id": "3d1f0707a14218b295716537e7ee77264da6f380f5f868f66e625c83e9ae4e95", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9b4e2c701c7f36b0de297227d627180594010e157a199e9801db8f869d99e4d6e8baa5693ab30e5aec75bc35b0496868ac79373b170ce211992964383c49bd45", - "tags": [ - [ - "e", - "40970fd0dcec2d6e95fcc70385b37cb4387d234acfe7ad483ece089072e5adb9" - ], - [ - "p", - "31da8e96a0d372f657280a3b678c5c8398b053d0891d458b7c8b0a752737a9e0" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690112212, - "id": "e24e855089aa4769587b61792cab3314a521703da921197aa80543b6d6a4a778", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b1fae809b4a20dd954f78877c33c872c647fb73043c945c7ccf24355f95b73bc382a2b3490f87791b320633dcf307c4178ab9bd4a8a416c7673f6dc13a10d779", - "tags": [ - [ - "e", - "9ab63d4a2a5d3c5154f1da7359cc4dbe78be286e120e863b3d5ea7aa0ae8d23b" - ], - [ - "p", - "3a5ccf9f1eced28f3a34db176054f17e0fe25492a33d734b4c0482a09a275eca" - ] - ] - }, - { - "content": "Report is part of free speech. You can say whatever you want. People are free to react to it. And then everyone can react to reports. \n\nReporting is part of Nostr, not only amethyst. Many clients implement it and relays use it to delete users and posts. Amethyst just displays them for everyone to see. Hiding it won't solve anything. \n\nOn the warning side, you can disable warnings on the security filter screens if you don't like it. ", - "created_at": 1690111912, - "id": "e8091b484dff5afdf25f0f4a4d1199944cb1ee13f3938f78030fccbd6da92a33", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "26b2ad6f938e396084629c10d48b85835bc4f0571fdcbde974e5b0eab052cd0f829265bdc80efd86790adb8ed2e51207dc6ca467d62bc8d949d8cfeccdbeacae", - "tags": [ - [ - "e", - "c038888ec69c6c8987f5b2dfd224ddb55ca039689b0a20a22287303ef8894f36", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "0c9b1e9fef76c88b63f86645dc33bb7777f0259ec41e674b61f4fc553f6db0e0" - ] - ] - }, - { - "content": "Change the keyboard. Graphene uses a very old version of the keyboard that doesn't work with newer UI frameworks. :( ", - "created_at": 1690111377, - "id": "600b878282a93e2fbd1533727127ab4ab3473fbe0fa80c263e9877bdba46e912", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5ad458d6a0de654da1370b0e88b6ad2478182e78a05c7c4d0df5d089863f4aa70f0683ad871f96b89f7b87af7b68c6fc9893f9d7a4ee393f99b579fd73eef712", - "tags": [ - [ - "e", - "6d195bd88b4a7d4b3522a862fad439d4351e0bc87659a5d50a34aea8c8499e1e", - "", - "root" - ], - [ - "e", - "1ee94a94cc5028a217a1d8159454145ccdaceb73206cc85791ac47d84d79e1ca" - ], - [ - "e", - "c9045bcc1bbba5a5934ca475cfb9b6eb94dd7863b4d56c841d4e0f112d541882", - "", - "reply" - ], - [ - "p", - "27154fb873badf69c3ea83a0da6e65d6a150d2bf8f7320fc3314248d74645c64" - ], - [ - "p", - "27154fb873badf69c3ea83a0da6e65d6a150d2bf8f7320fc3314248d74645c64" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "3a5ccf9f1eced28f3a34db176054f17e0fe25492a33d734b4c0482a09a275eca" - ] - ] - }, - { - "content": "Nostr is open and all reports are public. Anyone can build this. And I can use as another input to the filter. ", - "created_at": 1690084953, - "id": "de7c95cf799612ee6fb6f4e4d3d353e765fced03e8176ad112433e12c9950c08", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9cde5c0b0ad14f2d7466ae995af622562284576202b40ebbea462a67fd763ae25a54fcb83ef43709146f9e088cdeda3fcd9490ce167052d61bd1f5e3f3a914dd", - "tags": [ - [ - "e", - "fd2f4cd8122c3af6871458e7939c14a589d3af0fbdb0cd27208dcc67cf98df7c", - "", - "root" - ], - [ - "e", - "595c5a0f0cb5b6d06a0a7219c62d11a4283e122b3469fdc5bb57ed30e4ab25cb" - ], - [ - "e", - "c65fe276c2338588773707dfa2294a313721594ec93a04d6078624ebd2d13632", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ba2883fb4a7f62cb851b9f5411659791cffb2e3fc8b90f683ee5091f413880a1" - ] - ] - }, - { - "content": "Just build a system to expose false reports. Fight free speech with more free speech. ", - "created_at": 1690084772, - "id": "595c5a0f0cb5b6d06a0a7219c62d11a4283e122b3469fdc5bb57ed30e4ab25cb", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6f63e1c98bdb9b2fa9d34c47afe17a06d0a5d9da12c1c4d37355952e34ff4db9e0707514a73b4f86b7c4190584f4a31c7a2124493ae088eacc61f02c81779bc3", - "tags": [ - [ - "e", - "fd2f4cd8122c3af6871458e7939c14a589d3af0fbdb0cd27208dcc67cf98df7c", - "", - "root" - ], - [ - "e", - "b2231c9bc27017f9f57892ef75eeeba2a31a255e43401b689ebf3660caa6b22c" - ], - [ - "e", - "20a22ad4b7db92df61d4f8338846a3b322612d52efbd60a9cfc5c8d6aa791acd", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ba2883fb4a7f62cb851b9f5411659791cffb2e3fc8b90f683ee5091f413880a1" - ] - ] - }, - { - "content": "Nah... We have too many kids with the app. By default, the experience should be conservative. They can open it up when they are ready. ", - "created_at": 1690084580, - "id": "b2231c9bc27017f9f57892ef75eeeba2a31a255e43401b689ebf3660caa6b22c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e0cf116ac3872a4af3ea99bb84255fa46a6d0e99054a00936c5bdca4912d31c37f4687e27af77b17d4a3919c66de87ec709ce6d1432806e68881b54167ece253", - "tags": [ - [ - "e", - "fd2f4cd8122c3af6871458e7939c14a589d3af0fbdb0cd27208dcc67cf98df7c", - "", - "root" - ], - [ - "e", - "094aced9e82bcf37d554a6967aeef0f7cadad963ff6f84495b16b26269ddbc26" - ], - [ - "e", - "07cf4cfdccd7746e1dec48784a78569d106efce752d6dd0c0b196c1c395613d4", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ba2883fb4a7f62cb851b9f5411659791cffb2e3fc8b90f683ee5091f413880a1" - ] - ] - }, - { - "content": "Allows people to block you, yes. That's not censorship. They can always opt out if they don't like it. These days, we even have a list that only shows the blocked feed so users can confirm they don't want to see your posts. ", - "created_at": 1690084378, - "id": "094aced9e82bcf37d554a6967aeef0f7cadad963ff6f84495b16b26269ddbc26", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f0bf30ddeaf6e19c1a13146c98142d36b3559a909d330c866e1e2a9abd196801a88440a31cca574e7da2b1ce8f37c2f57374b720a570fda697b25e1aa54a2041", - "tags": [ - [ - "e", - "fd2f4cd8122c3af6871458e7939c14a589d3af0fbdb0cd27208dcc67cf98df7c", - "", - "root" - ], - [ - "e", - "52b562f2f95654d2b2a84b742285337eba5cc400ffc33bdbe21e7ee4a5f6198c" - ], - [ - "e", - "7994583bab3bde80a01b4a9b8703913eacac1e4fe7ee20cb21220ea5b5605bfb", - "", - "reply" - ], - [ - "p", - "ba2883fb4a7f62cb851b9f5411659791cffb2e3fc8b90f683ee5091f413880a1" - ] - ] - }, - { - "content": "We also need a data heavy client to make people accountable to their reports. If a report is false, everyone should know about it. Falsely reporting people should damage your reputation. ", - "created_at": 1690083028, - "id": "52b562f2f95654d2b2a84b742285337eba5cc400ffc33bdbe21e7ee4a5f6198c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "39e55f79a467361e56eb2d1cd49c321c99965855af3e0a976605b0fe494b7b1a963a1ff122baee02c01573c0665b5025e990258105816e75f3e0ccef764d630e", - "tags": [ - [ - "e", - "fd2f4cd8122c3af6871458e7939c14a589d3af0fbdb0cd27208dcc67cf98df7c", - "", - "reply" - ], - [ - "p", - "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" - ] - ] - }, - { - "content": "Hum.. I am not sure what you mean. The domain is clickable right now. There is no expectation from clicking the user name (there is no email or web address we can point to) ", - "created_at": 1690079870, - "id": "bde7b3599fde0d7a80a96b20393563382c5d1c622afb062940b0770ce1bd7e7e", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "201da0302b41f0b1ad45c723870c6b82a2352eea67ee890cedbeef394e8c32536a7fa3117e4057972002891e7f89bb3bec60214b14f3bb02a0e94295a87ffac6", - "tags": [ - [ - "e", - "f2845de7cb2d774af657ce57b2886debd9b5b9bec9660664bd40910ade0bc769", - "", - "root" - ], - [ - "e", - "f90bf3162e5430fa9398709f39c9fee0b81b175ab4fdc26f648b1c90fc5caa17" - ], - [ - "e", - "d5a7523bfba9a9d6144fe3f6de462555b6b4ee3aeb6e581ab308003bfb9d4660", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89d1ce9164f1f172daaa9c784153178cb1dec7912bf55f5dc07e0f1dabe40e6c" - ] - ] - }, - { - "content": "", - "created_at": 1690063233, - "id": "a0b29a3283c10b5bc63632e9d4e6554e46580b6320513a62da68c8298f464cc1", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "44aa72f7f5644f6f3f07e7ab5c76f00c2bf7621e6ff172743591672bf70a27e0deb5961b9e043c4bd3e95007320d75c470cd283b799b9cf8f9022e987465d86f", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_581d924e2f04b41cf2bb258623ec6800a7420f83bd81ff44.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "9180a00d8de2209c1d2623af0b5a492471f967d080e6620ec28e6f003ffb49bd" - ], - [ - "size", - "2371930" - ] - ] - }, - { - "content": "Spam :) ", - "created_at": 1690062330, - "id": "9edeca1c1c29db5cbee94c2f38637eb46774b84dd52c9d2a6d5910c8352d3898", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "071c1ff194a234f1009628994191b3e77a22874a68dc4d82e799d2f35f6c6f9edbe83eb79ad07fda3b8fd096fa83c938d340c49fc271bd197ecd640978c4ee74", - "tags": [ - [ - "e", - "ff460e6c65591f7c43bca28d26c9d67e01d32743e7b676abfdb54e7378c3b9eb", - "", - "root" - ], - [ - "e", - "93fec67f101706b4ab832466153df265c75593fbea8e3ef302410710fe833a56" - ], - [ - "e", - "bb953fe6a64516caa9a0c2285a29e5ded168572be6cae1f3daa63bd8321965f9" - ], - [ - "e", - "aa6f251e957f4ae00f0596359f3185b9579c3602e351bfdb0dd10da1ca3c2c44" - ], - [ - "e", - "be4b56d812d4ae5f1c31b147b18be3b60bbf3cbdf636a4f02e61fd850cfecc9c", - "", - "reply" - ], - [ - "p", - "ae11573ff5b6d1fe250da805e8278b8d7488052a84a3463f110c9cf2e920243a" - ], - [ - "p", - "5fd693e61a7969ecf5c11dbf5ce20aedac1cea71721755b037955994bf6061bb" - ], - [ - "p", - "c75160732ebd0d6f98238ffc4f87a269841b05f7ef5b008f0a6eb7d8b3235b35" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690062314, - "id": "f2e1535fb76026dc640c6a9ee171637553fa45a7beac7be1d61c59727f421a94", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "94953d6006f0d76f29f5b4b097ffdd3ef3becccad9020b1ef4620a3d567c085c5eda72fa139ebe845219e4be1b33ee54b78735df4ae9eafb563746d717de46ce", - "tags": [ - [ - "e", - "d84e9c154142dfb6327e6003358822b808d1e13f64d6be4182b05b97e4cd56bb" - ], - [ - "p", - "c75160732ebd0d6f98238ffc4f87a269841b05f7ef5b008f0a6eb7d8b3235b35" - ] - ] - }, - { - "content": "That shows that you are following this person", - "created_at": 1690061566, - "id": "f98bf74282c9719d53a89764c270b1338e9d3ee9bc81e48022e7d825bd48a52f", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0af6b4e3005dec7a59105e3c7d038f29c0006930ef934841864e241cb2cac4445e88c2786b7314e6ea4cefa2e172fdc1e8cf2ab2a75831bfd5dffe5e618457cd", - "tags": [ - [ - "e", - "42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5", - "", - "root" - ], - [ - "e", - "370eb5809959295eae9693ee07e1183501363a587f482d8e2fee7044994d97a4" - ], - [ - "p", - "4081035ac927281b3a086d12b6a6aed9f11872a2d82b8f5f1d0706244e84d535" - ] - ] - }, - { - "content": "Those are all from strangers. The spam filter can be disabled in the Security Filters option from the side menu. ", - "created_at": 1690061413, - "id": "8dba54845e5bcee2c3391a34843ac9faefa452961f9cb89c9e70f0233e5c03a0", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "01881e8ad06f625f446c48fdd7ca3ceff54f07c4c52d47c0b0e8c25b896b75879222e9481fe84024d73524d02bcb83eaf67850918202f7ab1e95580034f7d32b", - "tags": [ - [ - "e", - "ff460e6c65591f7c43bca28d26c9d67e01d32743e7b676abfdb54e7378c3b9eb", - "", - "root" - ], - [ - "e", - "f19ab878cd9aed173d5ca6f12fb0036a2bd992091e2f9e13f20887f7442b3413" - ], - [ - "e", - "4daa7e033c8cc3fc6e1e98fce4569c876ffa56897016a92e5e78586bc15a5d59", - "", - "reply" - ], - [ - "p", - "c75160732ebd0d6f98238ffc4f87a269841b05f7ef5b008f0a6eb7d8b3235b35" - ], - [ - "p", - "ae11573ff5b6d1fe250da805e8278b8d7488052a84a3463f110c9cf2e920243a" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "5fd693e61a7969ecf5c11dbf5ce20aedac1cea71721755b037955994bf6061bb" - ] - ] - }, - { - "content": "Yeah, that screen is up for a massive restructuring :) ", - "created_at": 1690060494, - "id": "f19ab878cd9aed173d5ca6f12fb0036a2bd992091e2f9e13f20887f7442b3413", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "db85ee76fb66a3eeee6f8036e283c5fd8974323225a47535014658e08eacdf220d3197997909c80f180b15adb71d4cc0842f5e4fe5280618d0e3d4199f3a8493", - "tags": [ - [ - "e", - "ff460e6c65591f7c43bca28d26c9d67e01d32743e7b676abfdb54e7378c3b9eb", - "", - "root" - ], - [ - "e", - "06ba84837bcda8cc94d9a11f45e2cf0c0998972c4686a17da8b63500be31191e", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "c75160732ebd0d6f98238ffc4f87a269841b05f7ef5b008f0a6eb7d8b3235b35" - ], - [ - "p", - "ae11573ff5b6d1fe250da805e8278b8d7488052a84a3463f110c9cf2e920243a" - ], - [ - "p", - "c75160732ebd0d6f98238ffc4f87a269841b05f7ef5b008f0a6eb7d8b3235b35" - ], - [ - "p", - "5fd693e61a7969ecf5c11dbf5ce20aedac1cea71721755b037955994bf6061bb" - ] - ] - }, - { - "content": "Yep, but on the private side of those lists. Only the author can see it", - "created_at": 1690056576, - "id": "25e3140b1d838154f06ee1f7dafd52d16b52d38bbf679245f65e3ab889758e7c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "adfca8fb093f442e66d51bec2a063f22e7a293157063a8637fb191aa7e41a4f0f1a06e126116dae11027406e958e7dc0d98eacc830281e8a5d3298880e51915c", - "tags": [ - [ - "e", - "ff460e6c65591f7c43bca28d26c9d67e01d32743e7b676abfdb54e7378c3b9eb", - "", - "root" - ], - [ - "e", - "aa6f251e957f4ae00f0596359f3185b9579c3602e351bfdb0dd10da1ca3c2c44" - ], - [ - "e", - "acba23d2aae16f161b6489515746febbf3b3d5a581ab581d464e7b93cbcf5c42", - "", - "reply" - ], - [ - "p", - "ae11573ff5b6d1fe250da805e8278b8d7488052a84a3463f110c9cf2e920243a" - ], - [ - "p", - "c75160732ebd0d6f98238ffc4f87a269841b05f7ef5b008f0a6eb7d8b3235b35" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "5fd693e61a7969ecf5c11dbf5ce20aedac1cea71721755b037955994bf6061bb" - ] - ] - }, - { - "content": "👀", - "created_at": 1690055271, - "id": "3be55d0c79a7803d31aa9aabbc72ee943d253fc4bb9b69655d54163b05a2b9df", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a5f26620c693bbe87a824c60f829a8d9a20afe982224c0e811bcb10c2ad7cea824761da226796d8f53041b25c60e8a7883fda40a8d68770ae826d19d7f8e7c61", - "tags": [ - [ - "e", - "011d95918a2c4fe8c6666784d8229984999126bb24520ef2f3ff2bb799c725fa" - ], - [ - "p", - "5fd693e61a7969ecf5c11dbf5ce20aedac1cea71721755b037955994bf6061bb" - ] - ] - }, - { - "content": "Block just hides the person from your view. It doesn't affect the person at all. Reporting does. Block is just for you. Reporting is when you are warning everyone else ", - "created_at": 1690055267, - "id": "aa6f251e957f4ae00f0596359f3185b9579c3602e351bfdb0dd10da1ca3c2c44", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ac3e68c9002292121c89b7ada44df8f69b54c9f3562c300d6d40b5a0979d293c907ceae39b266db368eb473064772e21f205152445e43c9141132125a649223f", - "tags": [ - [ - "e", - "ff460e6c65591f7c43bca28d26c9d67e01d32743e7b676abfdb54e7378c3b9eb", - "", - "root" - ], - [ - "e", - "93fec67f101706b4ab832466153df265c75593fbea8e3ef302410710fe833a56" - ], - [ - "e", - "bb953fe6a64516caa9a0c2285a29e5ded168572be6cae1f3daa63bd8321965f9", - "", - "reply" - ], - [ - "p", - "ae11573ff5b6d1fe250da805e8278b8d7488052a84a3463f110c9cf2e920243a" - ], - [ - "p", - "5fd693e61a7969ecf5c11dbf5ce20aedac1cea71721755b037955994bf6061bb" - ], - [ - "p", - "c75160732ebd0d6f98238ffc4f87a269841b05f7ef5b008f0a6eb7d8b3235b35" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690048291, - "id": "6ebe2878b5bca21ab869d71278c4ee25f1249a960b5f2c873d97b0a2d5f154c5", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8446c68226f4c486ecb40ca82817ae12eaad2ab31dba5985e16adb1e7a6b39830df81a371367e5ba7a10be2627b5b47f4e8fb02d68726b814a74667213bda6a4", - "tags": [ - [ - "e", - "927c65129de519fafecef2bd2cd75785f6843b2da0ba0697d574131f9953782c" - ], - [ - "p", - "1f297398e7abbfade212d7bf1e98bfbf682064a9a5cea4a5f3de49df63330302" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690048258, - "id": "84ec8afc369b68af39a44177b8a7e7a6146642bb3ebae85485eacf2a1195f4c2", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8be5d9851ee5fc0d0589ef960d1b7f211c6cbed005d06b8693d18f5fcfc1b8949e5353842fa3887de2875b25a528032fc55fcffa43af3df89509a4e28d987bbd", - "tags": [ - [ - "e", - "1de83a4e1cccd7a424ce97f67cc45d7cd2b41766dcca3fd59a59138aa982b9a7" - ], - [ - "p", - "f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690048141, - "id": "8f3ba22a76f92c56e0670f8c47d47d190aef401bfb4699d896d0b575f52ef455", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "bbc4655749a64f7cd973364e9fdd77a94b8900fbe874e140bdc1b7221e7e6a38441aa893ce9c1cdfcbfef91f307233ee6e39aa7e7bff40f5bb782aebef268f38", - "tags": [ - [ - "e", - "661435f046df5f20399924de66c34672eaeaa04f6b5b3c3918a2f74d2c768694" - ], - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "Each client does it's thing ", - "created_at": 1690044425, - "id": "ec0f4b6f3d7f08c2183cc397527b48f47973deba9eec2c77a6cedbf2652cc1bc", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "04e00c840222bbf02da8c15aac1906d2861a123bb4324b84f14e663b3975930d932eb7f85a4d16335a1afcf745577d177b4e81adcd2aa20c14f890eb5e321d89", - "tags": [ - [ - "e", - "e1574ee2757c6443502ad1de2e9bffabe146f6ed0edc15be6cee7fa9725af430", - "", - "root" - ], - [ - "e", - "8ff6ab31d730b8934e6a788be0a686c71ca41985ad87f6d15f3cf2d6ba99ea55" - ], - [ - "e", - "ccc770aa2e496461dd8c328e889e8f4ac3a02e4e2e0496bb083bd280e6bc2266" - ], - [ - "e", - "d4b98b5cdd30cf226fed081467dcd16caf6948b1cd389b2f6d7a1469d36ae864" - ], - [ - "e", - "e1bd0e07369d4fbc9141f767f8d643ef20db243bfbb5f171e1799dbeb33d27de", - "", - "reply" - ], - [ - "p", - "30782a8323b7c98b172c5a2af7206bb8283c655be6ddce11133611a03d5f1177" - ] - ] - }, - { - "content": "Only if you create a list of nsfw authors right now. ", - "created_at": 1690039711, - "id": "04ffa93f7c9c765191f6ff7c33b89870a5521226193b46739d283166e0457493", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8cfb4c7d3ea59ff087f801e6aac44bdb0f82dbb17241caf80f1896df5237d8398b446729456d71c296c47538661c0ee99403e5ce71c2c1d323e6279097720fbb", - "tags": [ - [ - "e", - "21db8800e3654871004b7653e549d5dc9c03028d05abb1c9417bed4405a47d77", - "", - "root" - ], - [ - "e", - "163d779823264345dc473001dba0987423c4c61438ec2b887695ef3f4d18e636" - ], - [ - "e", - "d9a46441a3df57e1549ad2d2d458fa4e95b73a9dc5034a6212e3a61112d58e92", - "", - "reply" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ] - ] - }, - { - "content": "People can just flip the always/never see sensitive content on Amethyst settings. The relay option won't matter. ", - "created_at": 1690038798, - "id": "163d779823264345dc473001dba0987423c4c61438ec2b887695ef3f4d18e636", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0e835e8b5e6e938dfd5ae6f42a7ae6d593725a42bc57985c729e12f709f5128ea83665b051edaa49aedbc50a4c2a91998481a796b3d75bc3509c068d9b534301", - "tags": [ - [ - "e", - "21db8800e3654871004b7653e549d5dc9c03028d05abb1c9417bed4405a47d77", - "", - "reply" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ] - ] - }, - { - "content": "Nip 50 is supposed to be that. But only very few relays implement it. ", - "created_at": 1690038557, - "id": "d4b98b5cdd30cf226fed081467dcd16caf6948b1cd389b2f6d7a1469d36ae864", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2a6152d146f5bdb7bc10e6e86fceee6ec2010c5ecff107b89f51d2dd577738b727f8fcfe6ede555b6a64799454e9f73c68baca41b9d0c18b55c44ac1949e9470", - "tags": [ - [ - "e", - "e1574ee2757c6443502ad1de2e9bffabe146f6ed0edc15be6cee7fa9725af430", - "", - "root" - ], - [ - "e", - "8ff6ab31d730b8934e6a788be0a686c71ca41985ad87f6d15f3cf2d6ba99ea55" - ], - [ - "e", - "ccc770aa2e496461dd8c328e889e8f4ac3a02e4e2e0496bb083bd280e6bc2266", - "", - "reply" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "d61f3bc5b3eb4400efdae6169a5c17cabf3246b514361de939ce4a1a0da6ef4a" - ], - [ - "p", - "532d830dffe09c13e75e8b145c825718fc12b0003f61d61e9077721c7fff93cb" - ], - [ - "p", - "30782a8323b7c98b172c5a2af7206bb8283c655be6ddce11133611a03d5f1177" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690034791, - "id": "5814e68e1a5f5cae768c0661065449b7bf981162b9e31553740a11749df1a668", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1bf9fae5ef84654c3b79598a72396072eb59f588151a132deac8948712774ea4c1f790e47075d7bcdeb09a993011896fa0532e69e5efeca9bee32c7f105d559b", - "tags": [ - [ - "e", - "84179e0bcd619efdd068c9a604f4fb3f1ed158c7798a2f7c8af6b4e1c9f1ab5b" - ], - [ - "p", - "31da8e96a0d372f657280a3b678c5c8398b053d0891d458b7c8b0a752737a9e0" - ] - ] - }, - { - "content": "🚀", - "created_at": 1690034686, - "id": "297d8d5ef9a77a74348fe0e490e515e6912e8bda2173a20ce31f6ceca1dc3c90", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "19e249457e3e695dab747a373dced6fbbf625c39d5212e9f020d73f30e39187b66a232d89cf070e1a5e147f012165fe1d5bde4c45ba4314dea4be43259469852", - "tags": [ - [ - "e", - "47e702b7a6c69e43d5113a0eeb49c2bf934611f3cf7eff98e215d798f53f4492" - ], - [ - "p", - "1c6b3be353041dd9e09bb568a4a92344e240b39ef5eb390f5e9e821273f0ae6f" - ] - ] - }, - { - "content": "Did you try specialized search engines like Apache Lucene and so on? Some of them seem to run very well on Android. It might be true for iOS as well. ", - "created_at": 1690034653, - "id": "8ff6ab31d730b8934e6a788be0a686c71ca41985ad87f6d15f3cf2d6ba99ea55", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d989836b6e209dfec45244ee467ae7a92ad9b6d35b5b31b81884191e81e75a726bc1064901874a463a3f5f63a2c454d00837f5ee668a3eecc4784b923bb3556b", - "tags": [ - [ - "e", - "e1574ee2757c6443502ad1de2e9bffabe146f6ed0edc15be6cee7fa9725af430", - "", - "reply" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ] - ] - }, - { - "content": "Unless you are going to do a massive bounty, bounty hunters will be either professionals with 3-4 hours to devote to the solution or high schoolers with around 10-15 hours of focus. If things feel that they will take longer, they are not going to do it. Neither group will have the time to learn any WoT concepts. \n\nThis means that the more especific you get, the easier the chances of somebody completing it. \n\nHere's a template: get code of server X, add a listener for event kind Y, which runs through the data Z, organizes in this way, calculates a score using this equation, sorts it by score and writes the result on a event kind W and sends it back to the network. You have to give them every detail. ", - "created_at": 1690034428, - "id": "79531a6456980a95d5177bb0904a116b771eef37a374c30621e3fcf6b57edb56", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1fc94a332ae92f993ef384e0613c2a62101776cb910e69c1a818f0fec165c8cd2af1471f514af41164793ca40345c7fbc2c6fbc260de6838040da9f9efd4f7ae", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "622cf2369280653f92b3b47b802feb93038a9db3d1253cbb1af23303fde84c72" - ], - [ - "e", - "084cb0d0d8e7cb6ee7cc3b4e0c14e1746c6192a329e5e644cf2aa42b0702dc87", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "e5272de914bd301755c439b88e6959a43c9d2664831f093c51e9c799a16a102f" - ] - ] - }, - { - "content": "Too many options. Keep it simple. Focus in one VERY simple use case. Fix ins and outs and let them fill the middle. Remove all the jargon. Otherwise it will just be too much for anyone to be interested. ", - "created_at": 1690030365, - "id": "622cf2369280653f92b3b47b802feb93038a9db3d1253cbb1af23303fde84c72", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a67e5db83686746310d721b2896cd14bd36343010cdd4b1e295e38e9b3f7bdd461904912e07f352cfe0bcf34b44f242edfd28cd14e7dc4b1e4bcf6fd1001e7a1", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "311df23c765f2c44322acd39b0838474cd6c911bdbbe5133561a63d7b81c8245" - ], - [ - "e", - "0fc743840d438b7ba2472e9a4c922a72f38ad9822f05e885e48dd5a70c9de141", - "", - "reply" - ], - [ - "p", - "e5272de914bd301755c439b88e6959a43c9d2664831f093c51e9c799a16a102f" - ] - ] - }, - { - "content": "List of posts or other people? If it is people, you can create/update nip 51 lists and Amethyst would offer then as top bar feed options automatically.", - "created_at": 1690029264, - "id": "311df23c765f2c44322acd39b0838474cd6c911bdbbe5133561a63d7b81c8245", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a4fbeb9f8b2f90e3bf578cb6ee7d3e144dee810ed20210a9ac862db0ad501829088fbccf5893a4d9052a6ecc6fb7577e6614d3472e29a742958e3b7fc1b66106", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "c936aea32b162c762c3b26ad7ff303869cd018a55804c28f5486c4545c37b55d" - ], - [ - "e", - "fc9a175bbd853076754d9ea1a3272e089875ded5c03b1d3b7d11e4c567ad1364", - "", - "reply" - ], - [ - "p", - "ba94849433a724544ab6794f79700bc980613aa93bc8c872a59c4f7fb85d36a5" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89e14be49ed0073da83b678279cd29ba5ad86cf000b6a3d1a4c3dc4aa4fdd02c" - ], - [ - "p", - "648c0f5302c75f38382a4d2c85a482b927cc61b2828a0794e36c6cc796de86a6" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "e5272de914bd301755c439b88e6959a43c9d2664831f093c51e9c799a16a102f" - ] - ] - }, - { - "content": "", - "created_at": 1690028553, - "id": "f4c3fa3b4e18028b986728b70fbd4f24747b28840ac2dc880fe128552332c37f", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3b7d8c66c8c7c8db6c12e274e455e072b9964c92915bf51421e421a61fdd0eb7822705a251f6a1faee7c02462bff739d18825f4c06cf23feb231336e0c3417e8", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_77519b031bb3bfe7956b501a01197a9508f376697f378577.webp" - ], - [ - "m", - "image/jpeg" - ], - [ - "x", - "667c8409013988802a168043034a06d4501719aa27ab6ebbc4b825db417f281c" - ], - [ - "size", - "26866" - ], - [ - "dim", - "510x640" - ], - [ - "blurhash", - "_BRfkB%M~qay-;xuofxuM{ayRjj[j[t7_3RjM{xuM{ayRj-;j[RjWBWBj[Rj4nt7%MWBxuRjxuWBt7ofRjRjj[fQ?bM{RjofRjofWBt7%MM{WBt7RjM{-;ayWBRjayWBt7" - ] - ] - }, - { - "content": "", - "created_at": 1690028054, - "id": "ab3df16710d9ccc53c08e9b54232ef0b378e3eaadf0acd0f7649800fd4787857", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3cb3fc0059720310a950543e3f14d84830b3b8ab748e7f29b6d4d8e4ee4abb60858056bcc1d438a2a549da236f83e78cf52ef8488389f4cdb3371c4e1e63c78c", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_4b1b9cad209ed9ce79cec1bea6c76836bef273d9f26ea42c.webp" - ], - [ - "m", - "image/jpeg" - ], - [ - "x", - "d9af8e835f0fe1024bebea6efd45348c6abecc2cd6cb12a5c217061f03cccb44" - ], - [ - "size", - "71462" - ], - [ - "dim", - "700x804" - ], - [ - "blurhash", - "{nK_5qWBogay-;t7%MWB_Naxjsa}RjWBRjof?cWBt7oeM{fQayoL%MofRjWBofj[ayayWAjtofj[ayjZWVayIUoeayWBofWVj[ofM{WBofoLayj[jtayWBayj[j]ayf6j[j[t7oeayayazj[j?WC" - ] - ] - }, - { - "content": "⚠️", - "created_at": 1690027967, - "id": "b69a97ffa74a84b2cd1d7ba53f6b02d4b84024cf32de1c3df6eb7be819ee90f5", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f50ba3ebf9dc452d8ea8862b7602c2837f96b23515caa05222353f82f2c30228f74d942121ab4a1acca3ee2304c501f5d92e1fedf77d0122614f59f40f8f68cb", - "tags": [ - [ - "e", - "2583ec8975b63ddd5c373d2c8bc7bba419362b8c9483945a78214edea52227c7" - ], - [ - "p", - "4796eb254645a3b0db24e77dd7bae72eadfe18fc4c24f2bc6c4e658c4fec4ed4" - ] - ] - }, - { - "content": "", - "created_at": 1690027967, - "id": "08c3212fa15443ee5b0b7c71e0192ec47e79deababfdd5637f7eac30d9d1b387", - "kind": 1984, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e48a9824005948ca96d4b16696a0ea75e255ba1f44a7ba9abf823b14992faab2b57d58b8198b36a3598ea075f2c5d1b38188dc3c4f90ccb8f84a636c1c87ce7d", - "tags": [ - [ - "e", - "2583ec8975b63ddd5c373d2c8bc7bba419362b8c9483945a78214edea52227c7", - "spam" - ], - [ - "p", - "4796eb254645a3b0db24e77dd7bae72eadfe18fc4c24f2bc6c4e658c4fec4ed4", - "spam" - ] - ] - }, - { - "content": "Have you built a data vending machine for that yet? https://github.com/nostr-protocol/nips/blob/67e950a2009e81df1b8c91b0a2ade0596e83f168/vending-machine.md", - "created_at": 1690027938, - "id": "c936aea32b162c762c3b26ad7ff303869cd018a55804c28f5486c4545c37b55d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0a25b1c1855391a31be333daeaea31b0654cf804f0c620b3c44651ab7d59d48816fbd26bd519e0a68ac558d4b9233931f0f20624e91e1291220cda94d67f8c28", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "467b16aa0975ae962b9322438448a5b94d28c9677aa0bf783f0d5a97c85238bb" - ], - [ - "e", - "8ac9aea5873049675b1340276158bd332f955230c7eb3c606a160bb15dad91df", - "", - "reply" - ], - [ - "p", - "ba94849433a724544ab6794f79700bc980613aa93bc8c872a59c4f7fb85d36a5" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89e14be49ed0073da83b678279cd29ba5ad86cf000b6a3d1a4c3dc4aa4fdd02c" - ], - [ - "p", - "648c0f5302c75f38382a4d2c85a482b927cc61b2828a0794e36c6cc796de86a6" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "e5272de914bd301755c439b88e6959a43c9d2664831f093c51e9c799a16a102f" - ], - [ - "r", - "https://github.com/nostr-protocol/nips/blob/67e950a2009e81df1b8c91b0a2ade0596e83f168/vending-machine.md" - ] - ] - }, - { - "content": "Yep, that makes a lot more sense :) ", - "created_at": 1690027857, - "id": "d8c51aa8ff8e880bfc229b556b762a8322d25a0273bf138f55a3bb5a4e6f3683", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "52fdfead0a8c473b7a467a820cfc19f0214f7dcce763223e0c74b35e627c97ae0f86875348592b551f006a8b0ef386d9c5f51c26330a6bd1f708ad7c14244fb4", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "9a88b1aa5e514e33a721a8e036e1e49654b31133f8922d27e9bc71d0f463063e" - ], - [ - "e", - "1326e784c89aae0d495b933710689757ffd307e4193e7de396b04e1b49c194a4", - "", - "reply" - ], - [ - "p", - "ba94849433a724544ab6794f79700bc980613aa93bc8c872a59c4f7fb85d36a5" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89e14be49ed0073da83b678279cd29ba5ad86cf000b6a3d1a4c3dc4aa4fdd02c" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" - ], - [ - "p", - "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - ] - ] - }, - { - "content": "", - "created_at": 1690027511, - "id": "e97c4db1ec0cf8701dae216a0883239fb870ef8e477f0f83c9935c8225d0186b", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "70803168e9f3a53c4f05ddb26ed8d68d716680ae5e77b1c41efc732abce1541adfc5d01b263d868169a0ee5791d69db982944db8ecc48c4f1ffbc8f75b2ff31b", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_fe2f3b78ab59248cd0e65015d39ab827b60f4bfbc1e91162.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "7e9ed8613fb4d077afded5b131cc9238c3e5e9737e85ea697028ee0acf9cd3c5" - ], - [ - "size", - "393081" - ] - ] - }, - { - "content": "No, the kinds to classify nip89s apps by. Right now it's only by event kind. We need to do “I use DVM npub1XX for kind:68001:job-req-feed-generation\"\n\nSo, you can filter nip89 apps not only by kind, but by each individual type job being offered. ", - "created_at": 1690027384, - "id": "9a88b1aa5e514e33a721a8e036e1e49654b31133f8922d27e9bc71d0f463063e", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "95dd34d7ff940ad5e92d0fe11ceac901494d5f62eb6c14f3cd53ed3872a46978a4e92859ee09645bee1c2bf5381ad039b437345c93bbdf18bc12412a3a929ef4", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "619c69ba1e8343d87ccf36260954a45bb52b8210c5facfd87861a06fcf5561b8" - ], - [ - "e", - "71bd71e53f0e857bf5915a181ffae08b26557158690170f32c3976d20727b2b3", - "", - "reply" - ], - [ - "p", - "ba94849433a724544ab6794f79700bc980613aa93bc8c872a59c4f7fb85d36a5" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89e14be49ed0073da83b678279cd29ba5ad86cf000b6a3d1a4c3dc4aa4fdd02c" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - ] - ] - }, - { - "content": "Sorry. We haven't optimized for old phones yet :( ", - "created_at": 1690027143, - "id": "f469473308fa5e222d3e5358bdd2eaf6b1c4c135f4ab4bf60dd6cd1c8ebfa7e2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7dbc9e95c3ccd98ad00dc84fb50bb78fd3a88e1d280c6fda72f4cc7155755aea71b377445144af8017f1c03d98908d67e3d46c2800368354c67c95ddc2519f5c", - "tags": [ - [ - "e", - "df9b11fd6029e3b4c27bfb5cb59aa152442a03d57bc5b759684263864ae729af", - "", - "root" - ], - [ - "e", - "3e646fa6294a2a87e6ccd619c39a50974d6c70216eae79d700bca6c46179a389", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "43d140f61e46792199dea8a8ab4634dd21f1aedaaa4fbd29add506f8029f1265" - ] - ] - }, - { - "content": "Eventually, yes. But specialized apps like those are always going to be better, simpler, faster in their specialization than Amethyst can be. ", - "created_at": 1690027096, - "id": "ae01161cfb1508092b9b4d9ac9a16809b354b2753490c870585da6b001e979f2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d25cd417e0cb9917d472a3d5707ff031c70654486ee79457496103af389f3434a530a2f2f3979ae36501ef81d160d3babb221f9aa98056b0bbe8d612be98d1c6", - "tags": [ - [ - "e", - "3d995935ead0e9a10af53b465a2c2c0d1e309d5b9cc563e8c0d6f0c569bb8c97", - "", - "root" - ], - [ - "e", - "540605b2e4ab1cadca0abe9806e96c06b643de78e34e1275133cf1dfb3817cbc" - ], - [ - "e", - "e79e452b991dc561d99eb33f278dcc26e0cb105eaf40eb9a3aae87ae62db315e" - ], - [ - "e", - "50719f470bc924b46617433b06dd67aeba0f9b19bcc810e89e5428a7118f81ee" - ], - [ - "e", - "3b992f41a24e66a78cb3c5779edd18c300a6a8a04afc722f8a9e6efbddac8f23" - ], - [ - "e", - "5d4e39e25d2453b8d42b2093d82ca99da9c65f6e8d56f3b97fee4e3b271299b3", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "5131f3572c960cfa0b5d262687565fe53a98c8d35bbfaa2daf029bc3f6eaec88" - ] - ] - }, - { - "content": "As long as there is a way to break further down from event kind, it should work. ", - "created_at": 1690026998, - "id": "619c69ba1e8343d87ccf36260954a45bb52b8210c5facfd87861a06fcf5561b8", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f9a77aa366699537f4e52d284bf4608c3959115b0ae2804adc47f69b39298385857f94c077c01d3a0e646d0f003c9104516f451d71af3a90ee3bb72ad6f5994e", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "1fc961d0a4f87cd225eef96695507f5a42aa446620090c4841faa4a84c22751b" - ], - [ - "e", - "d2c109bbcdb0ac2b0f6166b367d164a9d96e72605bd4f5c86dc31fca0be7ff1d", - "", - "reply" - ], - [ - "p", - "ba94849433a724544ab6794f79700bc980613aa93bc8c872a59c4f7fb85d36a5" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89e14be49ed0073da83b678279cd29ba5ad86cf000b6a3d1a4c3dc4aa4fdd02c" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690026846, - "id": "e799c69de8fa38f99997e48dbc2b5d203a841bcf1a20de848456c38d1199d29e", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f705dc055fa87d21e15579f6691d12cbe9270b1682edb81f0861780fbb09c4fddb92cc20659d2214db6b7436830149eefad724defbdb56a55abc24d143714326", - "tags": [ - [ - "e", - "3365db2747c4f5ee69b30cccf7c20eac703d2c61f2f4e0b1bdb6973ba211a037" - ], - [ - "p", - "4ea28e364020611166ad3f826fd476c05b2c7852fe3d691a2c43381ebe704d0a" - ] - ] - }, - { - "content": "Yep, DVMs the user can subscribe to are way better. But we need to figure out how to log down which DVMs the use wants to use for each task. ", - "created_at": 1690026543, - "id": "1fc961d0a4f87cd225eef96695507f5a42aa446620090c4841faa4a84c22751b", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7fbc9ab6433ebe48f29bf9c4cc3e6e48ad1fc057cfa8a292600a12ca4e95c14022770b7d679ebd248663b949b7cb1408862715e395082601232c11f462175b60", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "16ccafb23b3ea34d29a5ed546e30e21c29457458b389e59010d3f577e83937e5" - ], - [ - "e", - "9ed61ee9d569308861842675798444bd50f133a63bdb07deb6345be9efefe73d", - "", - "reply" - ], - [ - "p", - "ba94849433a724544ab6794f79700bc980613aa93bc8c872a59c4f7fb85d36a5" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89e14be49ed0073da83b678279cd29ba5ad86cf000b6a3d1a4c3dc4aa4fdd02c" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - ] - ] - }, - { - "content": "Create lists of people on Listr.lol or highlighter.com \n\nThose appear in your amethyst's top bar as options. ", - "created_at": 1690026476, - "id": "3b992f41a24e66a78cb3c5779edd18c300a6a8a04afc722f8a9e6efbddac8f23", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fbbf7043f61a63c1bee4f3d986fe6e6b9a58a9225cce97fc45acba1e6ddebf3310daeab1cd121e020f35d015830c843e02d8d0006abcf63d785d347cf4f1e923", - "tags": [ - [ - "e", - "3d995935ead0e9a10af53b465a2c2c0d1e309d5b9cc563e8c0d6f0c569bb8c97", - "", - "root" - ], - [ - "e", - "540605b2e4ab1cadca0abe9806e96c06b643de78e34e1275133cf1dfb3817cbc" - ], - [ - "e", - "e79e452b991dc561d99eb33f278dcc26e0cb105eaf40eb9a3aae87ae62db315e" - ], - [ - "e", - "50719f470bc924b46617433b06dd67aeba0f9b19bcc810e89e5428a7118f81ee", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "5131f3572c960cfa0b5d262687565fe53a98c8d35bbfaa2daf029bc3f6eaec88" - ], - [ - "r", - "Listr.lol" - ], - [ - "r", - "highlighter.com" - ] - ] - }, - { - "content": "Yep, I don't think it's good. It just reinforces large accounts. We are not here to centralize everything again. :) ", - "created_at": 1690026412, - "id": "467b16aa0975ae962b9322438448a5b94d28c9677aa0bf783f0d5a97c85238bb", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "356c955f44848aae2f188efa7a26c2f6f0fcb3784c22ded65b992d0a4b26dc967a818b890cd8e7c8228136c25589e9ecf4f5fcac766c53e339b96eda42b805bd", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "088c6a88368f2b7c0bcac5be688b8a493161add325c32742ac2e37439dcae5cf" - ], - [ - "e", - "d4bb741326defb5f62196196c4fdc6c899cf9f2be20de1de1a6c6dc9cf131e03" - ], - [ - "e", - "16ccafb23b3ea34d29a5ed546e30e21c29457458b389e59010d3f577e83937e5" - ], - [ - "e", - "670401ddf5959ddb5bbc72451d31e36d526d1879280dd3bb89321dd5fb46164d", - "", - "reply" - ], - [ - "p", - "ba94849433a724544ab6794f79700bc980613aa93bc8c872a59c4f7fb85d36a5" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89e14be49ed0073da83b678279cd29ba5ad86cf000b6a3d1a4c3dc4aa4fdd02c" - ], - [ - "p", - "648c0f5302c75f38382a4d2c85a482b927cc61b2828a0794e36c6cc796de86a6" - ] - ] - }, - { - "content": "We haven't yet figure out a way to make trending actually work. Right now all implementations look like Netflix movie algorithms that just bring a bunch of stuff you don't care and the things you care are harder to find :( ", - "created_at": 1690025979, - "id": "16ccafb23b3ea34d29a5ed546e30e21c29457458b389e59010d3f577e83937e5", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "644876edca3832f919ba921368d97a48ff95c63881825ee7c8bba53ea8d7016395b57c83a41f097b095e378ccb0bf2880c3af4c2b7ce3abfeb10b75f03743f7c", - "tags": [ - [ - "e", - "2738282425cf2d147fc0d01ff9d95ecd475202399a3805c40e193d2b20244bac", - "", - "root" - ], - [ - "e", - "088c6a88368f2b7c0bcac5be688b8a493161add325c32742ac2e37439dcae5cf" - ], - [ - "e", - "d4bb741326defb5f62196196c4fdc6c899cf9f2be20de1de1a6c6dc9cf131e03", - "", - "reply" - ], - [ - "p", - "ba94849433a724544ab6794f79700bc980613aa93bc8c872a59c4f7fb85d36a5" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "89e14be49ed0073da83b678279cd29ba5ad86cf000b6a3d1a4c3dc4aa4fdd02c" - ] - ] - }, - { - "content": "🤔", - "created_at": 1690025791, - "id": "4e750cceca0a0377fd97bc3fbe02329afac6753be8273d4051091d8b2cea2b87", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1e9091ee1f8df139d36d948c50f3a28df024f52fb4736eaa013304c17a92a915a214a7f8e5e0ae1ee05491510be63ea037f7bf31776a3e18d94c4bf2bb89e28e", - "tags": [ - [ - "e", - "ac3798231044db275288061a933064011544192f3b867644a1952ea76bbfbf23" - ], - [ - "p", - "c4f5e7a75a8ce3683d529cff06368439c529e5243c6b125ba68789198856cac7" - ] - ] - }, - { - "content": "Put it on a list and access it only when you want :) ", - "created_at": 1690025656, - "id": "e79e452b991dc561d99eb33f278dcc26e0cb105eaf40eb9a3aae87ae62db315e", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "768d7cf56d649dffba187a7d8e04f8f2f7aec4850277189d4025da4c37d741d4e05007393b775ced3e335747ada23ecce57d43a0d124c0462aeda070c274a2b5", - "tags": [ - [ - "e", - "3d995935ead0e9a10af53b465a2c2c0d1e309d5b9cc563e8c0d6f0c569bb8c97", - "", - "root" - ], - [ - "e", - "540605b2e4ab1cadca0abe9806e96c06b643de78e34e1275133cf1dfb3817cbc", - "", - "reply" - ], - [ - "p", - "50d94fc2d8580c682b071a542f8b1e31a200b0508bab95a33bef0855df281d63" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "5131f3572c960cfa0b5d262687565fe53a98c8d35bbfaa2daf029bc3f6eaec88" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690024223, - "id": "817f132a4daf21a41f30096ffdc97fddfd4681f9e66e9decc1548a7e5ad41d85", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d5b6fe39efad7254f37894035bc52edc508bd97911e53dbae69ad058644fc0f35100ac36598c2118fd2288178f3b1ac55e4881cd7ab016a5907d40b6bd296fa9", - "tags": [ - [ - "e", - "3e0242a1e3afac94f6ec5f72da83429287d8b726c04223342fc738e151a616a6" - ], - [ - "p", - "7ab1d3867722b4cbabb6c8503ab3f9265daa4f82e228cefe302621f4e5ee1f1c" - ] - ] - }, - { - "content": "🤙", - "created_at": 1690024192, - "id": "1c467891446567ff979de8c0aa3900c1f6d125131f119df522feff8929afcd86", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8e75d7e513399ddaf8800926b1c63554b96539ca7df4fcbb3e53240e1a4f8d359f1597d5af157626d3c777d4b95bd2a5fe9fe107d0adec8fcec0dcfbeeee166b", - "tags": [ - [ - "e", - "c581efd5a4d700022e040db861eecc0f5167539cb19f57b7bd1417b2360aa165" - ], - [ - "p", - "7c1521d55a53580a05990c6cc4bae09c9822169b6e544b1ee47005a6c3e9e9be" - ] - ] - }, - { - "content": "Amethyst doesn't have a local db yet :) it's all in memory. But search is only used to find new profiles when you click the search button. ", - "created_at": 1689999260, - "id": "c1309e7769630260fdfa5ff25858f3416eab72e78c8a80b9ecf33244b62b3848", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "904e705f75a25b9840589fbe86455b5929d6e1755a43b35e24ff339bdc7edd578e8c4e9580c6134ed86bb8af78fab6503ce4085342dc0e6244993d5e157bbc8a", - "tags": [ - [ - "e", - "dca4527bd76908cd8071fa80d9241b552c3c2348719bfa42c6bd8137a568e9d3", - "", - "root" - ], - [ - "e", - "a1c52b61bd6c9096a98ff51ff63e1cf54e868f481eea2a503f6fe3e806946d43" - ], - [ - "e", - "a1461580c93fc038bfad8c9a457b6e4156d4217e0d9f3b7f95e51ba82ce95c2b", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "7cc328a08ddb2afdf9f9be77beff4c83489ff979721827d628a542f32a247c0e" - ] - ] - }, - { - "content": "nostr:nevent1qqst4hmuwdt88ru05r99mqlf9e0a5c76hus738ns6p90d8s865mgqccpr4mhxue69uhkummnw3ezucnfw33k76twv4ezuum0vd5kzmp0qgszp55czrt2t7ftq3dduqhthtwfqdkhg8xxs6cqg9wy9dprdlj26tcrqsqqqpp8z68rfc", - "created_at": 1689998418, - "id": "2529de5d4177178cd1bc495ab3c9fd47728f1a8d3f2e33615918d57a33d88e77", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6545f19adb258d6fa5cd2ad10b648c15f0eb5c2ef12f19c0aff96e4afcf04f6a2c1cdb9f822a5ced89a62acc54c755b1356c6ef55b5b131c98f15628a327b3fd", - "tags": [ - [ - "e", - "745b854705717741bafb74d36e968e6dc120aa8a6abae7d6934abbbc4b0c0c11", - "", - "reply" - ], - [ - "e", - "badf7c7356738f8fa0ca5d83e92e5fda63dabf21e89e70d04af69e07d5368063", - "", - "mention" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "20d29810d6a5f92b045ade02ebbadc9036d741cc686b00415c42b4236fe4ad2f", - "", - "mention" - ] - ] - }, - { - "content": "Yep. Let's hope more relays enable search. Right now just nostr.band and nostr.wine do. Without them nothing works :( ", - "created_at": 1689998365, - "id": "a1c52b61bd6c9096a98ff51ff63e1cf54e868f481eea2a503f6fe3e806946d43", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6dfead703845bf105b7908a6007de6cf0ffb0ccd62d371930e2022dfe636e7c8d12c82c8370073b592c96ee4c08b89dffc1e310778cebe4d867bb5422aba4b24", - "tags": [ - [ - "e", - "dca4527bd76908cd8071fa80d9241b552c3c2348719bfa42c6bd8137a568e9d3", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "7cc328a08ddb2afdf9f9be77beff4c83489ff979721827d628a542f32a247c0e" - ], - [ - "r", - "nostr.band" - ], - [ - "r", - "nostr.wine" - ] - ] - }, - { - "content": "", - "created_at": 1689997153, - "id": "cb3c8ab48e449fd9f312bcd3dfc1706dd4dfb997853b8b6f8006c06603654c56", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1905563b8b682aea269c4cfb2a247cfc8ca4b2162f24a68ffa20b94d83d8ed54fea47d8cd94fde821d84b10ae6dd5ac1eeff31f062b4e12631b316571c82f3c1", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_e64adb648e5ff82dbcb1f4df76d3378c58b7a60a24738a3d.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "592e1b0c982a4dae025e35e6d08bb4df41aa330c542fefd1fc942a6cc605ded4" - ], - [ - "size", - "974483" - ] - ] - }, - { - "content": "", - "created_at": 1689997049, - "id": "07846fa8245c0ddb620debcb3fd735cc3a8df6b4a010e97e211eee20d58c6bbc", - "kind": 1065, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "61baf4dc3e84de957caf11deb63076de6db3bc28ea9dc1472b4e6ebfcf69be9d53a5c0533040585a255418706fd113e31e1ec847de56ebbae231fc04e172f42c", - "tags": [ - [ - "e", - "782621cb24a3a8ab85f31c15774bf1a78b4c8446430515a702976bd7a416d5af" - ], - [ - "m", - "image/jpeg" - ], - [ - "x", - "ad80abee20daa3a220763272a7e3090242188f71833edf970c42121a4e6d5504" - ], - [ - "size", - "36172" - ], - [ - "dim", - "554x554" - ], - [ - "blurhash", - "UUOOIzkC}@WU9]W:ELoM$+bIj]jE=}jZs,bI" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689996772, - "id": "c8df2b4bed40245191d8703bcacfdff60d18b79f9571a0fb4a83f3d7a206d019", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e83d039b5624f2a17914037b46727697ea63c64b54de84b66a14e996784f2d818349ef213368ef2b6c8d7e1202dd977235fb19bba376e0ccc173d89ed1cf80d8", - "tags": [ - [ - "e", - "badf7c7356738f8fa0ca5d83e92e5fda63dabf21e89e70d04af69e07d5368063" - ], - [ - "p", - "20d29810d6a5f92b045ade02ebbadc9036d741cc686b00415c42b4236fe4ad2f" - ] - ] - }, - { - "content": "", - "created_at": 1689996403, - "id": "e9f0ea803d47d2a4088a85160ec5e3b460d4d7ce80d8005706b43a670c9ec8ff", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "874d491cca43ac519c2fdc2b28203609b0d66f07a950bba18a72b51577237131ea131c22049753960f20a28cad8dd8bceca7da5f16d398f0469850c06b031c7b", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_c69a040d82b8085ee667b5c439f0ede384f3f9fcf758860c.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "b9af7ba10a32bd5ba80b375fe461724991f0c36216f175a2c68a8a9645d89e1e" - ], - [ - "size", - "1912315" - ] - ] - }, - { - "content": "", - "created_at": 1689996260, - "id": "83218f8e706f092398a99a458a64b847e1cd39d0eaf1813f20fcae34663f72e3", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "188e44752870fcb55594f0f5465fb17a6ff248aed5717b9b66c89ce69cb82f44ee55853c6798e828ffa3163ca11579395ad84374e71217b0ee0a481efcdf3b9a", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_d130b03e7f6a25183e930a37f1b35f5763896067d60b79ca.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "f3e8510dba57c20c8f3e00910cfa27bf660994d04d82f255f7822abb0e023cba" - ], - [ - "size", - "854488" - ] - ] - }, - { - "content": "", - "created_at": 1689994614, - "id": "5d9e383311d5e2da43c252e5029a311b43ad63f5a97a79b47f96b3654e419981", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fbebdff8e5077364ecaa8c6e9e71a743990b0ba12db0d346f0abdecded0abf65c3ab8d2be65da0ac6ab67788f93fd35e2ed3dbc950d07b6518212cca06e1ad6c", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_b6b4f0f16fc4cde884220091e8f43cbfa1ca1c9b7038fcf3.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "baa579aa8bd19a0c2bdc6d091012b67db89526eadf454cb5e5ee3863fc25bb51" - ], - [ - "size", - "14207658" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689992751, - "id": "6227574060cd0e32ec7f0e6c4c1bd59a049db49b88eb4a7fb72675c76fd3314e", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ab33e1e1b8399b9e0030c578c2a79f2468bc7bc8d0b5279abbf80c7fa23b05b89dae373f68a98fdbd2de081e8b27cdedf07bba8195b2e366f0c2f032446055ea", - "tags": [ - [ - "e", - "5fffbe60a6107d0492b0ad0a18586957472ec472762b931e3fdd2b5f5dd38ec9" - ], - [ - "p", - "7f14df43e1782029254e2b6aed560440b0d1d202ab4855fc70f25584d8d4d732" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689992748, - "id": "bcd6ffd307fb1497422afe873c12d021df5f825039411aaaafe9c43700db972c", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c43c4182dc8c06306f094c83e18f08ff54b0fe3964bddbca35ac66a1b73d2d4ff16891c37fc08f5e0528e4a157ea246de17028b6a638383b9e87a7cd38c33474", - "tags": [ - [ - "e", - "411f4bcd1a717a1b8266a47e646f27838f349c773b55298fb264a749dfd945d5" - ], - [ - "p", - "7f14df43e1782029254e2b6aed560440b0d1d202ab4855fc70f25584d8d4d732" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689985609, - "id": "3e8962e2fe9a240531d3971d70f40f87e3a3fd6ded501631ab95aee313ca6eeb", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1e1ce8acb6e9ec11bea55e6ca8a2cbcff2674d28a6336eda6d1c3b2e761670b10114c6b5f6d86cb54f2cb294b9ec6b92c2dfc024f183e72cf23d644437d2149a", - "tags": [ - [ - "e", - "fc2b936584da862e4926d85437accb5412cfe9c983edd517b88cddfdbf618954" - ], - [ - "p", - "20d29810d6a5f92b045ade02ebbadc9036d741cc686b00415c42b4236fe4ad2f" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689985596, - "id": "ae40b833935fa4844c9fc7e62622e653a67beff93d02091f0a4dd529e75e03a0", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e2a520fe8e0424d0c2310d1e9d1aa827f338348105d85d295b6e3165324da8ab2db219fdaf4c6851302839658ae077b654e9be02da34a8e6c0fd499adc482660", - "tags": [ - [ - "e", - "e91e975b8da19b4c092ac7581734e2168d45fe73e4b8f2049aab3788fa35ae54" - ], - [ - "p", - "4ea28e364020611166ad3f826fd476c05b2c7852fe3d691a2c43381ebe704d0a" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689984810, - "id": "f4bcad31c092a0042bb445f413c593e320b6a6c26941fbe106ca111ab52d7166", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "04b17cedec6de4e85b759eef2049da4492e1961106573f1e61bb4b79accf7b183ca20744e039c40939a3f7c8a3fd4e003783b68cad554f0f1795dafb283841e6", - "tags": [ - [ - "e", - "d269571c1d2ee39df436b3890d75373fededa88f48155df92f0469f80e69fd93" - ], - [ - "p", - "c6f7077f1699d50cf92a9652bfebffac05fc6842b9ee391089d959b8ad5d48fd" - ] - ] - }, - { - "content": "I am very happy with that idea. I think we should do this. ", - "created_at": 1689983150, - "id": "8bbfbb3a847fc22fd3446b68a7428fd1071d4e3b17a85502f2c9d7dd21471925", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c0e8227f5f211a1bd932742635c919f2f2d7cf749c15f069d7977c312f5bc952765cd5b5076a454b5f0acaa1f48f31c5c22a1cd5693c1258fa24d9b8b9780efb", - "tags": [ - [ - "e", - "f7ab0a2197676c2da1af737bb1c09e4c750b6ebad3223acf72c3648372540755", - "", - "root" - ], - [ - "e", - "7523b31c7ebf3c7230943b33076e7afcfafd69c10aa7deca5c455cbd41bcfa67", - "", - "reply" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "I have missed it myself. I am not sure how to make it more clear 🤔 \n\nI am just happy it's not a bug. ", - "created_at": 1689983110, - "id": "766c8ad5a213902deb33c7177b3a83559e4f140425ed9e5c96a4bb10305fb634", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ca0841bd17b42b5303e0923bc81f2065b8e44e1880480a6b8340f3e6b1bcbc25685eb6f1dff7101a11ea3417be632eafd761d8c3fd3104157f9c8cdadbd9c6c1", - "tags": [ - [ - "e", - "3d4837be2f1101014ff150cfaa71da66d4507d136f0befb535403ed4ff08f768", - "", - "root" - ], - [ - "e", - "a7bf27944116662a24a1fb68b420081aacce90f36ecad03965c45d81574b80ca" - ], - [ - "e", - "7ed23adc9508bf4bc57fc76af8874c09c9af9d6a4afa0e4b04db199a04461d62" - ], - [ - "e", - "40900f8a39b67e8688c2cad1f2ccc73f13cd0bb4af8ef8d88fa86f0bfc958b4f" - ], - [ - "e", - "56f22ef8b1c40cb9721b208f4231c88ee9fdd0372d7affbe426edeb8bd2803f0", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "c6f7077f1699d50cf92a9652bfebffac05fc6842b9ee391089d959b8ad5d48fd" - ] - ] - }, - { - "content": "And this is marked as Global? \n\nhttps://cdn.nostr.build/i/cdf3decc75007b18174c3ece49f94c51f930e28a01c126bac1045b4c3b67dec2.jpg", - "created_at": 1689982919, - "id": "fd4e2a1222c0c7b24d48c7dc9359a7d8311246c4f076914b8e72b94e1ceefce3", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e2bbf02d867d2b5d971e11131449805d7025abe446846c0400c8d0cdf3b61066d42c30dc23990d00f0f7a8454ae132d4f6b16553f9fbaff0bb708a4f976e3794", - "tags": [ - [ - "e", - "3d4837be2f1101014ff150cfaa71da66d4507d136f0befb535403ed4ff08f768", - "", - "root" - ], - [ - "e", - "a7bf27944116662a24a1fb68b420081aacce90f36ecad03965c45d81574b80ca" - ], - [ - "e", - "08297c8b2ce0bd53a336a3328d9b9a9970e2a81a28ef70a7b5734bf4bc26bdd1", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "c6f7077f1699d50cf92a9652bfebffac05fc6842b9ee391089d959b8ad5d48fd" - ], - [ - "r", - "https://cdn.nostr.build/i/cdf3decc75007b18174c3ece49f94c51f930e28a01c126bac1045b4c3b67dec2.jpg" - ] - ] - }, - { - "content": "We got a name! \nnostr:nevent1qqsdqxyjenhfw85v5gx7kxqen8055s7cw2puclm94js4gtddflvagmqppemhxue69uhkummn9ekx7mp0qgs0e0trlf8y0g8mel484etgx9qyma39x83nzlmhrzuazss0lh08d2crqsqqqqqp44zurc", - "created_at": 1689982779, - "id": "1abfbd6067af774e88a049b44885148337fb870595595c31c2510abf9159f86f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8ddd006e5ce070f94588bf136490682e585d506c377e7c86822ba7bdc704d88538a69da09e9ad9e037065db0985c9a147ae60b69148f791d848cfeed67e36e63", - "tags": [ - [ - "e", - "d01892ccee971e8ca20deb181999df4a43d87283cc7f65aca1542dad4fd9d46c", - "", - "mention" - ], - [ - "p", - "fcbd63fa4e47a0fbcfea7ae56831404df62531e3317f7718b9d1420ffdde76ab", - "", - "mention" - ] - ] - }, - { - "content": "Also, check if you haven't chosen the All Follow list in the notification feed. That will filter your notifications only to your follow list. ", - "created_at": 1689982726, - "id": "40900f8a39b67e8688c2cad1f2ccc73f13cd0bb4af8ef8d88fa86f0bfc958b4f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a816b3002595152cb878bbe3c74d6602f38c4ce12679229bddbb85efbad8aea025825c0c070ac79ea2ac29ebc225969aa99b163a9a3d5b783d61239710a55b0c", - "tags": [ - [ - "e", - "3d4837be2f1101014ff150cfaa71da66d4507d136f0befb535403ed4ff08f768", - "", - "root" - ], - [ - "e", - "a7bf27944116662a24a1fb68b420081aacce90f36ecad03965c45d81574b80ca" - ], - [ - "e", - "7ed23adc9508bf4bc57fc76af8874c09c9af9d6a4afa0e4b04db199a04461d62", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "c6f7077f1699d50cf92a9652bfebffac05fc6842b9ee391089d959b8ad5d48fd" - ] - ] - }, - { - "content": "Of course, we also easily allow the author of a reply to remove your user from the post. In those cases, you should not get notified anywhere. ", - "created_at": 1689982674, - "id": "7ed23adc9508bf4bc57fc76af8874c09c9af9d6a4afa0e4b04db199a04461d62", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "10a36e75f8fcd7a27d73eb9ea967487552eb3351acaee2e950e4301d713a7695cd053e8d5a94843469092fbd15104a4056a497c680bc7f2cd5a94c4bcf717e38", - "tags": [ - [ - "e", - "3d4837be2f1101014ff150cfaa71da66d4507d136f0befb535403ed4ff08f768", - "", - "root" - ], - [ - "e", - "a7bf27944116662a24a1fb68b420081aacce90f36ecad03965c45d81574b80ca", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "c6f7077f1699d50cf92a9652bfebffac05fc6842b9ee391089d959b8ad5d48fd" - ] - ] - }, - { - "content": "Amethyst only shows notifications when you are an author of one of the e tags (if you are the root, or the last reply, for instance, you always get it) or if you are directly cited in the text. This was a response to the hell threads that keep happening. In those cases, cited amethyst users receive the first citation but none of the replies to the post you were cited. ", - "created_at": 1689982605, - "id": "a7bf27944116662a24a1fb68b420081aacce90f36ecad03965c45d81574b80ca", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c540d90d6126d14ffe15d082050bf07c50a551c34d515857d6017086697af1713f003e1280d7074f85914d7b8175df722e912f0cf3a3c6da60aaa510c8211667", - "tags": [ - [ - "e", - "3d4837be2f1101014ff150cfaa71da66d4507d136f0befb535403ed4ff08f768", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "c6f7077f1699d50cf92a9652bfebffac05fc6842b9ee391089d959b8ad5d48fd" - ] - ] - }, - { - "content": "BHz4QOLgtnkLFMkWLeT7vYEog9hMj00OCdIOFn5tC0I=?iv=B7sbT7bbjVS23Vsa3XdClA==", - "created_at": 1689981957, - "id": "7fac13ad33c8cc8805b50d1cd944e50383af754597dcb24be3bcb0e7d73fa34a", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3f3f0d2d07998b8b164a4f8a463422ae1d0711d08e66d2956871926aafdafe9eb1530027766f1b8edbbb9b7078e154b9cd51cd73d1fab8c4fc6d60888a040b4d", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "zvK4PV/zfIScLBttRMRYRvJBOKjoxxy5++CuSB2un7eWdV5lfuXbdBMBn/e+jSu4?iv=ic1MXHOOCfk7LNg6+qfUFw==", - "created_at": 1689979685, - "id": "cab93844a5464ea9c3a9101f2818bc72e20531c49c061dba55177659f7ec6e3f", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d2c685d86c9cc220c0cb0436fe26ae92625d5df71575f6bfb9630258120a7309c9c3e440b02ef45129c2cda4299efd4c230b34f00dc52789bfd32708a05b47c2", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Y1YSzKaLNfyzk/rAeHjbnpqCwdNZVhz2Ogk4LaVOew0QLUQux/MkYL1POQb+icsD?iv=GuVyD9MvvB8prX7SuwzEvQ==", - "created_at": 1689979669, - "id": "a8899213890ab028d13961a1f4b7962140ca083ca0d834f537ecfe52a50f1b1d", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "4cb381c6cb5287bd8df253d540947c84f441c7a73dea56f32584ee1f860179ea04fa7500f3ad58f76630a02a09f127f93bd39052fb0c993238149d4024d939d0", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "9873Ylo0oUHthBI5gHDkuQ==?iv=NAf6J1gwgBYCX9aX19WXUA==", - "created_at": 1689979646, - "id": "b26f9295f51ea0498ef9008c208b27adbed68833c570c2d6ca9451b6ac8eec49", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3a96d2ebf9a2695a031daa48afcd4f5f21ce0f7406bb495d8c7513ac162e37986165d989dd1b6d302a753babb5e4d87358783dbe66fd18067ec3e5c89b5f2027", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Makes sense ", - "created_at": 1689979221, - "id": "840c1578c4e6c49f0a623dd0d50d9aacfafb3728e986f0bb529863987caaeb75", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "15e6d9161334d3abfebaf2ca2b9f292498d35d7199f6cb0b9974682f0339e95be8c972982e4aee0cfe95855db3a3a8cfb244f813c3236697ce9f4212a96715f2", - "tags": [ - [ - "e", - "bf7ae8649a76c977606a13ddd453942a3ba501783b23c121d1bd685a218cd002", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "84eaf37660225a312d27dbf72acf588106664d444bd432b1c8004c18fa109d63" - ] - ] - }, - { - "content": "OUQDJlyIyVPZEaJsh0Zh8wjpdPNqri3ua3KzNdVERNk=?iv=LMJ9yIbIEj0va6BSF4lOGg==", - "created_at": 1689978881, - "id": "cff285496df7108a40a3d78ad158848b4e6a0c85e34bfa45a2e5cda587ff6575", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6a701ec9868cec9a12926443d3f5d4ae09b1d114fefc3529bb59f09ce4ab712eb722ed94be7e0952251e474f4c5cdcd4bfd3cce7c80a2fdda73df7d7c9a21396", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "AJcI/HvqWp4WtZwC/jSwUavXG46/NPMV1gzkxyaMgYYNRoSZIvq6bR0+b7H+ImfbJvzq1HI81eCvVsyt/eM4JA==?iv=7jXjtbkrppHdmcQT3Huerg==", - "created_at": 1689978874, - "id": "b74800c167733cb13dd0241e212cfbd5e3b729d245912b810f51caf844059693", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c66d201aa976d4c0d37c9d435633e5b8d693d0c6a9e258f3618523899c46984772c3d58fc097ac2489ddbb2a3bcd4c6d4a48ea2ff6cc78b513bee81c0032578d", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "e0wITUuIQONaGOLT8tzD1liObF9LHsVScktSpgkgrPlpUo/YjzbyugjGZ3h5D+t073G2ZK0X7B4idNPZNhDrAA8HFcRqP2Vc+ADn3RUHD0Gx6BoQ/jwIy3gOnEV9oRttkawDv4HputQaeWYroIX19A==?iv=ea1Zp+6AM6Hs7Grc3EdzmQ==", - "created_at": 1689978795, - "id": "966dba764185afd72a596a74c91e706f5a28618f16962ddd3ba41ac19904b9d0", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "dc43d1cd5b000d94a453c9dcd3caf5d400ea2d23b200996be1367852b92f9575fc2894ed63758f24bf1d130dd3c6a044016ea70717aaf1772921544e9332fe35", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "AfKccxXWtZjL0ZV0U0gZzXjxmtomauxe9f0sQTIVN9+2cYL8njKAxEsWSQZbrgIZ?iv=lxtITUPcoSK15HeDT0S3TQ==", - "created_at": 1689978633, - "id": "fa2f35b2f2841f92d64a3a006792a3f361c2ad60507b55081bac5c4f0f3f464d", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "49b0d07eb6eaaa38e73c11f24fe4037f11e2dcd224168ea681a04283e1f3149368dd819eebe51957a5b5705d8a48c9b2b6ef575140f3cd842bcbe2851abed92b", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "8YAcpa1MZfvtAwVJ5/w16YQ7sipjBjbBRj1Fe2nnHJkT7O3GdIlk0V5TpREHDL5a?iv=AtGcsKmCEh9MTuofv/Xkzw==", - "created_at": 1689978554, - "id": "0219e6f056c0cebc919dc9e1a6043b5a5302f4a0fdb327c87d3216a2a4b8aa2b", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "97c587f226bf35d2aea3c4ab1b36c02008e792630cbf329af28a59dd06a4ecb7339260fd4e186d8e15eed6ac8a47549956c7873d783e5507cad3b57ce9dce041", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "TColF2a6KOL0tPR2Cq0oUUJ53oRsJVJ83q/rSEYCDcbpihSgLh2sPk43OSJ4hujoNTvkyy/TmIqq9x7U8R15gFb0WIw1lVvZ2owykU+2iDtnVJkcicXROLQVtj+x5nu0rP4NYJxsp275G0YzfwsY2ngigSX4a5aT3FXwloP649rYCuG+C1Uv2nqLbYl0lbkt1PkoubEc7MsqboDAZ5a02QFpS1QQ3kyscrPWlF8/MG97dVVnKZKmXgpt5e/uyZKkvCHQCR910qJTFt2el5t1Bb8uII9k6VMtXJWMO/KLHywH/kgbM6GC5l0enohwvnqK?iv=chSXqVgngEDxdbcjTXDNzw==", - "created_at": 1689978540, - "id": "e30b18b795404ca81ebaf2a5bac9b82301de22f598786e267b4dfb93335656ae", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5ac4871503ab5e78e5949e1301ea9a6286d44e18124c6f193447c96783a809eb942b1d571ab64c9afcb8016ae5ca41c66f67d8c1e71a56af6f9f3d198f08d5d6", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "yM5XtJP7JyKfg+F1bx/3Gu2FpOPx3dzjbvrM8O7HSok=?iv=yWgjpXyDICJWVFvWoSEdnQ==", - "created_at": 1689978135, - "id": "fb7b2ff803042667144416fada94d9e919ae1a6442ec644d609365380ca34c3d", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f0dfbf44bc54410fe14567236711175f5b842579bc942fa18d5979d2b58880fd6c879b8d4ae2e17fada6555ba08284ab8d75a49413588759c200fa8c389c8225", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "UkCJkOqT153btoDiD+4+VlToAtl2UlfFsLH/8sKr2lce5J7oQWBcLdQ5OiDjYjzJ?iv=UiYcO7+BONYURJf6Ezap7A==", - "created_at": 1689978078, - "id": "3b00f93d6ee7b42832aa34575170a74f50618b1095e65e0d325ef1c498b2171e", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0dd1469c4f6d8be190f828f9345477115e66176de9a4401f578b053b6b14f6c7c62896d7c74d88552e0dc2ec3494492b0cad807f1cbd0926cd1116176eea7380", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "G+wV6IdMdJ93uV0aa0lwQe1noHo7ctUiXuqmX/AbctZQrBkSGgpX3XUbr+0m1Zy08pALk0vRlBmve7NmdhLk1AT/Am23vbxxq5i9ox+UOMgw46VyjB5g01XrLhKDUHg8?iv=WxHcPBEYuLrFZOohJLlrlA==", - "created_at": 1689978068, - "id": "8a2da86643dbecb3272e72319a7a85c687648ed68e64b4530a163727a66b2fe1", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "30578d318a41da4e61aadcd8cc9ede9150f2adfecec92727a7d126c58dcab29ef86e923e458ff67b465cc31d42947ed90d2d5b9c21f8c6f56887cde860121b2f", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Qn7zesOytPT+WF1W0uRDFnEbltsxbbc2ie7+NBqSHyGlLJBAesuJ2Nay9ALOntBk?iv=fnhLxP/1sYXgjjqJKiTOBw==", - "created_at": 1689978037, - "id": "add78bec9b1669dfe4776b4029e9910f88af60e7cb4a3832feafd408b5093d04", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5cfcb4532dc1c18f9bdd3d1b695e58313a11fc780a6f6613f10524b55f47d7da6182b1c1043d9b9692549615264658e570894f8c853fabeec53e92892344845e", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "gU/iheSDEaeFKtJLVs+7IA==?iv=LlKtkWuSJfH4ErPRKWh2TQ==", - "created_at": 1689977622, - "id": "b1241ca4526477334d56cab686836dc3fdeaf6ab910c1fd7e474db135c87f48f", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b2a67ce55251f5b0ef42ec5cfa8581e99fdd069ba592d1f288d70f5801935f52fa8bb45ee89d8dcbf73b4879d189a16d64b674b7b02dfccf6f1b91f0295b43d6", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Lc5utJWxQ1j5dT74uZmgldkNzwufFEKXIEi43a2V5JoSqaAjjZj4SYgYFo81UbyCsX8+WvoOpyUBS9pmZ26+kw==?iv=fNF9u5WfZg1lWTUQY4w3Ug==", - "created_at": 1689977617, - "id": "8e0e0de3cfbcbbb8c40c6643524a599c9b445f3f00579d88f6595fa19031448e", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0a576c229f0959b34c47cd76d18c45f047f338c2280b9e435d04e6e94ea27cdc82223775942060741b2514a0a1f3fdc9a7a11ce646af79642cc038f0cff4cdf1", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "ptJxRhe3oiOuSJ84UqDxqg==?iv=DG1s8TtDwB89j3zBOnt2dA==", - "created_at": 1689977604, - "id": "98c010a3bf59659061d710791df4874d979f1131d8292a8cf423916b07196d49", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "41ad18e5cfef67760dc24859fd52b44b982ebd1ad10ffc50d8e5cc9cbc0d41e391dca0160aaf92d1ee3593720dfeca05f6bd13595e722ffc8e9c1e1d6779ae62", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "eIl+2IGO/rzItb9UkRntaMrt80VQvAMXu2p8o0G476Ed33CINCc7r2MrBS2OZCLMFIysREZmipm0FOwC4zMfwDdQ2VDuSvKx1Wr9yp0QeHaQuMO+fvXbAM8SAtmmmu8sJFIm1nHByF+IxvGHMZNyC0WdhJsLFcikwLREXX5vfn72PXNIt6CjOtoT3GfWYR9lXYZoikvcYoL7yMYEqXHqS9exQl3oJSa8aMQ11K197xUikSG8lnbMBrbPCTBljMdx74+0x5aEGXGtQwQKV25eGY+MImxAiMi2XBneI4JzEqUvXCgMZwYVz1QbtYY0ajOZGWKTV/P/IT/81ItgdMkpgEPC/+QaEegaZknxDCbNU8MeytI5uGEGKZSdKeJSk3vIsDKaz4DStlIFcLKtVi2tam8Op9JLpGYF8TThe1WlfWU0sCdlCut1LN+eDkt0LqaW8k8z9Fo2fD5lXvLNrdU2M8kco77dGAKcyvz1DB7uGTCXQJkrbfdZTW5BObF9EDALJPY1wGFt1IFkFYaXj5k27dO4q+NLMuDYOoREyVPedcyv9zzy/CIllOu0LlQN7JStufo2y4pNSdDKk53izyqQX2aoPH1X7ABN3MPaOZXZ3Frt9UYMrsZiZ1m3kPcGH+wrRocYl4uWwQUbfS2dvTfarOq1vi38m1ZdpLvaEVKWgrZ39gjBup5UHfv0LMiyYWEioBauxLBmyRnfsoU7wgszHhn5Wu0835Mv1wvgRvnlvSqj4NnaneV5d3U+DadNifgBReQyjNDLUGT/UlMdgso3gWbjPF4Q4M8dmCdlomwOa4KR/eFE2Sw1KPqO836/6K5xhkRcxuqEzIG7RKwEIMLGWg==?iv=/CzyaHppYO841qCLbDCo9w==", - "created_at": 1689977531, - "id": "7f86c6b8a04bea04f4b1097622aab3a7c1da0dbe402cac74b8119d3c7282b1c6", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f842721f12e20f24fd6a332d32114caec583d4e229ec3240c13def3292e260ca093eb22bb82fc8d8deaad9cddc59458275e89e5f68e86908c63875f45d5acb0a", - "tags": [ - [ - "p", - "c63c5b4e21b9b1ec6b73ad0449a6a8589f6bd8542cabd9e5de6ae474b28fe806" - ] - ] - }, - { - "content": "F5A58GD77ZjLyVrHN+JifSYzbBG+npbhJw6vnVbGtbI=?iv=ll19k4Ar2luPdqXHcsj/Qw==", - "created_at": 1689977465, - "id": "7b54d2c1cbedbace05ff968de66e95b7969c1e83dd5069f65a6de6be2cd9ebd5", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fcf6705371dfeefc15281d9ca5b7df534682a93531d1cfb6e13e1df57408cb079a390de2a861a2f2b60300a9dadee57933f006e091f646ead558868a9cf43b1e", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "VHiN84CzKCUh8uPgqS0n3SvulaWO2Ztg0FAMxoB52GQFsKLwTMFafvp+UVu/9o++fSHaQlsnUuobtwfS5Jv7PFhQpFrApLrFjRdOO7ijkhWwvHBqAQ3umh63aNjhS1MQ?iv=bnjEyVyuyYl0N+IFn9uvyA==", - "created_at": 1689977293, - "id": "59640cdddf28828cb3f75c6aeb4212811137ec990e3bf418c2ba19d764e6b198", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1f40ff28659001a244af4d73e41962b7bfd52d263bac36296616da4d0cc93cfbd391e9589b3711938412981cbeec17809b31d90a78eef4d7f6e7506e9815d6e1", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "These release scripts look familiar :) ", - "created_at": 1689977034, - "id": "aece58f5f5c7b98f5494ce7db0165adc8df7ae0c6b9bab581441bd91b0df3ce3", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c169b8e506011a263ff013bf56f3f52718e44a12e50f5a06b6679d20f12d28e8818aead329419667c41eef111e0b1927ee2ba2f689f7ce4883a46a240dd300cb", - "tags": [ - [ - "e", - "31c2e724b2c44fc395e24382ba8d80e8174160767bd02ec16f0a9ca3a6d220ff", - "", - "reply" - ], - [ - "p", - "df173277182f3155d37b330211ba1de4a81500c02d195e964f91be774ec96708" - ] - ] - }, - { - "content": "", - "created_at": 1689975807, - "id": "f0afbf83bb2e8c64b989776a7e674d917a6196c24cc313bd0d9a90a8032e3874", - "kind": 1984, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "547c76ef76f139814ab6ae33fa5efe03e5dd899003c182af97e11e0aea9739d68e5a95ed1c316533856f8b63674b9337b1ca6d73f4c9816fdabb563904ba2eeb", - "tags": [ - [ - "p", - "352b917a5d3d447b7078a9e6178b6514210564a927bb4003844df48d98419d11", - "spam" - ] - ] - }, - { - "content": "LITEQ50g9GvYEMlz/4HxI2O616p4Nizdsva6JPXL0TolilM+bAWGxSJ6R/hnInV7G3y+3HvCTxAwAQnV9UpS09q8Q2MEKg+eOptLCZdzd50=?iv=1fVnYnkBqLvHshEaqi00hg==", - "created_at": 1689975101, - "id": "6ceb478d0e6e01c4cbd06ef9957b85e37b57a3a04a3c63dd3e66a92b9a512c59", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f883a65cd1ad833cd24805eb3d1347aeff98e244f2c43d8956782ea1a6aaff71fa75a1e5a952a8da6309b02cc9add291c8e6332e279da44b2b0a494be745554b", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "4BwEVTjQtwPalZOqQLSS4wlZnOc6Ncf/7wnv6YGXxYKhplB9c81H0CtK9y1GYVWa9ld8hxNyM8QggB6xB3zmVLowrDqT1z3KEPohY0nRoRw=?iv=YrIYMh52kA3yj5g/akYRtA==", - "created_at": 1689975078, - "id": "bc79b93654de0d04a4abc0c881a9240ff4337da92f8062e69d69724d6df9ccd2", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "93d9a154ad18e29eabc67913cab8cb6d2ee20b6c55469afaed55a6c3942f2b100cdc7096b427f82313dbba5bebff2f2d724af4b587245ed36f611e9ec59a7e30", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "Make a script to update every hour. :) ", - "created_at": 1689973771, - "id": "7faf1a1ab9f093bf3f5696c8e7c4ea3473fe4142079198eca7efbb722aecd480", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "dc86d190b84b44db717f48eed16b29e5707bb336f59ebe1dd38b04525e6bd5d11977e6c2733d212ec1ee0c0fc6e3f76f2c6dfee398098408f26320daf0dcbef8", - "tags": [ - [ - "e", - "84b084e1d31a27a92f76cefd5e745a089e09f64e92e679c238b268af5406723d", - "", - "root" - ], - [ - "e", - "72efbd2fce58b9cc92ec861bc875b02a7252503192e7e3795e78ddc4a80af8fc", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185" - ] - ] - }, - { - "content": "A DVM to find which DVMs to use. ", - "created_at": 1689973691, - "id": "f4e1b1f74ebb814338a1c452dbdbf3aa97a849ffcc3044833bb338eb4528374b", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "17a447a47002507cc4f58b1985e9112551d51453d48d076be16824bb0361b3378657faf79e4868b64b1cb82f9ed58de16b0030afce0a09b1194aad1451d9a948", - "tags": [ - [ - "e", - "49f06defee1977eb5a9a2ab86fae6311c616b5455c3f63227753442f5175a0b3", - "", - "reply" - ], - [ - "p", - "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - ] - ] - }, - { - "content": "Not on chat yet. But it should work on other screens, assuming that the profile is loaded in memory. ", - "created_at": 1689972970, - "id": "f8a2486f4b5e24e31a653d99358062c67e13d20d68efc940504048385b7b4639", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a9e75594a467ede55727aa5160e4241b8bcfcd741f42524b16c06819f749e3737d307d24ff278bafcfb8f3b6a98318f8c1cc13a4337a0e22c9cb1e46ec06c6e6", - "tags": [ - [ - "e", - "42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5", - "", - "root" - ], - [ - "e", - "7d2ae83cfd768993ecdc105e6ecfb864f53a3a84945ac2cc7bef20a93eea9a48" - ], - [ - "p", - "aaaaaada01484648a650df7a59f4e6b0d48e226edd959aa237095f3b6a6faa79" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689972368, - "id": "6fc7fe8d7eb7b9d6e17b7ae1c8a42d5bd5c15de0f3d543b0899961d827bf2e12", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e8a9f9ccc5592892080e09ce9414da1ff75f9a4d7d4885fb9e011a0029d67aed8c305fb841b1b3fdcb0f839c851a59692aaef37a36a679c7be9328c67e904d8d", - "tags": [ - [ - "e", - "297b09d4c973412fefb9a47ad724e4f7ac62c7350eb32c45abdea99af98c2588" - ], - [ - "p", - "4ff36a4d67fa327ef1a686a575d0106b4781600900f68ccb5a40f7e455530baa" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689972158, - "id": "9c250df48d9899d18e634573297aade8e1e81175b272bc60a155e50274c130e4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c78c7b2d9cf42561aba618a11f94814aa6a6f86dd0791b89bf3b1d5db8d86782ffcd3bff3f5fd3f4e9e148d656f2b615128c7dd4217a002a8d91db96bf310e54", - "tags": [ - [ - "e", - "6a7a47dfef9bef875b58763dc6185903ffa4bbeb6f3d01db9999c2cc4bfb1800" - ], - [ - "p", - "21d98206ea80a4aed5a7efa97965b5ef08f8f1cf22ef295c1d14bcfcf4efc3aa" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689972155, - "id": "75f95f238fc8912757dc4d8720a1b76ad471bde1235e11f304c8b4bd8548826a", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ce8d68a1d67d24366870915dabc044be2f39e714a9c40dff0b988007cec7db7592c66f4e79b1c01a11ec9a7c4bc1f9dc95bf3bd936522165f9af5b360a0b92c1", - "tags": [ - [ - "e", - "38b911cf18013676cdab7699818415c52c8f3f76c673bcb7bd93eb8946caeb3b" - ], - [ - "p", - "31da8e96a0d372f657280a3b678c5c8398b053d0891d458b7c8b0a752737a9e0" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689971326, - "id": "b90073d643d6632831d65d76098be4a5bb2ef1f1edb040dce63965a09166d3a0", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "11352b96b205a1588c64b2c7941199370a80d13fcda0f507fc608fc86a53ffcb20641d365a1213729dc87676d359a5bf2594fb136ddd5c2e36c3b034c7225051", - "tags": [ - [ - "e", - "306f1ce3434139c9761742f13b3f30a91cc0287dfd187d19a0a314a93a1f5696" - ], - [ - "p", - "4149bd2ca7c08ab6321dc1f54176c78acd295daa2030dca04e8010ad992e714d" - ] - ] - }, - { - "content": "Yep, no full profile hiding yet. Though it could be possible to mark the entire profile as content sensitive. ", - "created_at": 1689971219, - "id": "5c2964fdd3a2c531ddb6dae4008f4c8daa26a12b1fdd1c5f23c93e8c2502977d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fb6230e03f1c7e2ad6ebba17e299593566f3f3e25e00e9f770e0a55d70e47a119b0692412dc3686891815c78cfc094ffbb323adc59684de8ecd398b949206145", - "tags": [ - [ - "e", - "f1b86fbbcdf3def82c539ea1cb47116eaeb81806cddf2b55986f79f73b9a1b97", - "", - "root" - ], - [ - "e", - "a2b6c4f5ce2f59e2b665623624935ab9a12ad899809de109eb62497a20674c39" - ], - [ - "e", - "825bbee3f59a086aea0f4ddbcea235e156ff10db4169af01f2b7b240eae42cb6" - ], - [ - "e", - "957ad7b333d2b068d42b3eccdcf1cf4aa2a7e3fd9b4fc3932fd4f43dc9c9d5b6" - ], - [ - "e", - "99ca15337411022cd6dd6ebd12970c678e039ce64b16dc801698a220d010707d", - "", - "reply" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "1b1e7b22eb297be33b16dbc01d89cf2ee88704390710069feee7ab9ed91deb1d" - ], - [ - "p", - "dd840e433b978795bb35a408bc61ef7e99688ba0b166f8cb4c7cebcb5318ecb0" - ], - [ - "p", - "c6402125e90e82792f580003bbf81a130bab2540d553331c5035ff0864e5a54b" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "D9ZDPT+ym8SiZVDXLY5r+ccfMfJOLZr/Fb34eYAkSNhE4bfz6VeucqqRflgqiZtnpJXzxzVu+ccVMlmOQKKBA0BQD7juHaaaHAXMUXbhLjw=?iv=Fax6ymzr/o0Vj+8pJqHyiA==", - "created_at": 1689970514, - "id": "10bb476b7e35472b292f69e14aab8825ba2921eed14bcfb175e71f5bd84682ca", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fc82e33f3737423385466c4f825cbb8de6232a5d81eb6abf0d0e09405ee0ca5217e307994becdd6f32b23dac4ff625218ffbe930810f372247cdb0f786985df0", - "tags": [ - [ - "p", - "8d9d2b77930ee54ec3e46faf774ddd041dbb4e4aa35ad47c025884a286dd65fa" - ], - [ - "e", - "2721a5c224fdd7b786fb97d5c173444a735b42903ce8daa9d7ac636658360ec6" - ], - [ - "p", - "8d9d2b77930ee54ec3e46faf774ddd041dbb4e4aa35ad47c025884a286dd65fa" - ] - ] - }, - { - "content": "Top-right button. ", - "created_at": 1689969132, - "id": "87f3e8669d345ff58a7314b59966dac2091c6bcd9f78f8670d0f559acec70216", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b112cd109be777d321ff77d9b2a51bf81da709547c21456e29e2e6340399021f313cddfd9e9f170f85a82b6cdd54aa66cdf59e38b49478f3ff71f3ae5097f933", - "tags": [ - [ - "e", - "2ae6e0e1978e9514561bb989f5da7e8adbcf8f1630d7034a3a9ec7118888fe26", - "", - "root" - ], - [ - "e", - "9f3e00e694697dbdd682a83ba9328956fbdee15ee98c8247f609c619d5b1ba48", - "", - "reply" - ], - [ - "p", - "55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "7bf7db83f73228f5df6ba34849f2af9fd54bf565b5ad698ac708249b310079a0" - ] - ] - }, - { - "content": "l0giUaY9CWhvb9TJDppm/TxERuBTIKu7EDV9iJn9pfAtoQAzhq6DOOZxspsFc54b?iv=0xlAHbPb/lU6u6M+mMrVgw==", - "created_at": 1689968865, - "id": "e79169091e1262551ce7d9720910ab4276e9ba3a90375f0eb6b82133d5033d37", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8b7559ccd3d527efad3e1f0de07fc73957d39d1261f665a7fe21c4aaccb9fce895eb7ce1371aadc06ef9ce2dd7eba6a2cc140ec05de6f1b7cbc53b6cf5612d1a", - "tags": [ - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "B0LQfQWsazGI7Z1U0YbsslTRgrikDPkURzlU/ZaA1dNb8xG/62ZJI6glJTmSTh7Nx0ZlnqviisPqU17cxWwjJe3vPM1xop/FDsha3ZdmFYY=?iv=jIcTUYXKc9pnAWlEvwNX8w==", - "created_at": 1689968856, - "id": "60b7f72e911d92f54f3db9d207a71fede0cf78692e110859c9e8915b7f745175", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0e227cf32752a175bb5be027064d6eed57b7f6913f092871533693124da6f6eac0ccb0491ec5fb88fc23995d0bed303c5f5e01a7a61adb6c76791767c84f62eb", - "tags": [ - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "GTncRNSHERzHjokQ4zWRCk8q+0Tj98EIWVfDlETRdnb34tUvZoK1NQ97BXzyj/aRJz3t6Qc91z46vLursOK2Sg==?iv=5v/i58l4GDhGx3BpXQciFA==", - "created_at": 1689968831, - "id": "c96f42508779710b8d09b8f3308e5e3ed8069983e574ae64fdcb23eea01877a6", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9a32548210a39226d8eda5ae21bd4f0d7159e4bfc4b7bd11014deebe735e8ab7cb80a525dc73b67127c4bb0646f738b8f4ac0ceee687daad02c6a55461fc7678", - "tags": [ - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "Hummmm.. looks like I need to fix tagging live activities. :( ", - "created_at": 1689968448, - "id": "860c9594fcdde6307bef4f6acb99f7f155e1061458b8c9894e3989b023c59d2f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6fbeae674d410eb00ee2a17a0735ad0c3e746bf6695d8239c1cd0094e45750752d8b68a4998724894448e887865cdca56c60d2a1e0cc07633b9e4d6f7bbde939", - "tags": [ - [ - "e", - "2ae6e0e1978e9514561bb989f5da7e8adbcf8f1630d7034a3a9ec7118888fe26", - "", - "reply" - ], - [ - "p", - "55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "Turn on Amethyst, go to nostr:npub12hcytyr8fumy3axde8wgeced523gyp6v6zczqktwuqeaztfc2xzsz3rdp4's radio, pin it to the background and keep browsing. 🤩\n\nnostr:naddr1qq9rzd3c8qenzv34xgesygz47pzeqe60xey0fnwfmjxwxtdz52pqwnxskqs9jmhqx0gj6wz3s5psgqqqwenslj8h0y", - "created_at": 1689968401, - "id": "2ae6e0e1978e9514561bb989f5da7e8adbcf8f1630d7034a3a9ec7118888fe26", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c43f4af5b693201d6073e3034dccf272954812547470c6f9a0f73b5dc6afa8b129de124676da58dc52efffb3f73449484508306e9d55154f70af8dfcb3a76d68", - "tags": [ - [ - "p", - "55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185", - "", - "mention" - ], - [ - "a", - "30311:55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185:1688312523", - "", - "mention" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689968322, - "id": "34f6196dd0ad0cdd727f936783cfd705271fe8504c5a114d18a03a16f0b2d825", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1b02863fcd487cbea1b8e6a45ffdcbfefd130e3560af1192398ad02349df452281b6b2ac5b2135791d8f80f64cf21957eba5951fa85a5eddbbdd9781a8de4629", - "tags": [ - [ - "e", - "c9d976864bcbe0a3be5b025c89e671874d16354dc34632f340bb4387124a80dc" - ], - [ - "p", - "55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185" - ], - [ - "a", - "30311:55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185:1688312523" - ] - ] - }, - { - "content": "", - "created_at": 1689968220, - "id": "e6e3cc971eaac101d1086cc6f8bdc140a631aba8cafbd12fd795b7c07b6ae333", - "kind": 1984, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1c2bd83a4745bc62684d4a78c6a0b000466ab95b49daba18115a9e92bb57525294f62f3df31e4397d87224f0644e7ede7140636eae36b0094a9cada49949507c", - "tags": [ - [ - "e", - "0a7c4bea9affd6a5614a17889514c7a2aeba60e63dc001743739f7598e3fed70", - "spam" - ], - [ - "p", - "9b0d19ebfbddc17922a0cd8df1d97e73d8ba106fc80a4d43b3f815f3f1a08983", - "spam" - ] - ] - }, - { - "content": "⚠️", - "created_at": 1689968220, - "id": "7878ced274809d1c8d0935de9f4ca67e12f61a6d3e8688e0f939e9616efd78b0", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "86d8360ec24069f6736c46edc01dd713555e0a7f56da5c48b9b015878f422f5a36faaf68dee1f77360f56890d7d4b9081df08da370a02489d30777fc9994afb1", - "tags": [ - [ - "e", - "0a7c4bea9affd6a5614a17889514c7a2aeba60e63dc001743739f7598e3fed70" - ], - [ - "p", - "9b0d19ebfbddc17922a0cd8df1d97e73d8ba106fc80a4d43b3f815f3f1a08983" - ] - ] - }, - { - "content": "Keep updating that event. Amethyst marks it as ended if you don't update. ", - "created_at": 1689968204, - "id": "84b084e1d31a27a92f76cefd5e745a089e09f64e92e679c238b268af5406723d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d7f66d9f224580504fd39bd6a8caca7941ec40efd015aa114c8b0b6500b32c74ed96622e57a5b907f39df73b753b2f20e765ca0ed533d36ad5dfa15473825a7c", - "tags": [ - [ - "e", - "6557bea21d980ce1fdf671fcee3d3295a6beb78f63d29729f5d284815cb57751", - "", - "reply" - ], - [ - "p", - "55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185" - ] - ] - }, - { - "content": "hDAdqWH/tj/dzqyXNL+7fzEZ83mJKsbHRXMdln4y+B2nnCWKkNTdrFxU+4L7DdQC?iv=Puix1vCTdriA+pLxfC/qnA==", - "created_at": 1689967568, - "id": "28cdc408713dcc255edcc8db05bc0e40eb486321d25c43b8d203de5e70941f4b", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c797ef7c1b05d81c24c1aa60cf491b2df71386634175bb2ebffa9f8c78c7f956d9f56fe586366cca91c3f25a3f9b951688aa8965c690c4b70150baf096c24f61", - "tags": [ - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "HqXbmGO8PjLriW8nFNTMsQ==?iv=llg6zk1KYvXem7OaE9bl8A==", - "created_at": 1689967556, - "id": "f88c0965f79b79d2fb58f93e844f46d91776c2d366374f226ddb935be6d95ded", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7e1b3c32dec8c5dd3ceb310ae2bc881aa8ce838a1fc9acc33ca9ba9907665e1cc972d0d229294c56c34f4c490b621f1f9a0df0f081181ed0c9e06dee7bf2c476", - "tags": [ - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "Sx4QIMpVV0QEq6oeXH5MylS1Y733BReuPr0otd423lI=?iv=LBuyRw8BsOpaBbU5xG+BAg==", - "created_at": 1689967552, - "id": "6af5ca2203c5b93249bd7fce7d6ff3fb426df38159927c85e0c263905ccd91b4", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "68d0d30378769c1ae389df6ed0bf20af7d35311f8fc26ea3067929d24d7a5ae896e78f3d38ebb264344e8f066782b230f51337e0941bf2f4ef83e74829006557", - "tags": [ - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "xGwYwz9X3f0s3xYD8tjeG0eWoXaDzLwXGth7ID6o4YzWNZv9uj245SNdQvYQuqzg?iv=UnnU6U0xomni3FQFRqQmKQ==", - "created_at": 1689967546, - "id": "90060a1cd906ce9ea5c790839ab1232aaff691e8931c44f57ccd725953f5a40f", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b6d27a3c34fc53bfc816693bdcbe77010b4c1f9d7e4817af043922746d7f200133243cf5e2f85837dae935c393e5c4c4b6cfb4ec22c245620facb2f2afceb246", - "tags": [ - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "Video is so hard :( I will keep an eye on it. ", - "created_at": 1689964286, - "id": "49b412af98a3b519f18266a67bf10577a68a7cdb3df26d234e491a54980d87c7", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2fb538efc3a33e80100a3dc78ddf779e15945f5b676afa5150f0b66382a409554087f2f9e8a1a983b41435db48911aba6b7a30664e12f7313ed4cd98a4356ac6", - "tags": [ - [ - "e", - "438c70e797d8bb3ddda9a1c15726a25f2034c1c9a96337d801a377448ca754c8", - "", - "root" - ], - [ - "e", - "885849c65696f340433c58a054df5ef27937ea5efe87405fcdcc60741748f7b5" - ], - [ - "e", - "dc6a448e730342262f978f1638137b3621e3166d1fa17efbe0ae972a24de0282" - ], - [ - "e", - "74d50ebd3d2104014265ddf72a81671e6d15cc6fdb68f4706eb5a6b3612d3c10", - "", - "reply" - ], - [ - "p", - "4b52aa385912d5ec98b773211aa884b1a6656e8fe6bf7a151a6a6f6adf45c417" - ], - [ - "p", - "4b52aa385912d5ec98b773211aa884b1a6656e8fe6bf7a151a6a6f6adf45c417" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b9e76546ba06456ed301d9e52bc49fa48e70a6bf2282be7a1ae72947612023dc" - ] - ] - }, - { - "content": "", - "created_at": 1689964202, - "id": "b2a975890c554d6071d9dd1200cfd2020bc8be752d5e845e8d6ab6e5eb92f7ce", - "kind": 5, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6682fb0170db6a48da22983af8ee44aea60c80b42f303599c0119d96e395c74ecb4ce6a10efb8c6dbc810b427e72d29374cccccac5a34dfdd418caa656faec2d", - "tags": [ - [ - "e", - "8b22b43b5c93e5b84830446c7ec610fa88155dc62ecca4d32514e63d49081335" - ] - ] - }, - { - "content": "Last message: https://github.com/nostr-protocol/nips/pull/468", - "created_at": 1689964112, - "id": "5ee95e9c26d48954d6e842bbde5aa2f54d3cd5cdd1e42eef1625f3fbdcda7795", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "861af1f7cfce98b5d84c728e4a0d666d91fa42b5a1d58eea1cffabd39215b2441f39bf1a8bac41dcf9778ca4b01fd1d45b535a51c423f7f591b551b7ac901858", - "tags": [ - [ - "e", - "f7ab0a2197676c2da1af737bb1c09e4c750b6ebad3223acf72c3648372540755", - "", - "root" - ], - [ - "e", - "ea9ff60451079f154495ce532c537e0509e2f9add03b24b0d5a16166732e4ba8", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ] - ] - }, - { - "content": "It's a very effective way to avoid reports. ", - "created_at": 1689964080, - "id": "d2186814284909245032b96a0ca44af635d4a4c2cf77e57c2119704df80ac9cb", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d2f1032e162dfc502edce54e862eed06e944677134c7e831e2caced19f2a6614d78440deb6e7cbad3c72c6f6bc834308ebb19e4df248a8b9d93bfd9ebc8b4aa6", - "tags": [ - [ - "e", - "409233edfd6dfbe4c052e53552cea2b5d99427107e638c08a5f76412638e2997", - "", - "root" - ], - [ - "e", - "c0c727063a3ba2e9c21604df63444fb97b7c39dc788734762f2bccea31fe45a3", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "c6f7077f1699d50cf92a9652bfebffac05fc6842b9ee391089d959b8ad5d48fd" - ], - [ - "p", - "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6" - ] - ] - }, - { - "content": "get the video urls and send me over if you can. ", - "created_at": 1689964038, - "id": "dc6a448e730342262f978f1638137b3621e3166d1fa17efbe0ae972a24de0282", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "62f6f79c609297e102ac206ab6e5d46f6132c0c6db1cedc27afa96e1e1883159cf9c36793aa6bfaf943e05edc67b2e908df87a38b7769c2768eea615848cd5ba", - "tags": [ - [ - "e", - "438c70e797d8bb3ddda9a1c15726a25f2034c1c9a96337d801a377448ca754c8", - "", - "root" - ], - [ - "e", - "885849c65696f340433c58a054df5ef27937ea5efe87405fcdcc60741748f7b5", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "4b52aa385912d5ec98b773211aa884b1a6656e8fe6bf7a151a6a6f6adf45c417" - ], - [ - "p", - "4b52aa385912d5ec98b773211aa884b1a6656e8fe6bf7a151a6a6f6adf45c417" - ] - ] - }, - { - "content": "Bt0pzANqo6JDNMOVSZtRGduXq7HpQB4pXZxi+jE6ziUhQor/HhA/iDUO5BbtMD5AfpOpqisuLzf7HywST79t5TVbtM7UGBm9/iTfcZeg5Fkyt+3V9G1ef/lTMw8b3BvB?iv=6T5YVB0wcifzlVwyasCJjw==", - "created_at": 1689963534, - "id": "fd438f5148e6e847ff748d564f806cb15a4603be5e0c27f8fb192bd3c3f6ed67", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f4f1e999f951e672340d01a8c1891fb475fc54b4275597f2ffa4d92f5f0085502d5345741542239a3bb508411bc9670dc22125c46e78957e99d4df415322abd5", - "tags": [ - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ] - ] - }, - { - "content": "Thank you for using content sensitivity ", - "created_at": 1689963327, - "id": "796d257f6e06d8145d0ed795f3695bc4c175d7a24890922be3852e4cd246e096", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7b2b3eec7f5c1cad7d655d59d521464c6ed429eda787ef31cb3d44b90e30d770419dc4034e0b887c7091a933f51fde3c7e92880a2bf2e17621f62617a1b5476a", - "tags": [ - [ - "e", - "409233edfd6dfbe4c052e53552cea2b5d99427107e638c08a5f76412638e2997", - "", - "reply" - ], - [ - "p", - "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6" - ] - ] - }, - { - "content": "8Ab731Z61Ct6sIERglBUgqRxjGrJHnyrq820HqMEywNhu1gIIPW+7dvM/XC0nv6BjXBLGuLHDswYbGhVMXxopQ==?iv=EKyBALmNq+k2B46m3v+mPw==", - "created_at": 1689963305, - "id": "0d7ea4e5dbcca7d6c7ce3e7013b2261fbdbd8b767821236c4c059b51da3bbe65", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "625170fff7fde4f0949ec574706cbf39b1eb8813bf676bf6ea22a5973cda0333467e0f748ddcddbdcfc357d6cddb8e4f49b4f8f0c7cdecbfcd80e40ec585f048", - "tags": [ - [ - "p", - "1c6b3be353041dd9e09bb568a4a92344e240b39ef5eb390f5e9e821273f0ae6f" - ] - ] - }, - { - "content": "0ONkFjclPM/XKdRfSCPfpobIMumwXkIEW2y6u13PG3M=?iv=sLeGSt50ih42yHN6V9xIvQ==", - "created_at": 1689963292, - "id": "df3e74b5af761d6f1ef71c0258e27d9894dffc346c9d4df3c3da29e0889975b2", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8c1f8338736612bb6f5de0d4f6deecba028a66e41c74d63f83cc85bb1d4e2b8106a82b7b58e1353a54fd8529363fac11514f67d5426a2aa06048c7c19d2d8a54", - "tags": [ - [ - "p", - "1c6b3be353041dd9e09bb568a4a92344e240b39ef5eb390f5e9e821273f0ae6f" - ] - ] - }, - { - "content": "Super strange.. all of them? ", - "created_at": 1689963074, - "id": "0ec5ff7ca4b1585cfe21db0e071f6d49c839ddbbeae9d322f1c30b016145276a", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3f2e3efdc3d54eff17c5ef2d2cc86985582fd8cddad7e2ec214b2f2bd52e0e40b3414fc43ad6578ceed602ca29084a0c7332a6c19ab5710b4901a79964b72078", - "tags": [ - [ - "e", - "438c70e797d8bb3ddda9a1c15726a25f2034c1c9a96337d801a377448ca754c8", - "", - "reply" - ], - [ - "p", - "4b52aa385912d5ec98b773211aa884b1a6656e8fe6bf7a151a6a6f6adf45c417" - ] - ] - }, - { - "content": "Yep, just click on Auto and set it for German (make sure to have a German keyboard installed in the OS) ", - "created_at": 1689959447, - "id": "aab95307fedb358bc79fa51699cb627e31774e5305bc178857d1a38d624932a6", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2461b06ff9a8c141646312c5a59a08a44b842f43386f73d32c925c18a62ae0b993560c6480719f3e1252d5a0d521bca7d077efe614f864e82421a8d19403f249", - "tags": [ - [ - "e", - "0b6153cc21d36e51edbd2c30c7c45dd2dde66c6bbd0b0b5d508a613f277b1ea6", - "", - "root" - ], - [ - "e", - "81d53f4fa555d6aa29175ff2235e34cba40a949eb3be8104176255451ebfadcc" - ], - [ - "e", - "01186521fa18cecbe9bebcf6d3b6194cef6dd36ae43a3b1306601e2cdf0debec" - ], - [ - "e", - "f8ec20358eb2d8c6f3335aa0a1da2ae40b0e3163fada3a543fd2c7ff2a1085b8" - ], - [ - "e", - "c7bf286ba483b4bceaf758b372d3d35d58398962e5e31a6b76ce38a614e5e5f1", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ], - [ - "p", - "ccc0c31d1067eac417d2cf562e09df0bfb8f6724addfcb01be9600a75116446a" - ] - ] - }, - { - "content": "We should have both implemented. Market decides. ", - "created_at": 1689959301, - "id": "47652f48803fa5e109ea9ffe514feb183a613ada5ad23df64f6be09971ed06bd", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c402d5cd2a50e0d0f26bcb1c15ee09b419d2985898aa83fe89a353270a0900ed6750cb6354222afa316ed29e16c61492f75215580323c1aa5cf47e82e89846fb", - "tags": [ - [ - "e", - "f7ab0a2197676c2da1af737bb1c09e4c750b6ebad3223acf72c3648372540755", - "", - "root" - ], - [ - "e", - "ea9ff60451079f154495ce532c537e0509e2f9add03b24b0d5a16166732e4ba8", - "wss://relay.damus.io/", - "reply" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ] - ] - }, - { - "content": "", - "created_at": 1689959268, - "id": "92dc035f4ee6747cf9b12f5d3265c6f015f4e0e2ed89ef78fa46dfe8f4536b24", - "kind": 5, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "300b8bb33684e433b4d7908c51f80286d4d51b2d3b82967aff78355fda768e0cbdce22fa58b5630a68ea622248f0d9363ce1dba86f7f743b25e778ebd6901b1f", - "tags": [ - [ - "e", - "8b22b43b5c93e5b84830446c7ec610fa88155dc62ecca4d32514e63d49081335" - ] - ] - }, - { - "content": "Very interesting... Maybe the app is never deleting the cache automatically? How much space do you have in total? ", - "created_at": 1689959088, - "id": "bf1866daf7c88ee0272062b10c26fd4d77c37e29fead13820b55f4307c25df28", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "26bd4ab68f0889678c6c8d17e1a2a612e2435cf3055bdbbbe81cb4795bf9897e930c6b82c5474e05946f4ff5cd31da6bad5256397a8bb0c9db0de411df3d930b", - "tags": [ - [ - "e", - "df9b11fd6029e3b4c27bfb5cb59aa152442a03d57bc5b759684263864ae729af", - "", - "root" - ], - [ - "e", - "c87acc1325604410e041e4a2a363e1d9ddd0c6eb97c05d5cf79a41101729b281", - "wss://filter.nostr.wine/", - "reply" - ], - [ - "p", - "0d1dd56ae3204328e45f78b1a64ac8f06d227129f775493ebe84cf28250d1ec6" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "ca89cb11f1c75d5b6622268ff43d2288ea8b2cb5b9aa996ff9ff704fc904b78b" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ] - ] - }, - { - "content": "You can do it in a new event kind that is similar to private messages. In that way, the only way to leak the message is to leak one's main private key. \n\nIt's possible to leak it but it has a cost. ", - "created_at": 1689958824, - "id": "19e4caf71bf318b48942caaeb8c10eda847ded4240fc51831ec8e73e52e09b39", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "49bad4e3a8e9511baac9c58d7de984dd754dd205f321c2dc4e92b757d043e1ad4f04fd9e605bcca5244134a87e1471377bbedb085f66c3630bce59f6698a4e60", - "tags": [ - [ - "e", - "f7ab0a2197676c2da1af737bb1c09e4c750b6ebad3223acf72c3648372540755", - "", - "root" - ], - [ - "e", - "3bddcbc6ca72750f7ed63e1468a632dae75ecce119a18a52c624c7c047fe2b42", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ] - ] - }, - { - "content": "Then just wait. ", - "created_at": 1689958465, - "id": "c7ea022e8d7826ecb7e92a7842e3cb6d29c18c9542b872aa56f08fecd3ec09c2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ee20a289e0d45068f04fb0c7fb6b98af8f020131b03246be70796f93227cf181fa4f637e55c4ca3271741de7efa67bc6f712ad5a6c53e1d2677b9f7c9184102c", - "tags": [ - [ - "e", - "df9b11fd6029e3b4c27bfb5cb59aa152442a03d57bc5b759684263864ae729af", - "", - "root" - ], - [ - "e", - "d1aa5d57ae4fb0fa142acbd0554f92ecbd7b43eb95811e9874710d17ae1c3988", - "wss://filter.nostr.wine/", - "reply" - ], - [ - "p", - "b45aca09dce5a9d8af39f5b116f306ba5b9cf175d54b99ef7fe44b14e176dfee" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "ca89cb11f1c75d5b6622268ff43d2288ea8b2cb5b9aa996ff9ff704fc904b78b" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ] - ] - }, - { - "content": "Once you sign and give that to somebody, you can never block its spread, independent of Nostr. We can make it harder, but somebody else can make it easier. ", - "created_at": 1689957408, - "id": "4145fe4ef02e0f19b43cbf5a360093b828ccf7eff205f6a92498354f10f3e584", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "583f5dbd61495a31b663e9eaa337d3d4e9f63a795bed5d578e85374c289ac75de32de47f7d08c41cb0352d1bfa3ff491484c14e01ebfe3eabed7833d0ea68a10", - "tags": [ - [ - "e", - "f7ab0a2197676c2da1af737bb1c09e4c750b6ebad3223acf72c3648372540755", - "", - "reply" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ] - ] - }, - { - "content": "⚠️", - "created_at": 1689956888, - "id": "fa03a5d6e5f2ea0b52bdb88c1656d90a18709cb1b9ab9ab184a22aaeeaddee85", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1d2ac2e49963532028beb37bec2ab69fa1ad09de2015fcb9d3fe54c0015c768b09096b0133f78e3d51c1e017bc3565ee10f615f227704cecec86645b969ac823", - "tags": [ - [ - "e", - "dd89366d32893dd2ee4f8b22a68c9d19673b031dbe7a780e1ac14a39354f1e58" - ], - [ - "p", - "c1a6940f84cb4d32564837d9ae055b036545c8e5f61cdd24f29786876436df8a" - ] - ] - }, - { - "content": "", - "created_at": 1689956888, - "id": "db4a85c524e8675494bab0cf0c1ef3a83809d1a954b159cd3a27b3fc0bac91ba", - "kind": 1984, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ca9b7e59d54d109f789fa4ae6e67ecad738f5bd266f8d71ae5561d03aedbbe63dd70264a203662138b2e1addcdf1c4039b6a708d66a27555a213b22c247f8405", - "tags": [ - [ - "e", - "dd89366d32893dd2ee4f8b22a68c9d19673b031dbe7a780e1ac14a39354f1e58", - "spam" - ], - [ - "p", - "c1a6940f84cb4d32564837d9ae055b036545c8e5f61cdd24f29786876436df8a", - "spam" - ] - ] - }, - { - "content": "", - "created_at": 1689956881, - "id": "ec4dfdfecf7979e5a5e8240d8a522893d414012e961e8dbe653c278bb82701dd", - "kind": 1984, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "84d0b6acda593495ea135c074c539c062826727568039ca0e4e575c4f30b63416a8501faba8088b5b4d19ba9275d3ad8dde05397c6d5d5d55cb868719af8153b", - "tags": [ - [ - "e", - "91d440406cbb8a6514e225723c42d4efc3d359da1ee57098a1d86cad3ab879cc", - "spam" - ], - [ - "p", - "ccec23ef54ebcfd3bcbf71c4e28d8c32087addda00710197e72275a04828648e", - "spam" - ] - ] - }, - { - "content": "⚠️", - "created_at": 1689956881, - "id": "d2ba718ea610c9f2715fa8e0a65f5568439b31a604ec33383e51654767e03116", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "4c0dfa3a5d1da1f14e5d1fd4e092d44e78d1dffb033b5d64af9ccb691bf0b9e23153867f71a42d768ba107988e752b800ff8b9f4972df5a3f420aa4a2200715f", - "tags": [ - [ - "e", - "91d440406cbb8a6514e225723c42d4efc3d359da1ee57098a1d86cad3ab879cc" - ], - [ - "p", - "ccec23ef54ebcfd3bcbf71c4e28d8c32087addda00710197e72275a04828648e" - ] - ] - }, - { - "content": "Actually, it's the second. It's just the first I advertised 😁", - "created_at": 1689956873, - "id": "72bfb72cd240f6fa6ad0f6aa502fb9f0f9d8d862bf61df28bac61c35ea2c531f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "21e168c8bad482131f6bf06b69540d11152911de296e657450c92214fe9073742d93d0063164c0516ee959c2f41610e61d0bc8c87a304695d05acd69c0cddfb5", - "tags": [ - [ - "e", - "fca1af2a576ce6f8455faa518475687e857c8dac514fad4148f56b68b25de64b", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ] - ] - }, - { - "content": "Thanks to nostr:npub1w4uswmv6lu9yel005l3qgheysmr7tk9uvwluddznju3nuxalevvs2d0jr5, Now you can choose which relays do you want to post to.\n\nhttps://cdn.nostr.build/i/d43712f8f8ec312dde3b376afe1339cab94b1750c1f89185cb69f5ba0c9a6687.jpg", - "created_at": 1689956778, - "id": "277fbd58c7f1ebcb09f7211361a540a38f07c717663b5494af1b9847236bb560", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2f60d9776f1453f24a70a471f73395660240931e541003154c48bb9e6f6358252ec678e3e5f6213ca209bf768ecd935fc1d266b1eb51b9852c62c0133121b335", - "tags": [ - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19", - "", - "mention" - ], - [ - "zap", - "greenart7c3@getalby.com" - ], - [ - "r", - "https://cdn.nostr.build/i/d43712f8f8ec312dde3b376afe1339cab94b1750c1f89185cb69f5ba0c9a6687.jpg" - ] - ] - }, - { - "content": "Did I forget that part ??? ", - "created_at": 1689956705, - "id": "60b045e3acdc14f003c241e78d6c802420375bd324e85660c43be3e84dbc9de2", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "4f6c79243266abba1e55952a95ccee0c33ae8c9d7be5503a9765407c545ebd2e80c4b65a6310f6538dc6d7b4b1ec0672afe6a2bef17b3f11882494e9771a1071", - "tags": [ - [ - "e", - "df9b11fd6029e3b4c27bfb5cb59aa152442a03d57bc5b759684263864ae729af", - "", - "root" - ], - [ - "e", - "bd3a2dcf591c43e69bf1d54d8a5fd7a379ad19458f79b08df6b756059558569e", - "", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "ca89cb11f1c75d5b6622268ff43d2288ea8b2cb5b9aa996ff9ff704fc904b78b" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "### #Amethyst v0.70.3: Fixes and Improvements\n\n- Stops Video playback when switching in and out of Tor\n- Adds a space when rendering inline images and url previews for nostr:npub1aeh2zw4elewy5682lxc6xnlqzjnxksq303gwu2npfaxd49vmde6qcq4nwx\n- Updated se/de/cs translations by nostr:npub1e2yuky03caw4ke3zy68lg0fz3r4gkt94hx4fjmlelacyljgyk79svn3eef\n- Moves the video caching service initialization foreground services.\n- Fix boosted notes from blocked users appearing as blank by nostr:npub1w4uswmv6lu9yel005l3qgheysmr7tk9uvwluddznju3nuxalevvs2d0jr5\n- Fix KeepPlayingButton color in light theme by nostr:npub1w4uswmv6lu9yel005l3qgheysmr7tk9uvwluddznju3nuxalevvs2d0jr5\n- Refactors ChatroomHeader compose\n- Moves the loading of an Accounts backup contacts to the IO Thread\n\nDownload:\n- [Play Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.3/amethyst-googleplay-universal-v0.70.3.apk)\n- [F-Droid Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.3/amethyst-fdroid-universal-v0.70.3.apk)", - "created_at": 1689956180, - "id": "df9b11fd6029e3b4c27bfb5cb59aa152442a03d57bc5b759684263864ae729af", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f36eca3f55f6a575ea5cb44e73ed5f98f8fb0c44086d4dba1e8f7e57d837e8749c5bf14825898572bd8cf612abeec12d825e4ad5fbdbf911540c77f241428da4", - "tags": [ - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "ca89cb11f1c75d5b6622268ff43d2288ea8b2cb5b9aa996ff9ff704fc904b78b" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ], - [ - "p", - "7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19" - ], - [ - "t", - "amethyst" - ] - ] - }, - { - "content": "UFNglwaQDiNRbqo4P7NHfA==?iv=gRBjwGJVDFtiGR/XEWGfgg==", - "created_at": 1689956136, - "id": "a42b28e1008356cccd329e3fc9b8f33d42bdfc02891d32bfa2218853f325344b", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "159df581567f73f2eec769c8b785399eb20a42211a7c569592f7359406c915432d353d6af8011fc723393e3057bcd23f5b8b1ccf52a682544ed0e1f367e249e2", - "tags": [ - [ - "p", - "ca89cb11f1c75d5b6622268ff43d2288ea8b2cb5b9aa996ff9ff704fc904b78b" - ] - ] - }, - { - "content": "It's 25-50MB for each translation model (each language pair that you see in the feed) + raw images and videos (which are big because we don't have a central server to scale them down, etc). \n\nMay profile pictures for instance are 10-20MB in size. Some GIFs are 50MB each. \n\nSo... It fills up quickly. ", - "created_at": 1689954869, - "id": "f13fa631fbfd476b06f7027d2944dd5b0cdb67d0755148c95d6030af213178a6", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c78bbcf217fd0b528876dde5443e429edf45536d079d14e844e41e126225893735c4ac025525f5e437ce6546e7eb2a5d21f09dc83bb2677b7077212c34d5c6bf", - "tags": [ - [ - "e", - "d8b836d465e495d4aba08c1ec2ad934009824c0bcf4274cd5a36828b25138503", - "", - "root" - ], - [ - "e", - "5660cd2929f688d17a0fd713301c4d3be0f9c8c76f9b4fde611f23385576f327", - "wss://nostr.mom/", - "reply" - ], - [ - "p", - "8ad25d02882c05d6ac20fa7c230dfd1c3d7f6de3976d9c5bd5ecc7bbb63495ab" - ], - [ - "p", - "ccc0c31d1067eac417d2cf562e09df0bfb8f6724addfcb01be9600a75116446a" - ], - [ - "p", - "0d1dd56ae3204328e45f78b1a64ac8f06d227129f775493ebe84cf28250d1ec6" - ], - [ - "p", - "8ad25d02882c05d6ac20fa7c230dfd1c3d7f6de3976d9c5bd5ecc7bbb63495ab" - ] - ] - }, - { - "content": "You know.. you can create lists these days.. http://listr.lol ", - "created_at": 1689954628, - "id": "c233de5e1d9e9d342c24484d694ddaf1a8f5b874f10de2b26ca1a76102f3db18", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f9c10d14b065f1d0ad82418e38231a03bb3dcb728c54431e3944b67068cd5405ccbce3fa690bae8f485da2647d8d7c61543b52cde87187709eac0daddefd2d93", - "tags": [ - [ - "e", - "51c78616f2de35d6c0b3a15ae2d23dd3c084bb976d20162ae5accd81a136571f", - "", - "root" - ], - [ - "e", - "30555fb1b6bf99910d21c243c236dc3fbd5488a06bf7151f21fe2385316f7f5d", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "916b7aca250f43b9f842faccc831db4d155088632a8c27c0d140f2043331ba57" - ], - [ - "p", - "f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9" - ], - [ - "p", - "e034d654802d7cfaa2d41a952801054114e09ad6a352b28288e23075ca919814" - ], - [ - "p", - "ad9738030ab84c04ffaec64abadd6cc682cb3501d193a5ff1c94b90770915558" - ], - [ - "p", - "385eacfa42fc0831b4975983c485e0c7c55ed0f5e4f56d79fa7a7151fb0a06d7" - ], - [ - "p", - "5b0183ab6c3e322bf4d41c6b3aef98562a144847b7499543727c5539a114563e" - ], - [ - "p", - "8fb140b4e8ddef97ce4b821d247278a1a4353362623f64021484b372f948000c" - ], - [ - "p", - "cfe3b4316d905335b6ce056ba0ec230b587a334381e82bf9a02a184f2d068f8d" - ], - [ - "p", - "c89cf36deea286da912d4145f7140c73495d77e2cfedfb652158daa7c771f2f8" - ], - [ - "p", - "52387c6b99cc42aac51916b08b7b51d2baddfc19f2ba08d82a48432849dbdfb2" - ], - [ - "p", - "5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78" - ], - [ - "p", - "958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c" - ], - [ - "p", - "d4338b7c3306491cfdf54914d1a52b80a965685f7361311eae5f3eaff1d23a5b" - ], - [ - "p", - "6f0ec447e0da5ad4b9a3a2aef3e56b24601ca2b46ad7b23381d1941002923274" - ], - [ - "p", - "ecfa3c5c82d589c867c044056f75d6cff794f1886d5ebcdd48ad851da47adae4" - ], - [ - "p", - "b83a28b7e4e5d20bd960c5faeb6625f95529166b8bdb045d42634a2f35919450" - ], - [ - "p", - "a8171781fd9e90ede3ea44ddca5d3abf828fe8eedeb0f3abb0dd3e563562e1fc" - ], - [ - "p", - "8be2fd2cf7cce65a56f0820b022125e9ab4044c7dc5e444e2c0c0eab7501b0d7" - ], - [ - "p", - "50c5c98ccc31ca9f1ef56a547afc4cb48195fe5603d4f7874a221db965867c8e" - ], - [ - "p", - "9f807153876ccb1db650a96fb7ada5a1dbaaa0dc3f22fd3fcf545204aeef43f5" - ], - [ - "p", - "668ceee55475f595ec0e8ef44c64bf9da8d9dd6008ac54dcd24b2501930b960e" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "b5ba65fbb0221a32b6c14400f505cfdd3651d43938a248a9265a516ec0c54240" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "c82bf12d7eb3df7e3cc7766e54363133ac17024a5df2e179c603106cdf203e15" - ], - [ - "p", - "404211c6e9763f49c8c0d8622e6fbf216550b748674247400a2527e0f95e3a79" - ], - [ - "p", - "b9e76546ba06456ed301d9e52bc49fa48e70a6bf2282be7a1ae72947612023dc" - ], - [ - "p", - "47d519cd3bfe5cc6705e32063ef39931946979eebb53425db5f2e4f19c3a3af5" - ], - [ - "p", - "00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700" - ], - [ - "p", - "f1b911af1c7a56073e3b83ba7eaa681467040e0fbbdd265445aa80e65c274c22" - ], - [ - "p", - "8867bed93e89c93d0d8ac98b2443c5554799edb9190346946b12e03f13664450" - ], - [ - "p", - "7560e065bdfe91872a336b4b15dacd2445257f429364c10efc38e6e7d8ffc1ff" - ], - [ - "p", - "f1f9b0996d4ff1bf75e79e4cc8577c89eb633e68415c7faf74cf17a07bf80bd8" - ], - [ - "p", - "803a613997a26e8714116f99aa1f98e8589cb6116e1aaa1fc9c389984fcd9bb8" - ], - [ - "p", - "a1c1984994512025327f52c7b6d3a1434a37fbb7a318380cab4832f8daacbb52" - ], - [ - "p", - "9984188a6578eb513fddcf658f389dbd532e54b82b628ad36666f7aa8f731b79" - ], - [ - "p", - "9168772564e66c07a776a3e2849b02d1a0ac88a7f8e621600c54493ca0de48ea" - ], - [ - "p", - "6fda5bce2882176bfbabfab503a1b5281329582d71c4be84bbb567e65c1a791f" - ], - [ - "p", - "a80455732d5bfa792f279011a8c871853182971994752b9cf1169611ff91a578" - ], - [ - "p", - "971615b70ad9ec896f8d5ba0f2d01652f1dfe5f9ced81ac9469ca7facefad68b" - ], - [ - "p", - "31da2214d943b6db29848bfe7e3cf8ec0380014414f06cddb0eeacc9af2508e2" - ], - [ - "p", - "26bd32c67232bdf16d05e763ec67d883015eb99fd1269025224c20c6cfdb0158" - ], - [ - "p", - "c43bbb58e2e6bc2f9455758257f6ba5329107bd4e8274068c2936c69d9980b7d" - ], - [ - "p", - "4ffc11bfa2f8516ae8bc7c6bf82275d358e47045446250be2d0e5612e2140828" - ], - [ - "p", - "50c59a1cb233d08d5a1fb493f520c6b5d7f77a2ba42e4666801a3e366b0a027e" - ], - [ - "p", - "a3c1a5ceda8b86b7cb64d5d6af58fc787ba400f2912b907969d27547f96545d0" - ], - [ - "p", - "1e9d809ea96f8d7227f06025f4ea2dd41e9426c4276d96a70770987c8013d21c" - ], - [ - "p", - "a12fb7fe051724a34ef3409ebcdb377b9d1157a79b7a2fcd8d008995f190d9fe" - ], - [ - "p", - "c02bedab495a8d73e23192fa161a0b8344821f48446811b1e810fac65b584f49" - ], - [ - "p", - "fe2d5cf62e95aab419b07b6f8a7b75d3cb3066fae25c6b44ace0f9f30c59303d" - ], - [ - "p", - "5133a0947abe801445c34e2f56151d8690f4789ab4c763275b14166e74c5830f" - ], - [ - "p", - "deab79dafa1c2be4b4a6d3aca1357b6caa0b744bf46ad529a5ae464288579e68" - ], - [ - "p", - "b43c91f2a7b9d21bba3ddb08cc321840df249364fb716213508bb17383e1d930" - ], - [ - "p", - "eeadea6cbb5018a190f0117857de513cc271d24c947d56cd82c54a6b64ae47a4" - ], - [ - "p", - "de90c5db36a4011f9d584dfc18de1a5724686867984793ef526331b51f8b43e9" - ], - [ - "p", - "6a02b7d5d5c1ceec3d0ad28dd71c4cfeebb6397b95fef5cd5032c9223a13d02a" - ], - [ - "p", - "cbb2f023b6aa09626d51d2f4ea99fa9138ea80ec7d5ffdce9feef8dcd6352031" - ], - [ - "p", - "df0aed92dff00d4ffeda2f4cd88d967dc576b5549400b92afb98a419aa06e6f5" - ], - [ - "p", - "72f9755501e1a4464f7277d86120f67e7f7ec3a84ef6813cc7606bf5e0870ff3" - ], - [ - "p", - "6e0a1f4852bc8fa42b8047d60a81930d88904ca3f2acdfb5b8413ab8c9f444e5" - ], - [ - "p", - "18905d0a5d623ab81a98ba98c582bd5f57f2506c6b808905fc599d5a0b229b08" - ], - [ - "p", - "90b9bec74789688e515125596ab6350bfe646176ac75742275063922c5fea010" - ], - [ - "p", - "ee603283febc4c31b09903392408a2fff1daf69ac2244a5e4ad07eca3bc79dec" - ], - [ - "p", - "f508d64aeb31bac052327841cc7dd59c9d37c182102a048a439098a8bb816dab" - ], - [ - "p", - "f07e0b1af066b4838386360a1a2cbb374429a9fbaab593027f3fcd3bd3b5c367" - ], - [ - "p", - "b82b98dad630f797edf2ee7e48224577ac93cfe899b3ca2a26d91b3edfaa2ae7" - ], - [ - "p", - "4ca4f5533e40da5e0508796d409e6bb35a50b26fc304345617ab017183d83ac0" - ], - [ - "p", - "7b2d73a3ac9714b06500005454b1b24ff255304eb488076822122101d0fcf7a2" - ], - [ - "p", - "4308ff20ced73871b69ed8bcada2a051bc3a05610d1183c54d67b47cd0f7035e" - ], - [ - "p", - "7f1b2d20466fd5ff836c6bca1a0849f9c77162cfc00b7e708a9142763c021673" - ] - ] - }, - { - "content": "Yes, because you can receive an order from the state to provide everything you have about a given IP. You can hash the requested IP to find somebody's past actions and deliver it. ", - "created_at": 1689952040, - "id": "b35f1b545a37833991adb956498d55fb652e3e19a9cfd1cb6cc658c0da547a6b", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b46fce54c4e8e3136f73c769240149bf1fed84c293c6b19ee1909a305e92a943f889ebb9637bdf1f632058c1e80a4c1393112cbf18007b54a544ca2c8fb6b23d", - "tags": [ - [ - "e", - "d5fbba30ba547c6335e843400d698e5d9e87463fa7f1d03ca555dcc70fb17c12", - "", - "reply" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ] - ] - }, - { - "content": "cxVTHgjC0TXaOTfTi0b/KJk+MLCff4HbxDT6zjwDG69KgMHIw/Yvn0NjHxW87PmHSDTlDaBGXKeDS/7BcY2nqg==?iv=f2tzSqTrlQoXwG8/46dOlw==", - "created_at": 1689951312, - "id": "ca2cd04e3cf4efc9534aed57b1899feae816e02c6a2e8671c2027d4d9f6893fa", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "af1214a7deb8c740b0e7ebc1f55d04e813fc69a4b1f225d7b4a47176230eda817a70f7730a21f518128abb415fb0107475d05a8a0c935a6f6864f26861810421", - "tags": [ - [ - "p", - "4b6147b45bbde75c2ce4cf93444675945c47f41ffd51e3446287bbd56ba668d2" - ] - ] - }, - { - "content": "https://github.com/nostr-protocol/nips/pull/673", - "created_at": 1689951049, - "id": "416181632a67703a81b42b9fea5ce5eae64e8d6c13e7abf46de4a1d66a2c509c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "70fb4cb049e4f4399327272847007fca1f7958c818053aa92679e7e3a665b64af019c0000f0004a13f2ba520d69e61529a8b7c35acfaf85b37cc9e1c7bab1c69", - "tags": [ - [ - "e", - "88c9c9b3fa3b378414e5225e78b7ec5c2a93ba5a508f43c380e70cafa3ade713", - "", - "root" - ], - [ - "e", - "cf98d38c498d3c21669d9e7fa9843589a0a481d17392c1d72848bdc0f9743e99", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "dd840e433b978795bb35a408bc61ef7e99688ba0b166f8cb4c7cebcb5318ecb0" - ], - [ - "p", - "c02bedab495a8d73e23192fa161a0b8344821f48446811b1e810fac65b584f49" - ], - [ - "p", - "77ce56f89d1228f7ff3743ce1ad1b254857b9008564727ebd5a1f317362f6ca7" - ] - ] - }, - { - "content": "We use 'e' with a 'mention' marker ", - "created_at": 1689942025, - "id": "05a786d700033851ba5bce7733e3259e9cfdde7c0cb0139406f5ab42744618b9", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "82707d97e8fbd4e5075bbfe86c377385113db6cb231160153ba9f21472466d7217cef48c0fc161a1d1aa83115dbfdea6abd568789808c3d2e5123d335130a716", - "tags": [ - [ - "e", - "acdd96b1297da7ac202c288e76bc7d85ebbacfb2339b1837cb35a0bfcc817a58", - "", - "reply" - ], - [ - "p", - "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" - ] - ] - }, - { - "content": "It's because our terms and conditions is hosted on GitHub, and F-froid doesn't like anything hosted in a non-free service. ", - "created_at": 1689941382, - "id": "664ef39828f333615e41daa08e975d69c4bbdf48eb94e4d78be94a2c8c53cba4", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7c767e3d95a36374ba2f79ad6eb3547309067e5f87d65dbd12cfe126f373eadb70ad20e3d5edd55f7eff165f0adb91503f8d8b5b52c501ae3cc580e508ddfe36", - "tags": [ - [ - "e", - "42416b010364982b8df9b9a696083b9df982b57fcf4dc907d3b978f42cdb36c3", - "", - "root" - ], - [ - "e", - "b648656bb2536f74e3ab7528e660d93c1400ca12ad6aa8fd06ba59e50643c905", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689941261, - "id": "0d71d842517f97ecd4b8df42a46e0dacae609e5db7d48540a25cad3808eaf346", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "34cb3ebc088c09bd4ddd9ae21a00efe862894bfe2140bfe99139b08aa8189a59456edf3dde9da08fb9870c2a366905cd9e96d41daa0d9e9353c332ea2be450dc", - "tags": [ - [ - "e", - "846479a923ab551c827422073e09b704249b5540e7a8728d4636bc27fb286647" - ], - [ - "p", - "7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194" - ] - ] - }, - { - "content": "It only does it on the Play version. F-droid doesn't allow the Google model we use to translate in device. ", - "created_at": 1689939108, - "id": "f8ec20358eb2d8c6f3335aa0a1da2ae40b0e3163fada3a543fd2c7ff2a1085b8", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e622c5c274ab4ed8acd99d1ccc9918a47deb9e64aec0f4a5172740ae4e0118d2f3743ee178f77bac79c73f3f7b14b9cc07fa1a314e6d0a756b659ce09895482a", - "tags": [ - [ - "e", - "0b6153cc21d36e51edbd2c30c7c45dd2dde66c6bbd0b0b5d508a613f277b1ea6", - "", - "root" - ], - [ - "e", - "81d53f4fa555d6aa29175ff2235e34cba40a949eb3be8104176255451ebfadcc" - ], - [ - "e", - "01186521fa18cecbe9bebcf6d3b6194cef6dd36ae43a3b1306601e2cdf0debec", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ], - [ - "p", - "ccc0c31d1067eac417d2cf562e09df0bfb8f6724addfcb01be9600a75116446a" - ] - ] - }, - { - "content": "Not in the plan, right now. But since Kotlin runs on desktop as well, somebody out there could make a desktop app using our code base. Put a bounty. Let's see if we can attract more devs. ", - "created_at": 1689939061, - "id": "5646ba53503e6a10c538f5f9789b47b4cc55a6a0d51f9cd00fe026e8d0223b9c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "25a749d25096b1e8e1fc8ec0c078bfc24b7ce7c9b453449a97017f95636d797dbe001f7f9b1af2ca5ef770de5492739ecaceb3ec06396ab774ce36e4dd4d2615", - "tags": [ - [ - "e", - "42416b010364982b8df9b9a696083b9df982b57fcf4dc907d3b978f42cdb36c3", - "", - "root" - ], - [ - "e", - "f6ebe924faf115031927d851b4d09bc981370d38bba28895078f0f5908021afa", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ccc0c31d1067eac417d2cf562e09df0bfb8f6724addfcb01be9600a75116446a" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689937268, - "id": "fe40d759d27e61ffe6be02d68c45c65bc9545b90247eefa3f668f4bb7dab6566", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "35002734dd66eb2c3088f053673c647e8ba7d6e4e5fc6bf73a6460d8b5a1a4691c828a0ff51ab4764bf4515b3597654b499bc8b1c54d65df472e94303d8d44d0", - "tags": [ - [ - "e", - "b43c9bb1520dbb4a30405c27b1dfe442232e53ace78168bbfb13258c6a7ae569" - ], - [ - "p", - "84eaf37660225a312d27dbf72acf588106664d444bd432b1c8004c18fa109d63" - ] - ] - }, - { - "content": "https://nostr.build/av/7b9b8019fecf3ae30a25f82ddd22c9fef7adb07cf444d87e078c93fc9ca74845.mp4", - "created_at": 1689907768, - "id": "e509d1900262f4ff82816e5f3250641cc29e7b07f4be966629b193718c59979f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e8f1a409c356a736019eb4a0d210fded04653bc1a1c869d245fd6a0b150e11c455c64bb838c868c488c9104e55cec2a0b187f8ca24786402f7e83a0d8d018257", - "tags": [ - [ - "e", - "50dafc0709a63aec5a1ccb97e979b4e6ab41faed89ef15590ed498b1bd654a7f", - "", - "reply" - ], - [ - "p", - "c4776f31e10298e4fe5b6a4b9d5ae240042f2ca17b5a37208f31166f2e88f05a" - ], - [ - "r", - "https://nostr.build/av/7b9b8019fecf3ae30a25f82ddd22c9fef7adb07cf444d87e078c93fc9ca74845.mp4" - ] - ] - }, - { - "content": "Imagine when you see the live streaming :) ", - "created_at": 1689907532, - "id": "019568d32c6507fd8677006e47afca2cc78bca9c3806158eb3e84838a23eddae", - "kind": 42, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "da67f7739fb06bc8faf7a8f5bc0b3672fa190b896ed4c8ba40f55ec1b0d7d2cf4f9a98652baea76dcca5409f5649ec2cb467852c3ee0ab3d015f0aad4708b91b", - "tags": [ - [ - "e", - "42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5", - "", - "root" - ], - [ - "e", - "4a5c12f52b19dd1f9c62a90e6a05d2dbfe4a0c04bba189ac2f7991732ed0a20e" - ], - [ - "p", - "f3ff8e7774e3b3a85c54041bfd73b60fa2b32ee1c5dc316a1d564234552116d9" - ] - ] - }, - { - "content": "XbR03T+g66nPBK8Qzo9y3YKZJVnusRAkq6WJDgZr6HaoTre+IMvp4t1XyXc2nft4rDy8hY9ll4dkdD7Rz1TWwykgaPTY+Y/SjmUDfiPzoG7gEFaFUUPTXQLrOuTfZUmXy85NwHIsHRC/O6P/YFpfVAzkaSZZ2HWWEn5xDCQ2wodYJNxR1o/so9RAyzRg5PUOvS/5JigbohCQea/yjedxjmFdA5YqNJEKi6QoOvUtEhA=?iv=OQVBz1rnHxytQ+E7rQv4MQ==", - "created_at": 1689901355, - "id": "0d778eeaf231b9c5cbf775446e520e265465ed4e1db864c0415e55eeef45d862", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ce58c8d40edad01244fadd38b5819f6fd11062e023f3244f21bc176abad1e42b9c286fd6f963869c1fc96c860b746fcebecd915992762c843c4ec38e5c7c5aba", - "tags": [ - [ - "p", - "7eb29c126b3628077e2e3d863b917a56b74293aa9d8a9abc26a40ba3f2866baf" - ] - ] - }, - { - "content": "Usually 1GB. But with the way many profile images go for 10-50MB, it can easily go up. ", - "created_at": 1689900854, - "id": "05a9d71cfe8ec6b931d980c2993b696cd7a4fd5043a3f5c35ea05b301a5411e3", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c46a68c8d2918707061b283c20308c397570c086953d54442b9fac8179a97ef5e2cb6f9e84be0d4db25cff63f13f5ed3316edd20ae0847be93ea10d87aa5f1cf", - "tags": [ - [ - "e", - "d8b836d465e495d4aba08c1ec2ad934009824c0bcf4274cd5a36828b25138503", - "", - "root" - ], - [ - "e", - "49b67dd8f173d56b99758522087aca6ab2a757e9ef1a17aec988558a3c0f0ce5" - ], - [ - "e", - "ec2980452b7025ac26449110486794c76fee7d48444d5435e983c72385457654", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ccc0c31d1067eac417d2cf562e09df0bfb8f6724addfcb01be9600a75116446a" - ] - ] - }, - { - "content": "Ouch, 2GB? I recommend buying a new phone :( ", - "created_at": 1689899880, - "id": "49b67dd8f173d56b99758522087aca6ab2a757e9ef1a17aec988558a3c0f0ce5", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b8c2b7a564b932f2e582e4d53b063877a48b7414ace4c72a6289df20740e4eb06997045ee37c575673fdf4bfe25fedb8478dc80728a5378df49a1277307b0a30", - "tags": [ - [ - "e", - "d8b836d465e495d4aba08c1ec2ad934009824c0bcf4274cd5a36828b25138503", - "", - "root" - ], - [ - "e", - "2e94de4d2a46d61aa549f9e83545f5dfe4bcc404d49bdaae9a42dd202b24dc16" - ], - [ - "e", - "9fbc8f192e8e6e3006aba7567cb29c6f60ad7c583b050a8765ea91af95faab37", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ccc0c31d1067eac417d2cf562e09df0bfb8f6724addfcb01be9600a75116446a" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689898662, - "id": "8ddae69f32ccb558e49222bdbbe9ec4137a0fbf4ae9614990fe34860f8ba173c", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d7ef27a7a3ee6a1cdb1fcaf131f045e9fa98d8a7f18bd507e051bae262c5ab51643b4321fea5bcf733e22a48ee61f612792f5003c97b15f87b40a1bf32cf90a8", - "tags": [ - [ - "e", - "a3f71ef8b8fe3542df4c8a4bc88539a53db31c23f3a780543ea2c3ee599f9a3b" - ], - [ - "p", - "fa47eab76aedb2895442da765a3a11d8a5a9a679884ebef8b977e0f36c912f0c" - ] - ] - }, - { - "content": "### #Amethyst v0.70.1: Quick Fix for F-Droid users\n\n- Restructures the spacing in the first and second rows of a post\n- Fixes Wake-Lock permission line that crashes on the F-droid version\n\nDownload:\n- [Play Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.1/amethyst-googleplay-universal-v0.70.1.apk)\n- [F-Droid Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.1/amethyst-fdroid-universal-v0.70.1.apk)", - "created_at": 1689898519, - "id": "42416b010364982b8df9b9a696083b9df982b57fcf4dc907d3b978f42cdb36c3", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a4f06bffed259dfb747c001c4e58ad9547e1ba5eda174a4d3c6f63903efc70742027d12443fb845b6a86e9de6a6d397b2cd2f520ab8274213c8f5b50c1c0293b", - "tags": [ - [ - "t", - "amethyst" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689898498, - "id": "effe7e685b36a6cbd3dadbc74ff6d59c44c103f784ebf3f9faeb58ad2a8afae8", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "af8d2f662d454ed7b221118af7a1324675dfbd5dd90a3582c4259b848917df01b1a6373e2c5233035508e578bfb3b8f14cae18306c0073d2f7ffbbd93b4c5847", - "tags": [ - [ - "e", - "99d97b784f54e315731e04e2fd3ff9166b2ea2093eb494844b10ad37b86c36ee" - ], - [ - "p", - "8e567e90f3214bb221a726c53c0b901dd23bdc4281e4dfe425014e33f1dd217b" - ] - ] - }, - { - "content": "Well, I only make this particular app for Android. People can of course install others. I'd just would like to avoid the extra work if Android solves it for us :) ", - "created_at": 1689898471, - "id": "06d414ca9e36bdfa02eac2f27b62298dad203dbf784e69d5c339e138ceeaa476", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "812cdda0e068cd30b21b4f700b1e738dc55e85bdaa1f03073479958d345bce6ed5a1e6c735cd9eed0ee773ccb26f1306b06708b5b70054f40d584f16db0e23b8", - "tags": [ - [ - "e", - "15280e46bcba956ac0be0ebb5de1c19d25beae8db5223951e16ecdd24b524519", - "", - "root" - ], - [ - "e", - "bfe8b13fa0a8a63ecfb3b7ad3bc26216efba5ae6aae7b95ec5749db8124d33e9", - "wss://filter.nostr.wine/", - "reply" - ], - [ - "p", - "b45aca09dce5a9d8af39f5b116f306ba5b9cf175d54b99ef7fe44b14e176dfee" - ], - [ - "p", - "b45aca09dce5a9d8af39f5b116f306ba5b9cf175d54b99ef7fe44b14e176dfee" - ] - ] - }, - { - "content": "PlGM8/MtS+vQnbR5HHbc9YXs+DaKNeKeP/JQwTHL7Gw=?iv=+CyNjnad2EJ/djDiMYeJKQ==", - "created_at": 1689898356, - "id": "901df0b16ee3ff8e864d278876093827f15dd9a39dff49b059775dbb319831c9", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "126f482832059ead0ea012dc7a5508517d4e08e7000e8681d2ba637993d49dc3b36735cd1a7b5d673c04245e8e02f2a27844a2b28fd2da6c02418fb5bdb11536", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "See if this version fixes it: https://github.com/vitorpamplona/amethyst/releases/tag/v0.70.1 ", - "created_at": 1689898240, - "id": "2ea9c229e5cf6d8e6cc8c2c018ef08d1366ab70bd9d7dbb499e2e388666fdbeb", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "52c8716c3d7afb35c58c1b7412db2cd44a08e57366349e8aae1c6015c5b078d3fd1b0c8f4ffb718cc81c0c462cecdf97f816c949621587cd635caefe56457cf1", - "tags": [ - [ - "e", - "15280e46bcba956ac0be0ebb5de1c19d25beae8db5223951e16ecdd24b524519", - "", - "root" - ], - [ - "e", - "107ea3c6074b2be4096c5d0233553db7ac326ede4678ba551498c13c80f0794e", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "8e567e90f3214bb221a726c53c0b901dd23bdc4281e4dfe425014e33f1dd217b" - ], - [ - "p", - "8e567e90f3214bb221a726c53c0b901dd23bdc4281e4dfe425014e33f1dd217b" - ] - ] - }, - { - "content": "They should store everything on Nostr. We have better infrastructure. 😃 ", - "created_at": 1689898211, - "id": "0b4cea57de5eadcf57efc6d1b44511c944085086410f3d400f13554d5c3eb132", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "732cf27c63e6fbcc4e7af2d7fbe2525af2aafe35f6effa270231f38393b13ae161cd9f58acf42ab3e7bbaebe15cab90b8fa4946484480d434e50d8dd36f6169d", - "tags": [ - [ - "e", - "3c4a16878ca8285dc65803a239b9ef7c6b01badeaed9b41b6e5af88a580c76a6", - "", - "reply" - ], - [ - "p", - "ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49" - ] - ] - }, - { - "content": "g5U/iOElAmZg1czy4FWXjbRuy3QG8LsGmW7QbwEYHjUEslUXqGNvG1P67+kt2IB6UnXUfUy0CCVTTHZ3UhXqJsfYfYNsME3JqRV3WOqDU/7Hb4zShj5YgbQHkai8tIhe?iv=aaWZ7SvNudW3QrZR+w7Ifg==", - "created_at": 1689898075, - "id": "1b0562bceb74fe5a051c0b23a1c76682268cf9857bafe3c7df15ad386623f797", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fa4fb247f84456b731e82fe511d806909df64c4c0a1f407f78dd97c5c65152b970ca4c204adaa1304dd2985ef7bb59da8b7c684d1528a214fc973783cb99fd1c", - "tags": [ - [ - "p", - "fa47eab76aedb2895442da765a3a11d8a5a9a679884ebef8b977e0f36c912f0c" - ] - ] - }, - { - "content": "Just go back to the previous version. \n\nI am not sure what's crashing for you, but there is a bug fix coming up in a few minutes as well. ", - "created_at": 1689898027, - "id": "48cb09f199294e25bc884fad3253c92dcbbe5b3b03ade1e9c4f079c97d0803a1", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3b09c5b8d314d35b6302203557bc7e01fdd4c94e2264e9cd895a16a31b14a0f7c106444ad84b137c3f34079b19aeeb05dc281b9bb4128a95c31c4877feee2c52", - "tags": [ - [ - "e", - "15280e46bcba956ac0be0ebb5de1c19d25beae8db5223951e16ecdd24b524519", - "", - "root" - ], - [ - "e", - "10443395bebea840ff883d98379f814eb694486a0f616efa8e53e07ef3b1dc92", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "8e567e90f3214bb221a726c53c0b901dd23bdc4281e4dfe425014e33f1dd217b" - ] - ] - }, - { - "content": "rAjdaIbE8aQNV4wl26DYoZtpy41jbPK60zFJ3eysPzo=?iv=Ef4GQxwtqFbfJ7iA10Halg==", - "created_at": 1689897433, - "id": "87702fa85d8d3b792be82275ba1c0763467b9c51c1b01970c238dbe601dc8e3e", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f8f4d672666d2856c6ab2a6b323610da9e13b1839413f4258ba6d479dd8d6266ba25df019eef35ac84e5160f5b66edc828deb6f26e9205a01f02b16d82780f25", - "tags": [ - [ - "p", - "fa47eab76aedb2895442da765a3a11d8a5a9a679884ebef8b977e0f36c912f0c" - ] - ] - }, - { - "content": "WTFQjqBoYqgRFXnqnGwfd0pNaeoL3pkbZxmCjuP6DSU=?iv=HrCg46zasY2X8fcVsqsMgQ==", - "created_at": 1689896526, - "id": "cadccbd35fa4e3719612a5441ae5165cc6d3ee083ed940184bf392e5fe3142d9", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "72004a76b723ef7bd5fbb3093279a77546764840665bd5ac92849f284b5a7f12f489346ce251385c9af39da3b8e6bfdd15672b2dd940aaf33ae473b5a58d897a", - "tags": [ - [ - "p", - "fa47eab76aedb2895442da765a3a11d8a5a9a679884ebef8b977e0f36c912f0c" - ] - ] - }, - { - "content": "QLzMfgQsc7ODjSrJrLxP6DUl+yCHFlLGmMINyYmp6xoi42+qLO7Ucssh4GqWCyY9?iv=niAXV5K/KMasL+eNCr2/DQ==", - "created_at": 1689896516, - "id": "fcdf61a01298305920b318c693f71b5f9ac322225a065fd4fd70d97bd69cdcce", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "4606e2fd335552dffbf33bd6f619f2b8253f07d25ed38c2a26b3fb490800bc23c551d435da5839f1d7541c8bd4867fc5c6228cbe4355bda95f83e6c485d787de", - "tags": [ - [ - "p", - "fa47eab76aedb2895442da765a3a11d8a5a9a679884ebef8b977e0f36c912f0c" - ] - ] - }, - { - "content": "Which android phone do you use again? Is it a memory issue ? If so it gets slow before crashing. ", - "created_at": 1689895792, - "id": "2e94de4d2a46d61aa549f9e83545f5dfe4bcc404d49bdaae9a42dd202b24dc16", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8ecc5eb799f021c715be69345b8209211203e65318248dbf071cd2ed24b1479a217354e192ac19fc50ac9ba20c9431d10f11a140377b4521d196fd240ecbcdbb", - "tags": [ - [ - "e", - "d8b836d465e495d4aba08c1ec2ad934009824c0bcf4274cd5a36828b25138503", - "", - "root" - ], - [ - "e", - "a0db5f1affbe065a92b0909ac480d17ea517d9ae03cc28f268468e7c82e7fe41", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ccc0c31d1067eac417d2cf562e09df0bfb8f6724addfcb01be9600a75116446a" - ] - ] - }, - { - "content": "Isn't that automated for Android APKs? The phone doesn't install the app if it doesn't match the previous version's signing keys. ", - "created_at": 1689895740, - "id": "83a06ca57bfdab4f635221e67f05a5827ddd0e91f75756b05692138b5c055e12", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a74648c78086553bf3572e86c2bea55421fa510f1a7804da1952b4d095fd2c1280890e54643bf78b5402c3565e8ffaecfd5cfad509498f208a7550471c264dcf", - "tags": [ - [ - "e", - "15280e46bcba956ac0be0ebb5de1c19d25beae8db5223951e16ecdd24b524519", - "", - "root" - ], - [ - "e", - "3eb596232de49ba67b1f47873d388cb389f93eb6b3a0449889588b3099402ff0", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b45aca09dce5a9d8af39f5b116f306ba5b9cf175d54b99ef7fe44b14e176dfee" - ] - ] - }, - { - "content": "### #Amethyst v0.70.0: Background Video Playback (alpha)\n\nNow you can \"pin\" streams and videos to the background and keep using the app/the phone while watching/listening to it. \n\nhttps://cdn.nostr.build/i/04b00315f81c574afa45ae9c5632952e9bd7bd472bebb45b6e83aa97a692546b.jpg\n\nKeep an eye out for bugs, this is a massive restructuring of how the video playback system used to work\n\n- Moves Video/Audio player to a foreground service.\n- Migrates Feed, Stories, and Live Stream screens to use that service\n- Blocks screen from going to sleep if a video is playing.\n- Blocks WIFI from going to sleep if an online video is playing.\n- Allows the app to pause while listening to media and continue playing\n- Manages cache for up to 30 videos in parallel for each of the 3 categories: local, streaming, progressive content\n- Activates the use of popups with artwork that points to the screen with the video\n- Creates a button to allow any video to play while browsing the app/phone\n- Moves app to SingleTop mode.\n- Keeps viewed position cached for up to 100 videos.\n- Restructures the starting screen from App Navigation\n\nDownload:\n- [Play Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.0/amethyst-googleplay-universal-v0.70.0.apk)\n- [F-Droid Edition](https://github.com/vitorpamplona/amethyst/releases/download/v0.70.0/amethyst-fdroid-universal-v0.70.0.apk)", - "created_at": 1689894483, - "id": "15280e46bcba956ac0be0ebb5de1c19d25beae8db5223951e16ecdd24b524519", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d1a1bcad4fcae1592e27ddc086d8e9f656e790536038a82a7560705348c964093c89c6058e4180a67f423a34e91157dfd48168a3db3c05e5d33aa261d5ebdf29", - "tags": [ - [ - "t", - "Amethyst" - ], - [ - "t", - "amethyst" - ], - [ - "r", - "https://cdn.nostr.build/i/04b00315f81c574afa45ae9c5632952e9bd7bd472bebb45b6e83aa97a692546b.jpg" - ], - [ - "r", - "https://github.com/vitorpamplona/amethyst/releases/download/v0.70.0/amethyst-googleplay-universal-v0.70.0.apk)" - ], - [ - "r", - "https://github.com/vitorpamplona/amethyst/releases/download/v0.70.0/amethyst-fdroid-universal-v0.70.0.apk)" - ] - ] - }, - { - "content": "kyZ2J/PX5HjuuY6Fnw4Wwbb7aigSPVVL5nEieJ2rxeKOtIxKkdk/rMuo03JVuKOFgV3+TmyUQS8KEEI0TCv1zu8mBvrQ66gk8SFcVFRlDHINWO4gqMV3hQub1+kbgO/YZv/ez4aM90+TAH+gLqb1Is4gAOOJ+aLCpeT5mAkmpwx4WPA99Q1jgqUix6Hhq9vAZWfbB+YnoCkkePlMYdM6iqhdMAPrPwTj6sauatmQCkBFTiPD5kCro750tKS63cvkx3AyYGDJWxkC8yURnqp8j9MPzXsGoNRTdVyimoJXFZyY/v/iRzeWQwFL2sHa1PIqKrqwEE/9mZY8YAqtrMx+5WB8tco0Aj5QnCJpocJ5XEB9M23Hl4/fMDrRGUrf0KCSmiSd5oljW5ruasb5VEEMgwO6RudG28Qafk/Z2cZ2s+nx9fjkOHkOaorOhCotPq9d2bd6VpqXc27BnKU/LyxRzFqXI2bVl7Gzl15nTobELgfjSYFIeUWYhbzr6n9MhCe2dqgHIt4FR5NUnHbLMHylo5zVBBQTkOQ5TX4BiE/55BbDqmudqNuQN1ZaFmKvRIaoIutFhopNwYRVe+Lj8NGcZ6jvR1sw+AcngJBdYYsAPkRisMELbeUkVNkmUcWbQIRNPsuTSKM8M/HSDAA9SBH2V5Rzd+8G9SrNoCGJoueABfJqjz0JHg9fc5X5qfa9/Ly5S0bgHhWU2wueMX85+UiD5G8yJF26Gd/wEr4YQrMnXT9xmTJQ/YusKmygOxcZ4yuC15stNV6hPnx1Dwr4KhISbw5+i76f/GFgbY7iX6nfKLsl+A6UxNGHkVUt1QJWRP/BxcXjVY/1ynQMmUlyIDu8E/ZbHCGvZuOnYow7+BDfTmKzgwKRoO8HcbijxsPG/nKF4QUIP6177l+wL/46E0EZGxroyT+w7a4QcD9lhqD8Bm4+6qFvBt1Ihl3RVlVzN6WzaKHVzs/WUhRYXNm4qzyYwjtCPR8jJ7MnfgFqFqDYye8Ac7CdIZvU/j2B3Xqk0ROLpcigFw/53sHJzfPz64QeE+Iq0Ikm52Vd9NqBCzQWJpMpi2mDPEL39P6AqE17sEFrEiEz5Ul6sl9gI0UywPSgf7grY3Thl/LmmRVl7LtDqWJxQ6/0BI05pUtFo9PF6ZfbA2gqt21gB6kRx3FXpxiHN+1KB+eBkyTUa/GwyAFwO+1noID2c17HlBYwrxikxCH8WD0qCjXmy2rzAUopDTbLmtrREfDTDSqm3Wy/3bDLYcB6rKcVVZUGQWp7heAbhk1i2LLouBQ4aCBE+Q8NoyFct7WWNZ788s2gBwA9xYx6haCnWu8x/72Fq8EayH8pakEWqNsAb9Ig7oxUZUbUFVlURp/4hFA6ypVEsVxPSikJ/iS9g1f9hO3vQ451jKWmVboq9ViRNSvIwI4xzB8/iYi1/R1NVanEZLovOP591TcDs+rCRL6xBpeZPM8NFWiqMo0K2Hr5/SLpYR2SFTcVG5x5OGCvAQO1CsrK6YxXEkRI7uy1oo7bYZm/LgzPzGcbESRhZrA2VmwtdE6LC/vTt7PlW8zxPAzja8ZeLkuKSZPlo9ahYHNtuHAVTHh5JojspOMJlGIjOrnZaSPZF4kjtOfhevF8b15YuE/EDLnv2EAyGR7U0zGm1ZSUgecOW6D9dBX1DrMLXbnSydaDxq76bmMIXzynqlQNkTHLPrj+leiB95gNaAc8NnMJoLeK7E9FiFxD?iv=0wUJgJRH2qM6M22nQWTtzg==", - "created_at": 1689894398, - "id": "ad2118124d93a34e78de1868a03b5db77269de9bd847008aa56d234ac435d911", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a32e5d31c055b090fe60ba719c8691c8500eaa9f0239e9b3ca823c8af7ef0251c470facd766d0915bf495d8414037a16692da9c487bc260cdb43f272a4aa2c22", - "tags": [ - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "gXTNhA9dmULS6RWEeUnGpJeK8jO62z9IXGTKEeZkFyLPyzR5cwhIyVDCPZra7fDs?iv=S/+MHIRTOC3YvN5SRg544A==", - "created_at": 1689894312, - "id": "9fddd6ed3006a4b02a4f61106f93422a875d9104e18ba17d44b41eb0d29118ba", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3332078b36bcff14ed9b4079c4615bf2a73d07d5982dbc0c3c225ad768d400f1d152de5912119a122c7366465a193bfe47817c2a03c575664074fb47dc5a56de", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "SVapbPIcn2mKwCD8+0X/ssrakEARyfHdunFpBqKHJXCwahK9G4A5+wT8Tn6HcmK+qALX/eCIEeotD9jQfT/yFw==?iv=V3qBEP8xd7627UWztQb/1Q==", - "created_at": 1689894286, - "id": "ad0a2b77c0575b49e3f05412a09abbd7575e76547e9565fde0315a89c16a5c26", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8fa4798a22452bffe5c56eeb0fabfc3cbb9b9ebe1ddf861fae41321befa3d67354fc588f3e664c004b5d5450df27dcb6687dc5261bcb24c986fae40d81114f0c", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "We could use another update from the user to identify that the stream is still live so that zap.stream doesn't need to keep updating the event to sustain its status. ", - "created_at": 1689893549, - "id": "6ce9b93a4fb5967d2f70225d0d8c7777c1f86d3fefa135229f8efcae338d783f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6126b61b95f23e5364f13a7f75899e582641398ad66aa77277182c839243f503e03fb36f5445366336ec6532dd03a3aa90951aa41ad2a153ffb114be9438d096", - "tags": [ - [ - "e", - "173eb29e7402ef1750db662d06b88a187ea9c0b31d4ceff1df5d048fe79be3fa", - "", - "root" - ], - [ - "e", - "4bee2e762c7d296bd66dd5b4a0e84dc7e0a98355ad5f18277ac65c06da9ab25d", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ], - [ - "p", - "00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700" - ], - [ - "p", - "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78" - ] - ] - }, - { - "content": "This could help in the updates to the LiveStream as well. ", - "created_at": 1689893064, - "id": "bf3bb95525800c504cb74c0c60a5e532fd1bc9d774613af6b6cf8125900a33b7", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "dcc36fde64e0b483114cec6ddf5f72b9f53a7deb9bf06475a4f36aed81b2d41d0b2982e77dee6d1a015c219db7bbe8672c5c43abd49646956d7a1ac669a6ee04", - "tags": [ - [ - "e", - "173eb29e7402ef1750db662d06b88a187ea9c0b31d4ceff1df5d048fe79be3fa", - "", - "root" - ], - [ - "e", - "fb6f8c9055d34b3fd2eca32f96a5193f9a491a623a57819b8c904e0504477190", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ], - [ - "p", - "00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700" - ], - [ - "p", - "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78" - ] - ] - }, - { - "content": "To the best of my understanding, that is only true if you use a different IP for each contact of yours. Otherwise, the server can easily bundle your queues and map out who you are. They call re-using IP an \"opt-it\" security issue. Even though most people are reusing the same IP for everything. ", - "created_at": 1689891763, - "id": "48735c6e1caa54c82015c1a11d86c9c3ff8e7e6102992bc32b78f6c5c4294f43", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b5e3b53de8cb327f7da73d2c9a09bf409d484e3dbca8ec7c844baf9b11ae9e3cef535b82d6c716260eff36bb672c1ab2a5ec85f445a539dba4cc919af0e8e0e1", - "tags": [ - [ - "e", - "dba7825c157548cb16be88cb771db063862ce2adb1969193cadcb29a164c536a", - "", - "root" - ], - [ - "e", - "0bf10092a54fee81dbd3ba2100eb80766276e93a30bf752961ae890be2993617", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "9110fe860a5e40a41e03d52d306a7b337ecf32d1090812ceaf423ec9b94954c8" - ], - [ - "p", - "04ea59bf576b9c41ad8d2137c538d4f499717bb3df14f5a20d9489dcc457774d" - ], - [ - "p", - "c998a5739f04f7fff202c54962aa5782b34ecb10d6f915bdfdd7582963bf9171" - ] - ] - }, - { - "content": "+", - "created_at": 1689875139, - "id": "7ae6e200034e48f561c22648e41f677cfb71a7713bcba6bec683c74727ef9619", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7d73b8fe475b99b11e8041728e32f55b505fa57f141fe9a301d7112336fc2cc09829734d27100168ce3a20894b8321965c3479f544346ec4e2828ad313e36178", - "tags": [ - [ - "e", - "39d9dae2bbd253e85c78c55ab89588a245a9c40ad03373fc355153d35119c80a" - ], - [ - "p", - "bf2376e17ba4ec269d10fcc996a4746b451152be9031fa48e74553dde5526bce" - ] - ] - }, - { - "content": "Same issue. The metadata is always somewhere. On Signal, the servers at the company know the destination user and the time of the message. They claim to not be saving it, but who knows... For SimpleX, it's similar, but on their relays instead. ", - "created_at": 1689874092, - "id": "06756e30fb3a5a5adcf0ce8953e428dedb6511b03cd5d219cb3f394e58dc1657", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6a26f8fd80c2ffef7ab5c0e505e2223ab57f4b4b049e7a5135afcf03c2fae44b71eca7a457f406c4fdbf3cf74c52a832eb354d303fa236c431ee0638680fc219", - "tags": [ - [ - "e", - "dba7825c157548cb16be88cb771db063862ce2adb1969193cadcb29a164c536a", - "", - "root" - ], - [ - "e", - "fc7fd52ed1a79e8f7a1dd6a84e38a04a73a38b92a7a43e4c76df9708adf70946", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "04ea59bf576b9c41ad8d2137c538d4f499717bb3df14f5a20d9489dcc457774d" - ], - [ - "p", - "04ea59bf576b9c41ad8d2137c538d4f499717bb3df14f5a20d9489dcc457774d" - ] - ] - }, - { - "content": "Clients generally filter by date, so you might not see some messages if you do this today. ", - "created_at": 1689873381, - "id": "cf1b4e3048fd829ba241bc84b850937cf8ad256208309fff0ffb92c6ad20cc00", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8463639628afe7493e61931e6613da239d489d2c9c3212e0c58ac622a166c6664cb13cb33b80531f4037da99d2bf53548ad4553104ce55e161aa5cfe11e53584", - "tags": [ - [ - "e", - "dba7825c157548cb16be88cb771db063862ce2adb1969193cadcb29a164c536a", - "", - "root" - ], - [ - "e", - "d8d90496d54ebf856ecb5624e4b9e07950dd5afb1c57ff2b1a25fddbef98185c" - ], - [ - "e", - "adc0937780518b6a35c3ac44e36b2c48d0e6643d3609847652c8a4c245bca2c3" - ], - [ - "e", - "c98d7ec7858ff362a45b60c8a6dcd03c9b66f30ad65e89755b66d0c38320c858", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "04ea59bf576b9c41ad8d2137c538d4f499717bb3df14f5a20d9489dcc457774d" - ] - ] - }, - { - "content": "🤔", - "created_at": 1689873007, - "id": "0900a6bf9d2ef4b4765074b26e277bd8ae573e8dd697fd2a2a2626f2e6deffc3", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d0a69e056d477f73ad70ad00ffab45cf33d685bae46a674552871eaf47f131ce2e063fe2064a4710f0393869a96712d0ae85e626b895e1f979e4478bdef8e56a", - "tags": [ - [ - "e", - "1a3cf67ecc40a0861fd39830417671a62c98ad35de0ee0ad9a78ff2b0170e1f7" - ], - [ - "p", - "21b419102da8fc0ba90484aec934bf55b7abcf75eedb39124e8d75e491f41a5e" - ] - ] - }, - { - "content": "🤔", - "created_at": 1689873006, - "id": "330f32a6c42c2f555cc1b2def25e521ea35823a81bb9fe36d08cab65bc5bfaba", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c1dd416e6ba387ce6b74a5e8e7040e2f3e01b0a3ccf95660ffa8383da9f0e7cfbed1e9294416c3f386a9cd071a30b9767801bb2cd47dc3026e6d3116e7c8f6d5", - "tags": [ - [ - "e", - "7f4c1bd91549cef6c1e960bb3beda056f559097cee1fc957c131b4029595d6f7" - ], - [ - "p", - "d0aa74cd95a651d3d2ab4fb18b58fe71b447d78d40f8dd46f1dbaed5603d35cd" - ] - ] - }, - { - "content": "Nah, governments can ask operators for their data", - "created_at": 1689872829, - "id": "deac3db2b74976056d8f5a4543aaffd9ddabe2209323861605bbbacbb1a2309d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f827a824cc259fdd1b222d29ca59c63afc5d5926039457cad968d9461787f4d6757dccfebf9c60cbf2d47c9cdd3388d2aca713326530bccc3bd8c33066e4db7d", - "tags": [ - [ - "e", - "dba7825c157548cb16be88cb771db063862ce2adb1969193cadcb29a164c536a", - "", - "root" - ], - [ - "e", - "60de51c3eedf47496b23b5bb16c9b0513d776d9eab4326255adfc9df791f5eb1", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "2ef0fccfd5a55e36bc8be3a525c1ce97f20eabaa94e69d82febfd641d9480c35" - ] - ] - }, - { - "content": "Governments establishing a stronger evidence based on a time collusion of separate evidences. ", - "created_at": 1689872769, - "id": "adc0937780518b6a35c3ac44e36b2c48d0e6643d3609847652c8a4c245bca2c3", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b46c04c7a396461959a0da797d2efb9ce1cf59fd00bb48bcb3f5b8985b7eae1168636119fdc982914acf5f5419b852d78a1a78f3453e6b1b0c561cb5bb57a441", - "tags": [ - [ - "e", - "dba7825c157548cb16be88cb771db063862ce2adb1969193cadcb29a164c536a", - "", - "root" - ], - [ - "e", - "d8d90496d54ebf856ecb5624e4b9e07950dd5afb1c57ff2b1a25fddbef98185c", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "04ea59bf576b9c41ad8d2137c538d4f499717bb3df14f5a20d9489dcc457774d" - ] - ] - }, - { - "content": "How do we hide the date/time of a DM message? ", - "created_at": 1689872583, - "id": "dba7825c157548cb16be88cb771db063862ce2adb1969193cadcb29a164c536a", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "69870943756995ebd822c0d56cd2ffe451fd8713bcddf7e8828dbe3f833823005f3e4a34170eaf4020fef416c66af03ddf00755eda42452c0b53c8079771a403", - "tags": [] - }, - { - "content": "O2u7Hl+o63AeQNONtyIXjDI/2Xi0WckHVWZ8aGJnO8hrT1XILWJ49X11Tz8eM25sW5vxceKR2gnYUh+paux3ZMkfhTYdcm63f9AYsyQBS8k=?iv=/iMP4rhqmyQXGU8+7llTuQ==", - "created_at": 1689872451, - "id": "175fc151ab6ba3d8c567e8bb372827ec94b875290068d4601251401042027edf", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "4a3e683e8a5073f191de3d49cbd5dfd4688382ceff1050addb5f5f6495bc7780d9d225ce346c23551141cb36442fedc2848f09db68d27f25fe2150200d1614ff", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "e2dv5uyGynDKSN73wEsul1qw9v6Lns/jEYGcZud+u9Yh5gO6cuHHjVcwlZvIysfiEEL/UkcM1LSkpsrzrk55z5Ruy4f3CJsacb4DTFX7eI0=?iv=rCyLaRVvDh5PyMR4rZrIUQ==", - "created_at": 1689872401, - "id": "b3fece9b46c5cd3a5243d2bb4d23db4ab8648ad7b0fa6348a519c3da895c3ede", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1ebeb7474c7a58a87d9738119fd692a7aa19ab65e231f43deb46c2d51814fa217194224871a7a8570e93eaeade1b7517e9cd13c54166d57c18aaf3a2fd0ce778", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "It's sad, but true. However, we have a bunch of new non-twitter apps to balance it off. \n\nnostr:nevent1qqspadh2506xtrpjtld0mu0e5ly29cdseu2u7vrx5thsxp88t4uy6dqppemhxue69uhkummn9ekx7mp0qgsph3c2q9yt8uckmgelu0yf7glruudvfluesqn7cuftjpwdynm2gygrqsqqqqqpz67xy5", - "created_at": 1689869163, - "id": "e35dd1efdb8d688b2dd82d8e87c10891c2c15e0bfa85d75302366397abffff6f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "16fa751c379b5107f0a8f7c975daacc95806f7d50a0b9f1fc58fbb8008c32278581f0937e3aae646e01d6bdb34a4f9eed8b783fe756378c8c20463e875b9dbc0", - "tags": [ - [ - "e", - "1eb6eaa3f4658c325fdafdf1f9a7c8a2e1b0cf15cf3066a2ef0304e75d784d34", - "", - "mention" - ], - [ - "p", - "1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411", - "", - "mention" - ] - ] - }, - { - "content": "+", - "created_at": 1689868629, - "id": "7f13a40f500a511d643ee6115877753a788f00c2b00d342a5c3cfbc99190b16b", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "22d6b5deedb017d291ae94d1e638a479397ae76c8eca229b193555bc436afc30e8f795a27224417b68a2b0a41e96414a14d203193facdc9ea2d0760ea7a4bf5c", - "tags": [ - [ - "e", - "9c27822da347c0083c2908d51f2429917e079e0fd1d623e334cc2946395dd123" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "I can see that you like good UX. I just wished you just asked for... say... to increase the space between the text and the image directly... instead of this snarky post: \n\nnostr:nevent1qqspxnxmq8gvh2zf64ktvqt6ahhme7qy86cpvzqgnmszj5dc2stsrpgprdmhxue69uhhyetvv9ujummjv9hxwetsd9kxctnyv4mz7qg3waehxw309ahx7um5wgh8w6twv5hszxnhwden5te0dehhxarj9ecxcetzvd5xz6tw9ehhyee0mrzlhx\n\nAnd since you like good UX, you should know that this is not how you ask for improvements from anyone, anywhere. You ask for empathy, but you didn't offer any of it to those building the product. \n\nThat post could have simply been: \"Hey Vitor, can we increase the distance here between the text and the image?\". That would have created a more productive conversation. But no, your wording wanted to shame me and the \"product\". Basically a \"look how bad this is!\". Maybe I deserve it, maybe I don't. But that language goes against what you are preaching all along. \n\nOn a last note, Amethyst is here it push for everything, all at once, and move forward as fast as we can. That comes at some UX expense, as you realized, and that's ok. With more help, we can probably offer more UX improvements, but at this time, the majority of the development is still on new features. We are still on version 0.x for a reason. We are not even half the way of an actual product yet. ", - "created_at": 1689868224, - "id": "209fbae56844f5d16e64fdb4026ffd966864de649062c30146f8e588bb5eb452", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fc3e11ca74034193f5c7044e80f6c5a4b035b7daa82147584c91fb8b931638daa43c5e7d576c4ca7bb295d4ca955a7e7f63658dce6e9ebe489b3a0473efaf3d8", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "7aeb2f3ccca028aa33a3ffc287e6538e492d61c0ccae70627275730fcc354ac6", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "Dude... I am here listening to you. I am not bothered at all. Why are you so angry at me all the time? ", - "created_at": 1689865738, - "id": "7edef713c3d24ea0271368c68e844ec1360c026f21c045c7b517a872de094259", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7ef93ac8f1bb45c1b8b11a8c7f168c82c7deeb3d3b31221c60fd0ec21a0f7a11ed4443f194bed7cfabdaa90e912d6cf25bb7e2ca85dfd813e9d74611ac469b36", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "cebe888ef52d02e679c32b0259e441095576bf9ca5a4508f69deb2a924c9f926", - "wss://relay.orangepill.dev/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "Yep, that's the thing I was trying to avoid. I don't like disregarding what authors do, even in these small details. If people add a line, there should be a line there. But I will do some research to see how to improve it. ", - "created_at": 1689865669, - "id": "4b771bbff33a16eb80f6568a5473c1415d8db077884b8135b105c661c64c0af7", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9517d5805d660b34e2574d7d95b3bcb25537dca821df8188d7367ce2b2189aeaf1eb53da84010e0d248054a3f9c8d6e616f0ef5eaa0e50d306eaeaef5bbd7474", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "9a8ddc77b81891173936d4d3c44501ec5873c1ac6a246e34f89425e4bc4d33bc", - "wss://relay.nostrati.com/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "I was just asking because you seem to care about this detail more than everyone else. But if you are offended by it, I am sorry. I won't ask you anything anymore. ", - "created_at": 1689865536, - "id": "72af445176b583364787978c772c929a550202cfb588da2e2a97bdef3601c93e", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ede069883773114b2303a9981db6d6f72125aa423ff1a58acf0aa01af0ba498240bf60cd2a6a8350f0a58c972754ffde1a267fdcaa967fb7200d6a5605249193", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "f49066620597bf34152ec79fdd44f4647016f9f519610bd2b470127915593a13", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "If there is a new line before the url, do they show an empty space, then? Or do they just disregard how the author wrote? ", - "created_at": 1689864705, - "id": "c469379a1f15f7bbcc2a5da7a8b5eb3cbaf1a90c9c1e28c2b424ba88114fa496", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "914cb11c0f23568631c72b41ebe14b5d12f665a7785e5cc28c2e77b8d959c1e62d9af1b4d5b056783f7534f605d4e462750ea34c9cdc44a938764fe1b35eb1a0", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "a4947c5d9a71d2d944e0cd1edcafaf25375ef1d4eefdc495d8ef58c38cfe6d48", - "wss://filter.nostr.wine/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "+", - "created_at": 1689862624, - "id": "79d66d3f15bea48b6d0ac94f1a940ea7a0ec936527f56b7296df12f127560999", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "5e1749add3f9f02d3044c2d2919313f8e616a7ff4bbd7dd0735ce475425dcf1d65f388f4705e4a18224ffe86e69a194037ebe21f749a515d18e537e75eab2080", - "tags": [ - [ - "e", - "7c3b8478c7fae8943356cbc72fffb91d0972402226da9d84a3f63d3a77bb44c9" - ], - [ - "p", - "7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194" - ] - ] - }, - { - "content": "+", - "created_at": 1689862150, - "id": "dd53ef21c2183dd451d8282291c54ffe30aa4a737b2111621f1a02beef772af4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fec7169c25bd4c995794b079f1acbf4212ce27555d4e20a57b5ed10be85e0a53c950db078c9c4460a2590baec3f0c88762e212411799b76da6ce529e886568ed", - "tags": [ - [ - "e", - "c0012d024315e94af4a3b78d88b5764b3db502689cc40e59f82051e57d69cffa" - ], - [ - "p", - "50c5c98ccc31ca9f1ef56a547afc4cb48195fe5603d4f7874a221db965867c8e" - ] - ] - }, - { - "content": "Do you count just anyone in any list you follow or do you want to break it down per list? ", - "created_at": 1689862073, - "id": "5836b1b6d60d819f7cdb9db7b723734ed46a43ee3905c712c379fe8430bea635", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a5e34cb72dec3b80098a9d092c122628e192020c9d96437c63729f9c2fa892d5cb73b43bc08f7b18ea9048db5938abf0e3cf5688d615dfc879f956154cdb2467", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "3a16231d3ae0dbd75a99c7d6038acef7ea2c510b123c566436965f813a638bf5", - "wss://relay.orangepill.dev/", - "reply" - ], - [ - "p", - "5fd693e61a7969ecf5c11dbf5ce20aedac1cea71721755b037955994bf6061bb" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805" - ] - ] - }, - { - "content": "+", - "created_at": 1689861399, - "id": "72c71b828d4ba31fd341a35bc2ca90e24dae437cfe8d1b4aea48354154222d09", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1d78e9b3459e05b3fe269ec8ef4351bf86d54783d14585bbb2c0a370b3e9e47f81998c0b47168e16f568208ab7e55c4db33e1375b5f1b840105926a0efa5cb0f", - "tags": [ - [ - "e", - "0c1560b408c5fd5fba808d72506faf0de36b684beb39ae130b625ff48ac78e76" - ], - [ - "p", - "f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0" - ] - ] - }, - { - "content": "+", - "created_at": 1689861396, - "id": "43a89e40238a6eb9cbf43bd5df47879e6952b4bb7f4cadf93ce57de2a16087f3", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "07801393346d8264c7833d4926c6daa456630be169f61b504e73c86e5976cf1dcc283bf9334238457523ab0f6feddd9ca4f9d4c005e077851654c8070b10b27d", - "tags": [ - [ - "e", - "f4bc628a982288fae1e8e49b4858a64943e6cf9bbf25cf04faba489ec26355aa" - ], - [ - "p", - "f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0" - ] - ] - }, - { - "content": "Ohhh... Community tabs for different kinds. Very smart. 🚀\n\nnostr:nevent1qqs2auwg7glxpsqg5nvwqyuvpnzx6vgjvw40v2kyg8ptrr5dj6rg6zcprdmhxue69uhhyetvv9ujumn0wd68y6trdpjhxtn0wfnj7q3qalpha9l6f7kk08jxfdaxrpqqnd7vwcz6e6cvtattgexjhxr2vrcqxpqqqqqqz4hge7g", - "created_at": 1689861199, - "id": "998372074cee04fc8b89bb385dd6eb0ceba8cf5012446222ebef7fcc33662f04", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "39ac7eda70f0fe0711db4bc00bc2bc1cec8e7a45fd27daff370660fcc074a75b1057956a2186a4ce5dd8617048b79e0770e09b80a57fa187e3025a169ac3deae", - "tags": [ - [ - "e", - "aef1c8f23e60c008a4d8e0138c0cc46d311263aaf62ac441c2b18e8d96868d0b", - "", - "mention" - ], - [ - "p", - "efc37e97fa4fad679e464b7a6184009b7cc7605aceb0c5f56b464d2b986a60f0", - "", - "mention" - ] - ] - }, - { - "content": "I think the issue is on how to link the list choice and the relay choice. Does each list have their relays? Or maybe each list have relay list options? Or maybe the relay list is global and works for all lists? \nMaking that make sense in the UI is a challenge. ", - "created_at": 1689860877, - "id": "81911e85a3c7de2db65564853d4914a244ead918c2a9d2a17ab9a4f707bc63ec", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9a2caf4c047ef61a84e5c1d54e5297707eeac4b6e839cd696336e3d55101fb77924689fbbe167e9d60460f48cb755e27805c0b478b6d98a96fd05e2264e9554b", - "tags": [ - [ - "e", - "d8b836d465e495d4aba08c1ec2ad934009824c0bcf4274cd5a36828b25138503", - "", - "root" - ], - [ - "e", - "4f26cec8a0e10ebd1be60ab8debaefd2de1a3f4e2f6c05910cbaa0d825c9439b", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ] - ] - }, - { - "content": "oJ8doMpCQ6ZfFxbyPiaH1Omq+QlT00sigyEEdmF0CqE93YpfSkTaawk69Y4G3RKet0JBbRZgwPlhtdhU2KBiRpQ8Ggf/W3cHayb5NeeaYB466R4GPeGfeAP2yV18ASnoUURqKH9j7kCazec6s38BKofrrlr/O2uARqTAZz+aff4MqMRqkjBwJXkUqwGQNgjZ7KXcSSi4R8g6eUfChTZaBEryxQh00zK+skAGhZFbvilgCSZ+PjDAohC/4Nz9kxK9jlRJZ48cjbZJlhSpcNv8Z4q5x7l4CWjZhomBjFgrbyXOXsdMUXb2Zy0ZaBkd27uk/O4SlWdT7oui+LC+sYd8CkfFln3Ho5kgFp7nnzi8emFowPKVVv3sU0J2Sc9Rw1nNnZT0ZKeOhqZq5MaRBPX2gDMhJf61n/JMImAKN7ZITgA1QJaw1mDplV+CdZ8kXHfn2gtOz+u+rGa9mJR/fsfgz30klfcixBUlKrQu43jorkU=?iv=wlPb/Dk80+TDdCjEVj1zxA==", - "created_at": 1689860762, - "id": "3082d8546d083e4c02e513e31fc7e8fa86d86d760958619a62fa9328df0592cf", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "26f8d38baa4b62826b067cea227fc2c169c1055f632becc9c6dc2dc26e4807c296c9d97a41f83a75d63297dc67a2918d27c0f2d42e5a815075603ddfc9a7524b", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "NmGECBQokRbj25yC1GLM+0EQp4uDQnbCUMAGr6BkfNGTPyGRV9Wp+nSMxU+5QWa6tfPPuT53FhSairq9lGgFxA==?iv=LWNGgfl2ZxKJaOulvEt+nw==", - "created_at": 1689860574, - "id": "786ecdd73e40b5a8df20fcd26a792b49fef7ee599002afce4c1286984316db13", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "27ff060daa027c8945b0908c25ef216e5442ccf92fab897e604a3dadcc7348c6a9b7e027c26e6777f5fd17f9b73cf1f1b5220c8bf3036c00c8215e772870138c", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "EmytAFZloV1YnquNnF4dS/SMoenFynEDbYcWjQF95sQ=?iv=uADsN7t5Gac2HA+6X87Ung==", - "created_at": 1689860432, - "id": "23e2d47970dd18fc49cf39e0e1db5ee94d03f7370809cd4de9748fc77bff4a0b", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "282e43b702199690d8d62543a09d3d469ba8544350b022c24cd2bc6838a6169a471c7a1839a58bb6b6592e0bcf9687561ca91d118d90d01d729cfd383407e611", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "zpV5c64Gr25S63G3P21ulXKzd2pItJXtq8sE8P72wtY=?iv=Zq+BthTWRbtlYb8mKvdmhg==", - "created_at": 1689860314, - "id": "3633e70aaccfc32800d2d435aeed6f447c55e646a3e94f2251e5deb2fff926a1", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c358edc8614575bf56b207452274de2800befa7d8905f306c66bbf4f8e44f5b1b2674fe5bfe1153ad3298a0f9281ec1135b2c1f57a05b006003c085eda755a24", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "For posting is ready to go: https://github.com/vitorpamplona/amethyst/pull/511\n\nFor viewing, I am not really sure where to put it yet in the UI. ", - "created_at": 1689860166, - "id": "b6fea7cc4087d399fb7b8b9e74cdca10c27d9756816665271737630db01d6326", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "361abef7aa4ece11a8cfa6371a3e2f5b5315ae0d31c3a10ac3d548940f62ba8982d1643d6c6228d84dda1aa9442872ca01fdc2830ba855d8494826a10f012f2b", - "tags": [ - [ - "e", - "d8b836d465e495d4aba08c1ec2ad934009824c0bcf4274cd5a36828b25138503", - "", - "root" - ], - [ - "e", - "b6aa079b9b7c174a42441857fcac737a1924229a7895e3cbfa74466256403fdb", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb" - ], - [ - "r", - "https://github.com/vitorpamplona/amethyst/pull/511" - ] - ] - }, - { - "content": "Amethyst is the Swiss Army Knife of Nostr clients. \n\nGM.", - "created_at": 1689860006, - "id": "d8b836d465e495d4aba08c1ec2ad934009824c0bcf4274cd5a36828b25138503", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f6a03ab1f6715956b000e40ac4e524ecd8112f6a985d387b671a5c8c96f74b5edaa75ad7364b2e0efe6e10cd61f28b76b6cfc16f31e6d0a98132c22852153660", - "tags": [] - }, - { - "content": "The off-place heart has been fixed, but I am in the middle of a massive refactoring to ship background media playback. I hope I can finish it today. ", - "created_at": 1689859895, - "id": "f0d79ad5e47832399d6e758c63e7ae6b3c4041abd60a6c3f2baf7bd3b5bec847", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "efc9be562ec6b9827408ab1343443226ef638b8b70ff7bd875ae4b12a9c6dc19c5eb10537dc09b8b19a321230e8441b0e88519d70a0fc464a1a22855570b6357", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "d29521c859bce7262b1e1a988c9288d88466851c2baffc6f7578b0d9f2937347", - "wss://filter.nostr.wine/", - "reply" - ], - [ - "p", - "648c0f5302c75f38382a4d2c85a482b927cc61b2828a0794e36c6cc796de86a6" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "Sorry, I just tried to provide feedback on why things are the way they are. ", - "created_at": 1689859533, - "id": "23aad9e03bbd73536e22e830f819868447211e8ef66953830df4b1797c50cf97", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f33c542e002f2d788b76cf55ee3fe144aaddf993f5a5c7e786fdd9ada1d3f180ac3686f0b504444abe8cf050d503052f16cf07b169da0128a5612f9ca378add3", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "c5d0cdba3717383bfdeafe50c1275c95de28b18d036df0a60699b9ca019522e2", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805" - ] - ] - }, - { - "content": "You can already do that with lists. Even if you have not created lists yet, you can pick between Global and Follow lists to see notifications from. If you want the feature right now, you can create a list of the people you care most and that list will appear in the Notification filter. \n\nThe only issue is that you need to make a list in a list client, like highlighter.com or listr.lol", - "created_at": 1689859394, - "id": "b4b1f87e23e0287022def5727e902c550fddab066777ea788e85202613a01876", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "161b8ff1c1bcf4b20d88d17a41dda3f28d937a5228c1db4d1922557c76cd16a710d836a8cec1639777882e676069df86225500bbb631096ed4c21112385b426d", - "tags": [ - [ - "e", - "2f93fdd2f638c4932deff5b2dfdeb8e0f3c464d837e579defc2f95e428574112", - "", - "reply" - ], - [ - "p", - "01ddee289b1a2e90874ca3428a7a414764a6cad1abfaa985c201e7aada16d38c" - ] - ] - }, - { - "content": "Yep, it's similar to how GitHub and Reddit do it. But in Nostr, reaction counts are less interesting because anyone can create an account, inflate numbers and change a reader's perception of how the post was received. \n\nIn Nostr, it is more important to know which person provided those reactions than in apps that centralize identity.", - "created_at": 1689859264, - "id": "98e44e39877beaae41a73c2ea0016087e1a933cff20978715b77abcbd15057ad", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0b5ac8ac7a02c0afb50e4b1f65d1d72e5c69cb6b019ed61fb788f476ff35767c219e324ecf81298cb91dab3afd8a16c10f56beaa87b3b9b5ba1f28963f7ef94f", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "ffdd0c0aa3242dfcde3a4dd2b40a8d7b72b1a35c59199b130936c311a6524fc1", - "wss://relay.orangepill.dev/", - "reply" - ], - [ - "p", - "5fd693e61a7969ecf5c11dbf5ce20aedac1cea71721755b037955994bf6061bb" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805" - ] - ] - }, - { - "content": "> I feel like the reactions take up a lot of unnecessary space \n\nThey are designed to be a little party about your post. In other apps, reactions are relegated as useless. And because of their UI choice, they definitely are useless. We are trying to bring meaningful reactions back. This means there should be an easy way to immediately extract meaning from the reaction set. The current interface is not perfect by any means (especially because this is mostly an old design updated constantly over the weeks), but that's what we are going for. \n\n> should maybe be collapsed into a consolidated view that can be expanded to see them all if the user wants to. \n\nThat already happens in the posts in the regular feed. When users come to notifications, they want to see everything that has nappened. Hiding things that happened because we couldn't find a nicer UI yet is not a good idea. \n\n> The stats would feel more natural below the post than above it.\n\nI agree. But this is \"new\". We changed some of the reaction design in the feed and also added inline replies at the top which should have inverted the reaction set look in notifications. We will get there some day. \n\n> there is no space between the pfp images so it just looks very busy and cluttered. \n\nI tested adding some spaces, but it made the experience in low-end phones (which already don't have much space) a lot worse. So, we reverted until we get a better idea. \n\n> The badge on the pfp has a lot going on and could be simplified. \n\nOn this image, it's just the profile picture and the badge uptop so you know which ones are the ones you follow. I am not sure why it is a \"lot\"\n\n> And there is also not enough space between the text and the image in the actual post.\n\nThat is a problem between clients. In your post, there is no new line between \"I’ve been missing you. \" and the image url. So, it should be as close to the text as possible to correctly represent what the author wanted. Adding space is not what the author wanted to do. ", - "created_at": 1689858675, - "id": "e8d93fb9fe8aad86af190d0c9780ca4c4e5019381914b8cb65fc521eba6036d0", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b2836ab980831edbf8b7ebe4948f8e65e49a172a8c0bc583264069fb2253787533a64ce294d60b876324d4646788ba8588b8ddcf33f58266f83b6a87e812de35", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "root" - ], - [ - "e", - "d300a620a29f9e09cca2f8c81270742729ce2593d1cbdcd2578a870c73e1355e", - "wss://relay.orangepill.dev/", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ], - [ - "p", - "7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805" - ] - ] - }, - { - "content": "It doesn't matter. Download counts are largely inflated, double counted, faked, etc. I can pay to get 1m download in my app. And Web apps are never downloaded. Since lots of people do use PWAs right now, there is no way to know, not even a ballpark number.", - "created_at": 1689854101, - "id": "1a930a4908d732e5b6956aba473cd6dc10344bdc0726ca384daf2c5621b4bd11", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "94ae3dfc434fa223c050fde595cd8f0e18943ad51b4c165eda129215adb250d1fbeff28a47b3969f4e04ea6213dfa3cc0d71eb6ba23e5ea4fe23ad7abdafba11", - "tags": [ - [ - "e", - "763c8078c7dd051a4a690001664b8dfe984070dd3efacd78846c4cdd2da3d068", - "", - "root" - ], - [ - "e", - "9dcca85455abf03edd6812c740d708370077922204a74933548b8c49a5a39f47" - ], - [ - "e", - "aa7fc08e620a6c44c409783356d866910df2247e5b0a4e8493f6d1611eb8ed1b", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "8dfbea712e6263402297a88613240948231dec9172bee9afe2c82b5af27a72cb" - ], - [ - "p", - "09ed4d0ef81d77ee634617e36c505bdd9a8a3b3030686dfac5f5e12a08becdab" - ] - ] - }, - { - "content": "No.. not at all. Any small relay operator and even clients are at the merci of the state. ", - "created_at": 1689853928, - "id": "c3675151e21f23455a36ec7611a45fc69e49da3ce6f7fbbb3aee7d696eee4533", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fac6ed996c0b989fc7983340e8a683ee2b61f058bdc75cd88b5fd993af257072a7f6bb39e2ae8faa095f70f7c7ccbe27b40805e322b8dbb85b0d5d3f35e7e213", - "tags": [ - [ - "e", - "25025a9422e006903a8bc8b7370f16bc1aeeeb7714c872751f02d8546bd603e5", - "", - "root" - ], - [ - "e", - "3212c3bb3d6607241aa71eaf28ecc838873fdd83a051497cfae39d2e34fa7d2d", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "09ed4d0ef81d77ee634617e36c505bdd9a8a3b3030686dfac5f5e12a08becdab" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689851999, - "id": "2a493246e80b3763dec1f04042607a3c53ddbaec602de94bcb61bb201a0f6994", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b3bfa5173003ae8b9217f7cd88226738545b22cbed21fe83adb1e28162525e5a162991bfd09bf72c87d317d1fcf98deb0f71159d12bd20b3a0c86233d6999d47", - "tags": [ - [ - "e", - "40e4da7d99af6b74270f6a41403ad4ef6fc221c4d1311c2afb878468b2a31ba1" - ], - [ - "p", - "1b9d72d38b422a09cefed126e88f82361d4b1cc11cd19a2fc04e17b00b0c7d15" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689851984, - "id": "98fa2f068d0993daace0d34916318fc08ba24e0c8d9b61474666104af24b008f", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2a13e46d8488437d06000d1eae343a3cd36725badd4f6028b019f6ed8a32e285f7cb0abab8f04574b54f5bc73743cb5033b08e5815a2216d2973a5fe44091937", - "tags": [ - [ - "e", - "94f3156cb584696e9ed2559b7aebaa57465518b0493408dbf93c8a6b27d6ca04" - ], - [ - "p", - "49e3ca8a4e680a8914b8736f72470c9e91f609905b01650c75d3e189a49f2172" - ] - ] - }, - { - "content": "XZNuUUWuMuNLom0yTq38jzxZaR9WkSCsdQRjt4q7FAU=?iv=F1s/jYGrdc2i+SMPTqBFgQ==", - "created_at": 1689851679, - "id": "ef72e739b14aebfa57b6c5d42bbc65f4a413247809c592f3b52b4f4b16cd2963", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d2b3bf56fc86a2d6f4274dc0d2fb46d47935e31bd952ae7753863dcdd0101d35978a027fd4f6da316bcfbf6aebbef323c460b6dcfc2e1e2cf35c8e9c52859dc8", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "E5diFaZYD9BL2VnxsPbFhszv7gPnULv+CqfY1mo7kNo=?iv=XFp9d80vSOYbIrs9e6H8rg==", - "created_at": 1689851672, - "id": "061c473461f3a4c067d8438630874451c43082695756c774b8f2bdfbbc8a94c4", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ad8d277e27dde2f1ff3389a47e744625f1e672413e33b8f6fe0b1e7a597e8627d6db6883c1cb23643ebcb40c281e9a57f25296b4455aca24283cc0cf342494e1", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "", - "created_at": 1689821830, - "id": "a2a0b38cca7cd77861264b47e27439180d9e8ec0c07257c824e29b7ae6cd7807", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "30f4a24336bf1f0e422770d4ac83b6fc9a14d8e5ccb925c25802ce8fe50e9684f6d32324d0a5702d0fceec85f1f38e8c96b62d405a2e150d4da572900a86ebc2", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_0e75717e2422fcae74a5728783dcab922aa26dced8dc16ac.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "efd7a96c5095ea679d4019a3eda955c430b021a917a350b022bb3c169e67d499" - ], - [ - "size", - "2720953" - ] - ] - }, - { - "content": "", - "created_at": 1689820944, - "id": "7d4d4011107a1728880da56b0f470a0304cbb05e3ea0cdb810ed3eb861e410f5", - "kind": 1065, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0af6a6f8b8e0933691c1644345a63fc1f91e2696faf592790b295e4b903b4c5e4f54a08a6a2911d6c06960df9a3d8cd36f21998161af3f24a37bc9b214996b89", - "tags": [ - [ - "e", - "2d4d14bb122911d7843a934355475528571f34d478d940db3079d9af58d3c448" - ], - [ - "m", - "image/jpeg" - ], - [ - "x", - "6e225189e0ca6deaac822e3f48fcc44d6132067bab26e59b1dd8f96e55e30969" - ], - [ - "size", - "45775" - ], - [ - "dim", - "495x669" - ], - [ - "blurhash", - "_7G*WnqG}Z9GO@IUEg.9Os9ZaftQ9tni^:%jM^KQRPNbV@03n3s?$~xCWBR*RfTKob,Xo$r;R+0QwaD$-;ogspW=%yR#Ef%3V@tRe.4oNgkDRijZo2Rj-iS5WaS0obV@oz" - ] - ] - }, - { - "content": "9m1+vEUF9wuhiBexLna0SA5wtRJOE5nP1iu5SpzO7II=?iv=Stum2j5gFWdgSUkATftsMw==", - "created_at": 1689818614, - "id": "e3848ec5ab89b4b4a90f1578e695fd5551f8396291ea4b11dbdf6b6a4c065d42", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "57a0bec436faa420590a50fa870e1de583e2615c6878d882c5bf117e4110e4aea9aa70c0b948110fe4d27123fd40d9ef9e4902b0dbbffcc76fc986c59bdb95de", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "IgoBo0FWxSXhIfE4fpowHM7HKTcC8H+O+xTVsIeLYpA=?iv=7mzzIDMSU4G+9pi4cNUnXg==", - "created_at": 1689818605, - "id": "b08b843073ef035a485162714c3df63f049d831cdf9925683507eb6b4c040ed4", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "51db96a77a2a85ea0c6b4d50defa60c569614640c83a4aff933e02d103a88b7b59ad67aed9f23129f4f4c85c3c1fc522172d4ed7842945b739343abb4a3879ef", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689817063, - "id": "d7fbbcef0a1ba76404891938c72589557b10f032cf3338e0a518b2285b5bc956", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e91283c33eb2525038cb88bb749cc58de7f7c527a63e336b8236a0ae198c812b69ea81e27f9ba4df4399fa75213b3b07a1b4518dbf1f5bc724c9b03081760b73", - "tags": [ - [ - "e", - "d4960970b0fcce6a8e19e9eaf88519d54df616e3dadcd260fa584cc3181711f9" - ], - [ - "p", - "f5f98ba54045a2fa8df2a97c35fc30299b9e0d51a701795c040ca80cedaf39b4" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689817021, - "id": "fb97468b31105ca6af4937048cae0eeaffb01576c79f6b06aed84131b0bdf188", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "485e37b048849165ac76e177d546da3ef5606cb4e4641260ad0660f20e52d0bdd53f7d8b4a87cd9584e1a63ffd0b183557c85258f41f3ca8c28d5ded697b8779", - "tags": [ - [ - "e", - "c87e225890d3d6d429663f4cab9057221088c484805b9ef2da0573aa558b9e91" - ], - [ - "p", - "f5f98ba54045a2fa8df2a97c35fc30299b9e0d51a701795c040ca80cedaf39b4" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689817012, - "id": "fa72f4d3ca47d559b0b5e627347aad6630c202fdd4000b0cdd70085f051f820e", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9c6a4e063706ec03bbf99b1f839ad95b4b5e98b527bb3102d0b5d83f629ccd89294bda01f8d50c238d2e0e96c5967ce41f649e8a73a4686e349256ca8bc41193", - "tags": [ - [ - "e", - "0190e4e11059dcf124eea8387529429c4fc24b7151b0c098edefd364ffd80274" - ], - [ - "p", - "b2833792cd5c95662538e620fed371728e90671b9d6bdefebe8f706c1f1a04da" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689817011, - "id": "b083690af84d9c7f1b7eb4da844e9132d0e9e20f94dc17dcf43e17ec1c285470", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e2adf0fc81bc1601da5b28835c946762479a3fda09d7bf3b0888b0e7df8cd3f5d7b731ec4254b588426b9376e67caa777c8e8df5d7cfeac5699af33e57977662", - "tags": [ - [ - "e", - "ceb3b15d4564ba20c8ffc2d7753059028ceb5c3679d2229081c62eee84782a3a" - ], - [ - "p", - "b2833792cd5c95662538e620fed371728e90671b9d6bdefebe8f706c1f1a04da" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689817009, - "id": "76ba23b7a75d204849ed6104a1c7b35b81b54aefdc90448ae97285d2908bf6b1", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8d8d5a2d851199943a1d3a87e93954ce6d90acd55d294ad76015e2583fabb95d39288953697a9eb184a74447d9bdd38e8a4435c736defd3237578ec8aa522291", - "tags": [ - [ - "e", - "9c289fe421d434b5f8800fdb6a5f064412b809218d11571beec7fc7fa5bb8877" - ], - [ - "p", - "7ab1d3867722b4cbabb6c8503ab3f9265daa4f82e228cefe302621f4e5ee1f1c" - ] - ] - }, - { - "content": "Let's go! Nostr Calendars are up. 🚀\n\nnostr:nevent1qqsgyhxkj9etqared6eg2c9d8zjndnpr8qyc37l9cuelk02zyccn2sgppemhxue69uhkummn9ekx7mp0qgsf03c2gsmx5ef4c9zmxvlew04gdh7u94afnknp33qvv3c94kvwxgsrqsqqqqqpp5cakn", - "created_at": 1689816781, - "id": "ac64c67c3dc8b6d43a7c15b94c0d5c382e235f65cae783ed13abe4bff6084163", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6d2c7e78d751c1f175ca559bea9da61b9c8b3dbdb916c2a15754b2d510642a2a27c176aea9e94f985c9a10d7e47b49443a164365fe9757a7ac2456ecd308587f", - "tags": [ - [ - "e", - "825cd69172b074796eb28560ad38a536cc23380988fbe5c733fb3d4226313541", - "", - "mention" - ], - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322", - "", - "mention" - ] - ] - }, - { - "content": "How do we get subtitles in multiple languages for Nostr videos? ", - "created_at": 1689801767, - "id": "276064d45865bfb223b1c7156ce555ee291c51b82e3096711c7fc9048bef014e", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "93dbfa2a47499ed5d9567fce061399a636af7ec8fe2b3d9e02d6db67dd2024fd0db7ea0c696f925633c9b929ca0f1f83b1617372af182f7cf2a9d26ccc4c8e2f", - "tags": [] - }, - { - "content": "AxnOIG1qFS+PKCRIDl/vOfhNlZpMWWxgFCfMAmXR5VR0WyuHgq51owAycbQMDTneEr1fdCQvUvij0VzAhtsWMQ==?iv=fkuPtAZC0sB3f5z95Q5OOA==", - "created_at": 1689796668, - "id": "fe3050a24ef6f71bc7c6f300161e963bd93d8e35b46d6896a679a24bc234def6", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "63e0e21357ccd969d00d8b8e3391212a21b99d37eaee66086bce4a75a580f1edb403010a9554e93735eb496199fc1d9dad8a5fb8c6a562ce15b081d8c8400283", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "seyXteTXE7xcuLVoJFxOxrioedOcMZZA2kHO7D5czLW7qIG9djYZmotp8/4AKUvW0ML9/Zg+cMB/l98T1+mFgS+j0LG0v5MYBH1EzQDZpyLlPIZSu+U6FjVX+mQ5xP/1VYbw6bYeN724EJE8A5uR/CeR5ba+7mU/lESmMSQbcG+81nVbauESmwN0/CtfameLcvWQksSclKUVUoK1T8xPdg==?iv=OhXj3Pdt/MWXB2vLQGKQ1A==", - "created_at": 1689796648, - "id": "bd4a822b08a4c60fff4e9643bb524bc10a15ef413f05b54e6d2c06c8f93d175d", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "330156d1bf8dcbbfde9a9690b9a2c470476599275a949d1a57b07904e1cb34d6832a4b0f48eae64bf9d990d2a75ec371057ac4e213780874288319173b9c021a", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "dOTrkPCovcomFiLrZaT5PHkdhIjUBA19y1/AI7i05h30rg3KFHNcAWAoKGIDXdVYd9zwp4614oaB5OwU8v50Vg==?iv=zYLVydZOtyn4esxHM2POUw==", - "created_at": 1689796524, - "id": "8a72bd5d8d93e511bc4b90f9c06db9a835533a41244b7ab8dc603dd8204c4848", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2e8930dcdacd7932c447652f8da5d2638fa64bcff4e4c04d0806472d7ac3b378ce8ed41dc7b5c32000d4117d217e6837438557964c24d55659fb9c415b0c6119", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "afy+lH9UsXeMDOXOIDcGWIbqGluAAOC9+Ou+hfz8YtJozeATNVXONKW9vywhW4uf/ug0daIa14ua+Htjru3k/4ZsSt4Lf5s3HL89JVvY8dNM4RQWY3ujCojCibipkHT3?iv=5ZpYFy/C0/lkBA0jUDitWw==", - "created_at": 1689796215, - "id": "1d4b12c76b6b59161c8167e4de7ffb9e6f8bda61abcc24f1352e37acfac5302a", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6be01d493cb564657b75b4a3f46a2e8c2f66c08e3c16266b4a39e2e377632f007e2c878971f01ffa1755b744fc71054a5ca7285993a3d6d5b9117f47d5fe18c1", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "hTpYWaI0Y2FGBRnAPWXblTqdiCrzqrlFlLfqCmDwjBYpa63jiCE2pS7bVcqSWMitjWVIyKhCN9fgVBYBFPvefamqJT9z0IZzKebvvs4BqB7Nd+Iz2nokOo4jOPeJqIu+?iv=OqPz5bYdh0+b4haP2XQKdA==", - "created_at": 1689796190, - "id": "3e2dbe64f489fb36298b6d9bebfcc6aeb0ed813a9743d64393eeaeede12d3bbf", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3cff6a0cfcac3221b028cff5dac1c5ff6db6237680c0c6b30b73ef1196300709671f1865c50e0f7146d69e9a7fedd320959ed777d66fb04776ca4be32c5faea8", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "fK7K+JZQjd+pGDqqY7iITMHhXNeqtbYM4yoRniviW3YAgOH3KW5htMwL4iE7BP22kbRCGD+KAugKCQS82eaADG0H4UzcQwRzDkcWfKkOBJZN4hyc+k2h/O73SCT2hjj3?iv=41MU3ZirxPhr7+5FRKko3g==", - "created_at": 1689796155, - "id": "a9cb0ef636892cf0a4c22d29da2b418d2668b94c75966550f8bca4be4b54f4f0", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "40da153bc8d11be451edb175ec9e5d896fd6415f1b288ddc83f84775bc990c930faf6061ed01152a8b69f0858a7f10025155e707e426bab08a1e57d13fef100d", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "6XrKnpAX88V6Htj3dRFhYJIrpvoQygXbFRHQ7U6Lvulf2w+Wi8ObX0duVSPhbTdx?iv=1pKalTwNvr/773dNsYxrsQ==", - "created_at": 1689795660, - "id": "c7423761b1b250f98795e26c52aaff8fe85bb28c23ed30bd206bfc4d84ce9580", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "26bab236f84777a5f7478744aa689795f1dcdff523f2f4e3f801d6a73f6b221f5d1f55e664ee4b9880566eedc5acdc3ff8fd39e85aae27b04a2f4022c0a71a65", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "d+fEU20cosND2HbmwFIJauroNtSmj+0vjS7JFTuSpVRZVlqsBYAudVHjIoBUoVhoZ6nRf1mYcf/DxCVwn08ZMvJAXqVgT5WPhylmKYm+6Y0=?iv=eJW6o5wA77YxIOLVyr08ow==", - "created_at": 1689795615, - "id": "f0d66292c0478c5876b12b330d5f8bb87ccce54249203d87440110c1e1e3f358", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f5e9328dd7f581af984fb02f41b62bfd0b14961586b612f668a8f9a1a237e1d47a5f7e7ecef4cfe6988c18b8ac7c58701e858c27d747510e3dccaa16a8235e99", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "jYW8dxVeSx76co1IsQTpqw==?iv=9TpMslZaeGk/Qc0kn6d0Lg==", - "created_at": 1689795614, - "id": "f4232c1aef99cf09ddf794392f4c37c4eca0d9d85bb2d1ae3ddf72da7632bc0b", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "bf5d8458087408d3a652d26c162fc405d31743a5f3de2c12fbca593ba3b3662e9052c2b3d7c9086dd79e4387a36762b55873544c4c762f104e3727d734365c83", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "wJqpUSs9Tqc+LJMiwF2Tl1d11sl7y85iM4qutodWeBNn3UMTpyA731WmTMxtwo59HwgDx7Y2wi/B5oLY7oBZUA==?iv=0stWUqHs9xD34aJcRP0Z9A==", - "created_at": 1689795571, - "id": "df846e0e2628a0102dc5b5839e151dbd483cf5e6ac29b7c5212a20a058a9aa33", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b65d1f339c88793dbfc0a0e46b91e53cd506732a6ece9d585041d8d1e0288b9cfd8b81d02a0efe4e6835d2b51258b2a2291af42f311dd1571977bbb22d1188e7", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "ol3R5HKU2HN5/6TlsnqPEw==?iv=0y+mRP8iHhHiIHlIb/Njqg==", - "created_at": 1689795555, - "id": "de8f70191affee06d10e83abf8a8000d5af3b6726f636dcb204631672551d206", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c98a7d07063f1f1f69a93838348123d6a6dd321cb8f720d876958e002e413e0dc95b9716f36ce1dfcfb51240c8ce7e0d8e835fe2e3fb209f3940a4fde582e0f3", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "+", - "created_at": 1689793683, - "id": "ba35efe39f4d25ef3f79f578c618456a04d27115333a8ad4b5558a70b6ba20d0", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "193233755ae8283a7e0bbafcea1656d21a68f90912a4e58afa491a11590d262ee9f7cc57ad625f8b7a5969d6266968783037282c7171413cfdb3308d1c739da4", - "tags": [ - [ - "e", - "ca1d6d0979a9892cdc6bb6c9f6f0ad752abf91a59e2ab047c8dc40ba864d94fa" - ], - [ - "p", - "ff27d01cb1e56fb58580306c7ba76bb037bf211c5b573c56e4e70ca858755af0" - ] - ] - }, - { - "content": "WW1FqQbpCQpDxsJeX/w3qSMNW6OMRN1FoWU6pE0fxVl2dsisbuts+pZplL8S/0AcQ+WrBcGIxd5O8w5ky8Wz6zWyge0VQ63fr07NWuitHr4=?iv=ZehOo9LmLkLSt42WdXYnFg==", - "created_at": 1689793047, - "id": "fde523a39bf03736ae928db7d709e6d50193e7a6c20747cc529656db012a6f6b", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "4a72e902dede3d8ebbcf1f662f8194573d0bd2cc26a66d66ff11a67d11471d24444329c4a3f75dadd7ffc51740394ba83f54ff6337882b5b7ee332e65f468d41", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "11d5n+hT39BBDvhG6kwgs3QtITRCilwvu2t1EyfnbW9zQDvhGImaVwcNSBJogPUWND81PxxSevsnRunX9IlpkE+NlxFvoRJETnjB7K7SYJgEm1AJS0gvOOZoJay6YgV+?iv=5O4lPYjvIlFJhZtbcOqBNg==", - "created_at": 1689793029, - "id": "617562fd855d45c2f4ee08f87c4f8cce815b4d2e94a51cf6c6d25b50789c6cb9", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "504ac9d67669273fbcc6d92535c7a01cd50915393baa190cac7d913b50fcd3606e2945b67370e37366327b70ed24fe2f45bd9be29c26342fd5fd9f5ad1db5c40", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "+", - "created_at": 1689792227, - "id": "4afd3e5db2ec5e356e2b734978f0c142d46dd547e2a74bc23d3a0a01c15273f4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1439d24fa6b4b40ad66ef01799d7196fdf70f9fd7f8cdf8d114e99235af0a0d994c28bde2f665dceda0cc31694ded3534e1e8d55e316dd6605c84eddae875eed", - "tags": [ - [ - "e", - "794fb8ee8d06f5961c40a11f6cbda46819ef87d6907c0d9fb05038ca13aa7a4e" - ], - [ - "p", - "876e724d762be346b89f47070758da679cdb969a2a17d3c5df93da832bb71acd" - ] - ] - }, - { - "content": "juGxq6AXk3XCL4JEp5A+BJ4A7hwL1n5AZjD55zC7+EI3PjXiYZcGDta1c0CUH4qVcxmTLSqUFOcs/Dwtd5Qea/hemj9/nIu3GJYMh6Ch0+SPDo0sfXaVecSCAaAmcObl?iv=l+1TL3C3hwFh+Izzz9MVVA==", - "created_at": 1689792194, - "id": "5425f9eeab69bedf79ca59cd730aae076b04b33cabf709e78560929680164294", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ba56b1630ad6dc18ff9d3169a5947011623281fd73dac87272bb6cb0b2cf316b0108171689728d49680f1b6da47169ff0cef2aa420d86326da2ed11ea7ec0394", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "For sure.", - "created_at": 1689792082, - "id": "ad71d5164ffd119c21f1386f5ebaa23faf93b0860bb2a8af6d2af63b5143a43f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e466cd8f8c06b0acbc66bd4f59cb0852ab4df16b8d70e63de280b39750c44a58f49972b06563fe9b4f74760a3a8be835111a12e874015b8b32016fa78d22ff90", - "tags": [ - [ - "e", - "25025a9422e006903a8bc8b7370f16bc1aeeeb7714c872751f02d8546bd603e5", - "", - "root" - ], - [ - "e", - "4c37c971eb747bb8952650778094269d48047e470b392129967e412ac80fb604", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "876e724d762be346b89f47070758da679cdb969a2a17d3c5df93da832bb71acd" - ] - ] - }, - { - "content": "peJPIP0HJSqAp5QnclIiewPTW6D8ABE5XFjsRLNExq1+m0ofqGlK+p6eUYTtXEkVY708OLjsn4n1BwzZ3VvBrRhAFTW1qiBgot9Mh3g14bwzwe0qTVIMFJX0Zh/Xt0eu?iv=nMfwVItwt7/FJ8wPd/Eqhw==", - "created_at": 1689792036, - "id": "2a129c01330a59c5e517af6fe0fc3e5c2c2ca1514a19df5351d07502efc220f8", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "23a492d737219cacf65b085a17a2db72ddfc3410616b297b59eaaee9bd10522754832cbbf35c7e422434300b50909d2ce7ad2e3a95017686621d2126634b199a", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "7yKCNmFIkil1iodXHUNPGg==?iv=QhwQSNtrZXzi4jw/06XOaQ==", - "created_at": 1689791999, - "id": "f7108bc890bdd5bd37ae38f7d11a02a8da5f02042b0b77423a74658fcddc9934", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e20c98f26702482353a7982cf48665a7fe9f6bacfe05af338339a70dea82d2575235ddb1b6ddcd752579d6a83171c47e0df5fa282992c4aac099730900b91d64", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "40VWtBtcLP3YFFX1QTw709kpQB0pTfY0UleW7S2iOJU=?iv=m7BNPpW5hyYeV/BuNR19AQ==", - "created_at": 1689791992, - "id": "19d8ee5db99a5631f71d4f4711bae78b5cc93c0c3552ab78fdff0df1c674979a", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f416f0a88ea4de2b2487fb5b07b353516ad5ca4c17bcacf2315d7ef612b312281f1e087a14ebade82e91f6cd4c27395bcc88af61f51cbfeac4c2ff2c6d7e6378", - "tags": [ - [ - "p", - "8083df6081d91b42bcf1042215e4bfc894af893cd07ea472e801bc0794da3934" - ] - ] - }, - { - "content": "5p2yM2M5i3h7H0nuTsP5RrsvWmKbUpucyHzxMZJ1wsf//jObdREH5wLvqPQ2w6i2WKD/T/808UTk+rb8ZPzlqLNUgYBMlD8bjz1IEVY7Hn8=?iv=3749TEgAq+mmP68ICxcakA==", - "created_at": 1689791923, - "id": "341bc18bbcb90e8dd6736376d179a137e42ab2d33b9a9d9af60f82b2069be88c", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c89bfc23afd50a4b669c5000a244bff10b114991983627c3da64b03de38f220792d14c75528cfd89b2ecefdb8093086d2ffa3b2b109ddb2a4be0b6b4dfe53bcc", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "n/Zh7u6uaozj+2mCIYhXuT2Oqn7uyYwYkqaBWPBOwsgO1dSqxHPLWwR5ZoiCPij9EWhtSI2BHEEy5OeYxqlLr51Cli4gzNpq03zxbEb+vulcrC0mXRBJXd3SIo/Cu/um?iv=putWwaSfX+fajySLJXgBeA==", - "created_at": 1689791780, - "id": "18d4f7440a02c83680b2a5744c0359fc088a80b6ca0dfe922c3e13103746926c", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8dcad60b4faa5727302a3e3f2fdca3ecbddb85d3e87724d0e8d7053f647960d5174482a22957776ef8f84a33b9af5d19c45971b5cbb43428ed754c3839c25459", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "T7+/09ia5+pzY0WDwzhGhQ==?iv=iAV94k1Vl1X1OYpekGbgLg==", - "created_at": 1689791735, - "id": "a044df6a86bb24b2468609f74a3fb639ad599d6bf14293efd6b257148d1df8c0", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ecfcb8838d80dfb943ee0d8fee094402484057ce6a85d35754a818707bf04becd299d41cc89519c378e545a461263f44d3e6adb6c201c2fdbae5cb7cb6c627a8", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "What's wrong with the image? ", - "created_at": 1689791634, - "id": "1a32a1345dab56de57b1d0e5e3e0f82197e782541cabd4d4ecd1b1ce55d495c8", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0e893b5c1c6adadc6d61868ea542d8320924234f8e6a8df75eb845e06abbbd386f2cc8717692bf18927bd52b58f936ea5bf0fcaf66c03b1bc7219c33f1508620", - "tags": [ - [ - "e", - "134cdb01d0cba849d56cb6017aedefbcf8043eb01608089ee02951b854170185", - "", - "reply" - ], - [ - "p", - "ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74" - ] - ] - }, - { - "content": "We haven't unlocked the power of communities yet. Amethyst will have a few UI changes to make the feeling of joining a community a little bit better. ", - "created_at": 1689791536, - "id": "5f74955acd83df8b9ef6031f19956685172beca93a4b03dfb56954a66782e9e8", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9d277d454cefe5e6313d8c10820321ef2a6d91ff2ff305f3ed7639869321ca78d3d7aff5205f5d02b2884499e16171d29d1959fca185e35f73f34de79f6966b7", - "tags": [ - [ - "e", - "eb612971888141cd5abeaaab8b7472028574f26155074f57598ca9eb237080af", - "", - "root" - ], - [ - "e", - "39c1e289861226f800d915a60484b498a531d4cade8cb3caed3dafcdb4ee891a", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "ff27d01cb1e56fb58580306c7ba76bb037bf211c5b573c56e4e70ca858755af0" - ], - [ - "p", - "ff27d01cb1e56fb58580306c7ba76bb037bf211c5b573c56e4e70ca858755af0" - ], - [ - "p", - "efc37e97fa4fad679e464b7a6184009b7cc7605aceb0c5f56b464d2b986a60f0" - ], - [ - "p", - "d0a1ffb8761b974cec4a3be8cbcb2e96a7090dcf465ffeac839aa4ca20c9a59e" - ], - [ - "p", - "f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0" - ] - ] - }, - { - "content": "D2c4aPXsJCcwJ9z6NGsQALQ/i1+bbhIHgOsdloA7mMyLqxWkCXNtiSa0wvJN8Bi9fYhjlOa1zT1tj8GWUYVbkH7gsgLnboTwCLr48JjKNZRHY2ske/sFpF+V3OMYCtkDRRh74p6yKv5x4b3KSvAdZmuGApkP37wf4tA9QSYj7Fg=?iv=E+UwaN6Acc5VuYlhJo2wrA==", - "created_at": 1689791426, - "id": "4c65727b37d96f7937024be773f048cf291569682a6ec93d1f2677eb872900eb", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "17494231e1e2ac82f6f5c0ed39bfda56e76687ec29fb45ca6eb56c2621fea1f1612b47247c0a1d9f52fa2f2502c838ea5401cbfa414adcabbafad38be49c17d3", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "hturKi69ZiXh/zuDehkuYisaZulgLhQweuejTUC/NgkSY726pRvx2eMaeeMp/GyXLIiXJmHBbGHN3WcriT1eWg==?iv=145wzmomdE0AgjYK90KDHA==", - "created_at": 1689791397, - "id": "4145c43d088936140a0d03f78fe65d075c09560118a1d10eb9a61f754ac0c3ba", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "28dd7c2ddcf93091f5e24afea68410f5b77c505a271e6eeb17396aa8e7acd47da4ae65f2c7f8fd7b416be2d72955e81cddd884b0e6b2d041cd269c17158907de", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "UGNJsE4FdyJR6HsTJKRZiZ2SjVC+Rur8wg++uOTi8iLdnDTdVhv4hEA41MbHYCjZnCZQO50fFsBICzFnziC1DA==?iv=GpYALl36b8bHbqAL14NZWg==", - "created_at": 1689789316, - "id": "881bccdc3e7ea2e211282406d8a24f9d8b13730be7f7e4aa20cb2a87c3a813ef", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c36ea50e7ad612a1e377851882b2db9f878d591115c769f83bd59344d24c45f4639a9e7b7e281bf2443b57612df932afc3f53f567218683c3b28077f2359c37c", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "Of course. But the question is how are they technically going to do it. There are many possibilities.", - "created_at": 1689788786, - "id": "bf39c47e2e5af5751dd5265744185df3d8205ab76a467331ef0bb97d288224af", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c035c989ecb3a567bd0b7d09339276f93d2973d99bed28ec7aaf8a653a27a3f80674804abe0b2eca980060709147431ca910cb7da795648becf72014be0cef1f", - "tags": [ - [ - "e", - "25025a9422e006903a8bc8b7370f16bc1aeeeb7714c872751f02d8546bd603e5", - "", - "root" - ], - [ - "e", - "69601e47112484a0fc1f173d0bceef8ee33ed56c5831a3d30d12693dda4fdf28", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "206e580157eae3395cdf954ff30501e16902074656a4b9493f36f896167496b2" - ] - ] - }, - { - "content": "fRxYgGAPTXND3ruRL3wx/w==?iv=jsuZZX/FaK2XciQ2Wir7yg==", - "created_at": 1689788740, - "id": "81c6f03692855f0e36a4b80d864aaacfecb549d39e390a5f44813e6df5c9f8f4", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ea0b345f1d05f62314c6d68a2938b888ccb1a3c0ebebe8848b3df72dc130711042f0144d9e3041c3521bd61ba2845a56bfe3bf745dcb8ebd9e01bd1e77710e53", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "LKXDKYSKDCjyq+6MkQgfGo5esbtZDs6yNBoY2WOiFHxBqa7Jywg556XC4eD/xaM1xh1S2Bd3eHRm3UT9sYJdk1ubyxDdiuKXSEPyhGuLBri76at3UgWfSs0wQknFS+cgnX8V9LhGGGpzMb+8kNZR36k3AEZfcjrbOvOVp0BLKIg=?iv=Glj5CCIi8+1zDbxw+2SeMg==", - "created_at": 1689788734, - "id": "d7f01cdc157a28c915e6077a14820cfb6535321e17d3199420f05d875353d1ae", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b7036aa95b6e68d34089897e1f8edf6263ef52848396894b2b619092fdb2f59ac13f68fb5666a56a65deb04409de0e4fc1e94afe0c3c09098e8b2edd3e04ad42", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "YcjKnGE+tJH/cds7X/vOroR6NVYYpRh0otIc/ZgeZvA=?iv=xsJsUMr3It1EXfc5ZRHPLA==", - "created_at": 1689788612, - "id": "18a06699806b3202f7eba5736d89f8d30302539f7e306bfb7623c1a21c600092", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c8e3241e90b60fac97c4457589816a56b22995be2ec2e2317d51e1d66fb897efb387b6cbeacbf261dda0804c9283211fbf1af1ac5bc9e9c5fdc78a2b2060014b", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "q/kqbaK7wnyDvJ4ORsOwfg==?iv=6rToBnTYx2KUnRTxPEHthA==", - "created_at": 1689788601, - "id": "ae37ff6bf243668b58d3b12a11123912a2e6f71ed1e60206d4e2234df6b9b6a3", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "eb5593f481e1d67d9e6faf18c17b59e5ec06dd8e6c5026b4d076cb3320e1c3ef8115de470005e7afdaacf1e0f1cebecfe8e9d5fdd73510b6fcbb71aad51b8494", - "tags": [ - [ - "p", - "99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64" - ] - ] - }, - { - "content": "No yet. ", - "created_at": 1689780075, - "id": "8df02766da387d6dc3bfc283c6b9c2e99650006fb5b1c88884b8d5014c25854d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1040be4fa70fb028dfb8bd622ef37407b7246db688e0e6ad942d8cf3cdba86b635a7f5f1a33feb4046ab77fd1f52ea28ffe98517070b942b1273e670a0f8603b", - "tags": [ - [ - "e", - "e5f11e003dfb5ed948bdd67525adef44c6534df4b529ea881337307810c3e6a8", - "", - "root" - ], - [ - "e", - "45e52aac94688eadc432a5ba9e81a213309c289c86618ce660617239cb7b7d9b", - "wss://nos.lol/", - "reply" - ], - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "Yep :)", - "created_at": 1689779927, - "id": "de53bc355935d7f20927b9cd580f8351263a0e78664678898267a70769e33573", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a45551d3f326875ccf410c546d770fd1b87af47022ed6125cf0c4b58cb66251efd0089daab8e19563c25c44690b314c227724ff9bb9fcc39c16727152cbbd119", - "tags": [ - [ - "e", - "e5f11e003dfb5ed948bdd67525adef44c6534df4b529ea881337307810c3e6a8", - "", - "root" - ], - [ - "e", - "6fc9fe5427f818be975d11a5647aeee0d669bd417a5422e669a679114313b42a", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "Sorry nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49 \n\nhttps://cdn.nostr.build/i/e1c9f560acf3e3fbc147d83792313bca299010e5a259b00a8e7ee9724eaa6946.jpg", - "created_at": 1689779837, - "id": "e5f11e003dfb5ed948bdd67525adef44c6534df4b529ea881337307810c3e6a8", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "64516164405895e616f16240ee6e0b2aafeea2e78f93d19dd68c22b17e8dd6723adff8508edd20e23c3e9fcabc2f04c86d2fc35d50918169c9dd207aa9f4c873", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "I am waiting for them to start tagging content I am required by law to filter out... ", - "created_at": 1689779811, - "id": "385078f5c6f4d466900e5267755a1a2db58ff0cb9519cf695c5a69391eba29cf", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f1890c97830f613abea4ab6f6958bab0d2afeb0bfc91261f0a9c517aa85c8007094bd6beaab44dbb85084952fff2c0207bb58e509176aa15c4cc5a99475410ea", - "tags": [ - [ - "e", - "25025a9422e006903a8bc8b7370f16bc1aeeeb7714c872751f02d8546bd603e5", - "", - "root" - ], - [ - "e", - "e19338dadac50e080bccc1457d5923aff9aaf88012401e9bc353c4c4b3c28839", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "c43bbb58e2e6bc2f9455758257f6ba5329107bd4e8274068c2936c69d9980b7d" - ] - ] - }, - { - "content": "We don't know what's going to happen when the state starts using Nostr.\n\nBut they will. ", - "created_at": 1689779396, - "id": "25025a9422e006903a8bc8b7370f16bc1aeeeb7714c872751f02d8546bd603e5", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9a4740dbfb4894634fc40d6c34151a4e5c2771daa9af119bac96e36fcf0b65a938ea1a8224ddbfbc70034e81dc0f9ab86033c7425488359392d604e1f8257765", - "tags": [] - }, - { - "content": "We are using kind 30,000 mostly because I think it is a good idea to create a feed of the muted folks. Since Amethyst shows all kind 30,000 as feeds, it's an easy trick to show the \"blocked\" feed as well. \n\nBut we can go either way. ", - "created_at": 1689779276, - "id": "24e3fab99020ab31228b2ed48eb63fa7800be963d5503c5c2598ee61990ebeba", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fdf665f4df27fcb7d407e43b888b9f25d96ad77fc95c9114ee3f50b5477e6cc8303f3966a031cff71ca0a9ab492152ebbbfcde597b62c22611d77a3628167e13", - "tags": [ - [ - "e", - "bab81750570876585535c8ac4a4d5f983ea4cb0675c94882af25b256d60f5a7e", - "", - "root" - ], - [ - "e", - "b9d1689cb4c5c3220fc2d8a3ef0731f6bdb2fb7cb2593a085c57488616932dfa", - "wss://filter.nostr.wine/", - "reply" - ], - [ - "p", - "d0a1ffb8761b974cec4a3be8cbcb2e96a7090dcf465ffeac839aa4ca20c9a59e" - ] - ] - }, - { - "content": "Not only relays will have to deal with this but clients as well. Agencies can tag Nostr content and write in law that clients operating in the jurisdiction must filter that content out. And agencies can easily enforce this via the PlayStore and the F-Droid store. \n\nWe don't know what's going to happen when the state starts using Nostr. ", - "created_at": 1689779139, - "id": "6d592b4cf06a528138af967f69e425c4175c7dd149776ead72718ca06c7c10a0", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "aa5d16975ac357fde1c7814e73ebfef5c326f98cf622ee5150c530c476f545d2db97e94a0278e1cbce7fef4e4546379083b71bf277351df57aea15a54e3e4fc8", - "tags": [ - [ - "e", - "810412a20e676fac2119d0401830601ad2b9bf640d39c5709ae047570476e06f", - "", - "reply" - ], - [ - "p", - "8dfbea712e6263402297a88613240948231dec9172bee9afe2c82b5af27a72cb" - ] - ] - }, - { - "content": "+", - "created_at": 1689778259, - "id": "218d0bcda05431434e82da0689cebd0f29edd9880dba67bed6dbd7106aa21402", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ba1c0b1bc595450196b982d8fde84751ce16b4e2da577a9ecb44c16f1c8fe0c2716edec606ff3cefc0569836f9507ca34c6a9411d9a463004fe5521255ba54d6", - "tags": [ - [ - "e", - "5a7eac5ce4ec6ffad268fb6bbd5450e2361a1ee20efc2aba3f94f41c49ac6d64" - ], - [ - "p", - "564e2192d2c4df33224c15d787cd0172fc8c7e6a7afd67bcc3f8e3447d765981" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689773079, - "id": "f2bae9c9b2c5b1db90828c1cbdd5892485a1a239303a7e7425922ec2757705c4", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a64442be4bd5d5d7248f120a966e5d995f8958cad3242f05b145e08ca859c2602d88508f9d8bedab29ad0027349fe5cbfd8e12832208f7ccbb7f0f4419197a2d", - "tags": [ - [ - "e", - "ceade31f339b0d1ef64d951e49153c08d33b995ea73f419cb9d65501438857f9" - ], - [ - "p", - "f5f98ba54045a2fa8df2a97c35fc30299b9e0d51a701795c040ca80cedaf39b4" - ] - ] - }, - { - "content": "+", - "created_at": 1689770561, - "id": "bbf5451dfa185bec87f2e274e451792d8d203d4f257649c7a54b699d159aebce", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2a74f27d5914cef15399d1a4b52f17c1825755b8a7b70e6d05dce67db7696272387dabc4b6f27cf76c62708b0ea167379ee17db00451a91020cc7a734c967df2", - "tags": [ - [ - "e", - "9fc46ca0fbdee0f4436f1d0b48d1303ea6b10bc6c5d47fad13bd96a6a1968ba6" - ], - [ - "p", - "7f5c2b4e48a0e9feca63a46b13cdb82489f4020398d60a2070a968caa818d75d" - ] - ] - }, - { - "content": "Qju4ICVAki2Ead6iINTA5GaOnJSwZy00Gilvyhm/LmjdnNEcQdQPXifheYc/1eMchN6VUxJDabiafPe1OjX+RD2iciBUlABOgpy+y+weUd8=?iv=BaIQNwhp6g4PiJu+MWdiuQ==", - "created_at": 1689770428, - "id": "389386ae9cbc4b1d5e4fefa464136b4f5eff12ad0e030b15076976a08c9b40c6", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1e14b2d38f73f965f987c05c909eafefd97bdb29c04b3cc6d78aad708c0106559282286f9073a45f6f7d4f840b94249de21d5a6e964708cf0fb800401932068e", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "D+mvo+RodsQgWegn9RjuWHyawp7sHFBpLgHW5+2yQLw84TKrY5svyR2NfEUmJcl3?iv=BkB0cjrode2kmi5foZf/qA==", - "created_at": 1689770406, - "id": "bef8d4b6c114ca46c03093577e72ae1aea26b1102242ed1c9d0220c78f31d707", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "87cb9e2c165d9bb931c73a6c8899363ffa975f423989363580090919219406a13c5be2932e0df676931583d8a2be86def4b56bc0f8021543dd1aa584efda08ad", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "Sd4jDtAA1cp5RPs3vlXKgKEcnnwyBCX/6gAI8iFUj+vlFhblJc7UCQ0E+FtgPeeK8GYB1lrmll9Z+Xcy8S8yAQ==?iv=YJ/u5liYySfupmcXDjGu/w==", - "created_at": 1689770387, - "id": "f75b58ebfaca4a9697397fe8d2b6f848d3d01908bbfaad613e37b995e0fe0629", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "59bace0ecd181d2a29c13eee6cf238ac70a22a45b6e0ef6d9df39a46a7f5f6243c26b223fc085027cf326fdaf1e8f63028071560abd48fd24f2d912be12bc0a2", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "V+RxWXXhMHFF9yQQmbWK6Q==?iv=QrXWO3cMXO6+rntdblFulw==", - "created_at": 1689770372, - "id": "331ec02999a4ae6aaf33eeb738dc4c9e8535f077b9573f92c78aa75b1c0caa00", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "edc43ce3d7ddcbcb5b72e9c8e869250ccebd76244cfd883f7a4ba0833c7a2d19a0052a6aafdfd0cab1ed7a3d31a58c3b976f5a16c3499e0ddd769849d027699e", - "tags": [ - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ] - ] - }, - { - "content": "I will repeat myself: It is utterly embarrassing that YouTube creators have more monetization tools for their creations than developers. \n\nThis starts to fix it: \n\nnostr:nevent1qqsdcan9s3j2pvhgugnfz5vkfsv6ehumxeqzl6lhgkx7vh3h6hg7hegpz4mhxue69uhhyetvv9ujuerpd46hxtnfduhszrnhwden5te0dehhxtnvdakz7kzntv4", - "created_at": 1689770176, - "id": "2526d5ce37b700d416fea47721d3260a605b3a3edbb916adddd8f547cccdb6cc", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f5d7339fa2d1be538e33d67e7cb7c267c54eb79a555719f245eae431471e50ead7735892395bf1bfc876d37c8849b0ff006188e22ceaec322d867f960699cd48", - "tags": [] - }, - { - "content": "An external service for larger purchases is great. But I think it is extremely important to also be able to one-click buy things from any Nostr interface without navigating away. I have explored a few options with Amethyst but it's not good yet. ", - "created_at": 1689769859, - "id": "f0bf7d248e55683e008eea97ad017f87b49e724539148bdfa937cb57caa588a4", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ffddf687fc80146e53901dc55547ef00dc010453efa337eaac7c84768daab445bd0b4d1187ca97b35e6d47c7440dc9a995fac7226bf79f60b14cc8784dfc8279", - "tags": [ - [ - "e", - "1a1be57cf73c27aefab4f0b733fe8ba433dbccc7ba2dc8c53c9764d077f79add", - "", - "root" - ], - [ - "e", - "3b24ba5bf6026fa7b210db0895df602084817c5521bccccf80a7bbf64607cff9", - "wss://relay.orangepill.dev/", - "reply" - ], - [ - "p", - "f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0" - ], - [ - "p", - "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0" - ] - ] - }, - { - "content": "Strange. Isn't it a relay issue? I noticed that the post is only in 5 relays. ", - "created_at": 1689768641, - "id": "aa82841f3da7f04319e9b5b0ef0d6a934da15fd575ba9ba2055bc7e542fb005a", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6eece2f872bbfb9459c7bb3e6d8b73328d3d40b300b8ec31c47165dabf69d30a039103f32c7acd4620e03a1f2a3a4f764bf6c8687524ab117e677c7c74eb0107", - "tags": [ - [ - "e", - "bbcc50d1d1487dca1ae3791ac651c709d5a0b91b139ed5a54f4a1aa2f077c465", - "", - "root" - ], - [ - "e", - "4289c7852d03444b1075f3ca4dd5cf79ad324ec0cd464144470c9db796918604" - ], - [ - "e", - "3c4f2cd1fd77b5f00b946b58a71fc1bc0dd3ba74eb70d6e89d1a1dc025036b44", - "", - "reply" - ], - [ - "p", - "74dcec31fd3b8cfd960bc5a35ecbeeb8b9cee8eb81f6e8da4c8067553709248d" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "532d830dffe09c13e75e8b145c825718fc12b0003f61d61e9077721c7fff93cb" - ], - [ - "p", - "564e2192d2c4df33224c15d787cd0172fc8c7e6a7afd67bcc3f8e3447d765981" - ] - ] - }, - { - "content": "LnYgC0RLdzVdatNVXo/iD6UN+dP4xDT/9sw2E95T958=?iv=rikKQozxy/jFNMVIDjqTlg==", - "created_at": 1689768433, - "id": "6e22cc856c25dc8154959147f4c71ac9ad687385135390bba42df621b0daa1fb", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ced9ab7e521432aa54d433b32869c21b402d9fb7e009eee6e70e6b0b2100edc4d78a3571dc79279c05ad11214e1d2429e5c764ac366b932bde2493beb71deee1", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "84qIV+GtKNOE6pCikWXafQ==?iv=IH/gXx+bmRGJz6SoM5pkVA==", - "created_at": 1689768426, - "id": "20ccf572dc67d15526c6a2d39115769a37d3a8dfabab54dec30307e2e137d634", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "34409de0e4e1c707d11d352bdbbbfd45eb5be266302ee5b701cd6f3df97ebf88958b011f41f7e1814c70d7716960d9ff611712c1f261c450ea46d084af43ae76", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "5w39JZPqwCg2wYp3fZi5DxJOfGS3ILijznewkli0xa8=?iv=3rXD8vh3AtHVd0RbFVlyRA==", - "created_at": 1689768408, - "id": "d67ff8794bf1e427c29c978a277e547bb8783799d8ba558a789636639fa64d5d", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "cf6ef7ca24fcceeca9095de854e0046098f508d5c4e13e05f283f98ef8b915da1300f6ca3e5929025151b128243980f7c7ed7a3ae958c8c3badb287fba2c0ec9", - "tags": [ - [ - "p", - "672196e844d54702dc5933bf339d53e1b2641a767264384323957f424fd57b04" - ] - ] - }, - { - "content": "Block the app? I am not sure what you mean", - "created_at": 1689766554, - "id": "95709faa74b8a044c55155344768f868035f4a2efaba9fdcafd91620a83c7ad7", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d9348bc5a286dfd6bcabf2e778f85b9aa85a2ce53892951232900dfa964734e9ba4ee6177b4def01c4b8d29478fa228ecee19f474ddbeacee5b5ec80c82787e5", - "tags": [ - [ - "e", - "ab53ded32616980073fc2c9c6ee2e8056ecc5bbd6d46c10a925fd96077a0a574", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b75b9a3131f4263add94ba20beb352a11032684f2dac07a7e1af827c6f3c1505" - ] - ] - }, - { - "content": "Yep, since February.", - "created_at": 1689766494, - "id": "67f9aefdac7e17525dcb9b9a8a4b62e8df734765c71df1b5a653b7e4e871b246", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "02d792d0446f213e8d0624ae50d376552baaeea7be6714aa186b5e2299546cd3e6227ec9e89692963e0ba50b680f7f2e3aa7a663b69e53ec48f96e9977ac7859", - "tags": [ - [ - "e", - "5fbedd48a63ed0a4c8c411b7c4eff4cca22b4430d0c2eabcfa1fdbef25dea8c5", - "", - "root" - ], - [ - "e", - "1b3898f53abd0fa5ad782f8d6175a441e14128d54d65a8ef008468cc5f9123a1", - "", - "reply" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "331dcd701d4785c9ed7f2cbc0d37e72448c810186c9066f16b9c6c69d454df6c" - ] - ] - }, - { - "content": "Over 100k, but downloads is not a good metric to follow. Daily active users from Nostr.band is way better. ", - "created_at": 1689766394, - "id": "9dcca85455abf03edd6812c740d708370077922204a74933548b8c49a5a39f47", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "4e22986a80e3fe0d76f06e70f19be3a1e26b3ad5bb918a750744033c6d7add144ab08532bec52c5edd8f010cc9c114b35ed973ca7f98daf5337c83e8a70c8fa4", - "tags": [ - [ - "e", - "763c8078c7dd051a4a690001664b8dfe984070dd3efacd78846c4cdd2da3d068", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "8dfbea712e6263402297a88613240948231dec9172bee9afe2c82b5af27a72cb" - ], - [ - "r", - "Nostr.band" - ] - ] - }, - { - "content": "What do you mean? I see this note on amethyst just fine. You don't see it? ", - "created_at": 1689765862, - "id": "4289c7852d03444b1075f3ca4dd5cf79ad324ec0cd464144470c9db796918604", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "605e4e0f4389037a02f6dbf16d72b9d616637d5ccf360c1fb40721febe76ac367839816263c20c99c3c4c381c2cb36789784888b7ee1ef780fcbac2e0eda9964", - "tags": [ - [ - "e", - "bbcc50d1d1487dca1ae3791ac651c709d5a0b91b139ed5a54f4a1aa2f077c465", - "", - "reply" - ], - [ - "p", - "74dcec31fd3b8cfd960bc5a35ecbeeb8b9cee8eb81f6e8da4c8067553709248d" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "532d830dffe09c13e75e8b145c825718fc12b0003f61d61e9077721c7fff93cb" - ], - [ - "p", - "564e2192d2c4df33224c15d787cd0172fc8c7e6a7afd67bcc3f8e3447d765981" - ] - ] - }, - { - "content": "", - "created_at": 1689735264, - "id": "568aa3a8feb50e84be9e4eb23e67a1c6caf64477a3f5beed397fd813fb341c51", - "kind": 1065, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c17f12eb3978813697517020585f79ec8f3fb0d40e304d96f04fa187534c9726644782aa2efb38b88cb096f0bdc982836d1d8088ef5a4330deb56f661aca7eae", - "tags": [ - [ - "e", - "2091531f8196ac2334bf5249f0593d25a47516d7b0f05b72f75898a4767105d4" - ], - [ - "m", - "image/jpeg" - ], - [ - "x", - "44746cee88a03743d35757aaf5b3ba178d527b71831387fb6df6b7ff1c1dfed5" - ], - [ - "size", - "70744" - ], - [ - "dim", - "700x787" - ], - [ - "blurhash", - "{bJQs1xtx[M|aKt6bGkB~qkC%MaeM{ozkCj[_3R-xuWBoIofbHay%gxZWWfQj[juWCayJCR+jbj@WVa}kBWBaeWBV@a#kCf6ofayRij?WBj[kCjsj[WBslWBWAj[j]j?bHWBR+fPRjoLWCWCoLWV" - ] - ] - }, - { - "content": "", - "created_at": 1689735142, - "id": "8baf7f4f57b2ccc2959d4013d8ce8984f23ac63fa501fc4779081183a8d1e607", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2e7ff6a7d5e66d20ebcc295965f5a3819d8b0756f100b3fb2a174a6988b8f989d8abfd81afacb607406019144a19830dee5ec0e81d621d93c825b632db2c152b", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_22f927d3b7728cd4a5e4a346fdde6dc8a5572072ffbc25b4.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "b9f569c3cc11bf0bafc96acd2ecbbb947a291ed28c04a109194122ecb16b96ab" - ], - [ - "size", - "4552970" - ] - ] - }, - { - "content": "", - "created_at": 1689734960, - "id": "257b87c845792f00af0850ec6c1c2c303c03c7de5ced8809d18886e731da4e8f", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "08949cd2e8c188fbc65879163fc62b449037a4540c9bdd918a5e0cd505810d61db0a221d84582a24c699f364db7439cb52bea21788370997f666ea580270ff3d", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_8e7b035017ec1de33d2b8566de0f29efa9bca2410efbbe49.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "c660cce3f512e9264baabc00b86f886b1a765507c318604695c2485843ee5568" - ], - [ - "size", - "1534508" - ] - ] - }, - { - "content": "", - "created_at": 1689733717, - "id": "523c5afe1411641ffe583c81e838fb5760ac86f933e731eeed1608ed6e469f2a", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f7eccf6879cd24054f088a317c65fec271c06b7c688ab03524321f02699a92a64384c343b14b4300eb21d04925dbb954b4d5fd929f7edfb2739964670f6ba276", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_16541715a9bcd12306d4f61bd5e039284128edcaafe3043f.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "f383c5b2f585a6a986f062ffc658afab97d3e12496037b336820c2aaedc21708" - ], - [ - "size", - "6121702" - ] - ] - }, - { - "content": "Reviewing a NIP vs writing a NIP.\nhttp://nostrcheck.me/media/vitorpamplona/nostrcheck.me_d1d268a25e132f26352546760b8f0fb22fc3c932760edd18.webp", - "created_at": 1689733437, - "id": "de7fa61fdd2072ad8d6b9e3c90cf970268de48290d24e67c0692c394eca466bf", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7f88ffb115a2ad74d347a336b85f858ba6daeee05262332bfb9eaa0502ffe8bb5631909a6a16a2ff0a70e513c640aef3c4eed8545448fc534dddae5dd374a026", - "tags": [ - [ - "r", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_d1d268a25e132f26352546760b8f0fb22fc3c932760edd18.webp" - ] - ] - }, - { - "content": "", - "created_at": 1689733322, - "id": "f36e5d3ecbb914f4861ff170b8377d571e6395a02d5d5ac7c17bd99e2df78e3b", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "de6ee5365d0e84255bfef9dca800c94c022ed7569d97069c7ef7d562556d3e9a20a852fa86579931f7370e9f85bcd4d24a64e78e64b1348493acfa6c519311df", - "tags": [ - [ - "url", - "https://nostr.build/i/457757ddef7ccc7c4306282d3442f9cc9a977a58773cee39c1d220055ddd07d8.jpg" - ], - [ - "m", - "image/jpeg" - ], - [ - "x", - "5fa74a9024ee9cfff829a4750929591f542fff4d45262bee6e22a241a2f77731" - ], - [ - "size", - "189954" - ], - [ - "dim", - "1170x1524" - ], - [ - "blurhash", - "_7ECI9+t-p%L%2~Bofy=Mx0z9sIoNan*%z~CM~E2NHIWX8%c?Z^%?aawsk%2TeJ9%0-:R-E1ae=|xa%2-pM}Nen$TIkoNYxrxYNHfj-owgxbxbxas:bcNFS1NbE2SgsSIW" - ] - ] - }, - { - "content": "Also, this is a tentative go solidify a single API for all service providers. \n\nhttps://github.com/nostr-protocol/nips/pull/547", - "created_at": 1689729262, - "id": "c3b4f7a5fb5b73b48acd49c00097bd48b334c506f7ba60f7e2f784e3ef6f86ad", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6724905af656ff6a3fce1a4e1003c03283b4a9b34ace65915d55431f84edff612ba7bf1a0bd7eaa301fc11372b8ac14bc94d0950d0c793cd3efc7ad372d6aac3", - "tags": [ - [ - "e", - "0fb88d12f3852b003ab2ef21a0d4be2fa5b1471a347fb979d93ae381014b740a", - "", - "reply" - ], - [ - "p", - "0f22c06eac1002684efcc68f568540e8342d1609d508bcd4312c038e6194f8b6" - ], - [ - "p", - "76c71aae3a491f1d9eec47cba17e229cda4113a0bbb6e6ae1776d7643e29cafa" - ], - [ - "r", - "https://github.com/nostr-protocol/nips/pull/547" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689724634, - "id": "e9c257a0586daf0767e313bb9ba569e432ecf17e3a9a8a7beb81254e29957020", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a66d4cac9ff56f55ff998a665a347485c8e985a6ddbed24dd1405aa3a21291d1ff91ca01b7d2659bf774e5fdf59ad38f17869e1426ed8fe74e53ead866fe25ff", - "tags": [ - [ - "e", - "83a23b4f0584bd4a34c210cbbb5d4dafd03f25b886d0f5f7e5f638139e69d8f7" - ], - [ - "p", - "89d1ce9164f1f172daaa9c784153178cb1dec7912bf55f5dc07e0f1dabe40e6c" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689724333, - "id": "a64c025b82d09bb1fb7d2eeaf810793d880cdd7f3cbb2c4cd30ea13582ca4afa", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e6f16f6dd109d84c54077a705d9e912d1cb2c15fab6b6d12ac434902dffe5dd36cacbb57c760686dd6097c828d93a3ac979b95ef239cb0d42a9041d0cc187234", - "tags": [ - [ - "e", - "473007f975b7e612910adcdb9979e81cc9e3a8a37066c4d03685cc1a8a33928b" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ] - ] - }, - { - "content": "W don't display all notifications. The app only displays it when you are directly cited or when it's a reply to a post you are the author. ", - "created_at": 1689724319, - "id": "c220414cf423280cb3e8f88174a6ee9b8df1b3ede4febe24fbcc1dfdcd0e2208", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9974f8f47a6479bdbf4f2e05bec747a43387a0d9752481ce80a0295c34e96df41b7523ad87ee78e30955f01951ee928ab3fc03a3a586e003932eecd5d8a3c543", - "tags": [ - [ - "e", - "6fd5fce21e31c71d7d27f5cf740f3570b296bde46894eccd5958f234e0e5a820", - "", - "root" - ], - [ - "e", - "bb271e57c3b96c9f7bfbb0e03964c3820d7dc629b46c30899dd11be7af4d4691" - ], - [ - "e", - "497eab572a2cd0716e92e63415b923e7c38f73a1dff0d1cd3216fe1bd51c8787" - ], - [ - "e", - "5e9aa9876a730974ecebef4f52742bd4a9877143146eddc4168424517667307f", - "", - "reply" - ], - [ - "p", - "89d1ce9164f1f172daaa9c784153178cb1dec7912bf55f5dc07e0f1dabe40e6c" - ], - [ - "p", - "180a6d42c7d64f8c3958d9d10dd5a4117eaaacea8e7f980781e9a53136cf5693" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ] - }, - { - "content": "That's because another client is erasing it. We have always saved hashtags in the contact list. It's was never local.", - "created_at": 1689724277, - "id": "eeae5dde847dec45663970e4fc8423ab4c2a372de0badc1730029bcbbaa39f84", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a8be54bde3be1b9170a3df82823822dffd1159a6561a2e2e84619528e212f0bf606c6a2527194506fb0536a598d0681109d63cac9394fd66943bde06392387fe", - "tags": [ - [ - "e", - "2485f76b226cc2489b20509d1042e4e6a7d1e4e1c0b540d1c8da86fc18804937", - "", - "root" - ], - [ - "e", - "46a660a9a9b87f8bcdc8471a61c53e2111537285a78f28ee62c495b539a7bd36" - ], - [ - "e", - "5057914f8a3c8425d6c2160c130a256c343dcd4943eaeb94c3f9bb83f03c19be" - ], - [ - "e", - "c67fe72ec0895e4e5c698ad669bd7b5e13ca936ad120a1dd574a86fc20e618ec", - "", - "reply" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "f0fb31d1810a9f95df3d178fcd67ca0b09879ad11e8689e56962cd839fb8ead4" - ] - ] - }, - { - "content": "Nostr devs are like: I am going to spend 2 hours and make a new app.. why not? ", - "created_at": 1689721709, - "id": "dd4375c77daa2335d53318fa39276b0840651e1e77fce1ed61465698e3af3fb1", - "kind": 1311, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6c109ac0f321b61060241790d85acdfb223b6143038aba381f4eed27a20bf175dd44c779981aa0b1d2897e42d0d145fce4557bcb710726252cfba8054c11072a", - "tags": [ - [ - "a", - "30311:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:1689719669", - "", - "root" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689721672, - "id": "cbbc2beb927c61a157f748d993d87c52fa0f097b5e468f3aa20b5029f5c08dc7", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9e8106799c6812d6ada4ea8db38ab58d978e33d14347cf6b38335a9594de6dfd95bfeea0a447e016c4689ac2528a01c5e79639643026ba41564260d1f69634c5", - "tags": [ - [ - "e", - "c9911b6d35b4c87c53feae668005604ee0e620274322dfec6570dde6fdd68aa0" - ], - [ - "p", - "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322" - ], - [ - "a", - "30311:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:1689719669" - ] - ] - }, - { - "content": "Because everything already is. ", - "created_at": 1689721283, - "id": "173122f70b71b0a057ed6bde5094abbda41540d68c5b1cccbbea5fd428578505", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "e82e5064d89be686f02d55ddf6dd7f3ccc206c154db3f18c9a89cdeb9ab399f15e2551f195db839b67c747ca32fd6362a3e6570dd5acdee4486cdffc992cd0c1", - "tags": [ - [ - "e", - "2485f76b226cc2489b20509d1042e4e6a7d1e4e1c0b540d1c8da86fc18804937", - "", - "root" - ], - [ - "e", - "19aa577d11b0dab38635548fb830f7f3eeb7f4de8c987d2d70d3526e23537c79" - ], - [ - "e", - "f03d390a0416e822a965d83d17ef61c0439979404eb0b0a79080053f64fe16f3", - "", - "reply" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "8e432ad14d3955d0863b975778f0c8817ef88c9f119d626da1a3face584bda73" - ] - ] - }, - { - "content": "https://github.com/nostr-protocol/nips/pull/673", - "created_at": 1689721195, - "id": "baf9d389c6b1e18a1676efd8904e52270198129c1f61dcc3db97e0c8cc49a000", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "73e5b4f28b8989e3aae1e7c31ddbcc43a392ac945186cb98719c9fb05d93e7bb90a5033b2fea99f5b3b9ab19128089b8f85ca0d0865ffda8daad5c81ade8e4a4", - "tags": [ - [ - "e", - "2485f76b226cc2489b20509d1042e4e6a7d1e4e1c0b540d1c8da86fc18804937", - "", - "root" - ], - [ - "e", - "46a660a9a9b87f8bcdc8471a61c53e2111537285a78f28ee62c495b539a7bd36" - ], - [ - "e", - "5057914f8a3c8425d6c2160c130a256c343dcd4943eaeb94c3f9bb83f03c19be" - ], - [ - "e", - "f8881207bfdca139717745ced0e86e0ee20d2e73417f21bb813c6ed151e920dc", - "", - "reply" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "r", - "https://github.com/nostr-protocol/nips/pull/673" - ] - ] - }, - { - "content": "I want to stop doing local settings. Everything should be on Nostr, on relays. ", - "created_at": 1689719485, - "id": "5057914f8a3c8425d6c2160c130a256c343dcd4943eaeb94c3f9bb83f03c19be", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "44a2c6edda25b215cd5187f309d0292bc188607384413bae08625ed6915d73bb95a348119f4a58f991e9bb97a19569c0678eee8599d9339f1e1e21d6d84923e3", - "tags": [ - [ - "e", - "2485f76b226cc2489b20509d1042e4e6a7d1e4e1c0b540d1c8da86fc18804937", - "", - "root" - ], - [ - "e", - "46a660a9a9b87f8bcdc8471a61c53e2111537285a78f28ee62c495b539a7bd36", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ] - ] - }, - { - "content": "Devs, who is using kind:10000 for Mute List instead of a kind:30000 with d tag=\"mute\"? \n\nWe should focus on just one way to do Mute Lists.", - "created_at": 1689719265, - "id": "bab81750570876585535c8ac4a4d5f983ea4cb0675c94882af25b256d60f5a7e", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "646f33f7f4c005d31c73b9687e041e6b49080606a71d789611a5129f9f1025ed6ada39d2ecb31f4f7c8fb50e33f3946ad11aae23d37c0388d964684772f89098", - "tags": [] - }, - { - "content": "Is this a global setup or each list will have their own keywords? ", - "created_at": 1689719025, - "id": "4738396f74638dca62d58a88764ededd2d89748e20f81f4fba574fb1af1a9b40", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "323a7cc7373289a83eca16c3696d37c05d0860539188eec90b931f54f29ae5e1ca7b6b561dffd4d1b65f5038dd0adab5af21063047667def894e72e9d0d35dcd", - "tags": [ - [ - "e", - "2485f76b226cc2489b20509d1042e4e6a7d1e4e1c0b540d1c8da86fc18804937", - "", - "root" - ], - [ - "e", - "25c76135357f79245f401168ee01aecb748c7434d8f12c3627a02fa41dd2d15f", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "d0aa74cd95a651d3d2ab4fb18b58fe71b447d78d40f8dd46f1dbaed5603d35cd" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ] - ] - }, - { - "content": "I meant on Nostr. Which NIP? ", - "created_at": 1689718940, - "id": "25c76135357f79245f401168ee01aecb748c7434d8f12c3627a02fa41dd2d15f", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a39d29dd625e2af0a636a09fca8047ea6abbeee9258713db413a9f975953ca625448878cd0db49db15bc6aa54e2df67aa8a72ba2b0f2dbdf44229bd4a3e7bdd6", - "tags": [ - [ - "e", - "2485f76b226cc2489b20509d1042e4e6a7d1e4e1c0b540d1c8da86fc18804937", - "", - "root" - ], - [ - "e", - "6e8e7ab0fc769cf059fbc93c40d7007bd8847a80433cd8e68c15be45bf1594bd", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "d0aa74cd95a651d3d2ab4fb18b58fe71b447d78d40f8dd46f1dbaed5603d35cd" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ], - [ - "p", - "d0aa74cd95a651d3d2ab4fb18b58fe71b447d78d40f8dd46f1dbaed5603d35cd" - ] - ] - }, - { - "content": "NIP-53 doesn't have direct invites though. I am very confused about what the invites are doing. Is this like join me now if you can, kind of invite? What happens if they reply yes? ", - "created_at": 1689718906, - "id": "6aae65ba6f84596984069e914b441bb2e29fd031c63a1e3647754c70a49576ad", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "680e70e6d5a2786349fd566cebb3f5678545854e7cb890bfe5ff68c8b374640acc04989e1285b27eb152ca765e938e8b0b39e8d3fb745857fcaf3c125da0ed68", - "tags": [ - [ - "e", - "8a7780984986beef1406caf4139a338349f8d194725eff881157cdc6e69cb983", - "", - "root" - ], - [ - "e", - "573cb50aa1485d3c41ae7324b6c5d469a979bed956417e6bc3d95825c61fe5ff", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "b8beebaac1fea45e8907a52b6d6a57707328276f2f000719de1cbe20b3b9fe80" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "deab79dafa1c2be4b4a6d3aca1357b6caa0b744bf46ad529a5ae464288579e68" - ], - [ - "p", - "2779f3d9f42c7dee17f0e6bcdcf89a8f9d592d19e3b1bbd27ef1cffd1a7f98d1" - ] - ] - }, - { - "content": "nostr:npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc 's Facebook Marketplace NIP was merged! 🚀\n\nhttps://github.com/nostr-protocol/nips/blob/master/99.md\n", - "created_at": 1689715846, - "id": "d7c2b6093d9dfa3f452b871da8b3290a42159db6cd084ff17bcd6c6e25fc2a06", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "90b8a3d9f17ba803b7b2e188a6acad31cda7179dbd9ba6fd13cc9a600d32b9330999d5718c5d34f7823457c2dba964ee46ba7dc34615b4820544d753283ea7d4", - "tags": [ - [ - "p", - "1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef" - ] - ] - }, - { - "content": "It has been on my todo-list for ages. I am not sure where to save it thought. ", - "created_at": 1689710487, - "id": "67cf4b517fb8cf8cde6ff822500fcfa7fde11d0677e8096b7f98f38b6c1dcd1e", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a6689c8dab94bf784a18ecaad285c74ef4332cf098eae040c092a1c05054b1479afe5bf066ec76d9eb0f8c86b2274d1688196ed9d7e5c01c68f89b6bd0b5ed84", - "tags": [ - [ - "e", - "2485f76b226cc2489b20509d1042e4e6a7d1e4e1c0b540d1c8da86fc18804937", - "", - "reply" - ], - [ - "p", - "9267545d2917b80f707ffdb44a8ff979182568ef7baa04ee756b1f01d4e3688a" - ] - ] - }, - { - "content": "I would guess they are requiring users to have a 'user' attribute such as a contact list or a user metadata kind set up. ", - "created_at": 1689710282, - "id": "69aa2f252f0d51e76147257b84866c237f4d05b6eeff41c12e22f717906268dc", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "461eb497159cc49ed2e44fe524e7f3658aa4ea561d9f74c13187f4fb2efa9ce4852c717cc057b85d1060044e69de294f5b8d4e174f1935d4d931d96344b07445", - "tags": [ - [ - "e", - "08f4c8cbe5cba4bc0c68863eabf8aa7c6ad22be19398cfd6ae137f541454a9b8", - "", - "root" - ], - [ - "e", - "fb96d54dcf8128f0ddd8994d53b81fff998e80043b45f15db257265df4d5dc23", - "wss://nostr.bitcoiner.social/", - "reply" - ], - [ - "p", - "43a22be283a77d24a3fa218e063e782da195d1adb0edd528b88ac9ba1bebcdfe" - ], - [ - "p", - "8a9402c71384dd0a387d3def483b8f89736fdfe26bc28276671820af942cca7e" - ], - [ - "p", - "532d830dffe09c13e75e8b145c825718fc12b0003f61d61e9077721c7fff93cb" - ] - ] - }, - { - "content": "https://github.com/nostr-protocol/nips/pull/597", - "created_at": 1689699142, - "id": "5571cc3a41f0cc0a36c38711307cefdb30504cf851e1328a2b4f852c29a0fa7d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2ce8c864668bb4c1b63a88727e796a870cb8498b20307a40a735fcc30e2759f93d73a96cddf95d9599316e9fcbc060938f87868a972f00fcc6bd24c2494bf44c", - "tags": [ - [ - "e", - "8a7780984986beef1406caf4139a338349f8d194725eff881157cdc6e69cb983", - "", - "root" - ], - [ - "e", - "3c4c22b112912148bfcb2e65ba02a200cb3363d4be8d1bdd77c5e2bf43b9a065" - ], - [ - "e", - "2c592975b96913fe5a856a67b41dff42e70fdfdb72922c86fdc59f31704e9c0b", - "", - "reply" - ], - [ - "p", - "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "deab79dafa1c2be4b4a6d3aca1357b6caa0b744bf46ad529a5ae464288579e68" - ], - [ - "p", - "b8beebaac1fea45e8907a52b6d6a57707328276f2f000719de1cbe20b3b9fe80" - ], - [ - "r", - "https://github.com/nostr-protocol/nips/pull/597" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689699060, - "id": "c43ff35ea35d8d58089e68ed52cf9fd6dfaf5f9e25f475aeb88a807818d58812", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fd8b3a15b4dabbde2dbbce1b1dbf3fa81bbc52c653b4473afee0498e1253379c094086a13d2c0e0a3c074b33a752c8faa22caf8faf0e403e64dd027a07228a4f", - "tags": [ - [ - "e", - "9909236b03e8581c67fa93a0409efa71638bda585943b0a1abad59a6196d3255" - ], - [ - "p", - "7ab1d3867722b4cbabb6c8503ab3f9265daa4f82e228cefe302621f4e5ee1f1c" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689699028, - "id": "20a5feb4699b42f94c0ef86f698d4b39dba306ffaf1a296de086185b21bc008e", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "f6856444b7ca2df1d3f8b20791b2068ed670c925f0be05c01444d4cd56a60925a35f0114a26ad54fc9799a4c0ec6390cae58755e56fafd47e923e75a6c84e720", - "tags": [ - [ - "e", - "f1dbc22d6c52e9ab63cdbd7ae563b317f00c6206aa7e378965e432b1928ae36c" - ], - [ - "p", - "3493a605e9c26c31ebe1d86a20f96082c4f584d6fde3cf98b9afc2d783ffc952" - ] - ] - }, - { - "content": "2 possible issues: \n- if you were using private bookmarks, some clients do not support it and might have erased that info. \n- if your relays failed to provide a bookmark record before you decided to add another post into it, the app will start a fresh list for you, erasing what was done before. ", - "created_at": 1689698818, - "id": "f50b94d7b1c87b7c9a022a6ea8815f5ae94aace648f1b8f154606d011e14e3a9", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "6054a616397ebb2331804aad0eefd7763354bc2a3900d33a6325bd23d38f5d53d30c1b6f244c4935e232302f5a542df2f9a3b41b0bc36d091081ae386a3810e9", - "tags": [ - [ - "e", - "a43fdf0ef52cb242995bf8d173fb5a8c4f308cb07dd2a6b627a5816e929b1f23", - "", - "root" - ], - [ - "e", - "9de05c2edd1d5221dc8428cde09467dda4dfb84a0431015b65cf8ceb347a3d7a", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "880b21ccbe2e079c9ac5a5d14314ce5d47adbfe6cd5c00116e75f472d9a3f910" - ] - ] - }, - { - "content": "Groups of people? Use highlighter.com or listr.lol for now", - "created_at": 1689683437, - "id": "51868a97d597d756d01f3bd54d73946783b6cc217faca7ab288cd0b2769146e7", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8bbfe64b5b37a07415f20b90703e7973578ae7213ed8b8eca6b080160ce426d1e6c3abd9c8d5f9440f3cbb9ee6456f6fda0f239c5c01002dfe777108c5b4106e", - "tags": [ - [ - "e", - "b220fa47738212e6935be76b73fb6a6124948113cda700c04dd349641e86c3fa", - "", - "reply" - ], - [ - "p", - "0d97beae567fcec9c6574f1c6ef6126ea969d4992c3198e51c0fac52c5274a14" - ], - [ - "r", - "highlighter.com" - ], - [ - "r", - "listr.lol" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689677043, - "id": "f5b58d047aef44426bd06c0862b0258668ba9ff48f007269c24ee955d9d927e3", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "93f58aaf7438b0e630fdbcbfce5df066a2ab8a7fee3351a10fce01b9b100fc48f03d9111337491fe917a96ee677e76930d59e42828c6598244be0a990d6cc10b", - "tags": [ - [ - "e", - "8c1360284291b9602f1ed196fc221b7b4349f8be31795f7161c931fbc4c0b264" - ], - [ - "p", - "18affadacb471657941485d8e3053e2be0daa95aa42f9c6f8680d62c758a9ab3" - ] - ] - }, - { - "content": "170,000 lines of code for a video player alone is the answer 😁😅", - "created_at": 1689676994, - "id": "8c05e5903746a676c53f5951af60b204aa74f7ac034bf0f042624c34d4fba0d3", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ffa6d381a1f5a5b578bf031feb5421ab2c5c9922b13b53a4a28a78e36ec022647ea8584431fdeb1b50872284226b9e1875ff566920096153e2771871d64fa1be", - "tags": [ - [ - "e", - "b3bcf12483811024e77cb1575b4345b88549fe0ee6a26df942c16547b34d7f36", - "", - "root" - ], - [ - "e", - "edf021fc9290fc7f7fe3bcd5c33904536a1710b6a525a33e696723fffb887627" - ], - [ - "e", - "2dce8555ed1824e129910aa57301771a0c1aba3d0f6b5529efcecd0a3f031e2a" - ], - [ - "e", - "8b4b4b56bb850a32efe4f45e68fd84d0ae2d5183062f507c6c68aecbaab29d28", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b8ef68a3073dae2a78a02e1d5921013bffbc82aa5039f77b6f7434512cc65de7" - ] - ] - }, - { - "content": "The relay architecture is terrible for curation. That's why relay-centric browsing is broken. ", - "created_at": 1689676644, - "id": "96f7ebeec77ef2945527c777c9eb0143cdee0a634461a0b52131396c0635650d", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7b75d01573bfee59f38469f410ec13f24155d87f913b26a88824af57f5f8b4b6fc87202558d167facc818a73f9286644075fd9474b84ea78382322085d23b04d", - "tags": [ - [ - "e", - "0133b5466212bcf7200ac43448cd44c996d09ec89eec785061637987f9e423de", - "", - "reply" - ], - [ - "p", - "1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411" - ] - ] - }, - { - "content": "No idea", - "created_at": 1689676119, - "id": "2dce8555ed1824e129910aa57301771a0c1aba3d0f6b5529efcecd0a3f031e2a", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1af2fb3bc6acc1a56ba42a6c0a6db9c4921ac399552de26d03128c69bd7e99b22b769cc2e309c95f7553282715dd2c8640fed3f04f160a1fb68feef83d3c3cbc", - "tags": [ - [ - "e", - "b3bcf12483811024e77cb1575b4345b88549fe0ee6a26df942c16547b34d7f36", - "", - "root" - ], - [ - "e", - "edf021fc9290fc7f7fe3bcd5c33904536a1710b6a525a33e696723fffb887627", - "", - "reply" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "b8ef68a3073dae2a78a02e1d5921013bffbc82aa5039f77b6f7434512cc65de7" - ] - ] - }, - { - "content": "{\"content\":\"Introducing Minibits Wallet for Android – a new Cashu mobile wallet with focus on performance and usability! \\n\\nMinibits aims to make ecash UX less technical.\\n\\nSign up for testing at https://minibits.cash or get one of the alpha releases on the GitHub repository! \\n\\nThis is still at a research stage, read the warnings before use. Please provide feedback and report bugs!\\n\\nhttps://github.com/minibits-cash/minibits_wallet\\nhttps://void.cat/d/SzRmh2jNzHKgKvKQb7bETV.webp\",\"created_at\":1689675049,\"id\":\"eff1e425d2790ec703bacb0373b067499edf24174b845ac1fb9172987552945b\",\"kind\":1,\"pubkey\":\"50d94fc2d8580c682b071a542f8b1e31a200b0508bab95a33bef0855df281d63\",\"sig\":\"1d868c7ec460c110b6861dadfcc6506e3edf9887bd1c5d3e40f35acbed10b9c6f6ca868c69cd6c9582665ffc05c73bd70905a92e26143c77f1a7ef121ccbfb1e\",\"tags\":[]}", - "created_at": 1689676096, - "id": "c2c56a4f0afb483d2e6d9bcacf5662a8b3de06db891a30c1da2f6e91114aa256", - "kind": 6, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "2da6d302cc4d8a0072573dc1ab4919d0e79c747b45f52b41f67e001a3e865aab0ada32348324adf490ef86e541b3497857d44eb8c74c2ff8212e8e3299b84438", - "tags": [ - [ - "e", - "eff1e425d2790ec703bacb0373b067499edf24174b845ac1fb9172987552945b" - ], - [ - "p", - "50d94fc2d8580c682b071a542f8b1e31a200b0508bab95a33bef0855df281d63" - ] - ] - }, - { - "content": "Possible? Sure. I am not sure if it's desirable. No one likes these translations services that require all your messages to get sent to a server. It would be a lot better if they created a local model to translate in-device like the Play version does. ", - "created_at": 1689676003, - "id": "855a4de95fc1bce83a4da7c28fe823365162a1413503cfbca9cbe322269b07ba", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "16566000229b6a4cb882f5337d0f6ac5513f80345c72f165739f6e058bdec9e9a34d24755f85111ae76f6e5b71c65b4adc669314ed8d1ac7d3af7868eafc6e66", - "tags": [ - [ - "e", - "305284085aa2e647f5f8ac0da34a3898674c10087c4d7a9653d5292d97585a4c", - "", - "root" - ], - [ - "e", - "4d1ce28ed36892e1c3892c05c36a49fadc00a628f194c99e88dd4f2d54e89024" - ], - [ - "e", - "f7f0a6cd0833758383e74399a6f92cef9cc0ffab1243562125d27a283a369b22" - ], - [ - "e", - "996566ec7df1d641e8842673c0b798626e31b8a60c6045e83d07e8c48d4ef948", - "", - "reply" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ba31f050a66d6aee73fb258405a44fcffa662e24784e6650944f8fc2d3089427" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689675731, - "id": "808dd71e183d66fbb206ba02bd8f7167e3192851091e70daa4fb691c69a7d4d6", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "94b58286c108e74b1c3428d7a1c6453c2f27e76a34400af9dcc4afd5f8af863d066e4e6bad885499cfd72c6fc6f10f19bbbb683e8ab4caf8cd2d9dd3524509a1", - "tags": [ - [ - "e", - "f75a1684c2982ce450bbfd1c6e6eeee3aac0d9c57e3a542e2d038f28e54fd2da" - ], - [ - "p", - "18affadacb471657941485d8e3053e2be0daa95aa42f9c6f8680d62c758a9ab3" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689675726, - "id": "7bd385d259bbf9d331eb4e1ca9ca78ef0d7ea1bb43d44daf2e2029d4c575014e", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d5801e6e34971ef41ae34dd1e714823ce8096dcc84f88ad566fd4abf9ffb5eeca82ef8152a88945cb7ec3ba9ffe50a7e21595b2d04daa6b88b586a3bdb790b6f", - "tags": [ - [ - "e", - "536959c20e829ddd2516afa9774c22c332cdb335770d363201f547b9918e1cf7" - ], - [ - "p", - "18affadacb471657941485d8e3053e2be0daa95aa42f9c6f8680d62c758a9ab3" - ] - ] - }, - { - "content": "GM, freaks. \n\nnostr:nevent1qqsy9u6jkzy4pa4ktcmrnhwa33uqqkyk6yugjgrkqcrefwlsewxly2cpz4mhxue69uhhyetvv9ujuerpd46hxtnfduhsygytpg474ahta7f9arnclrc2mfql0zvt3knj4zt3hzvc30mc2lfknupsgqqqqqqss5qlwl", - "created_at": 1689675330, - "id": "a6c102acb21bc9229f23722b4f1d55232c91901b1710be8a4a7c71c9ea128c16", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "a6444849124e0bd3479620c2102c1d6defb81852ef3c2118296452b5370901591b02102f5c148005ac8b69ba4fd86d106cc8673306c3a89150a09ca8b4feb790", - "tags": [ - [ - "e", - "42f352b08950f6b65e3639dddd8c78005896d138892076060794bbf0cb8df22b", - "", - "mention" - ], - [ - "p", - "8b0a2beaf6ebef925e8e78f8f0ada41f7898b8da72a8971b89988bf7857d369f", - "", - "mention" - ] - ] - }, - { - "content": "No, only on the Play version ", - "created_at": 1689674872, - "id": "f7f0a6cd0833758383e74399a6f92cef9cc0ffab1243562125d27a283a369b22", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "1ba2852e22e55b216ab87c5e2e2b3edc62accf811b033a51d2e4ce79bd015e517d909785db81220d9825c88e976e47498053c9d2995d26a09c9d3e82e6e0a944", - "tags": [ - [ - "e", - "305284085aa2e647f5f8ac0da34a3898674c10087c4d7a9653d5292d97585a4c", - "", - "root" - ], - [ - "e", - "4d1ce28ed36892e1c3892c05c36a49fadc00a628f194c99e88dd4f2d54e89024", - "", - "reply" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ], - [ - "p", - "ba31f050a66d6aee73fb258405a44fcffa662e24784e6650944f8fc2d3089427" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689674801, - "id": "b79a18aecbb705999848e430aa48ca8e4a02f205baf0abf1893ad78be5bd097a", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "8ff23133abaea20df1a6bb81e4d0c17184b10ef4a61c1d9420409b05a155b1765aba40ed409dafca1f1404a70d13f47b8c17b7192c361dd3552f80c3fb40117c", - "tags": [ - [ - "e", - "70526f1c71a579e9a7d0ca60f0c32ddcaa2fb0588e5ccc854ffd5eb706913c1c" - ], - [ - "p", - "d651b0cc52fe150819266fd62efb79e3f859161b33fc054ba98e43537e4a9601" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689674786, - "id": "9e44d17fb36c23f8122dcd1a052db0df8b77e67524efab0500b3bfee490fb150", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "52ea3aad9c774be769bd6129aaadba7cff8cf06a573887d2c64f6f4c1c04c7ffa54e2d2dfa60a2323d06cd57b9034a2db1991fbbaad331b8981542ef739ca8a6", - "tags": [ - [ - "e", - "88377d4a0fb02c73c8c9a9ec0c90d29ebe80c30e7e0dd357bd9fdc34719b467f" - ], - [ - "p", - "b2833792cd5c95662538e620fed371728e90671b9d6bdefebe8f706c1f1a04da" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689674730, - "id": "9cdd27028fa23568917ccee7fe7f1de15b43504e006515f7a0cb124075263b18", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b6261ca964542f01cb714f5089147e316cb30ae016bfa76462840f41c645f6f8e115998b4221a33ee78c025c78f0a3b3dc2961713640e561dce76e7bcea388c4", - "tags": [ - [ - "e", - "f637d77cf787a9f772b7926f9752fa5c2eed3e21e10c41f2e8ca0f7addf08821" - ], - [ - "p", - "b2833792cd5c95662538e620fed371728e90671b9d6bdefebe8f706c1f1a04da" - ] - ] - }, - { - "content": "🚀", - "created_at": 1689674506, - "id": "6714667912c344a403c50998ee0c3dcdc66b03174625525a838acf4ba99610e8", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0394f188cb33d3c177e384a639deb8992cc8d0fb94600b9176439b7e02ca4dd77f6e1e706bb18e03d542a2b02db6309c2f09bcce194de2342c1108196134ae88", - "tags": [ - [ - "e", - "2744bfaea2c88d8e1337f635f0e57e14d4ee44d69c67e630c9d15f1eeb86c822" - ], - [ - "p", - "98d3b91eb93faad55a2a43ee21d71262f793f4de3db9a5d7710970ba8a251881" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689674497, - "id": "d9af4d5f22a2989278ab2a5e8eb4310bfc8cf3ebb2331d5df74dadedd1beddcb", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "989b263e6f46c5b55cd56a78d3c38b6fb7d66033826d89b61696965e6ac584f7a487ea294612ca0ec256e64c22790e1c7b47e75ad1e6651c54bbe9122eea21e9", - "tags": [ - [ - "e", - "cdc0cd6cdf63c223ba85ddd0612ee3aa6b8a6e222d901c6389e54a9af7d72eb3" - ], - [ - "p", - "7635328aeba6447da86a1b6cd0608232718c045454861fc9e98f432eed66e812" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689674432, - "id": "3069edc36af6612cf734f943ae1fde2dda8bfd6c9ae90e92655fd4f6502280c6", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "0503f95c23a2aa99d0bc3bae631767ea08d64d161ec2a4609c6a0cc3f27b10b2c663442095458e9c59ad90942cf841f37018a33b44dbfc089a85db2397cf5996", - "tags": [ - [ - "e", - "c576696bb51e39aa44e3ca8ecc089ac760f5771961b5d689870f355876c0a12c" - ], - [ - "p", - "31da8e96a0d372f657280a3b678c5c8398b053d0891d458b7c8b0a752737a9e0" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689674426, - "id": "0bff08abd0c2d42180c7ab81b4605c46dd425d9a6aaa46796bae9e52b196d929", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "3df849993210969fe921274e42bc85dc7401993095bb6ddaa4441f85c08b29220e9851f5cb65c023f5163d55b3c142ec15a0b5464b68f618a73ac9e9fdb6804c", - "tags": [ - [ - "e", - "641ddd94ba362703b7d62819b0188d548837740eb7448a05390da2829c7ba11d" - ], - [ - "p", - "180a6d42c7d64f8c3958d9d10dd5a4117eaaacea8e7f980781e9a53136cf5693" - ] - ] - }, - { - "content": "🤙", - "created_at": 1689674423, - "id": "0daf05f8c55e150201937e621cdec9405b9e81f2305165ed36a5558321a581ad", - "kind": 7, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "ef61781ea0683789dadbe55c8448069ad3b95dd7fce6b174b91e0461d29a2d8c83dbc26e17d0ab686e389cf6850d5dc696a344da374861d84a66cf33a29fff2f", - "tags": [ - [ - "e", - "31ccd562c205061d6052946e7125a48c24a371a9459403d3b8fbb58c4c2d52bb" - ], - [ - "p", - "1b9d72d38b422a09cefed126e88f82361d4b1cc11cd19a2fc04e17b00b0c7d15" - ] - ] - }, - { - "content": "", - "created_at": 1689671952, - "id": "29f243eded2b46d7e96facb9bdd51e1a01a759ff5bf80f816e22c34b8fc6d89a", - "kind": 1984, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "082154083f66095ec70b8ae15ebd113e6ee57011b5e1c2d3adaad4fcc9612859e173c364eaf7ba2167387669555497b567b21ddc355cc4105f03f7ed67a0bcf5", - "tags": [ - [ - "p", - "5c070d057298297ff0dd72779a4126efd30c743907371cc9e44bb54861dc3fc9", - "nudity" - ] - ] - }, - { - "content": "", - "created_at": 1689647540, - "id": "01f9c880cff98ef2bbc3348f904be5817bc00a64ee4afb90ed357e3232ff75eb", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "df6eff31de9fb678dee844ce1334802e4578b049b7e4f3a5abf187303ab7acacd0de63f9e6c8ed5cd70a42b43a30c29aeee7fda28377b50677c702e58e156fa1", - "tags": [ - [ - "url", - "https://nostr.build/av/01b69af390dac66fab819c17d93de7b2c9e070f13f444d3a1a4db6cb785222d9.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "01b69af390dac66fab819c17d93de7b2c9e070f13f444d3a1a4db6cb785222d9" - ], - [ - "size", - "1099399" - ] - ] - }, - { - "content": "", - "created_at": 1689647463, - "id": "846a0bd2419f5faf68587a544dd8ad1302675f28c3643938e51377b855581739", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9dd403c8f62393c03a3194cfb25ff444197ee2fc1de46e0c0c8664f65a939846add90d768e6bc0380147d39b44e5600f68cd7102910bd96313df10ccec3b4f13", - "tags": [ - [ - "url", - "https://nostr.build/av/a921fefb2485ca7a2f93121b6eef1f868133eff1931a99e3c847bec96bb45df0.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "a921fefb2485ca7a2f93121b6eef1f868133eff1931a99e3c847bec96bb45df0" - ], - [ - "size", - "189820" - ] - ] - }, - { - "content": "", - "created_at": 1689647421, - "id": "e2a3d9b37e0d6d98bbd8b36a26e8825aa67a5328ebf745dd9f7239fea69d97f5", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "7502e7527cf42b647dfc936e399f44e8ca97943cf659b4d98ce541328b90520e28084fd62e13044478845de9b1f45af1b1c813e434dbaa692004f7f3a9cc1196", - "tags": [ - [ - "url", - "https://nostr.build/av/c32f2572a8f23053590a69cbdfa0cb1463a9c6d874dfbc745c2929d69da62ddf.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "c32f2572a8f23053590a69cbdfa0cb1463a9c6d874dfbc745c2929d69da62ddf" - ], - [ - "size", - "999370" - ] - ] - }, - { - "content": "", - "created_at": 1689646963, - "id": "3c7e59dcf0b5b682d1983306c92e6173b1247fca0419d837cf912933f670a148", - "kind": 1065, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "129cdc94b7cfc8b034731c0c93fb28cad71f96c489358ea63be5431ebbd0d5b78f813ea9430dfffa46e848ae2f524289d149951c9ad47188200d8da54f759aca", - "tags": [ - [ - "e", - "ad8095ae59d8202718df0cea762210513957e56ca13896b19793f167c2252494" - ], - [ - "m", - "image/jpeg" - ], - [ - "x", - "27685303c3efe890e7995959baa3c9c3fd46146801a61fec5039100dba0f659f" - ], - [ - "size", - "99764" - ], - [ - "dim", - "700x700" - ], - [ - "blurhash", - "U8RC[6-;~q-;-;j[WBWB-;ayWBay-:WBj[ay" - ] - ] - }, - { - "content": "One of our most important features. \n\nnostr:nevent1qqsqkc2nessaxmj3ak7jcvx8c3wa9h0xd34m6zctt4gg5cflyaa3afsprdmhxue69uhhyetvv9ujummjv9hxwetsd9kxctnyv4mz7q3qkmsnnxw6p8vlk2l2dh0443jkj0txl7jrww8qpx4vd428he0a8jqqxpqqqqqqz344mdr", - "created_at": 1689646713, - "id": "305284085aa2e647f5f8ac0da34a3898674c10087c4d7a9653d5292d97585a4c", - "kind": 1, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "cb0c8d9d2a800b445fd0091ac8e0d90eec909c626447b54357a66db89a4e68a2786e81fa69afe0b3c6ef1d32b42134d8acc3d0c3dc3b4aa4554931dbf2d4fcd8", - "tags": [ - [ - "e", - "0b6153cc21d36e51edbd2c30c7c45dd2dde66c6bbd0b0b5d508a613f277b1ea6", - "", - "mention" - ], - [ - "p", - "b6e13999da09d9fb2bea6ddf5ac65693d66ffa43738e009aac6d547be5fd3c80", - "", - "mention" - ] - ] - }, - { - "content": "", - "created_at": 1689645973, - "id": "fcfbcc09a29bccfacc30648f2896e98a743fe53b9575c2b74e22ef27132b418f", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "9afb7d2d297b056c6ee3ec07640158d89b736e98711caf65d9af0c102d5edae9f967d9138e9318c1ab5e26640527b0826bee942c631990e41cb303401317e440", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_037bcb8edf70a9558ac91aa3fe682d52629fc5d104a560a4.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "c213bc58d4976a10ad979803510c0354b35bbb4388c127513179862f513bc49c" - ], - [ - "size", - "634647" - ] - ] - }, - { - "content": "", - "created_at": 1689645460, - "id": "fe0e0f2ee6955b49c6b669e7a837a89c8f62bacb3c965659acfa2cc62a1aa432", - "kind": 1065, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "11225b4d9c32b97ab6be603f424304e022c92b1ecc8fc2398b93f8e1e1b407c7fc43fa02662d1d992dfff73801df36aca8c0f855bded7e409df6306acfdb6865", - "tags": [ - [ - "e", - "763298a22775bf8dcc7bd53a680c013772ca89684ebd7bcefc7893ccfae55418" - ], - [ - "m", - "image/jpeg" - ], - [ - "x", - "aa0c52d9b8a1ea1d8f13a8a7ce5347d54ae9498d4596720cc9a6a2d107a384ef" - ], - [ - "size", - "19585" - ], - [ - "dim", - "700x439" - ], - [ - "blurhash", - "rcQJ$X=]$~M}xXNHj@NHt59dt6%1s:fPRka}WXoexsRlj[t6WDfkazoeWC%0t6RlNHoes:oeayj[~9IqIpocRlt6fRt5R+^hIWM|ocRkoea|s.R+" - ] - ] - }, - { - "content": "", - "created_at": 1689644892, - "id": "cf1c11434611087cf4067cecac3d3cbf3a4c9cb3ab7d0d2ecda568f09922446c", - "kind": 1063, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "d9fe14a564778961e829343e5532af5d02ee22c74229ccb162252a1f22819d13ebf3c71911acbc9dba42a1cba53d83c4bf5cb7b47967ed20fb1db0b988b4a314", - "tags": [ - [ - "url", - "http://nostrcheck.me/media/vitorpamplona/nostrcheck.me_23d68bdbf34b80739e049afca249e8b1657865d97add8530.mp4" - ], - [ - "m", - "video/mp4" - ], - [ - "x", - "aabd46855472a53dbf4b53fe1a635e21866846a13f4dc3f64db1ea9f753994fb" - ], - [ - "size", - "1839932" - ] - ] - }, - { - "content": "FdG8mzOV58zqAkp7Qxv0WLTmWFvQloax9jYy974bV40=?iv=d4w5JdfkhAMEl41xUDZx7w==", - "created_at": 1689637676, - "id": "663d4a5985e3cad8f67eb65ad0e00d173caf765175cb55603694bb423a4cdfe2", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "fbc5da1ce36dcd903874429230297028ae7864dadf0c709a1308a837e14e8a79663646189f9a6448d7d27af318fcc2b7fdd51d252240935cdcdff301a179570d", - "tags": [ - [ - "p", - "8fb140b4e8ddef97ce4b821d247278a1a4353362623f64021484b372f948000c" - ] - ] - }, - { - "content": "o2Mg9Aje0jyl7nuUseRxsg==?iv=to7+pWNFngqM+mwIPy5AdQ==", - "created_at": 1689637614, - "id": "db71590c17eecf3119d78cbb5859dc3406be14854f65cdbb8bdccaa3d2a5df0f", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b19739ccf233092f79aa739deb09cbce4c3657f709692c9c8ab95f354dcfbace3f6e3e6aec440902b6bb1aec0f77dbb9b39733159ebc9feee3999b588488e91c", - "tags": [ - [ - "p", - "8fb140b4e8ddef97ce4b821d247278a1a4353362623f64021484b372f948000c" - ] - ] - }, - { - "content": "3uVnxDkGt4xxFs7zdSPpdxDR33Q2FJWqsnPPu4IDoP0thesChUq4DsYBidQ9iIh7?iv=KnNpoML3YnkaGI/DnD6CxQ==", - "created_at": 1689637180, - "id": "28f3ddb0d16d4a752c73dc7531c2d221d3689035e8695fdde111cd122edf5831", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "c1b26f20a66f2cf91caa9159fabf9ee17f1b98d98a250e6c67971763e38690ef013b1a81eceee504e85e99b8ea9747e89a35fa3a7207daef51a0d768df8f9458", - "tags": [ - [ - "p", - "8fb140b4e8ddef97ce4b821d247278a1a4353362623f64021484b372f948000c" - ] - ] - }, - { - "content": "Cwn68+FXCmX4W6qSl1eNiTbmn1vTeAHF25GpMBMid5Mg9x1BazZvpbT/k3/TgHS8W502zcYqCeyVhVPfPU87fQ==?iv=5/HJRrixXfJtO7/n8bDYZw==", - "created_at": 1689637166, - "id": "fa1b6d36c3194a2d7779f9d52c00f534fb0f389955da59edd1f5f9bac99c97d0", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "b48844f9754c36ab4e9469fcd70350a165ab631c740a2f285f62790a1cda8804f2b87da09c3ff9df755234a8bf3e12aae60c0b0461057680a3620531e499171e", - "tags": [ - [ - "p", - "8fb140b4e8ddef97ce4b821d247278a1a4353362623f64021484b372f948000c" - ] - ] - }, - { - "content": "+q5Stn5eAtTfm/ULw2SkApBV1gqztggFhMwa0OjCBx3syNt/asVFpoPqxguGd9QQErTTDIFDoHAiCX5vEIh6YQ==?iv=Cj00Q8hQLpbHfVh1hQb1oA==", - "created_at": 1689637117, - "id": "30d057504b23277b8b9d8654e46f2a66a3adcbd194706c9c37ce4864763b3d74", - "kind": 4, - "pubkey": "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "sig": "dcf3aec8217171253ab614be7cffc239f5767a0d9cd6bd396af6665016c7ed77263f446e1c8f5e10ed60cc81bc78c8ff4b908a2908df5a90ed210bd69784469a", - "tags": [ - [ - "p", - "8fb140b4e8ddef97ce4b821d247278a1a4353362623f64021484b372f948000c" - ] - ] - } -] \ No newline at end of file diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/ChatroomKeyTest.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/ChatroomKeyTest.kt deleted file mode 100644 index 8b234a64..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/ChatroomKeyTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.vitorpamplona.quartz - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.vitorpamplona.quartz.events.ChatroomKey -import kotlinx.collections.immutable.persistentSetOf -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class ChatroomKeyTest { - @Test - fun testEquals() { - val k1 = ChatroomKey(persistentSetOf("Key1", "Key2")) - val k2 = ChatroomKey(persistentSetOf("Key1", "Key2")) - - assertEquals(k1, k2) - assertEquals(k1.hashCode(), k2.hashCode()) - } -} diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/CitationTests.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/CitationTests.kt deleted file mode 100644 index 0ecd801b..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/CitationTests.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.vitorpamplona.quartz - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.vitorpamplona.quartz.events.Event -import com.vitorpamplona.quartz.events.TextNoteEvent -import junit.framework.TestCase.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class CitationTests { - val json = """ - { - "content": "Astral:\n\nhttps://void.cat/d/A5Fba5B1bcxwEmeyoD9nBs.webp\n\nIris:\n\nhttps://void.cat/d/44hTcVvhRps6xYYs99QsqA.webp\n\nSnort:\n\nhttps://void.cat/d/4nJD5TRePuQChM5tzteYbU.webp\n\nAmethyst agrees with Astral which I suspect are both wrong. nostr:npub13sx6fp3pxq5rl70x0kyfmunyzaa9pzt5utltjm0p8xqyafndv95q3saapa nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49 nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk nostr:npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z ", - "created_at": 1683596206, - "id": "98b574c3527f0ffb30b7271084e3f07480733c7289f8de424d29eae82e36c758", - "kind": 1, - "pubkey": "46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184b16bd8ce4d", - "sig": "4aa5264965018fa12a326686ad3d3bd8beae3218dcc83689b19ca1e6baeb791531943c15363aa6707c7c0c8b2d601deca1f20c32078b2872d356cdca03b04cce", - "tags": [ - [ - "e", - "27ac621d7dc4a932e1a79f984308e7d20656dd6fddb2ce9cdfcb6a67b9a7bcc3", - "", - "root" - ], - [ - "e", - "be7245af96210a0dd048cab4ad38e52dbd6c09a53ea21a7edb6be8898e5727cc", - "", - "reply" - ], - [ - "p", - "22aa81510ee63fe2b16cae16e0921f78e9ba9882e2868e7e63ad6d08ae9b5954" - ], - [ - "p", - "22aa81510ee63fe2b16cae16e0921f78e9ba9882e2868e7e63ad6d08ae9b5954" - ], - [ - "p", - "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24" - ], - [ - "p", - "ec4d241c334311b3a304433ee3442be29d0e88e7ec19b85edf2bba29b93565e2" - ], - [ - "p", - "0fe0b18b4dbf0e0aa40fcd47209b2a49b3431fc453b460efcf45ca0bd16bd6ac" - ], - [ - "p", - "8c0da4862130283ff9e67d889df264177a508974e2feb96de139804ea66d6168" - ], - [ - "p", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" - ], - [ - "p", - "4523be58d395b1b196a9b8c82b038b6895cb02b683d0c253a955068dba1facd0" - ], - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ], - "seenOn": [ - "wss://nostr.wine/" - ] -} -""" - - @Test - fun parseEvent() { - val event = Event.fromJson(json) as TextNoteEvent - - val expectedCitations = setOf( - "8c0da4862130283ff9e67d889df264177a508974e2feb96de139804ea66d6168", - "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed", - "4523be58d395b1b196a9b8c82b038b6895cb02b683d0c253a955068dba1facd0", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ) - - assertEquals(expectedCitations, event.citedUsers()) - } -} diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/CryptoUtilsTest.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/CryptoUtilsTest.kt deleted file mode 100644 index 905f48e9..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/CryptoUtilsTest.kt +++ /dev/null @@ -1,114 +0,0 @@ -package com.vitorpamplona.quartz - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.vitorpamplona.quartz.encoders.hexToByteArray -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class CryptoUtilsTest { - - @Test - fun testGetPublicFromPrivateKey() { - val privateKey = "f410f88bcec6cbfda04d6a273c7b1dd8bba144cd45b71e87109cfa11dd7ed561".hexToByteArray() - val publicKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - assertEquals("7d4b8806f1fd713c287235411bf95aa81b7242ead892733ec84b3f2719845be6", publicKey) - } - - @Test - fun testSharedSecretCompatibilityWithCoracle() { - val privateKey = "f410f88bcec6cbfda04d6a273c7b1dd8bba144cd45b71e87109cfa11dd7ed561" - val publicKey = "765cd7cf91d3ad07423d114d5a39c61d52b2cdbc18ba055ddbbeec71fbe2aa2f" - - val key = CryptoUtils.getSharedSecretNIP44(privateKey = privateKey.hexToByteArray(), pubKey = publicKey.hexToByteArray()) - - assertEquals("577c966f499dddd8e8dcc34e8f352e283cc177e53ae372794947e0b8ede7cfd8", key.toHexKey()) - } - - @Test - fun testSharedSecret() { - val sender = KeyPair() - val receiver = KeyPair() - - val sharedSecret1 = CryptoUtils.getSharedSecretNIP44(sender.privKey!!, receiver.pubKey) - val sharedSecret2 = CryptoUtils.getSharedSecretNIP44(receiver.privKey!!, sender.pubKey) - - assertEquals(sharedSecret1.toHexKey(), sharedSecret2.toHexKey()) - - val secretKey1 = KeyPair(privKey = sharedSecret1) - val secretKey2 = KeyPair(privKey = sharedSecret2) - - assertEquals(secretKey1.pubKey.toHexKey(), secretKey2.pubKey.toHexKey()) - assertEquals(secretKey1.privKey?.toHexKey(), secretKey2.privKey?.toHexKey()) - } - - @Test - fun encryptDecryptNIP4Test() { - val msg = "Hi" - - val privateKey = CryptoUtils.privkeyCreate() - val publicKey = CryptoUtils.pubkeyCreate(privateKey) - - val encrypted = CryptoUtils.encryptNIP04(msg, privateKey, publicKey) - val decrypted = CryptoUtils.decryptNIP04(encrypted, privateKey, publicKey) - - assertEquals(msg, decrypted) - } - - @Test - fun encryptDecryptNIP4WithJsonSchemaTest() { - val msg = "Hi" - - val privateKey = CryptoUtils.privkeyCreate() - val publicKey = CryptoUtils.pubkeyCreate(privateKey) - - val encrypted = CryptoUtils.encryptNIP04Json(msg, privateKey, publicKey) - val decrypted = CryptoUtils.decryptNIP04(encrypted, privateKey, publicKey) - - assertEquals(msg, decrypted) - } - - @Test - fun encryptDecryptNIP44Test() { - val msg = "Hi" - - val privateKey = CryptoUtils.privkeyCreate() - val publicKey = CryptoUtils.pubkeyCreate(privateKey) - - val encrypted = CryptoUtils.encryptNIP44(msg, privateKey, publicKey) - val decrypted = CryptoUtils.decryptNIP44(encrypted, privateKey, publicKey) - - assertEquals(msg, decrypted) - } - - @Test - fun encryptSharedSecretDecryptNIP4Test() { - val msg = "Hi" - - val privateKey = CryptoUtils.privkeyCreate() - val publicKey = CryptoUtils.pubkeyCreate(privateKey) - - val encrypted = CryptoUtils.encryptNIP04(msg, privateKey, publicKey) - val decrypted = CryptoUtils.decryptNIP04(encrypted, privateKey, publicKey) - - assertEquals(msg, decrypted) - } - - @Test - fun encryptSharedSecretDecryptNIP44Test() { - val msg = "Hi" - - val privateKey = CryptoUtils.privkeyCreate() - val publicKey = CryptoUtils.pubkeyCreate(privateKey) - val sharedSecret = CryptoUtils.getSharedSecretNIP44(privateKey, publicKey) - - val encrypted = CryptoUtils.encryptNIP44(msg, sharedSecret) - val decrypted = CryptoUtils.decryptNIP44(encrypted, sharedSecret) - - assertEquals(msg, decrypted) - } -} diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/EventSigCheck.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/EventSigCheck.kt deleted file mode 100644 index 7794c450..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/EventSigCheck.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.vitorpamplona.quartz - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.vitorpamplona.quartz.events.Event -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class EventSigCheck { - - val payload1 = "[\"EVENT\",\"40b9\",{\"id\":\"48a72b485d38338627ec9d427583551f9af4f016c739b8ec0d6313540a8b12cf\",\"kind\":1,\"pubkey\":\"3d842afecd5e293f28b6627933704a3fb8ce153aa91d790ab11f6a752d44a42d\",\"created_at\":1677940007,\"content\":\"I got asked about follower count again today. Why does my follower count go down when I delete public relays (in our list) and replace them with filter.nostr.wine? \\n\\nI’ll give you one final explanation to rule them all. First, let’s go over how clients calculate your follower count.\\n\\n1. Your client sends a request to all your connected relays asking for accounts who follow you\\n2. Relays answer back with the events requested\\n3. The client aggregates the event total and displays it\\n\\nEach relay has a set limit on how many stored events it will return per request. For some relays it’s 500, others 1000, some as high as 5000. Let’s say for simplicity that all your public relays use 500 as their limit. If you ask 10 relays for your followers the max possible answer you can get is 5000. That won’t change if you have 20,000 followers or 100,000. You may get back a “different” 5000 each time, but you’ll still cap out at 5000 because that is the most events your client will receive.\u2028\u2028Our limit on filter.nostr.wine is 2000 events. If you replace 10 public relays with only filter.nostr.wine, the MOST followers you will ever get back from our filter relay is 2000. That doesn’t mean you only have 2000 followers or that your reach is reduced in any way.\\n\\nAs long as you are writing to and reading from the same public relays, neither your reach nor any content was lost. That concludes my TED talk. I hope you all have a fantastic day and weekend.\",\"tags\":[],\"sig\":\"dcaf8ab98bb9179017b35bd814092850d1062b26c263dff89fb1ae8c019a324139d1729012d9d05ff0a517f76b1117d869b2cc7d36bea8aa5f4b94c5e2548aa8\"}]" - - @Test - fun testUnicode2028and2029ShouldNotBeEscaped() { - val msg = Event.mapper.readTree(payload1) - val event = Event.fromJson(msg[2]) - - // Should pass - event.checkSignature() - } - -} diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/GiftWrapEventTest.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/GiftWrapEventTest.kt deleted file mode 100644 index 8536549f..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/GiftWrapEventTest.kt +++ /dev/null @@ -1,560 +0,0 @@ -package com.vitorpamplona.quartz - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.vitorpamplona.quartz.encoders.hexToByteArray -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey -import com.vitorpamplona.quartz.events.ChatMessageEvent -import com.vitorpamplona.quartz.events.Event -import com.vitorpamplona.quartz.events.GiftWrapEvent -import com.vitorpamplona.quartz.events.Gossip -import com.vitorpamplona.quartz.events.NIP24Factory -import com.vitorpamplona.quartz.events.SealedGossipEvent -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotEquals -import org.junit.Assert.assertNotNull -import org.junit.Assert.assertNull -import org.junit.Assert.assertTrue -import org.junit.Assert.fail -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class GiftWrapEventTest { - @Test() - fun testNip24Utils() { - val sender = KeyPair() - val receiver = KeyPair() - val message = "Hola, que tal?" - - val events = NIP24Factory().createMsgNIP24( - message, - listOf(receiver.pubKey.toHexKey()), - sender.privKey!! - ) - - // Simulate Receiver - val eventsReceiverGets = events.filter { it.isTaggedUser(receiver.pubKey.toHexKey()) } - eventsReceiverGets.forEach { - val event = it.unwrap(receiver.privKey!!) - if (event is SealedGossipEvent) { - val innerData = event.unseal(receiver.privKey!!) - assertEquals(message, innerData?.content) - } else { - fail("Wrong Event") - } - } - - // Simulate Sender - val eventsSenderGets = events.filter { it.isTaggedUser(sender.pubKey.toHexKey()) } - eventsSenderGets.forEach { - val event = it.unwrap(sender.privKey!!) - if (event is SealedGossipEvent) { - val innerData = event.unseal(sender.privKey!!) - assertEquals(message, innerData?.content) - } else { - fail("Wrong Event") - } - } - } - - @Test() - fun testNip24UtilsForGroups() { - val sender = KeyPair() - val receiver1 = KeyPair() - val receiver2 = KeyPair() - val receiver3 = KeyPair() - val receiver4 = KeyPair() - val message = "Hola, que tal?" - - val receivers = listOf( - receiver1, - receiver2, - receiver3, - receiver4 - ) - - val events = NIP24Factory().createMsgNIP24( - message, - receivers.map { it.pubKey.toHexKey() }, - sender.privKey!! - ) - - // Simulate Receiver - receivers.forEach { receiver -> - val eventsReceiverGets = events.filter { it.isTaggedUser(receiver.pubKey.toHexKey()) } - eventsReceiverGets.forEach { - val event = it.unwrap(receiver.privKey!!) - if (event is SealedGossipEvent) { - val innerData = event.unseal(receiver.privKey!!) - assertEquals(message, innerData?.content) - } else { - fail("Wrong Event") - } - } - } - - // Simulate Sender - val eventsSenderGets = events.filter { it.isTaggedUser(sender.pubKey.toHexKey()) } - eventsSenderGets.forEach { - val event = it.unwrap(sender.privKey!!) - if (event is SealedGossipEvent) { - val innerData = event.unseal(sender.privKey!!) - assertEquals(message, innerData?.content) - } else { - fail("Wrong Event") - } - } - } - - @Test() - fun testInternalsSimpleMessage() { - val sender = KeyPair() - val receiver = KeyPair() - - val senderMessage = ChatMessageEvent.create( - msg = "Hi There!", - to = listOf(receiver.pubKey.toHexKey()), - privateKey = sender.privKey!! - ) - - // MsgFor the Receiver - - val encMsgFromSenderToReceiver = SealedGossipEvent.create( - event = senderMessage, - encryptTo = receiver.pubKey.toHexKey(), - privateKey = sender.privKey!! - ) - - // Should expose sender - assertEquals(encMsgFromSenderToReceiver.pubKey, sender.pubKey.toHexKey()) - // Should not expose receiver - assertTrue(encMsgFromSenderToReceiver.tags.isEmpty()) - - val giftWrapEventToReceiver = GiftWrapEvent.create( - event = encMsgFromSenderToReceiver, - recipientPubKey = receiver.pubKey.toHexKey() - ) - - // Should not be signed by neither sender nor receiver - assertNotEquals(giftWrapEventToReceiver.pubKey, sender.pubKey.toHexKey()) - assertNotEquals(giftWrapEventToReceiver.pubKey, receiver.pubKey.toHexKey()) - - // Should not include sender as recipient - assertNotEquals(giftWrapEventToReceiver.recipientPubKey(), sender.pubKey.toHexKey()) - - // Should be addressed to the receiver - assertEquals(giftWrapEventToReceiver.recipientPubKey(), receiver.pubKey.toHexKey()) - - // MsgFor the Sender - - val encMsgFromSenderToSender = SealedGossipEvent.create( - event = senderMessage, - encryptTo = sender.pubKey.toHexKey(), - privateKey = sender.privKey!! - ) - - // Should expose sender - assertEquals(encMsgFromSenderToSender.pubKey, sender.pubKey.toHexKey()) - // Should not expose receiver - assertTrue(encMsgFromSenderToSender.tags.isEmpty()) - - val giftWrapEventToSender = GiftWrapEvent.create( - event = encMsgFromSenderToSender, - recipientPubKey = sender.pubKey.toHexKey() - ) - - // Should not be signed by neither the sender, not the receiver - assertNotEquals(giftWrapEventToSender.pubKey, sender.pubKey.toHexKey()) - assertNotEquals(giftWrapEventToSender.pubKey, receiver.pubKey.toHexKey()) - - // Should not be addressed to the receiver - assertNotEquals(giftWrapEventToSender.recipientPubKey(), receiver.pubKey.toHexKey()) - // Should be addressed to the sender - assertEquals(giftWrapEventToSender.recipientPubKey(), sender.pubKey.toHexKey()) - - // Done - - println(senderMessage.toJson()) - println(encMsgFromSenderToReceiver.toJson()) - println(giftWrapEventToReceiver.toJson()) - println(giftWrapEventToSender.toJson()) - - // Receiver's side - // Unwrapping - - val unwrappedMsgForSenderBySender = giftWrapEventToSender.unwrap(sender.privKey!!) - val unwrappedMsgForReceiverBySender = giftWrapEventToReceiver.unwrap(sender.privKey!!) - - assertNotNull(unwrappedMsgForSenderBySender) - assertNull(unwrappedMsgForReceiverBySender) - - val unwrappedMsgForSenderByReceiver = giftWrapEventToSender.unwrap(receiver.privKey!!) - val unwrappedMsgForReceiverByReceiver = giftWrapEventToReceiver.unwrap(receiver.privKey!!) - - assertNull(unwrappedMsgForSenderByReceiver) - assertNotNull(unwrappedMsgForReceiverByReceiver) - - assertEquals(SealedGossipEvent.kind, unwrappedMsgForSenderBySender?.kind) - assertEquals(SealedGossipEvent.kind, unwrappedMsgForReceiverByReceiver?.kind) - - assertTrue(unwrappedMsgForSenderBySender is SealedGossipEvent) - assertTrue(unwrappedMsgForReceiverByReceiver is SealedGossipEvent) - - if (unwrappedMsgForSenderBySender is SealedGossipEvent && - unwrappedMsgForReceiverByReceiver is SealedGossipEvent - ) { - val unwrappedGossipToSenderByReceiver = unwrappedMsgForSenderBySender.unseal(receiver.privKey!!) - val unwrappedGossipToReceiverByReceiver = unwrappedMsgForReceiverByReceiver.unseal(receiver.privKey!!) - - assertNull(unwrappedGossipToSenderByReceiver) - assertNotNull(unwrappedGossipToReceiverByReceiver) - - val unwrappedGossipToSenderBySender = unwrappedMsgForSenderBySender.unseal(sender.privKey!!) - val unwrappedGossipToReceiverBySender = unwrappedMsgForReceiverByReceiver.unseal(sender.privKey!!) - - assertNotNull(unwrappedGossipToSenderBySender) - assertNull(unwrappedGossipToReceiverBySender) - - assertEquals("Hi There!", unwrappedGossipToReceiverByReceiver?.content) - assertEquals("Hi There!", unwrappedGossipToSenderBySender?.content) - } else { - fail() - } - } - - @Test() - fun testInternalsGroupMessage() { - val sender = KeyPair() - val receiverA = KeyPair() - val receiverB = KeyPair() - - val senderMessage = ChatMessageEvent.create( - msg = "Who is going to the party tonight?", - to = listOf(receiverA.pubKey.toHexKey(), receiverB.pubKey.toHexKey()), - privateKey = sender.privKey!! - ) - - val encMsgFromSenderToReceiverA = SealedGossipEvent.create( - event = senderMessage, - encryptTo = receiverA.pubKey.toHexKey(), - privateKey = sender.privKey!! - ) - - val encMsgFromSenderToReceiverB = SealedGossipEvent.create( - event = senderMessage, - encryptTo = receiverB.pubKey.toHexKey(), - privateKey = sender.privKey!! - ) - - val encMsgFromSenderToSender = SealedGossipEvent.create( - event = senderMessage, - encryptTo = sender.pubKey.toHexKey(), - privateKey = sender.privKey!! - ) - - // Should expose sender - assertEquals(encMsgFromSenderToReceiverA.pubKey, sender.pubKey.toHexKey()) - // Should not expose receiver - assertTrue(encMsgFromSenderToReceiverA.tags.isEmpty()) - - // Should expose sender - assertEquals(encMsgFromSenderToReceiverB.pubKey, sender.pubKey.toHexKey()) - // Should not expose receiver - assertTrue(encMsgFromSenderToReceiverB.tags.isEmpty()) - - // Should expose sender - assertEquals(encMsgFromSenderToSender.pubKey, sender.pubKey.toHexKey()) - // Should not expose receiver - assertTrue(encMsgFromSenderToSender.tags.isEmpty()) - - val giftWrapEventForReceiverA = GiftWrapEvent.create( - event = encMsgFromSenderToReceiverA, - recipientPubKey = receiverA.pubKey.toHexKey() - ) - - val giftWrapEventForReceiverB = GiftWrapEvent.create( - event = encMsgFromSenderToReceiverB, - recipientPubKey = receiverB.pubKey.toHexKey() - ) - - // Should not be signed by neither sender nor receiver - assertNotEquals(giftWrapEventForReceiverA.pubKey, sender.pubKey.toHexKey()) - assertNotEquals(giftWrapEventForReceiverA.pubKey, receiverA.pubKey.toHexKey()) - assertNotEquals(giftWrapEventForReceiverA.pubKey, receiverB.pubKey.toHexKey()) - - // Should not include sender as recipient - assertNotEquals(giftWrapEventForReceiverA.recipientPubKey(), sender.pubKey.toHexKey()) - - // Should be addressed to the receiver - assertEquals(giftWrapEventForReceiverA.recipientPubKey(), receiverA.pubKey.toHexKey()) - - // Should not be signed by neither sender nor receiver - assertNotEquals(giftWrapEventForReceiverB.pubKey, sender.pubKey.toHexKey()) - assertNotEquals(giftWrapEventForReceiverB.pubKey, receiverA.pubKey.toHexKey()) - assertNotEquals(giftWrapEventForReceiverB.pubKey, receiverB.pubKey.toHexKey()) - - // Should not include sender as recipient - assertNotEquals(giftWrapEventForReceiverB.recipientPubKey(), sender.pubKey.toHexKey()) - - // Should be addressed to the receiver - assertEquals(giftWrapEventForReceiverB.recipientPubKey(), receiverB.pubKey.toHexKey()) - - val giftWrapEventToSender = GiftWrapEvent.create( - event = encMsgFromSenderToSender, - recipientPubKey = sender.pubKey.toHexKey() - ) - - // Should not be signed by neither the sender, not the receiver - assertNotEquals(giftWrapEventToSender.pubKey, sender.pubKey.toHexKey()) - assertNotEquals(giftWrapEventToSender.pubKey, receiverA.pubKey.toHexKey()) - assertNotEquals(giftWrapEventToSender.pubKey, receiverB.pubKey.toHexKey()) - - // Should not be addressed to the receiver - assertNotEquals(giftWrapEventToSender.recipientPubKey(), receiverA.pubKey.toHexKey()) - assertNotEquals(giftWrapEventToSender.recipientPubKey(), receiverB.pubKey.toHexKey()) - // Should be addressed to the sender - assertEquals(giftWrapEventToSender.recipientPubKey(), sender.pubKey.toHexKey()) - - println(senderMessage.toJson()) - println(encMsgFromSenderToReceiverA.toJson()) - println(encMsgFromSenderToReceiverB.toJson()) - println(giftWrapEventForReceiverA.toJson()) - println(giftWrapEventForReceiverB.toJson()) - println(giftWrapEventToSender.toJson()) - - val unwrappedMsgForSenderBySender = giftWrapEventToSender.unwrap(sender.privKey!!) - val unwrappedMsgForReceiverBySenderA = giftWrapEventForReceiverA.unwrap(sender.privKey!!) - val unwrappedMsgForReceiverBySenderB = giftWrapEventForReceiverB.unwrap(sender.privKey!!) - - assertNotNull(unwrappedMsgForSenderBySender) - assertNull(unwrappedMsgForReceiverBySenderA) - assertNull(unwrappedMsgForReceiverBySenderB) - - val unwrappedMsgForSenderByReceiverA = giftWrapEventToSender.unwrap(receiverA.privKey!!) - val unwrappedMsgForReceiverAByReceiverA = giftWrapEventForReceiverA.unwrap(receiverA.privKey!!) - val unwrappedMsgForReceiverBByReceiverA = giftWrapEventForReceiverB.unwrap(receiverA.privKey!!) - - assertNull(unwrappedMsgForSenderByReceiverA) - assertNotNull(unwrappedMsgForReceiverAByReceiverA) - assertNull(unwrappedMsgForReceiverBByReceiverA) - - val unwrappedMsgForSenderByReceiverB = giftWrapEventToSender.unwrap(receiverB.privKey!!) - val unwrappedMsgForReceiverAByReceiverB = giftWrapEventForReceiverA.unwrap(receiverB.privKey!!) - val unwrappedMsgForReceiverBByReceiverB = giftWrapEventForReceiverB.unwrap(receiverB.privKey!!) - - assertNull(unwrappedMsgForSenderByReceiverB) - assertNull(unwrappedMsgForReceiverAByReceiverB) - assertNotNull(unwrappedMsgForReceiverBByReceiverB) - - assertEquals(SealedGossipEvent.kind, unwrappedMsgForSenderBySender?.kind) - assertEquals(SealedGossipEvent.kind, unwrappedMsgForReceiverAByReceiverA?.kind) - assertEquals(SealedGossipEvent.kind, unwrappedMsgForReceiverBByReceiverB?.kind) - - assertTrue(unwrappedMsgForSenderBySender is SealedGossipEvent) - assertTrue(unwrappedMsgForReceiverAByReceiverA is SealedGossipEvent) - assertTrue(unwrappedMsgForReceiverBByReceiverB is SealedGossipEvent) - - if (unwrappedMsgForSenderBySender is SealedGossipEvent && - unwrappedMsgForReceiverAByReceiverA is SealedGossipEvent && - unwrappedMsgForReceiverBByReceiverB is SealedGossipEvent - ) { - val unwrappedGossipToSenderByReceiverA = unwrappedMsgForSenderBySender.unseal(receiverA.privKey!!) - val unwrappedGossipToReceiverAByReceiverA = unwrappedMsgForReceiverAByReceiverA.unseal(receiverA.privKey!!) - val unwrappedGossipToReceiverBByReceiverA = unwrappedMsgForReceiverBByReceiverB.unseal(receiverA.privKey!!) - - assertNull(unwrappedGossipToSenderByReceiverA) - assertNotNull(unwrappedGossipToReceiverAByReceiverA) - assertNull(unwrappedGossipToReceiverBByReceiverA) - - val unwrappedGossipToSenderByReceiverB = unwrappedMsgForSenderBySender.unseal(receiverB.privKey!!) - val unwrappedGossipToReceiverAByReceiverB = unwrappedMsgForReceiverAByReceiverA.unseal(receiverB.privKey!!) - val unwrappedGossipToReceiverBByReceiverB = unwrappedMsgForReceiverBByReceiverB.unseal(receiverB.privKey!!) - - assertNull(unwrappedGossipToSenderByReceiverB) - assertNull(unwrappedGossipToReceiverAByReceiverB) - assertNotNull(unwrappedGossipToReceiverBByReceiverB) - - val unwrappedGossipToSenderBySender = unwrappedMsgForSenderBySender.unseal(sender.privKey!!) - val unwrappedGossipToReceiverABySender = unwrappedMsgForReceiverAByReceiverA.unseal(sender.privKey!!) - val unwrappedGossipToReceiverBBySender = unwrappedMsgForReceiverBByReceiverB.unseal(sender.privKey!!) - - assertNotNull(unwrappedGossipToSenderBySender) - assertNull(unwrappedGossipToReceiverABySender) - assertNull(unwrappedGossipToReceiverBBySender) - - assertEquals("Who is going to the party tonight?", unwrappedGossipToReceiverAByReceiverA?.content) - assertEquals("Who is going to the party tonight?", unwrappedGossipToReceiverBByReceiverB?.content) - assertEquals("Who is going to the party tonight?", unwrappedGossipToSenderBySender?.content) - } else { - fail() - } - } - - @Test - fun testCaseFromAmethyst1() { - val json = """ - { - "content":"{\"ciphertext\":\"AaTN5Mt7AOeMosjHeLfai89kmvW/qJ7W2VMttAwuh6hwRGV+ylJhpDbdVRhVmkCotbDjBgS6xioLrSDcdSngFOiVMHS5dTAP0MkQv09aZlBh/NgdmyfHHd24YlHPkDuF5Yb4Vmz7kq/vmjsNZvDrTen3TG2DcEoTV9GKexdMEqyBA4LsB2DLnWfpvOi0olDkGjPGSteTaU1nCdOtN8knoEKumrxwevvbygKphorvKX/j3ojMMb0AceJM6Cr6TRIvSsQnKGEv5V8qbC/uIrQoH3N108Fd/2SY2MWuyLKRnuak9F/w82MV13elq8ngyjcktLYM5yrPg5nrxZlyJsV8D7V/g/bvhoL+UmWe0XoCR5LXzy77SfIkgA1ePKEfGp5sD2CVIzXt9zHdFwGxAKZuyB4qwrRaAFrS2xx+Bw4nnEmF6V9NhfheSCmGzTILuTePx4ubvnYw/j8Hmqd6UvM3DBNnlJ3D6po0blirfWvMe/ea+Em4CMXfq8Iq+7r4gRx8azADygKeJ+C89GTBEvS9EvgrXCVfTMVTcFc44YAZhekOqYY1BOZgfxIV4gUiJfpMMd4B9MQv/tmnewrpTsq1reSQQcEW/mXT2cnMeCZbAIJSPg8usZ30QlrH+np+YSzFKWYDP1kThcV0ElEE2Ne8KaUUFIRE5KmhBQc/qtORefCpne5s7V7J5vLjT5rinsDzzENB1XVlmY1Icx42raP5tGAL1gOK5gRHLvtcgFQR3WcDRYaNqELiYxx41j9w9lz5e00Ttla255rZkb760KSLaBFBss6wYGiYCabVgtBNpkExpCFPPEd5eAZa5rNK2QrnojYsdxEnlicF6A+zSChLy/TbzxYwyQywDfoF9F8kBakPZkAhsciQViCii2KlieRq4OgJFZGndmnS82hyPqsoJIm22vWr1iqMvSBHo/9cLj/r+lfmGVOdgM62JHckPZjOLS0QWIb9gQiT+zXZG22+eZElMYbGXVpR1dyMaQtde8ivEVVLas6kMCVKaDTHEFglaCBXjJ3RNJv73HsG1kb0rMmOj8ltbBakjHpv7M59amavuu6SReYt\",\"nonce\":\"6anNjUdNwW6MNfoKzRZcz1R09N1h8G4L\",\"v\":1}", - "created_at":1690660515, - "id":"d90739741c2f5a8c1a03aab5dc219c0b708ed6b0566044495731cd0307cf19a5", - "kind":1059, - "pubkey":"a79b7162f8ebb9c9f7aa65a48977ab7f32aa097520bc543e4d625812154ff6af", - "sig":"9b012504e779632a2a1f55562fa9a85f8ae6245cbc149b83d25b2971249053abc77f65cc068e5d025b871d743678265fede70de4eaf5af642e675a5b6210077d", - "tags":[ - [ - "p", - "c55f0b0cb4dd180dd4395867b28dd4c208b709144a69fb7c31a46c369a5ad1c6" - ] - ] - } - """.trimIndent() - - val privateKey = "de6152a85a0dea3b09a08a6f8139a314d498a7b52f7e5c28858b64270abd4c70" - val gossip = unwrapUnsealGossip(json, privateKey) - - assertNotNull(gossip) - assertEquals("Hola, que tal?", gossip?.content) - } - - @Test - fun testCaseFromAmethyst2() { - val json = """ -{ - "content":"{\"ciphertext\":\"Zb0ZNYAcDG5y7BiCWgbxY/i7rN7TxPwr3Oaste6em4VcetuenaMu2SyH6OuCCxxmIa7kFennJD8ZCrev0086azsPNutl9I6OCoOfDQb2GoFaLoJAkE/FuW0uEoEJuN72KsKj05HEjOM6nqL2KiW0pxTCNmlGpweMwpXQdm2ItWkybNpq8+b4NJUDee2czBUd9Kr2ELbPISTYzA17z1IzPXGQw8c73NL+QX9I/QZjM/agqX2x5q11SU52xiRyVd9zHf7TMctZI4QEsqDB6xi54D1bAeZlMhVdcpQRpGDfqRz3KXFlhB3Bwdc8GLgY0aLTn6tJs4qrHP3mQkxFYk0mju0afoc0rloMEUHcBVtM18S9OrTPqfmSqFTQsjaT8g+PkmeiLBo1sXsMCS62w0abSZD9OzQtciMz70ZpcWoLjx5f8panjFClvg4tJ8czMURIHM/IFS1uKAUHBArGN8QpCw8MXQBblpyLDiEkFcSX334Zdps0OIw4z328JSdeejyRh4ks+NHDt9FcjC4iicEqfEh8OTkXuKqEAVkRyfAioNQxWQPnXDzMX0Q+BXvKzBA7NaEBDpbV36H/KnrpBBQwokV9/Byb6Seh3g6GSqRAWD3U6Nk2aBMXkD0xY8vnIqMckBeYHxn8BW7k1FdXFC9lE5xCxWZHkmksJ4f0NVaF37O6d8qOe6RK7bfUeF8/SouJEu+eEX1f4KCMboslwkdk8QA8bThGcRGn8GQBMrPKrpZwHYNyyH8jwt9pywigXJejRLDDnDp3FH/3dbZy5CfuNH6KGydf/O5xx1r316so1UPO1mL5LHJUFZVIaMaMMUsgq12gpI0lLEh5NJPpsi9e3ibkzEZGf7FlAJjJQURbQ8xacN7R+w3GWKbJNHiQbUZ2lXo6fwz33t0DrSqEW970yWPHlqxcpd27EI+qqb5IqfklQZ3RObZZBhzDvImaCPG+U7SmgLhPxnilpGjd5lw/ttiqJhPG9mYFMf1eJXSG+Q9VVkGzN7jxXYtx0q0WGjVq98ZGv5RSnF1d9+QVGCd1fiPS3rsaWdYWly8l0y2quYObJ6Mv3Wh3\",\"nonce\":\"/Q2UTTjVZthm/atcCuDjU1e4reF+ZSgZ\",\"v\":1}", - "created_at":1690660515, - "id":"087d9627d63135a5050758a69222e566c86702e930c9905f0b93ccd6bebeca3f", - "kind":1059, - "pubkey":"e59c00796ae2aa9077fc8bcd57fe8d32c0fc363f7c8b93d055c70804ffff3772", - "sig":"807cb641c314ca6910aaeefadcf87d859137520be1039eb40e39832ed59d456fdd800c5f88bba09e1b395ee90c66d5330847bdd010b63be9919bf091adbc2c2a", - "tags":[ - [ - "p", - "f85f315c06aaf19c2b30a96ca80d9644720655ee8d3ec43b84657a7c98f36a23" - ] - ] -} - """.trimIndent() - - val privateKey = "409ff7654141eaa16cd2161fe5bd127aeaef71f270c67587474b78998a8e3533" - val gossip = unwrapUnsealGossip(json, privateKey) - - assertNotNull(gossip) - assertEquals("Hola, que tal?", gossip?.content) - } - - @Test - fun testDecryptFromCoracle() { - val json = """ -{ - "content": "{\"ciphertext\":\"fo0/Ywyfu86cXKoOOeFFlMRv+LYM6GJUL+F/J4ARv6EcAufOZP46vimlurPBLPjNgzuGemGjlTFfC3vtq84AqIsqFo3dqKunq8Vp+mmubvxIQUDzOGYvM0WE/XOiW5LEe3U3Vq399Dq07xRpXELcp4EZxGyu4Fowv2Ppb4SKpH8g+9N3z2+bwYcSxBvI6SrL+hgmVMrRlgvsUHN1d53ni9ehRseBqrLj/DqyyEiygsKm6vnEZAPKnl1MrBaVOBZmGsyjAa/G4SBVVmk78sW7xWWvo4cV+C22FluDWUOdj/bYabH4aR4scnBX3GLYqfLuzGnuQlRNsb5unXVX41+39uXzROrmNP6iYVyYxy5tfoyN7PPZ4osoKpLDUGldmXHD6RjMcAFuou4hXt2JlTPmXpj/x8qInXId5mkmU4nTGiasvsCIpJljbCujwCjbjLTcD4QrjuhMdtSsAzjT0CDv5Lmc632eKRYtDu/9B+lkqBBkp7amhzbqp8suNTnybkvbGFQQGEQnsLfNJw/GGopAuthfi8zkTgUZR/LxFR7ZKAX73G+5PQSDSjPuGH/dQEnsFo45zsh1Xro8SfUQBsPphbX2GS31Lwu5vA30O922T4UiWuU+EdNgZR0JankQ5NPgvr1uS56C3v84VwdrNWQUCwC4eYJl4Mb/OdpEy9qwsisisppq6uuzxmxd1qx3JfocnGsvB7h2g2sG+0lyZADDSobOEZEKHaBP3w+dRcJW9D95EmzPym9GO0n+33OfqFQbda7G0rzUWfPDV0gXIuZcKs/HmDqepgIZN8FG7JhRBeAv0bCbKQACre0c8tzVEn5yCYemltScdKop3pC/r6gH50jRhAlFAiIKx8R+XwuMmJRqOcH4WfkpZlfVU85/I0XJOCHWKk6BnJi/NPP9zYiZiJe+5LecqMUVjtO0YAlv138+U/3FIT/anQ4H5bjVWBZmajwf\",\"nonce\":\"Mv70S6jgrs4D1rlqV9b5DddiymGAcVVe\",\"v\":1}", - "created_at": 1690528373, - "id": "6b108e4236c3c338236ee589388ce0f91f921e1532ae52e75d1d2add6f8e691a", - "kind": 1059, - "pubkey": "627dc0248335e2bf9adac14be9494139ebbeb12c422d7df5b0e3cd72d04c209c", - "sig": "be11da487196db298e4ffb7a03e74176c37441c88b39c95b518fadce6fd02f23c58b2c435ca38c24d512713935ab719dae80bf952267630809e1f84be8e95174", - "tags": [ - [ - "p", - "e7764a227c12ac1ef2db79ae180392c90903b2cec1e37f5c1a4afed38117185e" - ] - ], - "seenOn": [ - "wss://relay.damus.io/" - ] -} - """.trimIndent() - - val privateKey = "09e0051fdf5fdd9dd7a54713583006442cbdbf87bdcdab1a402f26e527d56771" - val gossip = unwrapUnsealGossip(json, privateKey) - - assertNotNull(gossip) - assertEquals("test", gossip?.content) - } - - @Test - fun testFromCoracle2() { - val json = """ -{ - "content": "{\"ciphertext\":\"Hn/dHo/I8Qk6QWWAiKyo/SfKJqQfHdV0O5tMmgqMyfHrsFoDY6IhGQP2EgCJ/6HsNQyO/8EMAmLW8w0PbDKlBKYGKGpaMwCA6B1r0rLjvu+149RJZuggRNm9rd7tNVNkNs38iqt1KYD++bohePm52q+VhAQikbX2gTONV82ROwZylAg9vjvMnYkDt45g6N97s9FRB6V7YMiUEtJnneMixa6klucpUuenQ4569tyt5vnUMD2VNhKYCc2jit2hf7k0DIhvZrVC3OdopUvxIuYYWr3r7XpuEB3HJ6Ji3ajHPzgGeFcItBR7uKZ9s6XU34F3keyZbxrv3yWHFM5NrOctAdZexSGpqWRW93M0KZUAp9HgQh3YzMLl8xt0mcrVywCgjU6Kx8IwkI0bjPU+Am8acY3cItted6hZQ4Vy1xFITdKVfPWDl3Ab59iBg9+IkY5C31wqsKPgPVVycwQE6UpaGW74gy3qZshwyoo01owvEIbVvrSJWXH7EUVvndDPvUbo+f+EVa84IEwVjPmY2oR7VsxVfqRBdmPg23OSw/9rzVybmruqaQHd3xrTTEcnG0qBc/ugCXsiuILTeScOovEnqIlKKK3KB36jMtdScdJB+b4YrzJInY1AvqU7IAgqe0vmo1LdbMtj7kjuxkXJhhQsunAbTvPigTrsOfJ08P9l7r/95kpxudgagEaW7XAjYVfLphseJT3Iy1IuQEyG5sshQ+pl/CYvkGide7ykHwm9pjSBVkD9Mdcn5X6lSnLNJEcwY43pz43r6Kq3L09qneILY3DSKyQ16Zcu1MiAMAM5r6JGvpAHqcMmixi9ORuiryjteTmY4L0vI7b3W/0RSUblXxUrb8IpeysBrFmiKJBgCoU0r/D/8tgR+Eewyp1qxKI4SfKG5GFH40zZ2oVvKyoHAR4x1oVDp/MttcnxkzAsCFL6QuJC9A/vImjsumpmYB/EChcZCOAsfqkuzH4VSjZx\",\"nonce\":\"K537d+7m5tUcXZfkr3Qk2J2G86vdBMmY\",\"v\":1}", - "created_at": 1690655012, - "id": "c4f97c6332b0a63912c44c9e1f8c7b23581dc67a8489ec1522ec205fea7133db", - "kind": 1059, - "pubkey": "8def03a22b1039256a3883d46c7ccd5562f61743100db401344284547de7ec61", - "sig": "25dcf24bdda99c04abc72274d9f7a30538a4a00a70ac4b39db4082b73823979858df93cd649c25edfb759857eac46ed70bb9ad0598f2e011d733a5a382bc4def", - "tags": [ - [ - "p", - "e7764a227c12ac1ef2db79ae180392c90903b2cec1e37f5c1a4afed38117185e" - ] - ] -} - """.trimIndent() - - val privateKey = "09e0051fdf5fdd9dd7a54713583006442cbdbf87bdcdab1a402f26e527d56771" - - val gossip = unwrapUnsealGossip(json, privateKey) - - assertEquals("asdfasdfasdf", gossip?.content) - assertEquals(1690659269L, gossip?.createdAt) - assertEquals("827ba09d32ab81d62c60f657b350198c8aaba84372dab9ad3f4f6b8b7274b707", gossip?.id) - assertEquals(14, gossip?.kind) - assertEquals("subject", gossip?.tags?.firstOrNull()?.get(0)) - assertEquals("test", gossip?.tags?.firstOrNull()?.get(1)) - } - - @Test - fun testFromCoracle3() { - val json = """ -{ - "content": "{\"ciphertext\":\"PGCodiacmCB/sClw0C6DQRpP/XIfNAKCVZdKLQpOqytgbFryhs9Z+cPldq2FajXzxs3jQsF7/EVQyWpuV8pXetvFT9tvzjg4Xcm7ZcooLUnAeAo2xZNcJontN4cGubuDqKuXy5n59yXP1fIxfnJxRTRRdCZ2edhsKeNR5NSByUi+StjV10rnfHt8AhZCpiXiZ/giTOsC4wdaeONPgMzMeljaJWLvl6n11VjmXhkx1mXIQt43CNB1hIqO3p89Mbd9p+nlLrOsR+Xs0TB4DCh4XTPbvgf7B7Z+PgOfl3GZfJy9x6TciLcF4E3Ba1zrPe4f79czCIEiJ1yrIKrzzYvv+it35DZQ8fgveFXpyHnNL29hml8PNjyOsFbCHVYLMGw88evI5PijOcpe1TtdoioX8kX5kVEQSKJXuoSjTorvbRPCgGzaa1m0J0uTpzri5VD22a/Jh2CcAnubg6w4JDdUWCogdSV3NqiJllo7ZF7WnZ3apPdRD23MEfphVBJrcLBUNlmwajnY5IvVTKTkZOP50r9dBapvMWXIo6M6zhy/5vVWJz57863pelYCRG4upaXZuNK9sMBtbiphxmFR83i8RML8KN8Q391Cd/xBN7TxJNo5p2YU25VeGZUAmHY8DYlMQDm8Br0nStAXp3T+DzTRL8FTECa8DJV+KTAPoCxqhv3B28Ehr0XAP75CsHoLU00G48cR7h3vQ0CnfKh6KXU6nnDA5OWfpMYpirACCpsnpSD0OaCQ3gkQp3zZNMS3HcOpnPK/IY7R0esbzgAkvNhkyxaIfPDdf+eRUSOA9+2Ji28MwjjY8Dw3SLdUqCOzIDjQeR/T5oNmaQJm3lZ8G0FxxC6ejD4VJX/NI/x+STeB9jWHWmHZvqKzV6JHNh6qmZb6TKSIPOHpafWFoeJFOmiiigf46sju9vRXmVEAx59HXWnvnvCBNJg877yCMulB6xyQuSdVDuotQU4tQZwCKedTHJ6GqjesM98UlJrDtdWQURwwW1qc7N8tS6PukmUVEf0jmbIWVIBmUlkcVuiSs1g1h1kjt8c4MnGTz3CSgpOd1MqxLrl9WwrTqM+YnE+yeZYUjFoewyKZIQ==\",\"nonce\":\"OdCZczJiUGR4bOGIElQ4UUH4dQmG5U/3\",\"v\":1}", - "kind": 1059, - "created_at": 1690772945, - "pubkey": "e01475e87896800b7285eb0daf263c59f811c8fc5bc8daa105d2c98b6d7c4952", - "tags": [ - [ - "p", - "b08d8857a92b4d6aa580ff55cc3c18c4edf313c83388c34abc118621f74f1a78" - ] - ], - "id": "d9fc85ece892ce45ffa737b3ddc0f8b752623181d75363b966191f8c03d2debe", - "sig": "1b20416b83f4b5b8eead11e29c185f46b5e76d1960e4505210ddd00f7a6973cc11268f52a8989e3799b774d5f3a55db95bed4d66a1b6e88ab54becec5c771c17" -} - """.trimIndent() - - val privateKey = "7dd22cafc512c0bc363a259f6dcda515b13ae3351066d7976fd0bb79cbd0d700" - - val gossip = unwrapUnsealGossip(json, privateKey) - - assertEquals("8d1a56008d4e31dae2fb8bef36b3efea519eff75f57033107e2aa16702466ef2", gossip?.id) - assertEquals("Howdy", gossip?.content) - assertEquals(1690833960L, gossip?.createdAt) - assertEquals(14, gossip?.kind) - assertEquals("p", gossip?.tags?.firstOrNull()?.get(0)) - assertEquals("b08d8857a92b4d6aa580ff55cc3c18c4edf313c83388c34abc118621f74f1a78", gossip?.tags?.firstOrNull()?.get(1)) - assertEquals("subject", gossip?.tags?.getOrNull(1)?.get(0)) - assertEquals("Stuff", gossip?.tags?.getOrNull(1)?.get(1)) - } - - fun unwrapUnsealGossip(json: String, privateKey: HexKey): Gossip? { - val pkBytes = privateKey.hexToByteArray() - - val wrap = Event.fromJson(json) as GiftWrapEvent - wrap.checkSignature() - - assertEquals(CryptoUtils.pubkeyCreate(pkBytes).toHexKey(), wrap.recipientPubKey()) - - val event = wrap.unwrap(pkBytes) - assertNotNull(event) - - return if (event is SealedGossipEvent) { - return event.unseal(pkBytes) - } else { - println(event?.toJson()) - fail("Event is not a Sealed Gossip") - null - } - } -} diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/HexEncodingTest.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/HexEncodingTest.kt deleted file mode 100644 index eb9164a8..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/HexEncodingTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.vitorpamplona.quartz - -import com.vitorpamplona.quartz.crypto.CryptoUtils -import org.junit.Assert.assertEquals -import org.junit.Test - -class HexEncodingTest { - - val TestHex = "48a72b485d38338627ec9d427583551f9af4f016c739b8ec0d6313540a8b12cf" - - @Test - fun testHexEncodeDecodeOurs() { - assertEquals( - TestHex, - com.vitorpamplona.quartz.encoders.Hex.encode( - com.vitorpamplona.quartz.encoders.Hex.decode(TestHex) - ) - ) - } - - @Test - fun testHexEncodeDecodeSecp256k1() { - assertEquals( - TestHex, - fr.acinq.secp256k1.Hex.encode( - fr.acinq.secp256k1.Hex.decode(TestHex) - ) - ) - } - - @Test - fun testRandoms() { - for (i in 0..1000) { - val bytes = CryptoUtils.privkeyCreate() - val hex = fr.acinq.secp256k1.Hex.encode(bytes) - assertEquals( - fr.acinq.secp256k1.Hex.encode(bytes), - com.vitorpamplona.quartz.encoders.Hex.encode(bytes) - ) - assertEquals( - bytes.toList(), - com.vitorpamplona.quartz.encoders.Hex.decode(hex).toList() - ) - } - } - -} \ No newline at end of file diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/LargeDBSignatureCheck.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/LargeDBSignatureCheck.kt deleted file mode 100644 index a52cf517..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/LargeDBSignatureCheck.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.vitorpamplona.quartz - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation -import com.fasterxml.jackson.module.kotlin.readValue -import com.vitorpamplona.quartz.events.Event -import junit.framework.TestCase.assertEquals -import junit.framework.TestCase.assertTrue -import kotlinx.coroutines.runBlocking -import org.junit.Test -import org.junit.runner.RunWith -import java.io.InputStreamReader - -@RunWith(AndroidJUnit4::class) -class LargeDBSignatureCheck { - - @Test - fun insertDatabaseSample() = runBlocking { - val fullDBInputStream = getInstrumentation().context.assets.open("nostr_vitor_short.json") - - val eventArray = Event.mapper.readValue>( - InputStreamReader(fullDBInputStream) - ) as List - - var counter = 0 - eventArray.forEach { - assertTrue(it.hasValidSignature()) - counter ++ - } - - assertEquals(eventArray.size, counter) - } - -} \ No newline at end of file diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/LnInvoiceUtilTest.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/LnInvoiceUtilTest.kt deleted file mode 100644 index 2f76c5fc..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/LnInvoiceUtilTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.vitorpamplona.quartz - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.vitorpamplona.quartz.encoders.LnInvoiceUtil -import org.junit.Assert -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class LnInvoiceUtilTest { - @Test - fun test100KAmountCalculation() { - val bolt11 = "lnbc1m1pjt9u0qsp553q90pj5mafzv20w45eqavned9tgwhl4q99n9s5ppcw24nzw3zeqpp5002kd3ktym67du86kj665fgaev7ka8ys7j5yz5fg686lr5e2gfkshp5dkk27nnuax05az3pk2r6ytxtvwn5j4xzsq9ajprhc7crjkmgvr3qxqyjw5qcqpjrzjqtzxvfsuxe4l92pf97tt4rcgpy2xalkmlwexh899wqxf83l8nwv4xzh0gvqq89qqqqqqqqlgqqqqq0gqvs9qxpqysgqx5mz04wd7kqu5zhhel9enr036hjrp4gga0nz084p2asjl36a0zmrk6mhqa249zsgqref2rlvhffm73u7rxgr47gden6rugup4ksvpzsqvds4pz" - // Context of the app under test. - Assert.assertEquals(100000, LnInvoiceUtil.getAmountInSats(bolt11).toLong()) - } - - @Test - fun test100GAmountCalculation() { - val bolt11 = "lnbc1000000000000000p1pjtxqf0pp5myqxhcufqy56elfsg9dd4dthnqptusnnpwnul7u86l95xzjgqd8shp5gueg34sgm3u3nxqjqyunvvqdu0pr6jz6mwh4ew4886f2lpf4cmrqxqztgsp5w0cdfd45dfnqwex5gn85x7fru3jcrxhlcx3enx835477m3gdfcuq9qyyssqelrcmm7p9qazgjuxtdg7sd8nq5cscl2tratjlclt5rk5mc7uq2lphq3r2a43j5ua4leakc4emq8yp2yxdnzvzszpw6u2afac0kgl7hspfj67ta" - // Context of the app under test. - Assert.assertEquals(100000000000, LnInvoiceUtil.getAmountInSats(bolt11).toLong()) - } -} diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/PrivateZapTests.kt b/quartz/src/androidTest/java/com/vitorpamplona/quartz/PrivateZapTests.kt deleted file mode 100644 index 212caab4..00000000 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/PrivateZapTests.kt +++ /dev/null @@ -1,134 +0,0 @@ -package com.vitorpamplona.quartz - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.events.Event -import com.vitorpamplona.quartz.events.LnZapEvent -import com.vitorpamplona.quartz.events.LnZapRequestEvent -import com.vitorpamplona.quartz.events.LnZapRequestEvent.Companion.createEncryptionPrivateKey -import com.vitorpamplona.quartz.encoders.Hex -import junit.framework.TestCase.assertNotNull -import junit.framework.TestCase.fail -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class PrivateZapTests { - - @Test - fun testPollZap() { - val poll = Event.fromJson( - """{ - "content": "New poll \n\n #zappoll", - "created_at": 1682440713, - "id": "16291ba452bb0786a4bf5c278d38de73c96b58c056ed75c5ea466b0795197288", - "kind": 6969, - "pubkey": "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a", - "sig": "ac05fa4004c3f7c42913c87b11bf9714bb61a3f0940863a6b9ff0f8105b399add72dbc09bf944c79b9a72ef009ec6905adedbd2c4c8fb3d2f57007bad8fcb279", - "tags": [ - [ - "poll_option", - "0", - "Test 1" - ], - [ - "poll_option", - "1", - "Test 2" - ], - [ - "value_maximum", - "null" - ], - [ - "value_minimum", - "null" - ], - [ - "consensus_threshold", - "null" - ], - [ - "closed_at", - "null" - ] - ], - "seenOn": [ - "wss://relay.damus.io/" - ] -} -""") - - val loggedIn = Hex.decode("e8e7197ccc53c9ed4cf9b1c8dce085475fa1ffdd71f2c14e44fe23d0bdf77598") - - val privateZapRequest = LnZapRequestEvent.create( - poll, - setOf("wss://relay.damus.io/"), - loggedIn, - 0, - "", - LnZapEvent.ZapType.PRIVATE - ) - - val recepientPK = privateZapRequest.zappedAuthor().firstOrNull() - val recepientPost = privateZapRequest.zappedPost().firstOrNull() - - if (recepientPK != null && recepientPost != null) { - val privateKey = createEncryptionPrivateKey(loggedIn.toHexKey(), recepientPost, privateZapRequest.createdAt) - val decodedPrivateZap = - privateZapRequest.getPrivateZapEvent(privateKey, recepientPK) - - println(decodedPrivateZap?.toJson()) - assertNotNull(decodedPrivateZap) - } else { - fail("Should not be null") - } - } - - @Test - fun testKind1PrivateZap() { - val textNote = Event.fromJson( - """{ - "content": "Testing copied author. \n\nnostr:npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z", - "created_at": 1682369982, - "id": "c757e1371d715c711ec9ef9740a3df6475d64b3d0af45ffcbfca08d273baf1c1", - "kind": 1, - "pubkey": "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a", - "sig": "1fb5b6fd980f4c2ef058d5f4f7b166c0e5fb21eff26fe9cacd87a9aa4feb344485841ebcc26a233bf8d6ea0a66acf0db2bfdb11ad1cb04bcea4cfa3e78c3eaf1", - "tags": [ - [ - "p", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" - ] - ], - "seenOn": [ - "wss://relay.damus.io/" - ] -} -""") - - val loggedIn = Hex.decode("e8e7197ccc53c9ed4cf9b1c8dce085475fa1ffdd71f2c14e44fe23d0bdf77598") - - val privateZapRequest = LnZapRequestEvent.create( - textNote, - setOf("wss://relay.damus.io/", "wss://relay.damus2.io/", "wss://relay.damus3.io/"), - loggedIn, - null, - "test", - LnZapEvent.ZapType.PRIVATE - ) - - val recepientPK = privateZapRequest.zappedAuthor().firstOrNull() - val recepientPost = privateZapRequest.zappedPost().firstOrNull() - - if (recepientPK != null && recepientPost != null) { - val privateKey = createEncryptionPrivateKey(loggedIn.toHexKey(), recepientPost, privateZapRequest.createdAt) - val decodedPrivateZap = privateZapRequest.getPrivateZapEvent(privateKey, recepientPK) - - println(decodedPrivateZap?.toJson()) - assertNotNull(decodedPrivateZap) - } else { - fail("Should not be null") - } - } -} diff --git a/quartz/src/main/AndroidManifest.xml b/quartz/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68..00000000 --- a/quartz/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/crypto/CryptoUtils.kt b/quartz/src/main/java/com/vitorpamplona/quartz/crypto/CryptoUtils.kt deleted file mode 100644 index ccf3f0a3..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/crypto/CryptoUtils.kt +++ /dev/null @@ -1,304 +0,0 @@ -package com.vitorpamplona.quartz.crypto - -import android.util.Log -import android.util.LruCache -import com.goterl.lazysodium.SodiumAndroid -import com.goterl.lazysodium.utils.Key -import com.vitorpamplona.quartz.encoders.Hex -import com.vitorpamplona.quartz.events.Event -import fr.acinq.secp256k1.Secp256k1 -import java.security.MessageDigest -import java.security.SecureRandom -import java.util.Base64 -import javax.crypto.Cipher -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec - - -object CryptoUtils { - private val sharedKeyCache04 = LruCache(200) - private val sharedKeyCache44 = LruCache(200) - - private val secp256k1 = Secp256k1.get() - private val libSodium = SodiumAndroid() - private val random = SecureRandom() - private val h02 = Hex.decode("02") - - fun clearCache() { - sharedKeyCache04.evictAll() - sharedKeyCache44.evictAll() - } - - fun randomInt(bound: Int): Int { - return random.nextInt(bound) - } - - /** - * Provides a 32B "private key" aka random number - */ - fun privkeyCreate() = random(32) - - fun random(size: Int): ByteArray { - val bytes = ByteArray(size) - random.nextBytes(bytes) - return bytes - } - - fun pubkeyCreate(privKey: ByteArray) = - secp256k1.pubKeyCompress(secp256k1.pubkeyCreate(privKey)).copyOfRange(1, 33) - - fun sign(data: ByteArray, privKey: ByteArray): ByteArray = - secp256k1.signSchnorr(data, privKey, null) - - fun verifySignature( - signature: ByteArray, - hash: ByteArray, - pubKey: ByteArray - ): Boolean { - return secp256k1.verifySchnorr(signature, hash, pubKey) - } - - fun sha256(data: ByteArray): ByteArray { - // Creates a new buffer every time - return MessageDigest.getInstance("SHA-256").digest(data) - } - - fun encryptNIP04(msg: String, privateKey: ByteArray, pubKey: ByteArray): String { - val info = encryptNIP04(msg, getSharedSecretNIP04(privateKey, pubKey)) - val encryptionInfo = EncryptedInfoString( - v = info.v, - nonce = Base64.getEncoder().encodeToString(info.nonce), - ciphertext = Base64.getEncoder().encodeToString(info.ciphertext) - ) - return "${encryptionInfo.ciphertext}?iv=${encryptionInfo.nonce}" - } - - fun encryptNIP04Json(msg: String, privateKey: ByteArray, pubKey: ByteArray): EncryptedInfo { - return encryptNIP04(msg, getSharedSecretNIP04(privateKey, pubKey)) - } - - fun encryptNIP04(msg: String, sharedSecret: ByteArray): EncryptedInfo { - val iv = ByteArray(16) - random.nextBytes(iv) - val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") - cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(sharedSecret, "AES"), IvParameterSpec(iv)) - //val ivBase64 = Base64.getEncoder().encodeToString(iv) - val encryptedMsg = cipher.doFinal(msg.toByteArray()) - //val encryptedMsgBase64 = Base64.getEncoder().encodeToString(encryptedMsg) - return EncryptedInfo(encryptedMsg, iv, Nip44Version.NIP04.versionCode) - } - - fun decryptNIP04(msg: String, privateKey: ByteArray, pubKey: ByteArray): String { - val sharedSecret = getSharedSecretNIP04(privateKey, pubKey) - return decryptNIP04(msg, sharedSecret) - } - - fun decryptNIP04(encryptedInfo: EncryptedInfo, privateKey: ByteArray, pubKey: ByteArray): String { - val sharedSecret = getSharedSecretNIP04(privateKey, pubKey) - return decryptNIP04(encryptedInfo.ciphertext, encryptedInfo.nonce, sharedSecret) - } - - fun decryptNIP04(msg: String, sharedSecret: ByteArray): String { - val parts = msg.split("?iv=") - return decryptNIP04(parts[0], parts[1], sharedSecret) - } - - private fun decryptNIP04(cipher: String, nonce: String, sharedSecret: ByteArray): String { - val iv = Base64.getDecoder().decode(nonce) - val encryptedMsg = Base64.getDecoder().decode(cipher) - return decryptNIP04(encryptedMsg, iv, sharedSecret) - } - - private fun decryptNIP04(encryptedMsg: ByteArray, iv: ByteArray, sharedSecret: ByteArray): String { - val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(sharedSecret, "AES"), IvParameterSpec(iv)) - return String(cipher.doFinal(encryptedMsg)) - } - - fun encryptNIP44(msg: String, privateKey: ByteArray, pubKey: ByteArray): EncryptedInfo { - val sharedSecret = getSharedSecretNIP44(privateKey, pubKey) - return encryptNIP44(msg, sharedSecret) - } - - fun encryptNIP44(msg: String, sharedSecret: ByteArray): EncryptedInfo { - val nonce = ByteArray(24) - random.nextBytes(nonce) - - val cipher = cryptoStreamXChaCha20Xor( - libSodium = libSodium, - messageBytes = msg.toByteArray(),//compress(msg), - nonce = nonce, - key = Key.fromBytes(sharedSecret) - ) - - return EncryptedInfo( - ciphertext = cipher ?: ByteArray(0), - nonce = nonce, - v = Nip44Version.NIP44.versionCode - ) - } - - fun decryptNIP44(encryptedInfo: EncryptedInfo, privateKey: ByteArray, pubKey: ByteArray): String? { - val sharedSecret = getSharedSecretNIP44(privateKey, pubKey) - return decryptNIP44(encryptedInfo, sharedSecret) - } - - fun decryptNIP44(encryptedInfo: EncryptedInfo, sharedSecret: ByteArray): String? { - return cryptoStreamXChaCha20Xor( - libSodium = libSodium, - messageBytes = encryptedInfo.ciphertext, - nonce = encryptedInfo.nonce, - key = Key.fromBytes(sharedSecret) - )?.decodeToString() //?.let { decompress(it) } - } - - /** - * @return 32B shared secret - */ - fun getSharedSecretNIP04(privateKey: ByteArray, pubKey: ByteArray): ByteArray { - val hash = combinedHashCode(privateKey, pubKey) - val preComputed = sharedKeyCache04[hash] - if (preComputed != null) return preComputed - - val computed = computeSharedSecretNIP04(privateKey, pubKey) - sharedKeyCache04.put(hash, computed) - return computed - } - - /** - * @return 32B shared secret - */ - fun computeSharedSecretNIP04(privateKey: ByteArray, pubKey: ByteArray): ByteArray = - secp256k1.pubKeyTweakMul(h02 + pubKey, privateKey).copyOfRange(1, 33) - - /** - * @return 32B shared secret - */ - fun getSharedSecretNIP44(privateKey: ByteArray, pubKey: ByteArray): ByteArray { - val hash = combinedHashCode(privateKey, pubKey) - val preComputed = sharedKeyCache44[hash] - if (preComputed != null) return preComputed - - val computed = computeSharedSecretNIP44(privateKey, pubKey) - sharedKeyCache44.put(hash, computed) - return computed - } - - /** - * @return 32B shared secret - */ - fun computeSharedSecretNIP44(privateKey: ByteArray, pubKey: ByteArray): ByteArray = - sha256(secp256k1.pubKeyTweakMul(h02 + pubKey, privateKey).copyOfRange(1, 33)) -} - -data class EncryptedInfo(val ciphertext: ByteArray, val nonce: ByteArray, val v: Int) -data class EncryptedInfoString(val ciphertext: String, val nonce: String, val v: Int) - -enum class Nip44Version(val versionCode: Int) { - NIP04(0), - NIP44(1) -} - - -fun encodeNIP44(info: EncryptedInfo): String { - return encodeByteArray(info) -} - -fun decodeNIP44(str: String): EncryptedInfo? { - if (str.isEmpty()) return null - return if (str[0] == '{') { - decodeJackson(str) - } else { - decodeByteArray(str) - } -} - -fun encodeByteArray(info: EncryptedInfo): String { - return Base64.getEncoder().encodeToString(byteArrayOf(info.v.toByte()) + info.nonce + info.ciphertext) -} - -fun decodeByteArray(base64: String): EncryptedInfo? { - return try { - val byteArray = Base64.getDecoder().decode(base64) - return EncryptedInfo( - v = byteArray[0].toInt(), - nonce = byteArray.copyOfRange(1, 25), - ciphertext = byteArray.copyOfRange(25, byteArray.size) - ) - } catch (e: Exception) { - Log.w("CryptoUtils", "Unable to Parse encrypted payload: ${base64}") - null - } -} - -fun encodeJackson(info: EncryptedInfo): String { - return Event.mapper.writeValueAsString( - EncryptedInfoString( - v = info.v, - nonce = Base64.getEncoder().encodeToString(info.nonce), - ciphertext = Base64.getEncoder().encodeToString(info.ciphertext) - ) - ) -} - -fun decodeJackson(json: String): EncryptedInfo { - val info = Event.mapper.readValue(json, EncryptedInfoString::class.java) - return EncryptedInfo( - v = info.v, - nonce = Base64.getDecoder().decode(info.nonce), - ciphertext = Base64.getDecoder().decode(info.ciphertext) - ) -} - -fun combinedHashCode(a: ByteArray, b: ByteArray): Int { - var result = 1 - for (element in a) result = 31 * result + element - for (element in b) result = 31 * result + element - return result -} - -/* -OLD Versions used for the Benchmark - -fun encodeKotlin(info: EncryptedInfo): String { - return Json.encodeToString( - EncryptedInfoString( - v = info.v, - nonce = Base64.getEncoder().encodeToString(info.nonce), - ciphertext = Base64.getEncoder().encodeToString(info.ciphertext) - ) - ) -} - -fun decodeKotlin(json: String): EncryptedInfo { - val info = Json.decodeFromString(json) - return EncryptedInfo( - v = info.v, - nonce = Base64.getDecoder().decode(info.nonce), - ciphertext = Base64.getDecoder().decode(info.ciphertext) - ) -} - -fun encodeCSV(info: EncryptedInfo): String { - return "${info.v},${Base64.getEncoder().encodeToString(info.nonce)},${Base64.getEncoder().encodeToString(info.ciphertext)}" -} - -fun decodeCSV(base64: String): EncryptedInfo { - val parts = base64.split(",") - return EncryptedInfo( - v = parts[0].toInt(), - nonce = Base64.getDecoder().decode(parts[1]), - ciphertext = Base64.getDecoder().decode(parts[2]) - ) -} - - -fun compress(input: String): ByteArray { - return DeflaterInputStream(input.toByteArray().inputStream()).readBytes() -} - -fun decompress(inputBytes: ByteArray): String { - return InflaterInputStream(inputBytes.inputStream()).bufferedReader().use { it.readText() } -} - -*/ \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/crypto/KeyPair.kt b/quartz/src/main/java/com/vitorpamplona/quartz/crypto/KeyPair.kt deleted file mode 100644 index adb67b99..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/crypto/KeyPair.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.vitorpamplona.quartz.crypto - -import com.vitorpamplona.quartz.encoders.toHexKey - -class KeyPair( - privKey: ByteArray? = null, - pubKey: ByteArray? = null -) { - val privKey: ByteArray? - val pubKey: ByteArray - - init { - if (privKey == null) { - if (pubKey == null) { - // create new, random keys - this.privKey = CryptoUtils.privkeyCreate() - this.pubKey = CryptoUtils.pubkeyCreate(this.privKey) - } else { - // this is a read-only account - check(pubKey.size == 32) - this.privKey = null - this.pubKey = pubKey - } - } else { - // as private key is provided, ignore the public key and set keys according to private key - this.privKey = privKey - this.pubKey = CryptoUtils.pubkeyCreate(privKey) - } - } - - override fun toString(): String { - return "KeyPair(privateKey=${privKey?.toHexKey()}, publicKey=${pubKey.toHexKey()}" - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/crypto/SodiumUtils.kt b/quartz/src/main/java/com/vitorpamplona/quartz/crypto/SodiumUtils.kt deleted file mode 100644 index 17b4e7a9..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/crypto/SodiumUtils.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.vitorpamplona.quartz.crypto - -import com.goterl.lazysodium.SodiumAndroid -import com.goterl.lazysodium.utils.Key - -/** - * I initially extended these methods from the Sodium and SodiumAndroid classes - * But JNI doesn't like it. There is some native method overriding bug - * when using Kotlin extensions - **/ - -fun /*Sodium.*/crypto_stream_xchacha20_xor_ic( - libSodium: SodiumAndroid, - cipher: ByteArray, - message: ByteArray, - messageLen: Long, - nonce: ByteArray, - ic: Long, - key: ByteArray -): Int { - /** - * C++ Code: - * - * unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES]; - * crypto_core_hchacha20(k2, n, k, NULL); - * return crypto_stream_chacha20_xor_ic( - * c, m, mlen, n + crypto_core_hchacha20_INPUTBYTES, ic, k2); - */ - val k2 = ByteArray(32) - - val nonceChaCha = nonce.drop(16).toByteArray() - assert(nonceChaCha.size == 8) - - libSodium.crypto_core_hchacha20(k2, nonce, key, null) - return libSodium.crypto_stream_chacha20_xor_ic( - cipher, - message, - messageLen, - nonceChaCha, - ic, - k2 - ) -} - -fun /*Sodium.*/crypto_stream_xchacha20_xor( - libSodium: SodiumAndroid, - cipher: ByteArray, - message: ByteArray, - messageLen: Long, - nonce: ByteArray, - key: ByteArray -): Int { - return crypto_stream_xchacha20_xor_ic(libSodium, cipher, message, messageLen, nonce, 0, key) -} - -fun /*SodiumAndroid.*/cryptoStreamXChaCha20Xor( - libSodium: SodiumAndroid, - cipher: ByteArray, - message: ByteArray, - messageLen: Long, - nonce: ByteArray, - key: ByteArray -): Boolean { - require(!(messageLen < 0 || messageLen > message.size)) { "messageLen out of bounds: $messageLen" } - return crypto_stream_xchacha20_xor( - libSodium, - cipher, - message, - messageLen, - nonce, - key - ) == 0 -} - -fun /*SodiumAndroid.*/cryptoStreamXChaCha20Xor( - libSodium: SodiumAndroid, - messageBytes: ByteArray, - nonce: ByteArray, - key: Key -): ByteArray? { - val mLen = messageBytes.size - val cipher = ByteArray(mLen) - val sucessful = cryptoStreamXChaCha20Xor(libSodium, cipher, messageBytes, mLen.toLong(), nonce, key.asBytes) - return if (sucessful) cipher else null -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/ATag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/ATag.kt deleted file mode 100644 index 8d0c78c7..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/ATag.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.Hex - -@Immutable -data class ATag(val kind: Int, val pubKeyHex: String, val dTag: String, val relay: String?) { - fun toTag() = "$kind:$pubKeyHex:$dTag" - - fun toNAddr(): String { - return TlvBuilder().apply { - addString(Nip19.TlvTypes.SPECIAL, dTag) - addStringIfNotNull(Nip19.TlvTypes.RELAY, relay) - addHex(Nip19.TlvTypes.AUTHOR, pubKeyHex) - addInt(Nip19.TlvTypes.KIND, kind) - }.build().toNAddress() - } - - companion object { - fun isATag(key: String): Boolean { - return key.startsWith("naddr1") || key.contains(":") - } - - fun parse(address: String, relay: String?): ATag? { - return if (address.startsWith("naddr") || address.startsWith("nostr:naddr")) { - parseNAddr(address) - } else { - parseAtag(address, relay) - } - } - - fun parseAtag(atag: String, relay: String?): ATag? { - return try { - val parts = atag.split(":") - Hex.decode(parts[1]) - ATag(parts[0].toInt(), parts[1], parts[2], relay) - } catch (t: Throwable) { - Log.w("ATag", "Error parsing A Tag: $atag: ${t.message}") - null - } - } - - fun parseNAddr(naddr: String): ATag? { - try { - val key = naddr.removePrefix("nostr:") - - if (key.startsWith("naddr")) { - val tlv = Tlv.parse(key.bechToBytes()) - - val d = tlv.firstAsString(Nip19.TlvTypes.SPECIAL) ?: "" - val relay = tlv.firstAsString(Nip19.TlvTypes.RELAY) - val author = tlv.firstAsHex(Nip19.TlvTypes.AUTHOR) - val kind = tlv.firstAsInt(Nip19.TlvTypes.KIND) - - if (kind != null && author != null) { - return ATag(kind, author, d, relay) - } - } - } catch (e: Throwable) { - Log.w("ATag", "Issue trying to Decode NIP19 $this: ${e.message}") - // e.printStackTrace() - } - - return null - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Bech32Util.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Bech32Util.kt deleted file mode 100644 index 6398225d..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Bech32Util.kt +++ /dev/null @@ -1,242 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -/* - * Copyright 2020 ACINQ SAS - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import kotlin.jvm.JvmStatic - -/** - * Bech32 works with 5 bits values, we use this type to make it explicit: whenever you see Int5 it means 5 bits values, - * and whenever you see Byte it means 8 bits values. - */ -private typealias Int5 = Byte - -/** - * Bech32 and Bech32m address formats. - * See https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki and https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki. - */ -object Bech32 { - const val alphabet: String = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" - const val alphabetUpperCase: String = "QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L" - - enum class Encoding(public val constant: Int) { - Bech32(1), - Bech32m(0x2bc830a3), - Beck32WithoutChecksum(0) - } - - // char -> 5 bits value - private val map = Array(255) { -1 } - - init { - for (i in 0..alphabet.lastIndex) { - map[alphabet[i].code] = i.toByte() - } - for (i in 0..alphabetUpperCase.lastIndex) { - map[alphabetUpperCase[i].code] = i.toByte() - } - } - - fun expand(hrp: String): Array { - val half = hrp.length + 1 - val size = half + hrp.length - return Array(size) { - when (it) { - in hrp.indices -> hrp[it].code.shr(5).toByte() - in half until size -> (hrp[it - half].code and 31).toByte() - else -> 0 - } - } - } - - private val GEN = arrayOf(0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3) - - fun polymod(values: Array, values1: Array): Int { - var chk = 1 - values.forEach { v -> - val b = chk shr 25 - chk = ((chk and 0x1ffffff) shl 5) xor v.toInt() - for (i in 0..5) { - if (((b shr i) and 1) != 0) chk = chk xor GEN[i] - } - } - values1.forEach { v -> - val b = chk shr 25 - chk = ((chk and 0x1ffffff) shl 5) xor v.toInt() - for (i in 0..5) { - if (((b shr i) and 1) != 0) chk = chk xor GEN[i] - } - } - return chk - } - - /** - * @param hrp human readable prefix - * @param int5s 5-bit data - * @param encoding encoding to use (bech32 or bech32m) - * @return hrp + data encoded as a Bech32 string - */ - @JvmStatic - public fun encode(hrp: String, int5s: ArrayList, encoding: Encoding): String { - require(hrp.lowercase() == hrp || hrp.uppercase() == hrp) { "mixed case strings are not valid bech32 prefixes" } - val dataWithChecksum = when (encoding) { - Encoding.Beck32WithoutChecksum -> int5s - else -> addChecksum(hrp, int5s, encoding) - } - - val charArray = CharArray(dataWithChecksum.size) { - alphabet[dataWithChecksum[it].toInt()] - }.concatToString() - - return hrp + "1" + charArray - } - - /** - * @param hrp human readable prefix - * @param data data to encode - * @param encoding encoding to use (bech32 or bech32m) - * @return hrp + data encoded as a Bech32 string - */ - @JvmStatic - public fun encodeBytes(hrp: String, data: ByteArray, encoding: Encoding): String = encode(hrp, eight2five(data), encoding) - - /** - * decodes a bech32 string - * @param bech32 bech32 string - * @param noChecksum if true, the bech32 string doesn't have a checksum - * @return a (hrp, data, encoding) tuple - */ - @JvmStatic - public fun decode(bech32: String, noChecksum: Boolean = false): Triple, Encoding> { - var pos = 0 - bech32.forEachIndexed { index, char -> - require( char.code in 33..126 ) { "invalid character ${char}" } - if (char == '1') { - pos = index - } - } - - val hrp = bech32.take(pos) - require(hrp.length in 1..83) { "hrp must contain 1 to 83 characters" } - - val data = Array(bech32.length - pos - 1) { - map[bech32[pos + 1 + it].code] - } - - return if (noChecksum) { - Triple(hrp, data, Encoding.Beck32WithoutChecksum) - } else { - val encoding = when (polymod(expand(hrp), data)) { - Encoding.Bech32.constant -> Encoding.Bech32 - Encoding.Bech32m.constant -> Encoding.Bech32m - else -> throw IllegalArgumentException("invalid checksum for $bech32") - } - Triple(hrp, data.copyOfRange(0, data.size-6), encoding) - } - } - - /** - * decodes a bech32 string - * @param bech32 bech32 string - * @param noChecksum if true, the bech32 string doesn't have a checksum - * @return a (hrp, data, encoding) tuple - */ - @JvmStatic - public fun decodeBytes(bech32: String, noChecksum: Boolean = false): Triple { - val (hrp, int5s, encoding) = decode(bech32, noChecksum) - return Triple(hrp, five2eight(int5s, 0), encoding) - } - - val ZEROS = arrayOf(0.toByte(), 0.toByte(), 0.toByte(), 0.toByte(), 0.toByte(), 0.toByte()) - - /** - * @param hrp Human Readable Part - * @param data data (a sequence of 5 bits integers) - * @param encoding encoding to use (bech32 or bech32m) - * @return a checksum computed over hrp and data - */ - private fun addChecksum(hrp: String, data: ArrayList, encoding: Encoding): ArrayList { - val values = expand(hrp) + data - val poly = polymod(values, ZEROS) xor encoding.constant - - for (i in 0 until 6) { - data.add((poly.shr(5 * (5 - i)) and 31).toByte()) - } - - return data - } - - /** - * @param input a sequence of 8 bits integers - * @return a sequence of 5 bits integers - */ - @JvmStatic - public fun eight2five(input: ByteArray): ArrayList { - var buffer = 0L - val output = ArrayList(input.size * 2) //larger array on purpose. Checksum is added later. - var count = 0 - input.forEach { b -> - buffer = (buffer shl 8) or (b.toLong() and 0xff) - count += 8 - while (count >= 5) { - output.add(((buffer shr (count - 5)) and 31).toByte()) - count -= 5 - } - } - if (count > 0) output.add(((buffer shl (5 - count)) and 31).toByte()) - return output - } - - /** - * @param input a sequence of 5 bits integers - * @return a sequence of 8 bits integers - */ - @JvmStatic - public fun five2eight(input: Array, offset: Int): ByteArray { - var buffer = 0L - val output = ArrayList(input.size) - var count = 0 - for (i in offset..input.lastIndex) { - val b = input[i] - buffer = (buffer shl 5) or (b.toLong() and 31) - count += 5 - while (count >= 8) { - output.add(((buffer shr (count - 8)) and 0xff).toByte()) - count -= 8 - } - } - require(count <= 4) { "Zero-padding of more than 4 bits" } - require((buffer and ((1L shl count) - 1L)) == 0L) { "Non-zero padding in 8-to-5 conversion" } - return output.toByteArray() - } -} - -fun ByteArray.toNsec() = Bech32.encodeBytes(hrp = "nsec", this, Bech32.Encoding.Bech32) -fun ByteArray.toNpub() = Bech32.encodeBytes(hrp = "npub", this, Bech32.Encoding.Bech32) -fun ByteArray.toNote() = Bech32.encodeBytes(hrp = "note", this, Bech32.Encoding.Bech32) -fun ByteArray.toNEvent() = Bech32.encodeBytes(hrp = "nevent", this, Bech32.Encoding.Bech32) -fun ByteArray.toNAddress() = Bech32.encodeBytes(hrp = "naddr", this, Bech32.Encoding.Bech32) -fun ByteArray.toLnUrl() = Bech32.encodeBytes(hrp = "lnurl", this, Bech32.Encoding.Bech32) - -fun String.bechToBytes(hrp: String? = null): ByteArray { - val decodedForm = Bech32.decodeBytes(this) - hrp?.also { - if (it != decodedForm.first) { - throw IllegalArgumentException("Expected $it but obtained ${decodedForm.first}") - } - } - return decodedForm.second -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/HexUtils.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/HexUtils.kt deleted file mode 100644 index 11ccbfde..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/HexUtils.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -/** Makes the distinction between String and Hex **/ -typealias HexKey = String - -fun ByteArray.toHexKey(): HexKey { - return Hex.encode(this) -} - -fun HexKey.hexToByteArray(): ByteArray { - return Hex.decode(this) -} - -object HexValidator { - private fun isHex2(c: Char): Boolean { - return when (c) { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F', ' ' -> true - else -> false - } - } - - fun isHex(hex: String?): Boolean { - if (hex == null) return false - var isHex = true - for (c in hex.toCharArray()) { - if (!isHex2(c)) { - isHex = false - break - } - } - return isHex - } -} - -object Hex { - private val hexCode = arrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f') - - // Faster if no calculations are needed. - private fun hexToBin(ch: Char): Int = when (ch) { - in '0'..'9' -> ch - '0' - in 'a'..'f' -> ch - 'a' + 10 - in 'A'..'F' -> ch - 'A' + 10 - else -> throw IllegalArgumentException("illegal hex character: $ch") - } - - @JvmStatic - fun decode(hex: String): ByteArray { - // faster version of hex decoder - require(hex.length % 2 == 0) - val outSize = hex.length / 2 - val out = ByteArray(outSize) - - for (i in 0 until outSize) { - out[i] = (hexToBin(hex[2 * i]) * 16 + hexToBin(hex[2 * i + 1])).toByte() - } - - return out - } - - @JvmStatic - fun encode(input: ByteArray): String { - val len = input.size - val out = CharArray(len * 2) - for (i in 0 until len) { - out[i*2] = hexCode[(input[i].toInt() shr 4) and 0xF] - out[i*2+1] = hexCode[input[i].toInt() and 0xF] - } - return String(out) - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/LnInvoiceUtil.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/LnInvoiceUtil.kt deleted file mode 100644 index 80d0f0f9..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/LnInvoiceUtil.kt +++ /dev/null @@ -1,173 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -import java.math.BigDecimal -import java.util.Locale -import java.util.regex.Pattern - -/** based on litecoinj */ -object LnInvoiceUtil { - private val invoicePattern = Pattern.compile("lnbc((?\\d+)(?[munp])?)?1[^1\\s]+", Pattern.CASE_INSENSITIVE) - - /** The Bech32 character set for encoding. */ - private const val CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" - - /** The Bech32 character set for decoding. */ - private val CHARSET_REV = byteArrayOf( - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 - ) - - /** Find the polynomial with value coefficients mod the generator as 30-bit. */ - private fun polymod(values: ByteArray): Int { - var c = 1 - for (v_i in values) { - val c0 = c ushr 25 and 0xff - c = c and 0x1ffffff shl 5 xor (v_i.toInt() and 0xff) - if (c0 and 1 != 0) c = c xor 0x3b6a57b2 - if (c0 and 2 != 0) c = c xor 0x26508e6d - if (c0 and 4 != 0) c = c xor 0x1ea119fa - if (c0 and 8 != 0) c = c xor 0x3d4233dd - if (c0 and 16 != 0) c = c xor 0x2a1462b3 - } - return c - } - - /** Expand a HRP for use in checksum computation. */ - private fun expandHrp(hrp: String): ByteArray { - val hrpLength = hrp.length - val ret = ByteArray(hrpLength * 2 + 1) - for (i in 0 until hrpLength) { - val c = hrp[i].code and 0x7f // Limit to standard 7-bit ASCII - ret[i] = (c ushr 5 and 0x07).toByte() - ret[i + hrpLength + 1] = (c and 0x1f).toByte() - } - ret[hrpLength] = 0 - return ret - } - - /** Verify a checksum. */ - private fun verifyChecksum(hrp: String, values: ByteArray): Boolean { - val hrpExpanded: ByteArray = expandHrp(hrp) - val combined = ByteArray(hrpExpanded.size + values.size) - System.arraycopy(hrpExpanded, 0, combined, 0, hrpExpanded.size) - System.arraycopy(values, 0, combined, hrpExpanded.size, values.size) - return polymod(combined) == 1 - } - - class AddressFormatException(message: String) : Exception(message) - - fun decodeUnlimitedLength(invoice: String): Boolean { - var lower = false - var upper = false - for (i in 0 until invoice.length) { - val c = invoice[i] - if (c.code < 33 || c.code > 126) throw AddressFormatException("Invalid character: $c, pos: $i") - if (c in 'a'..'z') { - if (upper) throw AddressFormatException("Invalid character: $c, pos: $i") - lower = true - } - if (c in 'A'..'Z') { - if (lower) throw AddressFormatException("Invalid character: $c, pos: $i") - upper = true - } - } - val pos = invoice.lastIndexOf('1') - if (pos < 1) throw AddressFormatException("Missing human-readable part") - val dataPartLength = invoice.length - 1 - pos - if (dataPartLength < 6) throw AddressFormatException("Data part too short: $dataPartLength") - val values = ByteArray(dataPartLength) - for (i in 0 until dataPartLength) { - val c = invoice[i + pos + 1] - if (CHARSET_REV.get(c.code).toInt() == -1) throw AddressFormatException("Invalid character: " + c + ", pos: " + (i + pos + 1)) - values[i] = CHARSET_REV.get(c.code) - } - val hrp = invoice.substring(0, pos).lowercase(Locale.ROOT) - if (!verifyChecksum(hrp, values)) throw AddressFormatException("Invalid Checksum") - return true - } - - /** - * Parses invoice amount according to - * https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md#human-readable-part - * @return invoice amount in bitcoins, zero if the invoice has no amount - * @throws RuntimeException if invoice format is incorrect - */ - private fun getAmount(invoice: String): BigDecimal { - try { - decodeUnlimitedLength(invoice) // checksum must match - } catch (e: AddressFormatException) { - throw IllegalArgumentException("Cannot decode invoice: $invoice", e) - } - - val matcher = invoicePattern.matcher(invoice) - require(matcher.matches()) { "Failed to match HRP pattern" } - val amountGroup = matcher.group("amount") - val multiplierGroup = matcher.group("multiplier") - if (amountGroup == null) { - return BigDecimal.ZERO - } - val amount = BigDecimal(amountGroup) - if (multiplierGroup == null) { - return amount - } - require(!(multiplierGroup == "p" && amountGroup[amountGroup.length - 1] != '0')) { "sub-millisatoshi amount" } - return amount.multiply(multiplier(multiplierGroup)) - } - - fun getAmountInSats(invoice: String): BigDecimal { - return getAmount(invoice).multiply(BigDecimal(100000000)) - } - - private fun multiplier(multiplier: String): BigDecimal { - return when (multiplier.lowercase()) { - "m" -> BigDecimal("0.001") - "u" -> BigDecimal("0.000001") - "n" -> BigDecimal("0.000000001") - "p" -> BigDecimal("0.000000000001") - else -> throw IllegalArgumentException("Invalid multiplier: $multiplier") - } - } - - /** - * Finds LN invoice in the provided input string and returns it. - * For example for input = "aaa bbb lnbc1xxx ccc" it will return "lnbc1xxx" - * It will only return the first invoice found in the input. - * - * @return the invoice if it was found. null for null input or if no invoice is found - */ - fun findInvoice(input: String?): String? { - if (input == null) { - return null - } - val matcher = invoicePattern.matcher(input) - return if (matcher.find()) { - matcher.group() - } else { - null - } - } - - /** - * If the string contains an LN invoice, returns a Pair of the start and end - * positions of the invoice in the string. Otherwise, returns (0, 0). This is - * used to ensure we don't accidentally cut an invoice in the middle when taking - * only a portion of the available text. - */ - fun locateInvoice(input: String?): Pair { - if (input == null) { - return Pair(0, 0) - } - val matcher = invoicePattern.matcher(input) - return if (matcher.find()) { - Pair(matcher.start(), matcher.end()) - } else { - Pair(0, 0) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/LnWithdrawalUtil.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/LnWithdrawalUtil.kt deleted file mode 100644 index bedf72d6..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/LnWithdrawalUtil.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -import java.util.regex.Pattern - -object LnWithdrawalUtil { - private val withdrawalPattern = Pattern.compile( - "lnurl.+", - Pattern.CASE_INSENSITIVE - ) - - /** - * Finds LN withdrawal in the provided input string and returns it. - * For example for input = "aaa bbb lnbc1xxx ccc" it will return "lnbc1xxx" - * It will only return the first withdrawal found in the input. - * - * @return the invoice if it was found. null for null input or if no invoice is found - */ - fun findWithdrawal(input: String?): String? { - if (input == null) { - return null - } - val matcher = withdrawalPattern.matcher(input) - return if (matcher.find()) { - matcher.group() - } else { - null - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Nip19.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Nip19.kt deleted file mode 100644 index 229a4f84..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Nip19.kt +++ /dev/null @@ -1,178 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.Hex -import java.util.regex.Pattern - -object Nip19 { - enum class Type { - USER, NOTE, EVENT, RELAY, ADDRESS - } - - enum class TlvTypes(val id: Byte) { - SPECIAL(0), - RELAY(1), - AUTHOR(2), - KIND(3); - } - - val nip19regex = Pattern.compile( - "(nostr:)?@?(nsec1|npub1|nevent1|naddr1|note1|nprofile1|nrelay1)([qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)([\\S]*)", - Pattern.CASE_INSENSITIVE - ) - - @Immutable - data class Return( - val type: Type, - val hex: String, - val relay: String? = null, - val author: String? = null, - val kind: Int? = null, - val additionalChars: String = "" - ) - - fun uriToRoute(uri: String?): Return? { - if (uri == null) return null - - try { - val matcher = nip19regex.matcher(uri) - if (!matcher.find()) { - return null - } - - val uriScheme = matcher.group(1) // nostr: - val type = matcher.group(2) // npub1 - val key = matcher.group(3) // bech32 - val additionalChars = matcher.group(4) // additional chars - - return parseComponents(uriScheme, type, key, additionalChars) - } catch (e: Throwable) { - Log.e("NIP19 Parser", "Issue trying to Decode NIP19 $uri: ${e.message}", e) - } - - return null - } - - fun parseComponents( - uriScheme: String?, - type: String, - key: String?, - additionalChars: String? - ): Return? { - return try { - val bytes = (type + key).bechToBytes() - val parsed = when (type.lowercase()) { - "npub1" -> npub(bytes) - "note1" -> note(bytes) - "nprofile1" -> nprofile(bytes) - "nevent1" -> nevent(bytes) - "nrelay1" -> nrelay(bytes) - "naddr1" -> naddr(bytes) - else -> null - } - parsed?.copy(additionalChars = additionalChars ?: "") - } catch (e: Throwable) { - Log.w("NIP19 Parser", "Issue trying to Decode NIP19 $key: ${e.message}", e) - null - } - } - - private fun npub(bytes: ByteArray): Return { - return Return(Type.USER, bytes.toHexKey()) - } - - private fun note(bytes: ByteArray): Return { - return Return(Type.NOTE, bytes.toHexKey()) - } - - private fun nprofile(bytes: ByteArray): Return? { - val tlv = Tlv.parse(bytes) - - val hex = tlv.firstAsHex(TlvTypes.SPECIAL) ?: return null - val relay = tlv.firstAsString(TlvTypes.RELAY) - - return Return(Type.USER, hex, relay) - } - - private fun nevent(bytes: ByteArray): Return? { - val tlv = Tlv.parse(bytes) - - val hex = tlv.firstAsHex(TlvTypes.SPECIAL) ?: return null - val relay = tlv.firstAsString(TlvTypes.RELAY) - val author = tlv.firstAsHex(TlvTypes.AUTHOR) - val kind = tlv.firstAsInt(TlvTypes.KIND.id) - - return Return(Type.EVENT, hex, relay, author, kind) - } - - private fun nrelay(bytes: ByteArray): Return? { - val relayUrl = Tlv.parse(bytes).firstAsString(TlvTypes.SPECIAL.id) ?: return null - - return Return(Type.RELAY, relayUrl) - } - - private fun naddr(bytes: ByteArray): Return? { - val tlv = Tlv.parse(bytes) - - val d = tlv.firstAsString(TlvTypes.SPECIAL.id) ?: "" - val relay = tlv.firstAsString(TlvTypes.RELAY.id) - val author = tlv.firstAsHex(TlvTypes.AUTHOR.id) ?: return null - val kind = tlv.firstAsInt(TlvTypes.KIND.id) ?: return null - - return Return(Type.ADDRESS, "$kind:$author:$d", relay, author, kind) - } - - public fun createNEvent(idHex: String, author: String?, kind: Int?, relay: String?): String { - return TlvBuilder().apply { - addHex(TlvTypes.SPECIAL, idHex) - addStringIfNotNull(TlvTypes.RELAY, relay) - addHexIfNotNull(TlvTypes.AUTHOR, author) - addIntIfNotNull(TlvTypes.KIND, kind) - }.build().toNEvent() - } -} - -fun decodePublicKey(key: String): ByteArray { - val parsed = Nip19.uriToRoute(key) - val pubKeyParsed = parsed?.hex?.hexToByteArray() - - return if (key.startsWith("nsec")) { - KeyPair(privKey = key.bechToBytes()).pubKey - } else if (pubKeyParsed != null) { - pubKeyParsed - } else { - Hex.decode(key) - } -} - -fun decodePublicKeyAsHexOrNull(key: String): HexKey? { - return try { - val parsed = Nip19.uriToRoute(key) - val pubKeyParsed = parsed?.hex - - if (key.startsWith("nsec")) { - KeyPair(privKey = key.bechToBytes()).pubKey.toHexKey() - } else if (pubKeyParsed != null) { - pubKeyParsed - } else { - Hex.decode(key).toHexKey() - } - } catch (e: Exception) { - null - } -} - - -fun TlvBuilder.addString(type: Nip19.TlvTypes, string: String) = addString(type.id, string) -fun TlvBuilder.addHex(type: Nip19.TlvTypes, key: HexKey) = addHex(type.id, key) -fun TlvBuilder.addInt(type: Nip19.TlvTypes, data: Int) = addInt(type.id, data) - -fun TlvBuilder.addStringIfNotNull(type: Nip19.TlvTypes, data: String?) = addStringIfNotNull(type.id, data) -fun TlvBuilder.addHexIfNotNull(type: Nip19.TlvTypes, data: HexKey?) = addHexIfNotNull(type.id, data) -fun TlvBuilder.addIntIfNotNull(type: Nip19.TlvTypes, data: Int?) = addIntIfNotNull(type.id, data) - -fun Tlv.firstAsInt(type: Nip19.TlvTypes) = firstAsInt(type.id) -fun Tlv.firstAsHex(type: Nip19.TlvTypes) = firstAsHex(type.id) -fun Tlv.firstAsString(type: Nip19.TlvTypes) = firstAsString(type.id) \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Tlv.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Tlv.kt deleted file mode 100644 index 02e4d80d..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Tlv.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -import java.io.ByteArrayOutputStream -import java.nio.ByteBuffer -import java.nio.ByteOrder - -class TlvBuilder() { - val outputStream = ByteArrayOutputStream() - - private fun add(type: Byte, byteArray: ByteArray) { - outputStream.write(byteArrayOf(type, byteArray.size.toByte())) - outputStream.write(byteArray) - } - - fun addString(type: Byte, string: String) = add(type, string.toByteArray(Charsets.UTF_8)) - fun addHex(type: Byte, key: HexKey) = add(type, key.hexToByteArray()) - fun addInt(type: Byte, data: Int) = add(type, data.to32BitByteArray()) - - fun addStringIfNotNull(type: Byte, data: String?) = data?.let { addString(type, it) } - fun addHexIfNotNull(type: Byte, data: HexKey?) = data?.let { addHex(type, it) } - fun addIntIfNotNull(type: Byte, data: Int?) = data?.let { addInt(type, it) } - - fun build(): ByteArray { - return outputStream.toByteArray() - } -} - -fun Int.to32BitByteArray(): ByteArray { - val bytes = ByteArray(4) - (0..3).forEach { - bytes[3 - it] = ((this ushr (8 * it)) and 0xFFFF).toByte() - } - return bytes -} - -fun ByteArray.toInt32(): Int? { - if (size != 4) return null - return ByteBuffer.wrap(this, 0, 4).order(ByteOrder.BIG_ENDIAN).int -} - -class Tlv(val data: Map>) { - fun asInt(type: Byte) = data[type]?.mapNotNull { it.toInt32() } - fun asHex(type: Byte) = data[type]?.map { it.toHexKey().intern() } - fun asString(type: Byte) = data[type]?.map { it.toString(Charsets.UTF_8) } - - fun firstAsInt(type: Byte) = data[type]?.firstOrNull()?.toInt32() - fun firstAsHex(type: Byte) = data[type]?.firstOrNull()?.toHexKey()?.intern() - fun firstAsString(type: Byte) = data[type]?.firstOrNull()?.toString(Charsets.UTF_8) - - companion object { - fun parse(data: ByteArray): Tlv { - val result = mutableMapOf>() - var rest = data - while (rest.isNotEmpty()) { - val t = rest[0] - val l = rest[1].toUByte().toInt() - val v = rest.sliceArray(IntRange(2, (2 + l) - 1)) - rest = rest.sliceArray(IntRange(2 + l, rest.size - 1)) - if (v.size < l) continue - - if (!result.containsKey(t)) { - result[t] = mutableListOf() - } - result[t]?.add(v) - } - return Tlv(result) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/AdvertisedRelayListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/AdvertisedRelayListEvent.kt deleted file mode 100644 index 2f256ee1..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/AdvertisedRelayListEvent.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class AdvertisedRelayListEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - override fun dTag() = fixedDTag - - fun relays(): List { - return tags.mapNotNull { - if (it.size > 1 && it[0] == "r") { - val type = when (it.getOrNull(2)) { - "read" -> AdvertisedRelayType.READ - "write" -> AdvertisedRelayType.WRITE - else -> AdvertisedRelayType.BOTH - } - - AdvertisedRelayInfo(it[1], type) - } else { - null - } - } - } - - companion object { - const val kind = 10002 - const val fixedDTag = "" - - fun create( - list: List, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): AdvertisedRelayListEvent { - val tags = list.map { - if (it.type == AdvertisedRelayType.BOTH) { - listOf(it.relayUrl) - } else { - listOf(it.relayUrl, it.type.code) - } - } - val msg = "" - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = CryptoUtils.sign(id, privateKey) - return AdvertisedRelayListEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig.toHexKey()) - } - } - - @Immutable - data class AdvertisedRelayInfo(val relayUrl: String, val type: AdvertisedRelayType) - - @Immutable - enum class AdvertisedRelayType(val code: String) { - BOTH(""), - READ("read"), - WRITE("write") - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/AppDefinitionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/AppDefinitionEvent.kt deleted file mode 100644 index c014bdc4..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/AppDefinitionEvent.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey -import java.io.ByteArrayInputStream - -@Immutable -class AppDefinitionEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun appMetaData() = try { - mapper.readValue( - ByteArrayInputStream(content.toByteArray(Charsets.UTF_8)), - UserMetadata::class.java - ) - } catch (e: Exception) { - e.printStackTrace() - Log.w("MT", "Content Parse Error ${e.localizedMessage} $content") - null - } - - fun supportedKinds() = tags.filter { it.size > 1 && it[0] == "k" }.mapNotNull { - runCatching { it[1].toInt() }.getOrNull() - } - - fun publishedAt() = tags.firstOrNull { it.size > 1 && it[0] == "published_at" }?.get(1) - - companion object { - const val kind = 31990 - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/AppRecommendationEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/AppRecommendationEvent.kt deleted file mode 100644 index d02a7264..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/AppRecommendationEvent.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class AppRecommendationEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun recommendations() = tags.filter { it.size > 1 && it[0] == "a" }.mapNotNull { - ATag.parse(it[1], it.getOrNull(2)) - } - - companion object { - const val kind = 31989 - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/AudioHeaderEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/AudioHeaderEvent.kt deleted file mode 100644 index a9ea96d6..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/AudioHeaderEvent.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.fasterxml.jackson.module.kotlin.readValue -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class AudioHeaderEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - fun download() = tags.firstOrNull { it.size > 1 && it[0] == DOWNLOAD_URL }?.get(1) - fun stream() = tags.firstOrNull { it.size > 1 && it[0] == STREAM_URL }?.get(1) - fun wavefrom() = tags.firstOrNull { it.size > 1 && it[0] == WAVEFORM }?.get(1)?.let { - mapper.readValue>(it) - } - - companion object { - const val kind = 1808 - - private const val DOWNLOAD_URL = "download_url" - private const val STREAM_URL = "stream_url" - private const val WAVEFORM = "waveform" - - fun create( - description: String, - downloadUrl: String, - streamUrl: String? = null, - wavefront: String? = null, - sensitiveContent: Boolean? = null, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): AudioHeaderEvent { - val tags = listOfNotNull( - downloadUrl.let { listOf(DOWNLOAD_URL, it) }, - streamUrl?.let { listOf(STREAM_URL, it) }, - wavefront?.let { listOf(WAVEFORM, it) }, - sensitiveContent?.let { - if (it) { - listOf("content-warning", "") - } else { - null - } - } - ) - - val content = description - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return AudioHeaderEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/AudioTrackEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/AudioTrackEvent.kt deleted file mode 100644 index 57b1d38d..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/AudioTrackEvent.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class AudioTrackEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - fun participants() = tags.filter { it.size > 1 && it[0] == "p" }.map { Participant(it[1], it.getOrNull(2)) } - fun type() = tags.firstOrNull { it.size > 1 && it[0] == TYPE }?.get(1) - fun price() = tags.firstOrNull { it.size > 1 && it[0] == PRICE }?.get(1) - fun cover() = tags.firstOrNull { it.size > 1 && it[0] == COVER }?.get(1) - - // fun subject() = tags.firstOrNull { it.size > 1 && it[0] == SUBJECT }?.get(1) - fun media() = tags.firstOrNull { it.size > 1 && it[0] == MEDIA }?.get(1) - - companion object { - const val kind = 31337 - - private const val TYPE = "c" - private const val PRICE = "price" - private const val COVER = "cover" - private const val SUBJECT = "subject" - private const val MEDIA = "media" - - fun create( - type: String, - media: String, - price: String? = null, - cover: String? = null, - subject: String? = null, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): AudioTrackEvent { - val tags = listOfNotNull( - listOf(MEDIA, media), - listOf(TYPE, type), - price?.let { listOf(PRICE, it) }, - cover?.let { listOf(COVER, it) }, - subject?.let { listOf(SUBJECT, it) } - ) - - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return AudioTrackEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} - -data class Participant(val key: String, val role: String?) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeAwardEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeAwardEvent.kt deleted file mode 100644 index d956d23d..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeAwardEvent.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class BadgeAwardEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - fun awardees() = taggedUsers() - - fun awardDefinition() = taggedAddresses() - - companion object { - const val kind = 8 - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeDefinitionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeDefinitionEvent.kt deleted file mode 100644 index 410a6a20..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeDefinitionEvent.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class BadgeDefinitionEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun name() = tags.firstOrNull { it.size > 1 && it[0] == "name" }?.get(1) - fun thumb() = tags.firstOrNull { it.size > 1 && it[0] == "thumb" }?.get(1) - fun image() = tags.firstOrNull { it.size > 1 && it[0] == "image" }?.get(1) - fun description() = tags.firstOrNull { it.size > 1 && it[0] == "description" }?.get(1) - - companion object { - const val kind = 30009 - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeProfilesEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeProfilesEvent.kt deleted file mode 100644 index a4801eca..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/BadgeProfilesEvent.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class BadgeProfilesEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun badgeAwardEvents() = tags.filter { it.firstOrNull() == "e" }.mapNotNull { it.getOrNull(1) } - fun badgeAwardDefinitions() = tags.filter { it.firstOrNull() == "a" }.mapNotNull { - val aTagValue = it.getOrNull(1) - val relay = it.getOrNull(2) - - if (aTagValue != null) ATag.parse(aTagValue, relay) else null - } - - companion object { - const val kind = 30008 - const val standardDTAg = "profile_badges" - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/BaseTextNoteEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/BaseTextNoteEvent.kt deleted file mode 100644 index 16783326..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/BaseTextNoteEvent.kt +++ /dev/null @@ -1,148 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.HexKey -import com.vitorpamplona.quartz.encoders.Nip19 -import com.vitorpamplona.quartz.encoders.Nip19.nip19regex -import java.util.regex.Pattern - -val tagSearch = Pattern.compile("(?:\\s|\\A)\\#\\[([0-9]+)\\]") -val hashtagSearch = Pattern.compile("(?:\\s|\\A)#([^\\s!@#\$%^&*()=+./,\\[{\\]};:'\"?><]+)") - -@Immutable -open class BaseTextNoteEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - kind: Int, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - fun mentions() = taggedUsers() - open fun replyTos() = taggedEvents() - - @Transient - private var citedUsersCache: Set? = null - - @Transient - private var citedNotesCache: Set? = null - - fun citedUsers(): Set { - citedUsersCache?.let { return it } - - val matcher = tagSearch.matcher(content) - val returningList = mutableSetOf() - while (matcher.find()) { - try { - val tag = matcher.group(1)?.let { tags[it.toInt()] } - if (tag != null && tag.size > 1 && tag[0] == "p") { - returningList.add(tag[1]) - } - } catch (e: Exception) { - } - } - - val matcher2 = nip19regex.matcher(content) - while (matcher2.find()) { - val uriScheme = matcher2.group(1) // nostr: - val type = matcher2.group(2) // npub1 - val key = matcher2.group(3) // bech32 - val additionalChars = matcher2.group(4) // additional chars - - try { - val parsed = Nip19.parseComponents(uriScheme, type, key, additionalChars) - - if (parsed != null) { - val tag = tags.firstOrNull { it.size > 1 && it[1] == parsed.hex } - - if (tag != null && tag[0] == "p") { - returningList.add(tag[1]) - } - } - } catch (e: Exception) { - Log.w("Unable to parse cited users that matched a NIP19 regex", e) - } - } - - citedUsersCache = returningList - return returningList - } - - fun findCitations(): Set { - citedNotesCache?.let { return it } - - val citations = mutableSetOf() - // Removes citations from replies: - val matcher = tagSearch.matcher(content) - while (matcher.find()) { - try { - val tag = matcher.group(1)?.let { tags[it.toInt()] } - if (tag != null && tag.size > 1 && tag[0] == "e") { - citations.add(tag[1]) - } - if (tag != null && tag.size > 1 && tag[0] == "a") { - citations.add(tag[1]) - } - } catch (e: Exception) { - } - } - - val matcher2 = nip19regex.matcher(content) - while (matcher2.find()) { - val uriScheme = matcher2.group(1) // nostr: - val type = matcher2.group(2) // npub1 - val key = matcher2.group(3) // bech32 - val additionalChars = matcher2.group(4) // additional chars - - val parsed = Nip19.parseComponents(uriScheme, type, key, additionalChars) - - if (parsed != null) { - try { - val tag = tags.firstOrNull { it.size > 1 && it[1] == parsed.hex } - - if (tag != null && tag[0] == "e") { - citations.add(tag[1]) - } - if (tag != null && tag[0] == "a") { - citations.add(tag[1]) - } - } catch (e: Exception) { - } - } - } - - citedNotesCache = citations - return citations - } - - fun tagsWithoutCitations(): List { - val repliesTo = replyTos() - val tagAddresses = taggedAddresses().filter { it.kind != CommunityDefinitionEvent.kind }.map { it.toTag() } - if (repliesTo.isEmpty() && tagAddresses.isEmpty()) return emptyList() - - val citations = findCitations() - - return if (citations.isEmpty()) { - repliesTo + tagAddresses - } else { - repliesTo.filter { it !in citations } - } - } -} - -fun findHashtags(content: String): List { - val matcher = hashtagSearch.matcher(content) - val returningList = mutableSetOf() - while (matcher.find()) { - try { - val tag = matcher.group(1) - if (tag != null && tag.isNotBlank()) { - returningList.add(tag) - } - } catch (e: Exception) { - } - } - return returningList.toList() -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/BookmarkListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/BookmarkListEvent.kt deleted file mode 100644 index f99f837b..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/BookmarkListEvent.kt +++ /dev/null @@ -1,91 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class BookmarkListEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) { - var decryptedContent = "" - - companion object { - const val kind = 30001 - - fun create( - name: String = "", - events: List? = null, - users: List? = null, - addresses: List? = null, - content: String, - pubKey: HexKey, - createdAt: Long = TimeUtils.now() - ): BookmarkListEvent { - val tags = mutableListOf>() - tags.add(listOf("d", name)) - - events?.forEach { - tags.add(listOf("e", it)) - } - users?.forEach { - tags.add(listOf("p", it)) - } - addresses?.forEach { - tags.add(listOf("a", it.toTag())) - } - - val id = generateId(pubKey, createdAt, kind, tags, content) - return BookmarkListEvent(id.toHexKey(), pubKey, createdAt, tags, content, "") - } - - fun create( - name: String = "", - - events: List? = null, - users: List? = null, - addresses: List? = null, - - privEvents: List? = null, - privUsers: List? = null, - privAddresses: List? = null, - - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): BookmarkListEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey) - val content = createPrivateTags(privEvents, privUsers, privAddresses, privateKey, pubKey) - - val tags = mutableListOf>() - tags.add(listOf("d", name)) - - events?.forEach { - tags.add(listOf("e", it)) - } - users?.forEach { - tags.add(listOf("p", it)) - } - addresses?.forEach { - tags.add(listOf("a", it.toTag())) - } - - val id = generateId(pubKey.toHexKey(), createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return BookmarkListEvent(id.toHexKey(), pubKey.toHexKey(), createdAt, tags, content, sig.toHexKey()) - } - - fun create( - unsignedEvent: BookmarkListEvent, signature: String - ): BookmarkListEvent { - return BookmarkListEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarDateSlotEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarDateSlotEvent.kt deleted file mode 100644 index a9b23443..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarDateSlotEvent.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class CalendarDateSlotEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - fun location() = tags.firstOrNull { it.size > 1 && it[0] == "location" }?.get(1) - fun start() = tags.firstOrNull { it.size > 1 && it[0] == "start" }?.get(1) - fun end() = tags.firstOrNull { it.size > 1 && it[0] == "end" }?.get(1) - - // ["start", ""], - // ["end", ""], - - companion object { - const val kind = 31922 - - fun create( - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): CalendarDateSlotEvent { - val tags = mutableListOf>() - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return CalendarDateSlotEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarEvent.kt deleted file mode 100644 index 9005e5eb..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarEvent.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class CalendarEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - companion object { - const val kind = 31924 - - fun create( - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): CalendarEvent { - val tags = mutableListOf>() - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return CalendarEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarRSVPEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarRSVPEvent.kt deleted file mode 100644 index 28210450..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarRSVPEvent.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class CalendarRSVPEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - fun status() = tags.firstOrNull { it.size > 1 && it[0] == "location" }?.get(1) - fun start() = tags.firstOrNull { it.size > 1 && it[0] == "start" }?.get(1) - fun end() = tags.firstOrNull { it.size > 1 && it[0] == "end" }?.get(1) - - // ["L", "status"], - // ["l", "", "status"], - // ["L", "freebusy"], - // ["l", "", "freebusy"] - - companion object { - const val kind = 31925 - - fun create( - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): CalendarRSVPEvent { - val tags = mutableListOf>() - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return CalendarRSVPEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarTimeSlotEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarTimeSlotEvent.kt deleted file mode 100644 index d0bc3369..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/CalendarTimeSlotEvent.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class CalendarTimeSlotEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun location() = tags.firstOrNull { it.size > 1 && it[0] == "location" }?.get(1) - fun start() = tags.firstOrNull { it.size > 1 && it[0] == "start" }?.get(1)?.toLongOrNull() - fun end() = tags.firstOrNull { it.size > 1 && it[0] == "end" }?.get(1)?.toLongOrNull() - - fun startTmz() = tags.firstOrNull { it.size > 1 && it[0] == "start_tzid" }?.get(1)?.toLongOrNull() - fun endTmz() = tags.firstOrNull { it.size > 1 && it[0] == "end_tzid" }?.get(1)?.toLongOrNull() - - // ["start", ""], - // ["end", ""], - // ["start_tzid", ""], - // ["end_tzid", ""], - - companion object { - const val kind = 31923 - - fun create( - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): CalendarTimeSlotEvent { - val tags = mutableListOf>() - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return CalendarTimeSlotEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelCreateEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelCreateEvent.kt deleted file mode 100644 index 28e43f9f..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelCreateEvent.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.key -import com.fasterxml.jackson.module.kotlin.readValue -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class ChannelCreateEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - fun channelInfo(): ChannelData = try { - mapper.readValue(content) - } catch (e: Exception) { - Log.e("ChannelMetadataEvent", "Can't parse channel info $content", e) - ChannelData(null, null, null) - } - - companion object { - const val kind = 40 - - fun create(channelInfo: ChannelData?, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ChannelCreateEvent { - val content = try { - if (channelInfo != null) { - mapper.writeValueAsString(channelInfo) - } else { - "" - } - } catch (t: Throwable) { - Log.e("ChannelCreateEvent", "Couldn't parse channel information", t) - "" - } - - val pubKey = keyPair.pubKey.toHexKey() - val tags = emptyList>() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.pubKey) - return ChannelCreateEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(unsignedEvent: ChannelCreateEvent, signature: String): ChannelCreateEvent { - return ChannelCreateEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } - - @Immutable - data class ChannelData(val name: String?, val about: String?, val picture: String?) -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelHideMessageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelHideMessageEvent.kt deleted file mode 100644 index 7e8b2413..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelHideMessageEvent.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class ChannelHideMessageEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel { - override fun channel() = tags.firstOrNull { - it.size > 3 && it[0] == "e" && it[3] == "root" - }?.get(1) ?: tags.firstOrNull { - it.size > 1 && it[0] == "e" - }?.get(1) - - fun eventsToHide() = tags.filter { it.firstOrNull() == "e" }.mapNotNull { it.getOrNull(1) } - - companion object { - const val kind = 43 - - fun create(reason: String, messagesToHide: List?, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ChannelHideMessageEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val tags = - messagesToHide?.map { - listOf("e", it) - } ?: emptyList() - - val id = generateId(pubKey, createdAt, kind, tags, reason) - val sig = CryptoUtils.sign(id, privateKey) - return ChannelHideMessageEvent(id.toHexKey(), pubKey, createdAt, tags, reason, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMessageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMessageEvent.kt deleted file mode 100644 index 07e33ca7..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMessageEvent.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class ChannelMessageEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel { - - override fun channel() = tags.firstOrNull { - it.size > 3 && it[0] == "e" && it[3] == "root" - }?.get(1) ?: tags.firstOrNull { - it.size > 1 && it[0] == "e" - }?.get(1) - - override fun replyTos() = tags.filter { it.firstOrNull() == "e" && it.getOrNull(1) != channel() }.mapNotNull { it.getOrNull(1) } - - companion object { - const val kind = 42 - - fun create( - message: String, - channel: String, - replyTos: List? = null, - mentions: List? = null, - zapReceiver: String?, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now(), - markAsSensitive: Boolean, - zapRaiserAmount: Long?, - geohash: String? = null - ): ChannelMessageEvent { - val content = message - val tags = mutableListOf( - listOf("e", channel, "", "root") - ) - replyTos?.forEach { - tags.add(listOf("e", it)) - } - mentions?.forEach { - tags.add(listOf("p", it)) - } - zapReceiver?.let { - tags.add(listOf("zap", it)) - } - if (markAsSensitive) { - tags.add(listOf("content-warning", "")) - } - zapRaiserAmount?.let { - tags.add(listOf("zapraiser", "$it")) - } - geohash?.let { - tags.add(listOf("g", it)) - } - - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return ChannelMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create( - unsignedEvent: ChannelMessageEvent, signature: String - ): ChannelMessageEvent { - return ChannelMessageEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} - -interface IsInPublicChatChannel { - fun channel(): String? -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMetadataEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMetadataEvent.kt deleted file mode 100644 index 245397b5..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMetadataEvent.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class ChannelMetadataEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel { - - override fun channel() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1) - fun channelInfo() = - try { - mapper.readValue(content, ChannelCreateEvent.ChannelData::class.java) - } catch (e: Exception) { - Log.e("ChannelMetadataEvent", "Can't parse channel info $content", e) - ChannelCreateEvent.ChannelData(null, null, null) - } - - companion object { - const val kind = 41 - - fun create(newChannelInfo: ChannelCreateEvent.ChannelData?, originalChannelIdHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ChannelMetadataEvent { - val content = - if (newChannelInfo != null) { - mapper.writeValueAsString(newChannelInfo) - } else { - "" - } - - val pubKey = keyPair.pubKey.toHexKey() - val tags = listOf(listOf("e", originalChannelIdHex, "", "root")) - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return ChannelMetadataEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(unsignedEvent: ChannelMetadataEvent, signature: String): ChannelMetadataEvent { - return ChannelMetadataEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMuteUserEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMuteUserEvent.kt deleted file mode 100644 index 74702aa2..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChannelMuteUserEvent.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class ChannelMuteUserEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel { - override fun channel() = tags.firstOrNull { - it.size > 3 && it[0] == "e" && it[3] == "root" - }?.get(1) ?: tags.firstOrNull { - it.size > 1 && it[0] == "e" - }?.get(1) - - fun usersToMute() = tags.filter { it.firstOrNull() == "p" }.mapNotNull { it.getOrNull(1) } - - companion object { - const val kind = 44 - - fun create(reason: String, usersToMute: List?, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ChannelMuteUserEvent { - val content = reason - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val tags = - usersToMute?.map { - listOf("p", it) - } ?: emptyList() - - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return ChannelMuteUserEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageEvent.kt deleted file mode 100644 index b41c6042..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageEvent.kt +++ /dev/null @@ -1,109 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey -import kotlinx.collections.immutable.ImmutableSet -import kotlinx.collections.immutable.toImmutableSet - -@Immutable -class ChatMessageEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : WrappedEvent(id, pubKey, createdAt, kind, tags, content, sig), ChatroomKeyable { - /** - * Recepients intended to receive this conversation - */ - fun recipientsPubKey() = tags.mapNotNull { - if (it.size > 1 && it[0] == "p") it[1] else null - } - - fun replyTo() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1) - - fun talkingWith(oneSideHex: String): Set { - val listedPubKeys = recipientsPubKey() - - val result = if (pubKey == oneSideHex) { - listedPubKeys.toSet().minus(oneSideHex) - } else { - listedPubKeys.plus(pubKey).toSet().minus(oneSideHex) - } - - if (result.isEmpty()) { - // talking to myself - return setOf(pubKey) - } - - return result - } - - override fun chatroomKey(toRemove: String): ChatroomKey { - return ChatroomKey(talkingWith(toRemove).toImmutableSet()) - } - - companion object { - const val kind = 14 - - fun create( - msg: String, - to: List? = null, - subject: String? = null, - replyTos: List? = null, - mentions: List? = null, - zapReceiver: String? = null, - markAsSensitive: Boolean = false, - zapRaiserAmount: Long? = null, - geohash: String? = null, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): ChatMessageEvent { - val content = msg - val tags = mutableListOf>() - to?.forEach { - tags.add(listOf("p", it)) - } - replyTos?.forEach { - tags.add(listOf("e", it)) - } - mentions?.forEach { - tags.add(listOf("p", it, "", "mention")) - } - zapReceiver?.let { - tags.add(listOf("zap", it)) - } - if (markAsSensitive) { - tags.add(listOf("content-warning", "")) - } - zapRaiserAmount?.let { - tags.add(listOf("zapraiser", "$it")) - } - geohash?.let { - tags.add(listOf("g", it)) - } - subject?.let { - tags.add(listOf("subject", it)) - } - - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, ClassifiedsEvent.kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return ChatMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} - -interface ChatroomKeyable { - fun chatroomKey(toRemove: HexKey): ChatroomKey -} - -@Stable -data class ChatroomKey( - val users: ImmutableSet -) \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ClassifiedsEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ClassifiedsEvent.kt deleted file mode 100644 index e22b0e0c..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ClassifiedsEvent.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class ClassifiedsEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun title() = tags.firstOrNull { it.size > 1 && it[0] == "title" }?.get(1) - fun image() = tags.firstOrNull { it.size > 1 && it[0] == "image" }?.get(1) - fun summary() = tags.firstOrNull { it.size > 1 && it[0] == "summary" }?.get(1) - fun price() = tags.firstOrNull { it.size > 1 && it[0] == "price" }?.let { - Price(it[1], it.getOrNull(2), it.getOrNull(3)) - } - fun location() = tags.firstOrNull { it.size > 1 && it[0] == "location" }?.get(1) - - fun publishedAt() = try { - tags.firstOrNull { it.size > 1 && it[0] == "published_at" }?.get(1)?.toLongOrNull() - } catch (_: Exception) { - null - } - - companion object { - const val kind = 30402 - - fun create( - dTag: String, - title: String?, - image: String?, - summary: String?, - price: Price?, - location: String?, - publishedAt: Long?, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): ClassifiedsEvent { - val tags = mutableListOf>() - - tags.add(listOf("d", dTag)) - title?.let { tags.add(listOf("title", it)) } - image?.let { tags.add(listOf("image", it)) } - summary?.let { tags.add(listOf("summary", it)) } - price?.let { - if (it.frequency != null && it.currency != null) { - tags.add(listOf("price", it.amount, it.currency, it.frequency)) - } else if (it.currency != null) { - tags.add(listOf("price", it.amount, it.currency)) - } else { - tags.add(listOf("price", it.amount)) - } - } - location?.let { tags.add(listOf("location", it)) } - publishedAt?.let { tags.add(listOf("publishedAt", it.toString())) } - title?.let { tags.add(listOf("title", it)) } - - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return ClassifiedsEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} - -data class Price(val amount: String, val currency: String?, val frequency: String?) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/CommunityDefinitionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/CommunityDefinitionEvent.kt deleted file mode 100644 index 447261d0..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/CommunityDefinitionEvent.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class CommunityDefinitionEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun description() = tags.firstOrNull { it.size > 1 && it[0] == "description" }?.get(1) - fun image() = tags.firstOrNull { it.size > 1 && it[0] == "image" }?.get(1) - fun rules() = tags.firstOrNull { it.size > 1 && it[0] == "rules" }?.get(1) - - fun moderators() = tags.filter { it.size > 1 && it[0] == "p" }.map { Participant(it[1], it.getOrNull(3)) } - - companion object { - const val kind = 34550 - - fun create( - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): CommunityDefinitionEvent { - val tags = mutableListOf>() - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return CommunityDefinitionEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/CommunityPostApprovalEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/CommunityPostApprovalEvent.kt deleted file mode 100644 index 8089e8bf..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/CommunityPostApprovalEvent.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class CommunityPostApprovalEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - fun containedPost(): Event? = try { - content.ifBlank { null }?.let { - fromJson(it) - } - } catch (e: Exception) { - Log.w("CommunityPostEvent", "Failed to Parse Community Approval Contained Post of $id with $content") - null - } - - fun communities() = tags.filter { it.size > 1 && it[0] == "a" }.mapNotNull { - val aTag = ATag.parse(it[1], it.getOrNull(2)) - - if (aTag?.kind == CommunityDefinitionEvent.kind) { - aTag - } else { - null - } - } - - fun approvedEvents() = tags.filter { - it.size > 1 && (it[0] == "e" || (it[0] == "a" && ATag.parse(it[1], null)?.kind != CommunityDefinitionEvent.kind)) - }.map { - it[1] - } - - companion object { - const val kind = 4550 - - fun create(approvedPost: Event, community: CommunityDefinitionEvent, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): GenericRepostEvent { - val content = approvedPost.toJson() - - val communities = listOf("a", community.address().toTag()) - val replyToPost = listOf("e", approvedPost.id()) - val replyToAuthor = listOf("p", approvedPost.pubKey()) - val kind = listOf("k", "${approvedPost.kind()}") - - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val tags: List> = listOf(communities, replyToPost, replyToAuthor, kind) - val id = generateId(pubKey, createdAt, GenericRepostEvent.kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return GenericRepostEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ContactListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ContactListEvent.kt deleted file mode 100644 index df3aa027..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ContactListEvent.kt +++ /dev/null @@ -1,355 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable -import com.fasterxml.jackson.module.kotlin.readValue -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey -import com.vitorpamplona.quartz.encoders.decodePublicKey - -@Immutable -data class Contact(val pubKeyHex: String, val relayUri: String?) - -@Stable -class ContactListEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - // This function is only used by the user logged in - // But it is used all the time. - - @delegate:Transient - val verifiedFollowKeySet: Set by lazy { - tags.filter { it.size > 1 && it[0] == "p" }.mapNotNull { - try { - decodePublicKey(it[1]).toHexKey() - } catch (e: Exception) { - Log.w("ContactListEvent", "Can't parse tags as a follows: ${it[1]}", e) - null - } - }.toSet() - } - - @delegate:Transient - val verifiedFollowTagSet: Set by lazy { - unverifiedFollowTagSet().map { it.lowercase() }.toSet() - } - - @delegate:Transient - val verifiedFollowGeohashSet: Set by lazy { - unverifiedFollowGeohashSet().map { it.lowercase() }.toSet() - } - - @delegate:Transient - val verifiedFollowCommunitySet: Set by lazy { - unverifiedFollowAddressSet().toSet() - } - - @delegate:Transient - val verifiedFollowKeySetAndMe: Set by lazy { - verifiedFollowKeySet + pubKey - } - - fun unverifiedFollowKeySet() = tags.filter { it[0] == "p" }.mapNotNull { it.getOrNull(1) } - fun unverifiedFollowTagSet() = tags.filter { it[0] == "t" }.mapNotNull { it.getOrNull(1) } - fun unverifiedFollowGeohashSet() = tags.filter { it[0] == "g" }.mapNotNull { it.getOrNull(1) } - - fun unverifiedFollowAddressSet() = tags.filter { it[0] == "a" }.mapNotNull { it.getOrNull(1) } - - fun follows() = tags.filter { it[0] == "p" }.mapNotNull { - try { - Contact(decodePublicKey(it[1]).toHexKey(), it.getOrNull(2)) - } catch (e: Exception) { - Log.w("ContactListEvent", "Can't parse tags as a follows: ${it[1]}", e) - null - } - } - - fun followsTags() = tags.filter { it[0] == "t" }.mapNotNull { - it.getOrNull(2) - } - - fun relays(): Map? = try { - if (content.isNotEmpty()) { - mapper.readValue>(content) - } else { - null - } - } catch (e: Exception) { - Log.w("ContactListEvent", "Can't parse content as relay lists: $content", e) - null - } - - companion object { - const val kind = 3 - - fun createFromScratch( - followUsers: List, - followTags: List, - followGeohashes: List, - followCommunities: List, - followEvents: List, - relayUse: Map?, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): ContactListEvent { - val content = if (relayUse != null) { - mapper.writeValueAsString(relayUse) - } else { - "" - } - - val tags = followUsers.map { - if (it.relayUri != null) { - listOf("p", it.pubKeyHex, it.relayUri) - } else { - listOf("p", it.pubKeyHex) - } - } + followTags.map { - listOf("t", it) - } + followEvents.map { - listOf("e", it) - } + followCommunities.map { - if (it.relay != null) { - listOf("a", it.toTag(), it.relay) - } else { - listOf("a", it.toTag()) - } - } + followGeohashes.map { - listOf("g", it) - } - - return create( - content = content, - tags = tags, - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun followUser(earlierVersion: ContactListEvent, pubKeyHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (earlierVersion.isTaggedUser(pubKeyHex)) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.plus(element = listOf("p", pubKeyHex)), - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun unfollowUser(earlierVersion: ContactListEvent, pubKeyHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (!earlierVersion.isTaggedUser(pubKeyHex)) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex }, - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun followHashtag(earlierVersion: ContactListEvent, hashtag: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (earlierVersion.isTaggedHash(hashtag)) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.plus(element = listOf("t", hashtag)), - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun unfollowHashtag(earlierVersion: ContactListEvent, hashtag: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (!earlierVersion.isTaggedHash(hashtag)) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.filter { it.size > 1 && !it[1].equals(hashtag, true) }, - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun followGeohash(earlierVersion: ContactListEvent, hashtag: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (earlierVersion.isTaggedGeoHash(hashtag)) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.plus(element = listOf("g", hashtag)), - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun unfollowGeohash(earlierVersion: ContactListEvent, hashtag: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (!earlierVersion.isTaggedGeoHash(hashtag)) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.filter { it.size > 1 && it[1] != hashtag }, - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun followEvent(earlierVersion: ContactListEvent, idHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (earlierVersion.isTaggedEvent(idHex)) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.plus(element = listOf("e", idHex)), - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun unfollowEvent(earlierVersion: ContactListEvent, idHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (!earlierVersion.isTaggedEvent(idHex)) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.filter { it.size > 1 && it[1] != idHex }, - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun followAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)), - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun unfollowAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - if (!earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion - - return create( - content = earlierVersion.content, - tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() }, - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun updateRelayList(earlierVersion: ContactListEvent, relayUse: Map?, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent { - val content = if (relayUse != null) { - mapper.writeValueAsString(relayUse) - } else { - "" - } - - return create( - content = content, - tags = earlierVersion.tags, - keyPair = keyPair, - createdAt = createdAt - ) - } - - fun create( - unsignedEvent: Event, - signature: String - ): ContactListEvent { - return ContactListEvent( - unsignedEvent.id, - unsignedEvent.pubKey, - unsignedEvent.createdAt, - unsignedEvent.tags, - unsignedEvent.content, - signature - ) - } - - fun create( - content: String, - tags: List>, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): ContactListEvent { - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return ContactListEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - } - - data class ReadWrite(val read: Boolean, val write: Boolean) -} - -@Stable -class UserMetadata { - var name: String? = null - var username: String? = null - var display_name: String? = null - var displayName: String? = null - var picture: String? = null - var banner: String? = null - var website: String? = null - var about: String? = null - - var nip05: String? = null - var nip05Verified: Boolean = false - var nip05LastVerificationTime: Long? = 0 - - var domain: String? = null - var lud06: String? = null - var lud16: String? = null - - var twitter: String? = null - - var updatedMetadataAt: Long = 0 - var latestMetadata: MetadataEvent? = null - var tags: ImmutableListOfLists? = null - - fun anyName(): String? { - return display_name ?: displayName ?: name ?: username - } - - fun anyNameStartsWith(prefix: String): Boolean { - return listOfNotNull(name, username, display_name, displayName, nip05, lud06, lud16) - .any { it.contains(prefix, true) } - } - - fun lnAddress(): String? { - return (lud16?.trim() ?: lud06?.trim())?.ifBlank { null } - } - - fun bestUsername(): String? { - return name?.ifBlank { null } ?: username?.ifBlank { null } - } - - fun bestDisplayName(): String? { - return displayName?.ifBlank { null } ?: display_name?.ifBlank { null } - } - - fun nip05(): String? { - return nip05?.ifBlank { null } - } - - fun profilePicture(): String? { - if (picture.isNullOrBlank()) picture = null - return picture - } -} - -@Stable -data class ImmutableListOfLists(val lists: List> = emptyList()) - -fun List>.toImmutableListOfLists(): ImmutableListOfLists { - return ImmutableListOfLists(this) -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/DeletionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/DeletionEvent.kt deleted file mode 100644 index 05b4faa9..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/DeletionEvent.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class DeletionEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - fun deleteEvents() = tags.map { it[1] } - - companion object { - const val kind = 5 - - fun create(deleteEvents: List, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): DeletionEvent { - val content = "" - val pubKey = keyPair.pubKey.toHexKey() - val tags = deleteEvents.map { listOf("e", it) } - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return DeletionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(unsignedEvent: DeletionEvent, signature: String): DeletionEvent { - return DeletionEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/EmojiPackEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/EmojiPackEvent.kt deleted file mode 100644 index 8e41d5d9..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/EmojiPackEvent.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class EmojiPackEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - companion object { - const val kind = 30030 - - fun create( - name: String = "", - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): EmojiPackEvent { - val content = "" - val pubKey = CryptoUtils.pubkeyCreate(privateKey) - - val tags = mutableListOf>() - tags.add(listOf("d", name)) - - val id = generateId(pubKey.toHexKey(), createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return EmojiPackEvent(id.toHexKey(), pubKey.toHexKey(), createdAt, tags, content, sig.toHexKey()) - } - } -} - -@Immutable -data class EmojiUrl(val code: String, val url: String) { - fun encode(): String { - return ":$code:$url" - } - - companion object { - fun decode(encodedEmojiSetup: String): EmojiUrl? { - val emojiParts = encodedEmojiSetup.split(":", limit = 3) - return if (emojiParts.size > 2) { - EmojiUrl(emojiParts[1], emojiParts[2]) - } else { - null - } - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/EmojiPackSelectionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/EmojiPackSelectionEvent.kt deleted file mode 100644 index a73a395b..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/EmojiPackSelectionEvent.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class EmojiPackSelectionEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - companion object { - const val kind = 10030 - - fun create( - listOfEmojiPacks: List?, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): EmojiPackSelectionEvent { - val msg = "" - val pubKey = keyPair.pubKey.toHexKey() - val tags = mutableListOf>() - - listOfEmojiPacks?.forEach { - tags.add(listOf("a", it.toTag())) - } - - val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return EmojiPackSelectionEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig?.toHexKey() ?: "") - } - - fun create( - unsignedEvent: EmojiPackSelectionEvent, signature: String - ): EmojiPackSelectionEvent { - return EmojiPackSelectionEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/Event.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/Event.kt deleted file mode 100644 index 5aa91ebf..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/Event.kt +++ /dev/null @@ -1,423 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.SerializerProvider -import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.fasterxml.jackson.databind.module.SimpleModule -import com.fasterxml.jackson.databind.ser.std.StdSerializer -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.Hex -import com.vitorpamplona.quartz.encoders.HexKey -import com.vitorpamplona.quartz.encoders.Nip19 -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.utils.TimeUtils -import java.math.BigDecimal -import java.util.* - - -@Immutable -open class Event( - val id: HexKey, - @JsonProperty("pubkey") - val pubKey: HexKey, - @JsonProperty("created_at") - val createdAt: Long, - val kind: Int, - val tags: List>, - val content: String, - val sig: HexKey -) : EventInterface { - - override fun countMemory(): Long { - return 12L + - id.bytesUsedInMemory() + - pubKey.bytesUsedInMemory() + - tags.sumOf { it.sumOf { it.bytesUsedInMemory() } } + - content.bytesUsedInMemory() + - sig.bytesUsedInMemory() - } - - override fun id(): HexKey = id - - override fun pubKey(): HexKey = pubKey - - override fun createdAt(): Long = createdAt - - override fun kind(): Int = kind - - override fun tags(): List> = tags - - override fun content(): String = content - - override fun sig(): HexKey = sig - - override fun toJson(): String = mapper.writeValueAsString(toJsonObject()) - - fun hasAnyTaggedUser() = tags.any { it.size > 1 && it[0] == "p" } - - override fun taggedUsers() = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] } - override fun taggedEvents() = tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] } - - override fun taggedUrls() = tags.filter { it.size > 1 && it[0] == "r" }.map { it[1] } - - override fun firstTaggedUser() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.let { it[1] } - override fun firstTaggedEvent() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.let { it[1] } - override fun firstTaggedUrl() = tags.firstOrNull { it.size > 1 && it[0] == "r" }?.let { it[1] } - override fun firstTaggedAddress() = tags.firstOrNull { it.size > 1 && it[0] == "a" }?.let { - val aTagValue = it[1] - val relay = it.getOrNull(2) - - ATag.parse(aTagValue, relay) - } - - override fun taggedEmojis() = tags.filter { it.size > 2 && it[0] == "emoji" }.map { EmojiUrl(it[1], it[2]) } - - override fun isSensitive() = tags.any { - (it.size > 0 && it[0].equals("content-warning", true)) || - (it.size > 1 && it[0] == "t" && it[1].equals("nsfw", true)) || - (it.size > 1 && it[0] == "t" && it[1].equals("nude", true)) - } - - override fun subject() = tags.firstOrNull() { it.size > 1 && it[0] == "subject" }?.get(1) - - override fun zapraiserAmount() = tags.firstOrNull() { - (it.size > 1 && it[0] == "zapraiser") - }?.get(1)?.toLongOrNull() - - override fun zapAddress() = tags.firstOrNull { it.size > 1 && it[0] == "zap" }?.get(1) - - override fun taggedAddresses() = tags.filter { it.size > 1 && it[0] == "a" }.mapNotNull { - val aTagValue = it[1] - val relay = it.getOrNull(2) - - ATag.parse(aTagValue, relay) - } - - override fun hashtags() = tags.filter { it.size > 1 && it[0] == "t" }.map { it[1] } - override fun geohashes() = tags.filter { it.size > 1 && it[0] == "g" }.map { it[1] } - - override fun matchTag1With(text: String) = tags.any { it.size > 1 && it[1].contains(text, true) } - - override fun isTaggedUser(idHex: String) = tags.any { it.size > 1 && it[0] == "p" && it[1] == idHex } - override fun isTaggedUsers(idHexes: Set) = tags.any { it.size > 1 && it[0] == "p" && it[1] in idHexes } - - override fun isTaggedEvent(idHex: String) = tags.any { it.size > 1 && it[0] == "e" && it[1] == idHex } - - override fun isTaggedAddressableNote(idHex: String) = tags.any { it.size > 1 && it[0] == "a" && it[1] == idHex } - - override fun isTaggedAddressableNotes(idHexes: Set) = tags.any { it.size > 1 && it[0] == "a" && it[1] in idHexes } - - override fun isTaggedHash(hashtag: String) = tags.any { it.size > 1 && it[0] == "t" && it[1].equals(hashtag, true) } - - override fun isTaggedGeoHash(hashtag: String) = tags.any { it.size > 1 && it[0] == "g" && it[1].startsWith(hashtag, true) } - override fun isTaggedHashes(hashtags: Set) = tags.any { it.size > 1 && it[0] == "t" && it[1].lowercase() in hashtags } - override fun isTaggedGeoHashes(hashtags: Set) = tags.any { it.size > 1 && it[0] == "g" && it[1].lowercase() in hashtags } - override fun firstIsTaggedHashes(hashtags: Set) = tags.firstOrNull { it.size > 1 && it[0] == "t" && it[1].lowercase() in hashtags }?.getOrNull(1) - - override fun firstIsTaggedAddressableNote(addressableNotes: Set) = tags.firstOrNull { it.size > 1 && it[0] == "a" && it[1] in addressableNotes }?.getOrNull(1) - - override fun isTaggedAddressableKind(kind: Int): Boolean { - val kindStr = kind.toString() - return tags.any { it.size > 1 && it[0] == "a" && it[1].startsWith(kindStr) } - } - - override fun expiration() = try { - tags.firstOrNull { it.size > 1 && it[0] == "expiration" }?.get(1)?.toLongOrNull() - } catch (_: Exception) { - null - } - - override fun isExpired() = (expiration() ?: Long.MAX_VALUE) < TimeUtils.now() - - override fun getTagOfAddressableKind(kind: Int): ATag? { - val kindStr = kind.toString() - val aTag = tags - .firstOrNull { it.size > 1 && it[0] == "a" && it[1].startsWith(kindStr) } - ?.getOrNull(1) - ?: return null - - return ATag.parse(aTag, null) - } - - override fun getPoWRank(): Int { - var rank = 0 - for (i in 0..id.length) { - if (id[i] == '0') { - rank += 4 - } else if (id[i] in '4'..'7') { - rank += 1 - break - } else if (id[i] in '2'..'3') { - rank += 2 - break - } else if (id[i] == '1') { - rank += 3 - break - } else { - break - } - } - return rank - } - - override fun getGeoHash(): String? { - return tags.firstOrNull { it.size > 1 && it[0] == "g" }?.get(1)?.ifBlank { null } - } - - override fun getReward(): BigDecimal? { - return try { - tags.firstOrNull { it.size > 1 && it[0] == "reward" }?.get(1)?.let { BigDecimal(it) } - } catch (e: Exception) { - null - } - } - - open fun toNIP19(): String { - return if (this is AddressableEvent) { - ATag(kind, pubKey, dTag(), null).toNAddr() - } else { - Nip19.createNEvent(id, pubKey, kind, null) - } - } - - fun toNostrUri(): String { - return "nostr:${toNIP19()}" - } - - fun hasCorrectIDHash() = id.equals(generateId()) - fun hasVerifedSignature() = CryptoUtils.verifySignature(Hex.decode(sig), Hex.decode(id), Hex.decode(pubKey)) - - /** - * Checks if the ID is correct and then if the pubKey's secret key signed the event. - */ - override fun checkSignature() { - if (!hasCorrectIDHash()) { - throw Exception( - """|Unexpected ID. - | Event: ${toJson()} - | Actual ID: $id - | Generated: ${generateId()} - """.trimIndent() - ) - } - if (!hasVerifedSignature()) { - throw Exception("""Bad signature!""") - } - } - - override fun hasValidSignature(): Boolean { - return try { - hasCorrectIDHash() && hasVerifedSignature() - } catch (e: Exception) { - Log.w("Event", "Event $id does not have a valid signature: ${toJson()}", e) - false - } - } - - fun makeJsonForId(): String { - return makeJsonForId(pubKey, createdAt, kind, tags, content) - } - - private fun generateId(): String { - return CryptoUtils.sha256(makeJsonForId().toByteArray()).toHexKey() - } - - private class EventDeserializer : StdDeserializer(Event::class.java) { - override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): Event { - return fromJson(jp.codec.readTree(jp)) - } - } - - private class GossipDeserializer : StdDeserializer(Gossip::class.java) { - override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): Gossip { - val jsonObject: JsonNode = jp.codec.readTree(jp) - return Gossip( - id = jsonObject.get("id")?.asText()?.intern(), - pubKey = jsonObject.get("pubkey")?.asText()?.intern(), - createdAt = jsonObject.get("created_at")?.asLong(), - kind = jsonObject.get("kind")?.asInt(), - tags = jsonObject.get("tags")?.map { - it.mapNotNull { s -> if (s?.isNull ?: true) null else s.asText().intern() } - }, - content = jsonObject.get("content")?.asText() - ) - } - } - - private class EventSerializer: StdSerializer(Event::class.java) { - override fun serialize(event: Event, gen: JsonGenerator, provider: SerializerProvider) { - gen.writeStartObject() - gen.writeStringField("id", event.id) - gen.writeStringField("pubkey", event.pubKey) - gen.writeNumberField("created_at", event.createdAt) - gen.writeNumberField("kind", event.kind) - gen.writeArrayFieldStart("tags") - event.tags.forEach { tag -> - gen.writeArray(tag.toTypedArray(), 0, tag.size) - } - gen.writeEndArray() - gen.writeStringField("content", event.content) - gen.writeStringField("sig", event.sig) - gen.writeEndObject() - } - } - - private class GossipSerializer: StdSerializer(Gossip::class.java) { - override fun serialize(event: Gossip, gen: JsonGenerator, provider: SerializerProvider) { - gen.writeStartObject() - event.id?.let { gen.writeStringField("id", it) } - event.pubKey?.let { gen.writeStringField("pubkey", it) } - event.createdAt?.let { gen.writeNumberField("created_at", it) } - event.kind?.let { gen.writeNumberField("kind", it) } - event.tags?.let { - gen.writeArrayFieldStart("tags") - event.tags.forEach { tag -> - gen.writeArray(tag.toTypedArray(), 0, tag.size) - } - gen.writeEndArray() - } - event.content?.let { gen.writeStringField("content", it) } - gen.writeEndObject() - } - } - - fun toJsonObject(): JsonNode { - val factory = mapper.nodeFactory - - return factory.objectNode().apply { - put("id", id) - put("pubkey", pubKey) - put("created_at", createdAt) - put("kind", kind) - put( - "tags", - factory.arrayNode(tags.size).apply { - tags.forEach { tag -> - add( - factory.arrayNode(tag.size).apply { - tag.forEach { add(it) } - } - ) - } - } - ) - put("content", content) - put("sig", sig) - } - } - - companion object { - val mapper = jacksonObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .registerModule(SimpleModule() - .addSerializer(Event::class.java, EventSerializer()) - .addDeserializer(Event::class.java, EventDeserializer()) - .addSerializer(Gossip::class.java, GossipSerializer()) - .addDeserializer(Gossip::class.java, GossipDeserializer()) - .addDeserializer(Response::class.java, ResponseDeserializer()) - .addDeserializer(Request::class.java, RequestDeserializer()) - ) - - fun fromJson(jsonObject: JsonNode): Event { - return EventFactory.create( - id = jsonObject.get("id").asText().intern(), - pubKey = jsonObject.get("pubkey").asText().intern(), - createdAt = jsonObject.get("created_at").asLong(), - kind = jsonObject.get("kind").asInt(), - tags = jsonObject.get("tags").map { - it.mapNotNull { s -> if (s.isNull) null else s.asText().intern() } - }, - content = jsonObject.get("content").asText(), - sig = jsonObject.get("sig").asText() - ) - } - - fun fromJson(json: String): Event = mapper.readValue(json, Event::class.java) - fun toJson(event: Event): String = mapper.writeValueAsString(event) - - fun makeJsonForId(pubKey: HexKey, createdAt: Long, kind: Int, tags: List>, content: String): String { - val factory = mapper.nodeFactory - val rawEvent = factory.arrayNode(6).apply { - add(0) - add(pubKey) - add(createdAt) - add(kind) - add( - factory.arrayNode(tags.size).apply { - tags.forEach { tag -> - add( - factory.arrayNode(tag.size).apply { - tag.forEach { add(it) } - } - ) - } - } - ) - add(content) - } - - return mapper.writeValueAsString(rawEvent) - } - - fun generateId(pubKey: HexKey, createdAt: Long, kind: Int, tags: List>, content: String): ByteArray { - return CryptoUtils.sha256(makeJsonForId(pubKey, createdAt, kind, tags, content).toByteArray()) - } - - fun create(privateKey: ByteArray, kind: Int, tags: List> = emptyList(), content: String = "", createdAt: Long = TimeUtils.now()): Event { - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = Companion.generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey).toHexKey() - return Event(id.toHexKey(), pubKey, createdAt, kind, tags, content, sig) - } - } -} - -@Immutable -open class WrappedEvent( - id: HexKey, - @JsonProperty("pubkey") - pubKey: HexKey, - @JsonProperty("created_at") - createdAt: Long, - kind: Int, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - @Transient - var host: Event? = null // host event to broadcast when needed -} - -@Immutable -interface AddressableEvent { - fun dTag(): String - fun address(): ATag -} - -@Immutable -open class BaseAddressableEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - kind: Int, - tags: List>, - content: String, - sig: HexKey -): Event(id, pubKey, createdAt, kind, tags, content, sig), AddressableEvent { - override fun dTag() = tags.firstOrNull { it.size > 1 && it[0] == "d" }?.get(1) ?: "" - override fun address() = ATag(kind, pubKey, dTag(), null) -} - -fun String.bytesUsedInMemory(): Int { - return (8 * ((((this.length) * 2) + 45) / 8)) -} - diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/EventFactory.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/EventFactory.kt deleted file mode 100644 index 1069f58c..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/EventFactory.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.vitorpamplona.quartz.events - -import com.vitorpamplona.quartz.encoders.toHexKey - -class EventFactory { - companion object { - fun create( - id: String, - pubKey: String, - createdAt: Long, - kind: Int, - tags: List>, - content: String, - sig: String - ) = when (kind) { - AdvertisedRelayListEvent.kind -> AdvertisedRelayListEvent(id, pubKey, createdAt, tags, content, sig) - AppDefinitionEvent.kind -> AppDefinitionEvent(id, pubKey, createdAt, tags, content, sig) - AppRecommendationEvent.kind -> AppRecommendationEvent(id, pubKey, createdAt, tags, content, sig) - AudioHeaderEvent.kind -> AudioHeaderEvent(id, pubKey, createdAt, tags, content, sig) - AudioTrackEvent.kind -> AudioTrackEvent(id, pubKey, createdAt, tags, content, sig) - BadgeAwardEvent.kind -> BadgeAwardEvent(id, pubKey, createdAt, tags, content, sig) - BadgeDefinitionEvent.kind -> BadgeDefinitionEvent(id, pubKey, createdAt, tags, content, sig) - BadgeProfilesEvent.kind -> BadgeProfilesEvent(id, pubKey, createdAt, tags, content, sig) - BookmarkListEvent.kind -> BookmarkListEvent(id, pubKey, createdAt, tags, content, sig) - CalendarEvent.kind -> CalendarEvent(id, pubKey, createdAt, tags, content, sig) - CalendarDateSlotEvent.kind -> CalendarDateSlotEvent(id, pubKey, createdAt, tags, content, sig) - CalendarTimeSlotEvent.kind -> CalendarTimeSlotEvent(id, pubKey, createdAt, tags, content, sig) - CalendarRSVPEvent.kind -> CalendarRSVPEvent(id, pubKey, createdAt, tags, content, sig) - ChannelCreateEvent.kind -> ChannelCreateEvent(id, pubKey, createdAt, tags, content, sig) - ChannelHideMessageEvent.kind -> ChannelHideMessageEvent(id, pubKey, createdAt, tags, content, sig) - ChannelMessageEvent.kind -> ChannelMessageEvent(id, pubKey, createdAt, tags, content, sig) - ChannelMetadataEvent.kind -> ChannelMetadataEvent(id, pubKey, createdAt, tags, content, sig) - ChannelMuteUserEvent.kind -> ChannelMuteUserEvent(id, pubKey, createdAt, tags, content, sig) - ChatMessageEvent.kind -> { - if (id.isBlank()) { - val id = Event.generateId(pubKey, createdAt, kind, tags, content).toHexKey() - ChatMessageEvent(id, pubKey, createdAt, tags, content, sig) - } else { - ChatMessageEvent(id, pubKey, createdAt, tags, content, sig) - } - } - ClassifiedsEvent.kind -> ClassifiedsEvent(id, pubKey, createdAt, tags, content, sig) - CommunityDefinitionEvent.kind -> CommunityDefinitionEvent(id, pubKey, createdAt, tags, content, sig) - CommunityPostApprovalEvent.kind -> CommunityPostApprovalEvent(id, pubKey, createdAt, tags, content, sig) - ContactListEvent.kind -> ContactListEvent(id, pubKey, createdAt, tags, content, sig) - DeletionEvent.kind -> DeletionEvent(id, pubKey, createdAt, tags, content, sig) - - EmojiPackEvent.kind -> EmojiPackEvent(id, pubKey, createdAt, tags, content, sig) - EmojiPackSelectionEvent.kind -> EmojiPackSelectionEvent(id, pubKey, createdAt, tags, content, sig) - SealedGossipEvent.kind -> SealedGossipEvent(id, pubKey, createdAt, tags, content, sig) - - FileHeaderEvent.kind -> FileHeaderEvent(id, pubKey, createdAt, tags, content, sig) - FileStorageEvent.kind -> FileStorageEvent(id, pubKey, createdAt, tags, content, sig) - FileStorageHeaderEvent.kind -> FileStorageHeaderEvent(id, pubKey, createdAt, tags, content, sig) - GenericRepostEvent.kind -> GenericRepostEvent(id, pubKey, createdAt, tags, content, sig) - GiftWrapEvent.kind -> GiftWrapEvent(id, pubKey, createdAt, tags, content, sig) - HighlightEvent.kind -> HighlightEvent(id, pubKey, createdAt, tags, content, sig) - LiveActivitiesEvent.kind -> LiveActivitiesEvent(id, pubKey, createdAt, tags, content, sig) - LiveActivitiesChatMessageEvent.kind -> LiveActivitiesChatMessageEvent(id, pubKey, createdAt, tags, content, sig) - LnZapEvent.kind -> LnZapEvent(id, pubKey, createdAt, tags, content, sig) - LnZapPaymentRequestEvent.kind -> LnZapPaymentRequestEvent(id, pubKey, createdAt, tags, content, sig) - LnZapPaymentResponseEvent.kind -> LnZapPaymentResponseEvent(id, pubKey, createdAt, tags, content, sig) - LnZapPrivateEvent.kind -> LnZapPrivateEvent(id, pubKey, createdAt, tags, content, sig) - LnZapRequestEvent.kind -> LnZapRequestEvent(id, pubKey, createdAt, tags, content, sig) - LongTextNoteEvent.kind -> LongTextNoteEvent(id, pubKey, createdAt, tags, content, sig) - MetadataEvent.kind -> MetadataEvent(id, pubKey, createdAt, tags, content, sig) - NNSEvent.kind -> NNSEvent(id, pubKey, createdAt, tags, content, sig) - PeopleListEvent.kind -> PeopleListEvent(id, pubKey, createdAt, tags, content, sig) - PinListEvent.kind -> PinListEvent(id, pubKey, createdAt, tags, content, sig) - PollNoteEvent.kind -> PollNoteEvent(id, pubKey, createdAt, tags, content, sig) - PrivateDmEvent.kind -> PrivateDmEvent(id, pubKey, createdAt, tags, content, sig) - ReactionEvent.kind -> ReactionEvent(id, pubKey, createdAt, tags, content, sig) - RecommendRelayEvent.kind -> RecommendRelayEvent(id, pubKey, createdAt, tags, content, sig) - RelaySetEvent.kind -> RelaySetEvent(id, pubKey, createdAt, tags, content, sig) - ReportEvent.kind -> ReportEvent(id, pubKey, createdAt, tags, content, sig) - RepostEvent.kind -> RepostEvent(id, pubKey, createdAt, tags, content, sig) - StatusEvent.kind -> StatusEvent(id, pubKey, createdAt, tags, content, sig) - TextNoteEvent.kind -> TextNoteEvent(id, pubKey, createdAt, tags, content, sig) - else -> Event(id, pubKey, createdAt, kind, tags, content, sig) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/EventInterface.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/EventInterface.kt deleted file mode 100644 index 61ba9dbc..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/EventInterface.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey -import java.math.BigDecimal - -@Immutable -interface EventInterface { - fun countMemory(): Long - - fun id(): HexKey - - fun pubKey(): HexKey - - fun createdAt(): Long - - fun kind(): Int - - fun tags(): List> - - fun content(): String - - fun sig(): HexKey - - fun toJson(): String - - fun checkSignature() - - fun hasValidSignature(): Boolean - - fun isTaggedUser(idHex: String): Boolean - fun isTaggedUsers(idHex: Set): Boolean - - fun isTaggedEvent(idHex: String): Boolean - - fun isTaggedAddressableNote(idHex: String): Boolean - fun isTaggedAddressableNotes(idHexes: Set): Boolean - - fun isTaggedHash(hashtag: String): Boolean - fun isTaggedGeoHash(hashtag: String): Boolean - - fun isTaggedHashes(hashtags: Set): Boolean - fun isTaggedGeoHashes(hashtags: Set): Boolean - - fun firstIsTaggedHashes(hashtags: Set): String? - fun firstIsTaggedAddressableNote(addressableNotes: Set): String? - - fun isTaggedAddressableKind(kind: Int): Boolean - fun getTagOfAddressableKind(kind: Int): ATag? - - fun expiration(): Long? - - fun hashtags(): List - fun geohashes(): List - - fun getReward(): BigDecimal? - fun getPoWRank(): Int - fun getGeoHash(): String? - - fun zapAddress(): String? - fun isSensitive(): Boolean - fun subject(): String? - fun zapraiserAmount(): Long? - - fun taggedAddresses(): List - fun taggedUsers(): List - fun taggedEvents(): List - fun taggedUrls(): List - - fun firstTaggedAddress(): ATag? - fun firstTaggedUser(): HexKey? - fun firstTaggedEvent(): HexKey? - fun firstTaggedUrl(): String? - - fun taggedEmojis(): List - fun matchTag1With(text: String): Boolean - fun isExpired(): Boolean -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/FileHeaderEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/FileHeaderEvent.kt deleted file mode 100644 index 92a0dd0f..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/FileHeaderEvent.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class FileHeaderEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - fun url() = tags.firstOrNull { it.size > 1 && it[0] == URL }?.get(1) - fun encryptionKey() = tags.firstOrNull { it.size > 2 && it[0] == ENCRYPTION_KEY }?.let { AESGCM(it[1], it[2]) } - fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == MIME_TYPE }?.get(1) - fun hash() = tags.firstOrNull { it.size > 1 && it[0] == HASH }?.get(1) - fun size() = tags.firstOrNull { it.size > 1 && it[0] == FILE_SIZE }?.get(1) - fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == DIMENSION }?.get(1) - fun magnetURI() = tags.firstOrNull { it.size > 1 && it[0] == MAGNET_URI }?.get(1) - fun torrentInfoHash() = tags.firstOrNull { it.size > 1 && it[0] == TORRENT_INFOHASH }?.get(1) - fun blurhash() = tags.firstOrNull { it.size > 1 && it[0] == BLUR_HASH }?.get(1) - - fun hasUrl() = tags.any { it.size > 1 && it[0] == URL } - - companion object { - const val kind = 1063 - - private const val URL = "url" - private const val ENCRYPTION_KEY = "aes-256-gcm" - private const val MIME_TYPE = "m" - private const val FILE_SIZE = "size" - private const val DIMENSION = "dim" - private const val HASH = "x" - private const val MAGNET_URI = "magnet" - private const val TORRENT_INFOHASH = "i" - private const val BLUR_HASH = "blurhash" - - fun create( - url: String, - mimeType: String? = null, - description: String? = null, - hash: String? = null, - size: String? = null, - dimensions: String? = null, - blurhash: String? = null, - magnetURI: String? = null, - torrentInfoHash: String? = null, - encryptionKey: AESGCM? = null, - sensitiveContent: Boolean? = null, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): FileHeaderEvent { - val tags = listOfNotNull( - listOf(URL, url), - mimeType?.let { listOf(MIME_TYPE, mimeType) }, - hash?.let { listOf(HASH, it) }, - size?.let { listOf(FILE_SIZE, it) }, - dimensions?.let { listOf(DIMENSION, it) }, - blurhash?.let { listOf(BLUR_HASH, it) }, - magnetURI?.let { listOf(MAGNET_URI, it) }, - torrentInfoHash?.let { listOf(TORRENT_INFOHASH, it) }, - encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) }, - sensitiveContent?.let { - if (it) { - listOf("content-warning", "") - } else { - null - } - } - ) - - val content = description ?: "" - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return FileHeaderEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - } -} - -data class AESGCM(val key: String, val nonce: String) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/FileStorageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/FileStorageEvent.kt deleted file mode 100644 index 010864f9..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/FileStorageEvent.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey -import java.util.Base64 - -@Immutable -class FileStorageEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - fun type() = tags.firstOrNull { it.size > 1 && it[0] == TYPE }?.get(1) - fun decryptKey() = tags.firstOrNull { it.size > 2 && it[0] == DECRYPT }?.let { AESGCM(it[1], it[2]) } - - fun decode(): ByteArray? { - return try { - Base64.getDecoder().decode(content) - } catch (e: Exception) { - Log.e("FileStorageEvent", "Unable to decode base 64 ${e.message} $content") - null - } - } - - companion object { - const val kind = 1064 - - private const val TYPE = "type" - private const val DECRYPT = "decrypt" - - fun encode(bytes: ByteArray): String { - return Base64.getEncoder().encodeToString(bytes) - } - - fun create( - mimeType: String, - data: ByteArray, - pubKey: HexKey, - createdAt: Long = TimeUtils.now() - ): FileStorageEvent { - val tags = listOfNotNull( - listOf(TYPE, mimeType) - ) - - val content = encode(data) - val id = generateId(pubKey, createdAt, kind, tags, content) - return FileStorageEvent(id.toHexKey(), pubKey, createdAt, tags, content, "") - } - - fun create( - mimeType: String, - data: ByteArray, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): FileStorageEvent { - val tags = listOfNotNull( - listOf(TYPE, mimeType) - ) - - val content = encode(data) - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return FileStorageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/FileStorageHeaderEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/FileStorageHeaderEvent.kt deleted file mode 100644 index 2554ac1a..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/FileStorageHeaderEvent.kt +++ /dev/null @@ -1,122 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class FileStorageHeaderEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - fun dataEventId() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1) - - fun encryptionKey() = tags.firstOrNull { it.size > 2 && it[0] == ENCRYPTION_KEY }?.let { AESGCM(it[1], it[2]) } - fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == MIME_TYPE }?.get(1) - fun hash() = tags.firstOrNull { it.size > 1 && it[0] == HASH }?.get(1) - fun size() = tags.firstOrNull { it.size > 1 && it[0] == FILE_SIZE }?.get(1) - fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == DIMENSION }?.get(1) - fun magnetURI() = tags.firstOrNull { it.size > 1 && it[0] == MAGNET_URI }?.get(1) - fun torrentInfoHash() = tags.firstOrNull { it.size > 1 && it[0] == TORRENT_INFOHASH }?.get(1) - fun blurhash() = tags.firstOrNull { it.size > 1 && it[0] == BLUR_HASH }?.get(1) - - companion object { - const val kind = 1065 - - private const val ENCRYPTION_KEY = "aes-256-gcm" - private const val MIME_TYPE = "m" - private const val FILE_SIZE = "size" - private const val DIMENSION = "dim" - private const val HASH = "x" - private const val MAGNET_URI = "magnet" - private const val TORRENT_INFOHASH = "i" - private const val BLUR_HASH = "blurhash" - - fun create( - storageEvent: FileStorageEvent, - mimeType: String? = null, - description: String? = null, - hash: String? = null, - size: String? = null, - dimensions: String? = null, - blurhash: String? = null, - magnetURI: String? = null, - torrentInfoHash: String? = null, - encryptionKey: AESGCM? = null, - sensitiveContent: Boolean? = null, - pubKey: HexKey, - createdAt: Long = TimeUtils.now() - ): FileStorageHeaderEvent { - val tags = listOfNotNull( - listOf("e", storageEvent.id), - mimeType?.let { listOf(MIME_TYPE, mimeType) }, - hash?.let { listOf(HASH, it) }, - size?.let { listOf(FILE_SIZE, it) }, - dimensions?.let { listOf(DIMENSION, it) }, - blurhash?.let { listOf(BLUR_HASH, it) }, - magnetURI?.let { listOf(MAGNET_URI, it) }, - torrentInfoHash?.let { listOf(TORRENT_INFOHASH, it) }, - encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) }, - sensitiveContent?.let { - if (it) { - listOf("content-warning", "") - } else { - null - } - } - ) - - val content = description ?: "" - val id = generateId(pubKey, createdAt, kind, tags, content) - return FileStorageHeaderEvent(id.toHexKey(), pubKey, createdAt, tags, content, "") - } - - fun create( - storageEvent: FileStorageEvent, - mimeType: String? = null, - description: String? = null, - hash: String? = null, - size: String? = null, - dimensions: String? = null, - blurhash: String? = null, - magnetURI: String? = null, - torrentInfoHash: String? = null, - encryptionKey: AESGCM? = null, - sensitiveContent: Boolean? = null, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): FileStorageHeaderEvent { - val tags = listOfNotNull( - listOf("e", storageEvent.id), - mimeType?.let { listOf(MIME_TYPE, mimeType) }, - hash?.let { listOf(HASH, it) }, - size?.let { listOf(FILE_SIZE, it) }, - dimensions?.let { listOf(DIMENSION, it) }, - blurhash?.let { listOf(BLUR_HASH, it) }, - magnetURI?.let { listOf(MAGNET_URI, it) }, - torrentInfoHash?.let { listOf(TORRENT_INFOHASH, it) }, - encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) }, - sensitiveContent?.let { - if (it) { - listOf("content-warning", "") - } else { - null - } - } - ) - - val content = description ?: "" - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return FileStorageHeaderEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/GeneralListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/GeneralListEvent.kt deleted file mode 100644 index 9a98b586..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/GeneralListEvent.kt +++ /dev/null @@ -1,139 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.fasterxml.jackson.module.kotlin.readValue -import com.vitorpamplona.quartz.encoders.hexToByteArray -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -abstract class GeneralListEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - kind: Int, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun category() = dTag() - fun bookmarkedPosts() = taggedEvents() - fun bookmarkedPeople() = taggedUsers() - - fun plainContent(privKey: ByteArray): String? { - if (content.isBlank()) return null - - return try { - val sharedSecret = CryptoUtils.getSharedSecretNIP04(privKey, pubKey.hexToByteArray()) - - return CryptoUtils.decryptNIP04(content, sharedSecret) - } catch (e: Exception) { - Log.w("GeneralList", "Error decrypting the message ${e.message} for ${dTag()}") - null - } - } - - @Transient - private var privateTagsCache: List>? = null - - fun privateTags(privKey: ByteArray): List>? { - if (privateTagsCache != null) { - return privateTagsCache - } - - privateTagsCache = try { - plainContent(privKey)?.let { mapper.readValue>>(it) } - } catch (e: Throwable) { - Log.w("GeneralList", "Error parsing the JSON ${e.message}") - null - } - return privateTagsCache - } - - fun privateTags(content: String): List>? { - if (privateTagsCache != null) { - return privateTagsCache - } - - privateTagsCache = try { - content.let { mapper.readValue>>(it) } - } catch (e: Throwable) { - Log.w("GeneralList", "Error parsing the JSON ${e.message}") - null - } - return privateTagsCache - } - - fun privateTagsOrEmpty(privKey: ByteArray): List> { - return privateTags(privKey) ?: emptyList() - } - - fun privateTagsOrEmpty(content: String): List> { - return privateTags(content) ?: emptyList() - } - - fun privateTaggedUsers(privKey: ByteArray) = privateTags(privKey)?.filter { it.size > 1 && it[0] == "p" }?.map { it[1] } - fun privateTaggedUsers(content: String) = privateTags(content)?.filter { it.size > 1 && it[0] == "p" }?.map { it[1] } - fun privateHashtags(privKey: ByteArray) = privateTags(privKey)?.filter { it.size > 1 && it[0] == "t" }?.map { it[1] } - fun privateHashtags(content: String) = privateTags(content)?.filter { it.size > 1 && it[0] == "t" }?.map { it[1] } - fun privateGeohashes(privKey: ByteArray) = privateTags(privKey)?.filter { it.size > 1 && it[0] == "g" }?.map { it[1] } - fun privateGeohashes(content: String) = privateTags(content)?.filter { it.size > 1 && it[0] == "g" }?.map { it[1] } - fun privateTaggedEvents(privKey: ByteArray) = privateTags(privKey)?.filter { it.size > 1 && it[0] == "e" }?.map { it[1] } - fun privateTaggedEvents(content: String) = privateTags(content)?.filter { it.size > 1 && it[0] == "e" }?.map { it[1] } - - fun privateTaggedAddresses(privKey: ByteArray) = privateTags(privKey)?.filter { it.firstOrNull() == "a" }?.mapNotNull { - val aTagValue = it.getOrNull(1) - val relay = it.getOrNull(2) - - if (aTagValue != null) ATag.parse(aTagValue, relay) else null - } - - fun privateTaggedAddresses(content: String) = privateTags(content)?.filter { it.firstOrNull() == "a" }?.mapNotNull { - val aTagValue = it.getOrNull(1) - val relay = it.getOrNull(2) - - if (aTagValue != null) ATag.parse(aTagValue, relay) else null - } - - companion object { - fun createPrivateTags( - privEvents: List? = null, - privUsers: List? = null, - privAddresses: List? = null, - - privateKey: ByteArray, - pubKey: ByteArray - ): String { - val privTags = mutableListOf>() - privEvents?.forEach { - privTags.add(listOf("e", it)) - } - privUsers?.forEach { - privTags.add(listOf("p", it)) - } - privAddresses?.forEach { - privTags.add(listOf("a", it.toTag())) - } - val msg = mapper.writeValueAsString(privTags) - - return CryptoUtils.encryptNIP04( - msg, - privateKey, - pubKey - ) - } - - fun encryptTags( - privateTags: List>? = null, - privateKey: ByteArray - ): String { - return CryptoUtils.encryptNIP04( - msg = mapper.writeValueAsString(privateTags), - privateKey = privateKey, - pubKey = CryptoUtils.pubkeyCreate(privateKey) - ) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/GenericRepostEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/GenericRepostEvent.kt deleted file mode 100644 index adbea501..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/GenericRepostEvent.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class GenericRepostEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - fun boostedPost() = tags.filter { it.firstOrNull() == "e" }.mapNotNull { it.getOrNull(1) } - fun originalAuthor() = tags.filter { it.firstOrNull() == "p" }.mapNotNull { it.getOrNull(1) } - - fun containedPost() = try { - fromJson(content) - } catch (e: Exception) { - null - } - - companion object { - const val kind = 16 - - fun create(boostedPost: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): GenericRepostEvent { - val content = boostedPost.toJson() - - val replyToPost = listOf("e", boostedPost.id()) - val replyToAuthor = listOf("p", boostedPost.pubKey()) - - val pubKey = keyPair.pubKey.toHexKey() - var tags: List> = listOf(replyToPost, replyToAuthor) - - if (boostedPost is AddressableEvent) { - tags = tags + listOf(listOf("a", boostedPost.address().toTag())) - } - - tags = tags + listOf(listOf("k", "${boostedPost.kind()}")) - - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return GenericRepostEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(unsignedEvent: GenericRepostEvent, signature: String): GenericRepostEvent { - return GenericRepostEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/GiftWrapEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/GiftWrapEvent.kt deleted file mode 100644 index 3946c7f9..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/GiftWrapEvent.kt +++ /dev/null @@ -1,114 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.hexToByteArray -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.Nip44Version -import com.vitorpamplona.quartz.crypto.decodeNIP44 -import com.vitorpamplona.quartz.crypto.encodeNIP44 -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class GiftWrapEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - @Transient - private var cachedInnerEvent: Map = mapOf() - - fun cachedGift(privKey: ByteArray): Event? { - val hex = privKey.toHexKey() - if (cachedInnerEvent.contains(hex)) return cachedInnerEvent[hex] - - val myInnerEvent = unwrap(privKey = privKey) - if (myInnerEvent is WrappedEvent) { - myInnerEvent.host = this - } - - cachedInnerEvent = cachedInnerEvent + Pair(hex, myInnerEvent) - return myInnerEvent - } - - fun cachedGift(pubKey: ByteArray, decryptedContent: String): Event? { - val hex = pubKey.toHexKey() - if (cachedInnerEvent.contains(hex)) return cachedInnerEvent[hex] - - val myInnerEvent = unwrap(decryptedContent) - if (myInnerEvent is WrappedEvent) { - myInnerEvent.host = this - } - - cachedInnerEvent = cachedInnerEvent + Pair(hex, myInnerEvent) - return myInnerEvent - } - - fun unwrap(privKey: ByteArray) = try { - plainContent(privKey)?.let { fromJson(it) } - } catch (e: Exception) { - // Log.e("UnwrapError", "Couldn't Decrypt the content", e) - null - } - - fun unwrap(decryptedContent: String) = try { - plainContent(decryptedContent)?.let { fromJson(it) } - } catch (e: Exception) { - // Log.e("UnwrapError", "Couldn't Decrypt the content", e) - null - } - - private fun plainContent(privKey: ByteArray): String? { - if (content.isEmpty()) return null - - return try { - val toDecrypt = decodeNIP44(content) ?: return null - - return when (toDecrypt.v) { - Nip44Version.NIP04.versionCode -> CryptoUtils.decryptNIP04(toDecrypt, privKey, pubKey.hexToByteArray()) - Nip44Version.NIP44.versionCode -> CryptoUtils.decryptNIP44(toDecrypt, privKey, pubKey.hexToByteArray()) - else -> null - } - } catch (e: Exception) { - Log.w("GeneralList", "Error decrypting the message ${e.message}") - null - } - } - - private fun plainContent(decryptedContent: String): String? { - if (decryptedContent.isEmpty()) return null - return decryptedContent - } - - fun recipientPubKey() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.get(1) - - companion object { - const val kind = 1059 - - fun create( - event: Event, - recipientPubKey: HexKey, - createdAt: Long = TimeUtils.randomWithinAWeek() - ): GiftWrapEvent { - val privateKey = CryptoUtils.privkeyCreate() // GiftWrap is always a random key - val sharedSecret = CryptoUtils.getSharedSecretNIP44(privateKey, recipientPubKey.hexToByteArray()) - - val content = encodeNIP44( - CryptoUtils.encryptNIP44( - toJson(event), - sharedSecret - ) - ) - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val tags = listOf(listOf("p", recipientPubKey)) - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return GiftWrapEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/HTTPAuthorizationEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/HTTPAuthorizationEvent.kt deleted file mode 100644 index c22abc29..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/HTTPAuthorizationEvent.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class HTTPAuthorizationEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - companion object { - const val kind = 27235 - - fun create( - url: String, - method: String, - body: String? = null, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): HTTPAuthorizationEvent { - var hash = "" - body?.let { - hash = CryptoUtils.sha256(it.toByteArray()).toHexKey() - } - - val tags = listOfNotNull( - listOf("u", url), - listOf("method", method), - listOf("payload", hash) - ) - - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return HTTPAuthorizationEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig?.toHexKey() ?: "") - } - - fun create( - unsignedEvent: HTTPAuthorizationEvent, signature: String - ): HTTPAuthorizationEvent { - return HTTPAuthorizationEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/HighlightEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/HighlightEvent.kt deleted file mode 100644 index 33078358..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/HighlightEvent.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class HighlightEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - fun inUrl() = taggedUrls().firstOrNull() - fun author() = taggedUsers().firstOrNull() - fun quote() = content - - fun inPost() = taggedAddresses().firstOrNull() - - companion object { - const val kind = 9802 - - fun create( - msg: String, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): HighlightEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val tags = mutableListOf>() - val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = CryptoUtils.sign(id, privateKey) - return HighlightEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LiveActivitiesChatMessageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LiveActivitiesChatMessageEvent.kt deleted file mode 100644 index 3e84f352..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LiveActivitiesChatMessageEvent.kt +++ /dev/null @@ -1,94 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class LiveActivitiesChatMessageEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - private fun innerActivity() = tags.firstOrNull { - it.size > 3 && it[0] == "a" && it[3] == "root" - } ?: tags.firstOrNull { - it.size > 1 && it[0] == "a" - } - - private fun activityHex() = innerActivity()?.let { - it.getOrNull(1) - } - - fun activity() = innerActivity()?.let { - if (it.size > 1) { - val aTagValue = it[1] - val relay = it.getOrNull(2) - - ATag.parse(aTagValue, relay) - } else { - null - } - } - - override fun replyTos() = taggedEvents().minus(activityHex() ?: "") - - companion object { - const val kind = 1311 - - fun create( - message: String, - activity: ATag, - replyTos: List? = null, - mentions: List? = null, - zapReceiver: String?, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now(), - markAsSensitive: Boolean, - zapRaiserAmount: Long?, - geohash: String? = null - ): LiveActivitiesChatMessageEvent { - val content = message - val tags = mutableListOf( - listOf("a", activity.toTag(), "", "root") - ) - replyTos?.forEach { - tags.add(listOf("e", it)) - } - mentions?.forEach { - tags.add(listOf("p", it)) - } - zapReceiver?.let { - tags.add(listOf("zap", it)) - } - if (markAsSensitive) { - tags.add(listOf("content-warning", "")) - } - zapRaiserAmount?.let { - tags.add(listOf("zapraiser", "$it")) - } - geohash?.let { - tags.add(listOf("g", it)) - } - - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return LiveActivitiesChatMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create( - unsignedEvent: LiveActivitiesChatMessageEvent, signature: String - ): LiveActivitiesChatMessageEvent { - return LiveActivitiesChatMessageEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LiveActivitiesEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LiveActivitiesEvent.kt deleted file mode 100644 index 9dde9302..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LiveActivitiesEvent.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class LiveActivitiesEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun title() = tags.firstOrNull { it.size > 1 && it[0] == "title" }?.get(1) - fun summary() = tags.firstOrNull { it.size > 1 && it[0] == "summary" }?.get(1) - fun image() = tags.firstOrNull { it.size > 1 && it[0] == "image" }?.get(1) - fun streaming() = tags.firstOrNull { it.size > 1 && it[0] == "streaming" }?.get(1) - fun starts() = tags.firstOrNull { it.size > 1 && it[0] == "starts" }?.get(1)?.toLongOrNull() - fun ends() = tags.firstOrNull { it.size > 1 && it[0] == "ends" }?.get(1) - fun status() = checkStatus(tags.firstOrNull { it.size > 1 && it[0] == "status" }?.get(1)) - fun currentParticipants() = tags.firstOrNull { it.size > 1 && it[0] == "current_participants" }?.get(1) - fun totalParticipants() = tags.firstOrNull { it.size > 1 && it[0] == "total_participants" }?.get(1) - - fun participants() = tags.filter { it.size > 1 && it[0] == "p" }.map { Participant(it[1], it.getOrNull(3)) } - - fun checkStatus(eventStatus: String?): String? { - return if (eventStatus == STATUS_LIVE && createdAt < TimeUtils.eightHoursAgo()) { - STATUS_ENDED - } else { - eventStatus - } - } - - fun participantsIntersect(keySet: Set): Boolean { - return tags.any { it.size > 1 && it[0] == "p" && it[1] in keySet } - } - - companion object { - const val kind = 30311 - - const val STATUS_LIVE = "live" - const val STATUS_PLANNED = "planned" - const val STATUS_ENDED = "ended" - - fun create( - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): LiveActivitiesEvent { - val tags = mutableListOf>() - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return LiveActivitiesEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapEvent.kt deleted file mode 100644 index ab1982a9..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapEvent.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.encoders.HexKey -import com.vitorpamplona.quartz.encoders.LnInvoiceUtil - -@Immutable -class LnZapEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : LnZapEventInterface, Event(id, pubKey, createdAt, kind, tags, content, sig) { - // This event is also kept in LocalCache (same object) - @Transient val zapRequest: LnZapRequestEvent? - override fun containedPost(): LnZapRequestEvent? = try { - description()?.ifBlank { null }?.let { - fromJson(it) - } as? LnZapRequestEvent - } catch (e: Exception) { - Log.w("LnZapEvent", "Failed to Parse Contained Post ${description()}", e) - null - } - - init { - zapRequest = containedPost() - } - - override fun zappedPost() = tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] } - - override fun zappedAuthor() = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] } - - override fun zappedPollOption(): Int? = try { - zapRequest?.tags?.firstOrNull { it.size > 1 && it[0] == POLL_OPTION }?.get(1)?.toInt() - } catch (e: Exception) { - Log.e("LnZapEvent", "ZappedPollOption failed to parse", e) - null - } - - override fun zappedRequestAuthor(): String? = zapRequest?.pubKey() - - override fun amount() = amount - - // Keeps this as a field because it's a heavier function used everywhere. - val amount by lazy { - try { - lnInvoice()?.let { LnInvoiceUtil.getAmountInSats(it) } - } catch (e: Exception) { - Log.e("LnZapEvent", "Failed to Parse LnInvoice ${description()}", e) - null - } - } - override fun content(): String { - return content - } - - fun lnInvoice() = tags.firstOrNull { it.size > 1 && it[0] == "bolt11" }?.get(1) - - private fun description() = tags.firstOrNull { it.size > 1 && it[0] == "description" }?.get(1) - - companion object { - const val kind = 9735 - } - - enum class ZapType() { - PUBLIC, - PRIVATE, - ANONYMOUS, - NONZAP - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapEventInterface.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapEventInterface.kt deleted file mode 100644 index e65ac694..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapEventInterface.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import java.math.BigDecimal - -@Immutable -interface LnZapEventInterface : EventInterface { - - fun zappedPost(): List - - fun zappedPollOption(): Int? - - fun zappedAuthor(): List - - fun zappedRequestAuthor(): String? - - fun amount(): BigDecimal? - - fun containedPost(): Event? -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPaymentRequestEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPaymentRequestEvent.kt deleted file mode 100644 index 2f46d58f..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPaymentRequestEvent.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.hexToByteArray -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class LnZapPaymentRequestEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - // Once one of an app user decrypts the payment, all users else can see it. - @Transient - private var lnInvoice: String? = null - - fun walletServicePubKey() = tags.firstOrNull() { it.size > 1 && it[0] == "p" }?.get(1) - - fun lnInvoice(privKey: ByteArray, pubkey: ByteArray): String? { - if (lnInvoice != null) { - return lnInvoice - } - - return try { - val sharedSecret = CryptoUtils.getSharedSecretNIP04(privKey, pubkey) - - val jsonText = CryptoUtils.decryptNIP04(content, sharedSecret) - - val payInvoiceMethod = mapper.readValue(jsonText, Request::class.java) - - lnInvoice = (payInvoiceMethod as? PayInvoiceMethod)?.params?.invoice - - return lnInvoice - } catch (e: Exception) { - Log.w("BookmarkList", "Error decrypting the message ${e.message}") - null - } - } - - companion object { - const val kind = 23194 - - fun create( - lnInvoice: String, - walletServicePubkey: String, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): LnZapPaymentRequestEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey) - val serializedRequest = mapper.writeValueAsString(PayInvoiceMethod.create(lnInvoice)) - - val content = CryptoUtils.encryptNIP04( - serializedRequest, - privateKey, - walletServicePubkey.hexToByteArray() - ) - - val tags = mutableListOf>() - tags.add(listOf("p", walletServicePubkey)) - - val id = generateId(pubKey.toHexKey(), createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return LnZapPaymentRequestEvent(id.toHexKey(), pubKey.toHexKey(), createdAt, tags, content, sig.toHexKey()) - } - } -} - -// REQUEST OBJECTS - -abstract class Request(var method: String? = null) - -// PayInvoice Call -class PayInvoiceParams(var invoice: String? = null) - -class PayInvoiceMethod(var params: PayInvoiceParams? = null) : Request("pay_invoice") { - - companion object { - fun create(bolt11: String): PayInvoiceMethod { - return PayInvoiceMethod(PayInvoiceParams(bolt11)) - } - } -} - - -class RequestDeserializer : StdDeserializer(Request::class.java) { - override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): Request? { - val jsonObject: JsonNode = jp.codec.readTree(jp) - val method = jsonObject.get("method")?.asText() - - if (method == "pay_invoice") { - return jp.codec.treeToValue(jsonObject, PayInvoiceMethod::class.java) - } - return null - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPaymentResponseEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPaymentResponseEvent.kt deleted file mode 100644 index 9055bbeb..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPaymentResponseEvent.kt +++ /dev/null @@ -1,132 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class LnZapPaymentResponseEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - // Once one of an app user decrypts the payment, all users else can see it. - @Transient - private var response: Response? = null - - fun requestAuthor() = tags.firstOrNull() { it.size > 1 && it[0] == "p" }?.get(1) - fun requestId() = tags.firstOrNull() { it.size > 1 && it[0] == "e" }?.get(1) - - private fun decrypt(privKey: ByteArray, pubKey: ByteArray): String? { - return try { - val sharedSecret = CryptoUtils.getSharedSecretNIP04(privKey, pubKey) - - val retVal = CryptoUtils.decryptNIP04(content, sharedSecret) - - if (retVal.startsWith(PrivateDmEvent.nip18Advertisement)) { - retVal.substring(16) - } else { - retVal - } - } catch (e: Exception) { - Log.w("PrivateDM", "Error decrypting the message ${e.message}") - null - } - } - - fun response(privKey: ByteArray, pubKey: ByteArray): Response? { - if (response != null) response - - return try { - if (content.isNotEmpty()) { - val decrypted = decrypt(privKey, pubKey) - response = mapper.readValue(decrypted, Response::class.java) - response - } else { - null - } - } catch (e: Exception) { - Log.w("LnZapPaymentResponseEvent", "Can't parse content as a payment response: $content", e) - null - } - } - - companion object { - const val kind = 23195 - } -} - -// RESPONSE OBJECTS -abstract class Response( - @JsonProperty("result_type") - val resultType: String -) - -// PayInvoice Call - -class PayInvoiceSuccessResponse(val result: PayInvoiceResultParams? = null) : - Response("pay_invoice") { - class PayInvoiceResultParams(val preimage: String) -} - -class PayInvoiceErrorResponse(val error: PayInvoiceErrorParams? = null) : - Response("pay_invoice") { - class PayInvoiceErrorParams(val code: ErrorType?, val message: String?) - - enum class ErrorType { - @JsonProperty(value = "RATE_LIMITED") - RATE_LIMITED, // The client is sending commands too fast. It should retry in a few seconds. - @JsonProperty(value = "NOT_IMPLEMENTED") - NOT_IMPLEMENTED, // The command is not known or is intentionally not implemented. - @JsonProperty(value = "INSUFFICIENT_BALANCE") - INSUFFICIENT_BALANCE, // The wallet does not have enough funds to cover a fee reserve or the payment amount. - @JsonProperty(value = "QUOTA_EXCEEDED") - QUOTA_EXCEEDED, // The wallet has exceeded its spending quota. - @JsonProperty(value = "RESTRICTED") - RESTRICTED, // This public key is not allowed to do this operation. - @JsonProperty(value = "UNAUTHORIZED") - UNAUTHORIZED, // This public key has no wallet connected. - @JsonProperty(value = "INTERNAL") - INTERNAL, // An internal error. - @JsonProperty(value = "OTHER") - OTHER // Other error. - } -} - - -class ResponseDeserializer : StdDeserializer(Response::class.java) { - override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): Response? { - val jsonObject: JsonNode = jp.codec.readTree(jp) - val resultType = jsonObject.get("result_type")?.asText() - - if (resultType == "pay_invoice") { - val result = jsonObject.get("result") - val error = jsonObject.get("error") - if (result != null) { - return jp.codec.treeToValue(jsonObject, PayInvoiceSuccessResponse::class.java) - } - if (error != null) { - return jp.codec.treeToValue(jsonObject, PayInvoiceErrorResponse::class.java) - } - } else { - // tries to guess - if (jsonObject.get("result")?.get("preimage") != null) { - return jp.codec.treeToValue(jsonObject, PayInvoiceSuccessResponse::class.java) - } - if (jsonObject.get("error")?.get("code") != null) { - return jp.codec.treeToValue(jsonObject, PayInvoiceErrorResponse::class.java) - } - } - return null - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPrivateEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPrivateEvent.kt deleted file mode 100644 index 899ae867..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapPrivateEvent.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.Bech32 -import com.vitorpamplona.quartz.encoders.HexKey -import com.vitorpamplona.quartz.encoders.LnInvoiceUtil -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.utils.TimeUtils -import java.nio.charset.Charset -import java.security.SecureRandom -import javax.crypto.BadPaddingException -import javax.crypto.Cipher -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec - -@Immutable -class LnZapPrivateEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - companion object { - const val kind = 9733 - - fun create( - privateKey: ByteArray, - tags: List> = emptyList(), - content: String = "", - createdAt: Long = TimeUtils.now() - ): Event { - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey).toHexKey() - return Event(id.toHexKey(), pubKey, createdAt, kind, tags, content, sig) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapRequestEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapRequestEvent.kt deleted file mode 100644 index 9b2ebde0..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LnZapRequestEvent.kt +++ /dev/null @@ -1,239 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.* -import com.vitorpamplona.quartz.encoders.Bech32 -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey -import com.vitorpamplona.quartz.encoders.hexToByteArray -import com.vitorpamplona.quartz.encoders.toHexKey -import java.nio.charset.Charset -import java.security.SecureRandom -import javax.crypto.BadPaddingException -import javax.crypto.Cipher -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec - -@Immutable -class LnZapRequestEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - @Transient - private var privateZapEvent: Event? = null - - fun zappedPost() = tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] } - - fun zappedAuthor() = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] } - - fun isPrivateZap() = tags.any { t -> t.size >= 2 && t[0] == "anon" && t[1].isNotBlank() } - - fun getPrivateZapEvent(loggedInUserPrivKey: ByteArray, pubKey: HexKey): Event? { - if (privateZapEvent != null) return privateZapEvent - - val anonTag = tags.firstOrNull { t -> t.size >= 2 && t[0] == "anon" } - if (anonTag != null) { - val encnote = anonTag[1] - if (encnote.isNotBlank()) { - try { - val note = decryptPrivateZapMessage(encnote, loggedInUserPrivKey, pubKey.hexToByteArray()) - val decryptedEvent = fromJson(note) - if (decryptedEvent.kind == 9733) { - privateZapEvent = decryptedEvent - return privateZapEvent - } - } catch (e: Exception) { - e.printStackTrace() - } - } - } - return null - } - - companion object { - const val kind = 9734 - - fun create( - originalNote: EventInterface, - relays: Set, - privateKey: ByteArray, - pollOption: Int?, - message: String, - zapType: LnZapEvent.ZapType, - createdAt: Long = TimeUtils.now() - ): LnZapRequestEvent { - var content = message - var privkey = privateKey - var pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - var tags = listOf( - listOf("e", originalNote.id()), - listOf("p", originalNote.pubKey()), - listOf("relays") + relays - ) - if (originalNote is AddressableEvent) { - tags = tags + listOf(listOf("a", originalNote.address().toTag())) - } - if (pollOption != null && pollOption >= 0) { - tags = tags + listOf(listOf(POLL_OPTION, pollOption.toString())) - } - if (zapType == LnZapEvent.ZapType.ANONYMOUS) { - tags = tags + listOf(listOf("anon", "")) - privkey = CryptoUtils.privkeyCreate() - pubKey = CryptoUtils.pubkeyCreate(privkey).toHexKey() - } else if (zapType == LnZapEvent.ZapType.PRIVATE) { - val encryptionPrivateKey = createEncryptionPrivateKey(privateKey.toHexKey(), originalNote.id(), createdAt) - val noteJson = (LnZapPrivateEvent.create(privkey, listOf(tags[0], tags[1]), message)).toJson() - val encryptedContent = encryptPrivateZapMessage(noteJson, encryptionPrivateKey, originalNote.pubKey().hexToByteArray()) - tags = tags + listOf(listOf("anon", encryptedContent)) - content = "" // make sure public content is empty, as the content is encrypted - privkey = encryptionPrivateKey // sign event with generated privkey - pubKey = CryptoUtils.pubkeyCreate(encryptionPrivateKey).toHexKey() // updated event with according pubkey - } - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privkey) - return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - - fun createPublic( - originalNote: EventInterface, - relays: Set, - pubKey: HexKey, - pollOption: Int?, - message: String, - createdAt: Long = TimeUtils.now() - ): LnZapRequestEvent { - var tags = listOf( - listOf("e", originalNote.id()), - listOf("p", originalNote.pubKey()), - listOf("relays") + relays - ) - if (originalNote is AddressableEvent) { - tags = tags + listOf(listOf("a", originalNote.address().toTag())) - } - if (pollOption != null && pollOption >= 0) { - tags = tags + listOf(listOf(POLL_OPTION, pollOption.toString())) - } - - val id = generateId(pubKey, createdAt, kind, tags, message) - return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, message, "") - } - - fun createAnonymous( - originalNote: EventInterface, - relays: Set, - pollOption: Int?, - message: String, - createdAt: Long = TimeUtils.now() - ): LnZapRequestEvent { - var tags = listOf( - listOf("e", originalNote.id()), - listOf("p", originalNote.pubKey()), - listOf("relays") + relays - ) - if (originalNote is AddressableEvent) { - tags = tags + listOf(listOf("a", originalNote.address().toTag())) - } - if (pollOption != null && pollOption >= 0) { - tags = tags + listOf(listOf(POLL_OPTION, pollOption.toString())) - } - - tags = tags + listOf(listOf("anon", "")) - val privkey = CryptoUtils.privkeyCreate() - val pubKey = CryptoUtils.pubkeyCreate(privkey).toHexKey() - - val id = generateId(pubKey, createdAt, kind, tags, message) - val sig = CryptoUtils.sign(id, privkey) - return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, message, sig.toHexKey()) - } - - fun create( - userHex: String, - relays: Set, - privateKey: ByteArray, - message: String, - zapType: LnZapEvent.ZapType, - createdAt: Long = TimeUtils.now() - ): LnZapRequestEvent { - var content = message - var privkey = privateKey - var pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - var tags = listOf( - listOf("p", userHex), - listOf("relays") + relays - ) - if (zapType == LnZapEvent.ZapType.ANONYMOUS) { - privkey = CryptoUtils.privkeyCreate() - pubKey = CryptoUtils.pubkeyCreate(privkey).toHexKey() - tags = tags + listOf(listOf("anon", "")) - } else if (zapType == LnZapEvent.ZapType.PRIVATE) { - val encryptionPrivateKey = createEncryptionPrivateKey(privateKey.toHexKey(), userHex, createdAt) - val noteJson = LnZapPrivateEvent.create(privkey, listOf(tags[0], tags[1]), message).toJson() - val encryptedContent = encryptPrivateZapMessage(noteJson, encryptionPrivateKey, userHex.hexToByteArray()) - tags = tags + listOf(listOf("anon", encryptedContent)) - content = "" - privkey = encryptionPrivateKey - pubKey = CryptoUtils.pubkeyCreate(encryptionPrivateKey).toHexKey() - } - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privkey) - return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - - - fun createEncryptionPrivateKey(privkey: String, id: String, createdAt: Long): ByteArray { - val str = privkey + id + createdAt.toString() - val strbyte = str.toByteArray(Charset.forName("utf-8")) - return CryptoUtils.sha256(strbyte) - } - - private fun encryptPrivateZapMessage(msg: String, privkey: ByteArray, pubkey: ByteArray): String { - val sharedSecret = CryptoUtils.getSharedSecretNIP04(privkey, pubkey) - val iv = ByteArray(16) - SecureRandom().nextBytes(iv) - - val keySpec = SecretKeySpec(sharedSecret, "AES") - val ivSpec = IvParameterSpec(iv) - - val utf8message = msg.toByteArray(Charset.forName("utf-8")) - val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec) - val encryptedMsg = cipher.doFinal(utf8message) - - val encryptedMsgBech32 = Bech32.encode("pzap", Bech32.eight2five(encryptedMsg), Bech32.Encoding.Bech32) - val ivBech32 = Bech32.encode("iv", Bech32.eight2five(iv), Bech32.Encoding.Bech32) - - return encryptedMsgBech32 + "_" + ivBech32 - } - - private fun decryptPrivateZapMessage(msg: String, privkey: ByteArray, pubkey: ByteArray): String { - val sharedSecret = CryptoUtils.getSharedSecretNIP04(privkey, pubkey) - if (sharedSecret.size != 16 && sharedSecret.size != 32) { - throw IllegalArgumentException("Invalid shared secret size") - } - val parts = msg.split("_") - if (parts.size != 2) { - throw IllegalArgumentException("Invalid message format") - } - val iv = parts[1].run { Bech32.decode(this).second } - val encryptedMsg = parts.first().run { Bech32.decode(this).second } - val encryptedBytes = Bech32.five2eight(encryptedMsg, 0) - val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") - cipher.init( - Cipher.DECRYPT_MODE, SecretKeySpec(sharedSecret, "AES"), IvParameterSpec( - Bech32.five2eight(iv, 0)) - ) - - try { - val decryptedMsgBytes = cipher.doFinal(encryptedBytes) - return String(decryptedMsgBytes) - } catch (ex: BadPaddingException) { - throw IllegalArgumentException("Bad padding: ${ex.message}") - } - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/LongTextNoteEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/LongTextNoteEvent.kt deleted file mode 100644 index 09184f2a..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/LongTextNoteEvent.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class LongTextNoteEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig), AddressableEvent { - override fun dTag() = tags.filter { it.firstOrNull() == "d" }.mapNotNull { it.getOrNull(1) }.firstOrNull() ?: "" - override fun address() = ATag(kind, pubKey, dTag(), null) - - fun topics() = tags.filter { it.firstOrNull() == "t" }.mapNotNull { it.getOrNull(1) } - fun title() = tags.filter { it.firstOrNull() == "title" }.mapNotNull { it.getOrNull(1) }.firstOrNull() - fun image() = tags.filter { it.firstOrNull() == "image" }.mapNotNull { it.getOrNull(1) }.firstOrNull() - fun summary() = tags.filter { it.firstOrNull() == "summary" }.mapNotNull { it.getOrNull(1) }.firstOrNull() - - fun publishedAt() = try { - tags.firstOrNull { it.size > 1 && it[0] == "published_at" }?.get(1)?.toLongOrNull() - } catch (_: Exception) { - null - } - - companion object { - const val kind = 30023 - - fun create(msg: String, replyTos: List?, mentions: List?, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): LongTextNoteEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val tags = mutableListOf>() - replyTos?.forEach { - tags.add(listOf("e", it)) - } - mentions?.forEach { - tags.add(listOf("p", it)) - } - val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = CryptoUtils.sign(id, privateKey) - return LongTextNoteEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/MetadataEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/MetadataEvent.kt deleted file mode 100644 index 6bc69ddb..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/MetadataEvent.kt +++ /dev/null @@ -1,168 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Stable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey -import java.io.ByteArrayInputStream - -@Stable -abstract class IdentityClaim( - val identity: String, - val proof: String -) { - abstract fun toProofUrl(): String - abstract fun platform(): String - - fun platformIdentity() = "${platform()}:$identity" - - companion object { - fun create(platformIdentity: String, proof: String): IdentityClaim? { - val (platform, identity) = platformIdentity.split(':') - - return when (platform.lowercase()) { - GitHubIdentity.platform -> GitHubIdentity(identity, proof) - TwitterIdentity.platform -> TwitterIdentity(identity, proof) - TelegramIdentity.platform -> TelegramIdentity(identity, proof) - MastodonIdentity.platform -> MastodonIdentity(identity, proof) - else -> throw IllegalArgumentException("Platform $platform not supported") - } - } - } -} - -class GitHubIdentity( - identity: String, - proof: String -) : IdentityClaim(identity, proof) { - override fun toProofUrl() = "https://gist.github.com/$identity/$proof" - - override fun platform() = platform - - companion object { - val platform = "github" - - fun parseProofUrl(proofUrl: String): GitHubIdentity? { - return try { - if (proofUrl.isBlank()) return null - val path = proofUrl.removePrefix("https://gist.github.com/").split("?")[0].split("/") - - GitHubIdentity(path[0], path[1]) - } catch (e: Exception) { - null - } - } - } -} - -class TwitterIdentity( - identity: String, - proof: String -) : IdentityClaim(identity, proof) { - override fun toProofUrl() = "https://twitter.com/$identity/status/$proof" - - override fun platform() = platform - - companion object { - val platform = "twitter" - - fun parseProofUrl(proofUrl: String): TwitterIdentity? { - return try { - if (proofUrl.isBlank()) return null - val path = proofUrl.removePrefix("https://twitter.com/").split("?")[0].split("/") - - TwitterIdentity(path[0], path[2]) - } catch (e: Exception) { - null - } - } - } -} - -class TelegramIdentity( - identity: String, - proof: String -) : IdentityClaim(identity, proof) { - override fun toProofUrl() = "https://t.me/$proof" - - override fun platform() = platform - - companion object { - val platform = "telegram" - } -} - -class MastodonIdentity( - identity: String, - proof: String -) : IdentityClaim(identity, proof) { - override fun toProofUrl() = "https://$identity/$proof" - - override fun platform() = platform - - companion object { - val platform = "mastodon" - - fun parseProofUrl(proofUrl: String): MastodonIdentity? { - return try { - if (proofUrl.isBlank()) return null - val path = proofUrl.removePrefix("https://").split("?")[0].split("/") - - return MastodonIdentity("${path[0]}/${path[1]}", path[2]) - } catch (e: Exception) { - null - } - } - } -} - -class MetadataEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - fun contactMetaData() = try { - mapper.readValue( - ByteArrayInputStream(content.toByteArray(Charsets.UTF_8)), - UserMetadata::class.java - ) - } catch (e: Exception) { - // e.printStackTrace() - Log.w("MT", "Content Parse Error: ${e.localizedMessage} $content") - null - } - - fun identityClaims() = tags.filter { it.firstOrNull() == "i" }.mapNotNull { - try { - IdentityClaim.create(it.get(1), it.get(2)) - } catch (e: Exception) { - Log.e("MetadataEvent", "Can't parse identity [${it.joinToString { "," }}]", e) - null - } - } - - companion object { - const val kind = 0 - - fun create(contactMetaData: String, identities: List, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): MetadataEvent { - val tags = mutableListOf>() - - identities.forEach { - tags.add(listOf("i", it.platformIdentity(), it.proof)) - } - - val id = generateId(pubKey, createdAt, kind, tags, contactMetaData) - val sig = if (privateKey == null) null else CryptoUtils.sign(id, privateKey) - return MetadataEvent(id.toHexKey(), pubKey, createdAt, tags, contactMetaData, sig?.toHexKey() ?: "") - } - - fun create(unsignedEvent: MetadataEvent, signature: String): MetadataEvent { - return MetadataEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/MuteListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/MuteListEvent.kt deleted file mode 100644 index 69cca028..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/MuteListEvent.kt +++ /dev/null @@ -1,110 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.fasterxml.jackson.module.kotlin.readValue -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.hexToByteArray -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class MuteListEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun plainContent(privKey: ByteArray): String? { - return try { - val sharedSecret = CryptoUtils.getSharedSecretNIP04(privKey, pubKey.hexToByteArray()) - - return CryptoUtils.decryptNIP04(content, sharedSecret) - } catch (e: Exception) { - Log.w("BookmarkList", "Error decrypting the message ${e.message}") - null - } - } - - @Transient - private var privateTagsCache: List>? = null - - fun privateTags(privKey: ByteArray): List>? { - if (privateTagsCache != null) { - return privateTagsCache - } - - privateTagsCache = try { - plainContent(privKey)?.let { mapper.readValue>>(it) } - } catch (e: Throwable) { - Log.w("BookmarkList", "Error parsing the JSON ${e.message}") - null - } - return privateTagsCache - } - - fun privateTaggedUsers(privKey: ByteArray) = privateTags(privKey)?.filter { it.firstOrNull() == "p" }?.mapNotNull { it.getOrNull(1) } - fun privateTaggedEvents(privKey: ByteArray) = privateTags(privKey)?.filter { it.firstOrNull() == "e" }?.mapNotNull { it.getOrNull(1) } - fun privateTaggedAddresses(privKey: ByteArray) = privateTags(privKey)?.filter { it.firstOrNull() == "a" }?.mapNotNull { - val aTagValue = it.getOrNull(1) - val relay = it.getOrNull(2) - - if (aTagValue != null) ATag.parse(aTagValue, relay) else null - } - - companion object { - const val kind = 10000 - - fun create( - events: List? = null, - users: List? = null, - addresses: List? = null, - - privEvents: List? = null, - privUsers: List? = null, - privAddresses: List? = null, - - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): MuteListEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey) - - val privTags = mutableListOf>() - privEvents?.forEach { - privTags.add(listOf("e", it)) - } - privUsers?.forEach { - privTags.add(listOf("p", it)) - } - privAddresses?.forEach { - privTags.add(listOf("a", it.toTag())) - } - val msg = mapper.writeValueAsString(privTags) - - val content = CryptoUtils.encryptNIP04( - msg, - privateKey, - pubKey - ) - - val tags = mutableListOf>() - events?.forEach { - tags.add(listOf("e", it)) - } - users?.forEach { - tags.add(listOf("p", it)) - } - addresses?.forEach { - tags.add(listOf("a", it.toTag())) - } - - val id = generateId(pubKey.toHexKey(), createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return MuteListEvent(id.toHexKey(), pubKey.toHexKey(), createdAt, tags, content, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/NIP24Factory.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/NIP24Factory.kt deleted file mode 100644 index d91e8bc4..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/NIP24Factory.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.vitorpamplona.quartz.events - -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -class NIP24Factory { - fun createMsgNIP24( - msg: String, - to: List, - from: ByteArray, - subject: String? = null, - replyTos: List? = null, - mentions: List? = null, - zapReceiver: String? = null, - markAsSensitive: Boolean = false, - zapRaiserAmount: Long? = null, - geohash: String? = null - ): List { - val senderPublicKey = CryptoUtils.pubkeyCreate(from).toHexKey() - - val senderMessage = ChatMessageEvent.create( - msg = msg, - to = to, - privateKey = from, - subject = subject, - replyTos = replyTos, - mentions = mentions, - zapReceiver = zapReceiver, - markAsSensitive = markAsSensitive, - zapRaiserAmount = zapRaiserAmount, - geohash = geohash - ) - - return to.plus(senderPublicKey).map { - GiftWrapEvent.create( - event = SealedGossipEvent.create( - event = senderMessage, - encryptTo = it, - privateKey = from - ), - recipientPubKey = it - ) - } - } - - fun createReactionWithinGroup(content: String, originalNote: EventInterface, to: List, from: KeyPair): List { - val senderPublicKey = CryptoUtils.pubkeyCreate(from.privKey!!).toHexKey() - - val senderReaction = ReactionEvent.create( - content, - originalNote, - from - ) - - return to.plus(senderPublicKey).map { - GiftWrapEvent.create( - event = SealedGossipEvent.create( - event = senderReaction, - encryptTo = it, - privateKey = from.privKey - ), - recipientPubKey = it - ) - } - } - - fun createReactionWithinGroup(emojiUrl: EmojiUrl, originalNote: EventInterface, to: List, from: KeyPair): List { - val senderPublicKey = CryptoUtils.pubkeyCreate(from.privKey!!).toHexKey() - - val senderReaction = ReactionEvent.create( - emojiUrl, - originalNote, - from - ) - - return to.plus(senderPublicKey).map { - GiftWrapEvent.create( - event = SealedGossipEvent.create( - event = senderReaction, - encryptTo = it, - privateKey = from.privKey - ), - recipientPubKey = it - ) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/NNSEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/NNSEvent.kt deleted file mode 100644 index 5940bb45..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/NNSEvent.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class NNSEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun ip4() = tags.firstOrNull { it.size > 1 && it[0] == "ip4" }?.get(1) - fun ip6() = tags.firstOrNull { it.size > 1 && it[0] == "ip6" }?.get(1) - fun version() = tags.firstOrNull { it.size > 1 && it[0] == "version" }?.get(1) - - companion object { - const val kind = 30053 - - fun create( - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): NNSEvent { - val tags = mutableListOf>() - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return NNSEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/PeopleListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/PeopleListEvent.kt deleted file mode 100644 index b3e814fc..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/PeopleListEvent.kt +++ /dev/null @@ -1,236 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey -import kotlinx.collections.immutable.ImmutableSet -import kotlinx.collections.immutable.persistentSetOf -import kotlinx.collections.immutable.toImmutableSet - -@Immutable -class PeopleListEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) { - var decryptedContent: String? = null - var publicAndPrivateUserCache: ImmutableSet? = null - - fun publicAndPrivateUsers(privateKey: ByteArray?): ImmutableSet { - publicAndPrivateUserCache?.let { - return it - } - - val privateUserList = privateKey?.let { - privateTagsOrEmpty(privKey = it).filter { it.size > 1 && it[0] == "p" }.map { it[1] }.toSet() - } ?: emptySet() - val publicUserList = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] }.toSet() - - publicAndPrivateUserCache = (privateUserList + publicUserList).toImmutableSet() - - return publicAndPrivateUserCache ?: persistentSetOf() - } - - fun publicAndPrivateUsers(decryptedContent: String): ImmutableSet { - publicAndPrivateUserCache?.let { - return it - } - - val privateUserList = privateTagsOrEmpty(decryptedContent).filter { it.size > 1 && it[0] == "p" }.map { it[1] }.toSet() - - val publicUserList = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] }.toSet() - - publicAndPrivateUserCache = (privateUserList + publicUserList).toImmutableSet() - - return publicAndPrivateUserCache ?: persistentSetOf() - } - - fun isTaggedUser(idHex: String, isPrivate: Boolean, privateKey: ByteArray): Boolean { - return if (isPrivate) { - privateTagsOrEmpty(privKey = privateKey).any { it.size > 1 && it[0] == "p" && it[1] == idHex } - } else { - isTaggedUser(idHex) - } - } - - fun isTaggedUser(idHex: String, isPrivate: Boolean, content: String): Boolean { - return if (isPrivate) { - privateTagsOrEmpty(content).any { it.size > 1 && it[0] == "p" && it[1] == idHex } - } else { - isTaggedUser(idHex) - } - } - - companion object { - const val kind = 30000 - const val blockList = "mute" - - fun createListWithUser(name: String, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent { - return if (isPrivate) { - create( - content = encryptTags(listOf(listOf("p", pubKeyHex)), privateKey), - tags = listOf(listOf("d", name)), - privateKey = privateKey, - createdAt = createdAt - ) - } else { - create( - content = "", - tags = listOf(listOf("d", name), listOf("p", pubKeyHex)), - privateKey = privateKey, - createdAt = createdAt - ) - } - } - - fun createListWithUser(name: String, pubKeyHex: String, isPrivate: Boolean, pubKey: HexKey, encryptedContent: String, createdAt: Long = TimeUtils.now()): PeopleListEvent { - return if (isPrivate) { - create( - content = encryptedContent, - tags = listOf(listOf("d", name)), - pubKey = pubKey, - createdAt = createdAt - ) - } else { - create( - content = "", - tags = listOf(listOf("d", name), listOf("p", pubKeyHex)), - pubKey = pubKey, - createdAt = createdAt - ) - } - } - - fun addUsers(earlierVersion: PeopleListEvent, listPubKeyHex: List, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent { - return if (isPrivate) { - create( - content = encryptTags( - privateTags = earlierVersion.privateTagsOrEmpty(privKey = privateKey).plus( - listPubKeyHex.map { - listOf("p", it) - } - ), - privateKey = privateKey - ), - tags = earlierVersion.tags, - privateKey = privateKey, - createdAt = createdAt - ) - } else { - create( - content = earlierVersion.content, - tags = earlierVersion.tags.plus( - listPubKeyHex.map { - listOf("p", it) - } - ), - privateKey = privateKey, - createdAt = createdAt - ) - } - } - - fun addUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, pubKey: HexKey, encryptedContent: String, createdAt: Long = TimeUtils.now()): PeopleListEvent { - return if (isPrivate) { - create( - content = encryptedContent, - tags = earlierVersion.tags, - pubKey = pubKey, - createdAt = createdAt - ) - } else { - create( - content = earlierVersion.content, - tags = earlierVersion.tags.plus(element = listOf("p", pubKeyHex)), - pubKey = pubKey, - createdAt = createdAt - ) - } - } - - fun addUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent { - if (earlierVersion.isTaggedUser(pubKeyHex, isPrivate, privateKey)) return earlierVersion - - return if (isPrivate) { - create( - content = encryptTags( - privateTags = earlierVersion.privateTagsOrEmpty(privKey = privateKey).plus(element = listOf("p", pubKeyHex)), - privateKey = privateKey - ), - tags = earlierVersion.tags, - privateKey = privateKey, - createdAt = createdAt - ) - } else { - create( - content = earlierVersion.content, - tags = earlierVersion.tags.plus(element = listOf("p", pubKeyHex)), - privateKey = privateKey, - createdAt = createdAt - ) - } - } - - fun removeUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, encryptedContent: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): PeopleListEvent { - return if (isPrivate) { - create( - content = encryptedContent, - tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex }, - pubKey = pubKey, - createdAt = createdAt - ) - } else { - create( - content = earlierVersion.content, - tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex }, - pubKey = pubKey, - createdAt = createdAt - ) - } - } - - fun removeUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent { - if (!earlierVersion.isTaggedUser(pubKeyHex, isPrivate, privateKey)) return earlierVersion - - return if (isPrivate) { - create( - content = encryptTags( - privateTags = earlierVersion.privateTagsOrEmpty(privKey = privateKey).filter { it.size > 1 && it[1] != pubKeyHex }, - privateKey = privateKey - ), - tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex }, - privateKey = privateKey, - createdAt = createdAt - ) - } else { - create( - content = earlierVersion.content, - tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex }, - privateKey = privateKey, - createdAt = createdAt - ) - } - } - - fun create(content: String, tags: List>, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return PeopleListEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - - fun create(content: String, tags: List>, pubKey: HexKey, createdAt: Long = TimeUtils.now()): PeopleListEvent { - val id = generateId(pubKey, createdAt, kind, tags, content) - return PeopleListEvent(id.toHexKey(), pubKey, createdAt, tags, content, "") - } - - fun create(unsignedEvent: PeopleListEvent, signature: String): PeopleListEvent { - return PeopleListEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/PinListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/PinListEvent.kt deleted file mode 100644 index b1a71965..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/PinListEvent.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class PinListEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - fun pins() = tags.filter { it.size > 1 && it[0] == "pin" }.map { it[1] } - - companion object { - const val kind = 33888 - - fun create( - pins: List, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): PinListEvent { - val tags = mutableListOf>() - pins.forEach { - tags.add(listOf("pin", it)) - } - - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return PinListEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/PollNoteEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/PollNoteEvent.kt deleted file mode 100644 index 6b63e4e2..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/PollNoteEvent.kt +++ /dev/null @@ -1,126 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -const val POLL_OPTION = "poll_option" -const val VALUE_MAXIMUM = "value_maximum" -const val VALUE_MINIMUM = "value_minimum" -const val CONSENSUS_THRESHOLD = "consensus_threshold" -const val CLOSED_AT = "closed_at" - -@Immutable -class PollNoteEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - // ots: String?, TODO implement OTS: https://github.com/opentimestamps/java-opentimestamps - content: String, - sig: HexKey -) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun pollOptions() = - tags.filter { it.size > 2 && it[0] == POLL_OPTION } - .associate { it[1].toInt() to it[2] } - - fun getTagInt(property: String): Int? { - val number = tags.firstOrNull() { it.size > 1 && it[0] == property }?.get(1) - - return if (number.isNullOrBlank() || number == "null") { - null - } else { - number.toInt() - } - } - - companion object { - const val kind = 6969 - - fun create( - msg: String, - replyTos: List?, - mentions: List?, - addresses: List?, - pubKey: HexKey, - privateKey: ByteArray?, - createdAt: Long = TimeUtils.now(), - pollOptions: Map, - valueMaximum: Int?, - valueMinimum: Int?, - consensusThreshold: Int?, - closedAt: Int?, - zapReceiver: String?, - markAsSensitive: Boolean, - zapRaiserAmount: Long?, - geohash: String? = null - ): PollNoteEvent { - val tags = mutableListOf>() - replyTos?.forEach { - tags.add(listOf("e", it)) - } - mentions?.forEach { - tags.add(listOf("p", it)) - } - addresses?.forEach { - tags.add(listOf("a", it.toTag())) - } - pollOptions.forEach { poll_op -> - tags.add(listOf(POLL_OPTION, poll_op.key.toString(), poll_op.value)) - } - tags.add(listOf(VALUE_MAXIMUM, valueMaximum.toString())) - tags.add(listOf(VALUE_MINIMUM, valueMinimum.toString())) - tags.add(listOf(CONSENSUS_THRESHOLD, consensusThreshold.toString())) - tags.add(listOf(CLOSED_AT, closedAt.toString())) - - if (zapReceiver != null) { - tags.add(listOf("zap", zapReceiver)) - } - if (markAsSensitive) { - tags.add(listOf("content-warning", "")) - } - zapRaiserAmount?.let { - tags.add(listOf("zapraiser", "$it")) - } - geohash?.let { - tags.add(listOf("g", it)) - } - - val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = if (privateKey == null) null else CryptoUtils.sign(id, privateKey) - return PollNoteEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig?.toHexKey() ?: "") - } - - fun create( - unsignedEvent: PollNoteEvent, signature: String - ): PollNoteEvent { - return PollNoteEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} - -/* -{ - "id": <32-bytes lowercase hex-encoded sha256 of the serialized event data> - "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>, - "created_at": , - "kind": 6969, - "tags": [ - ["e", <32-bytes hex of the id of the poll event>, ], - ["p", <32-bytes hex of the key>, ], - ["poll_option", "0", "poll option 0 description string"], - ["poll_option", "1", "poll option 1 description string"], - ["poll_option", "n", "poll option description string"], - ["value_maximum", "maximum satoshi value for inclusion in tally"], - ["value_minimum", "minimum satoshi value for inclusion in tally"], - ["consensus_threshold", "required percentage to attain consensus <0..100>"], - ["closed_at", "unix timestamp in seconds"], - ], - "ots": - "content": , - "sig": <64-bytes hex of the signature of the sha256 hash of the serialized event data, which is the same as the "id" field> -} - */ diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/PrivateDmEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/PrivateDmEvent.kt deleted file mode 100644 index 0d7e99ac..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/PrivateDmEvent.kt +++ /dev/null @@ -1,140 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey -import com.vitorpamplona.quartz.encoders.HexValidator -import com.vitorpamplona.quartz.encoders.Hex -import kotlinx.collections.immutable.persistentSetOf - -@Immutable -class PrivateDmEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig), ChatroomKeyable { - /** - * This may or may not be the actual recipient's pub key. The event is intended to look like a - * nip-04 EncryptedDmEvent but may omit the recipient, too. This value can be queried and used - * for initial messages. - */ - private fun recipientPubKey() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.get(1) - - fun recipientPubKeyBytes() = recipientPubKey()?.runCatching { Hex.decode(this) }?.getOrNull() - - fun verifiedRecipientPubKey(): HexKey? { - val recipient = recipientPubKey() - return if (HexValidator.isHex(recipient)) { - recipient - } else { - null - } - } - - fun talkingWith(oneSideHex: String): HexKey { - return if (pubKey == oneSideHex) verifiedRecipientPubKey() ?: pubKey else pubKey - } - - override fun chatroomKey(toRemove: String): ChatroomKey { - return ChatroomKey(persistentSetOf(talkingWith(toRemove))) - } - - /** - * To be fully compatible with nip-04, we read e-tags that are in violation to nip-18. - * - * Nip-18 messages should refer to other events by inline references in the content like - * `[](e/c06f795e1234a9a1aecc731d768d4f3ca73e80031734767067c82d67ce82e506). - */ - fun replyTo() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1) - - fun with(pubkeyHex: String): Boolean { - return pubkeyHex == pubKey || - tags.any { it.size > 1 && it[0] == "p" && it[1] == pubkeyHex } - } - - fun plainContent(privKey: ByteArray, pubKey: ByteArray): String? { - return try { - val sharedSecret = CryptoUtils.getSharedSecretNIP04(privKey, pubKey) - - val retVal = CryptoUtils.decryptNIP04(content, sharedSecret) - - if (retVal.startsWith(nip18Advertisement)) { - retVal.substring(16) - } else { - retVal - } - } catch (e: Exception) { - Log.w("PrivateDM", "Error decrypting the message ${e.message}") - null - } - } - - companion object { - const val kind = 4 - - const val nip18Advertisement = "[//]: # (nip18)\n" - - fun create( - recipientPubKey: ByteArray, - msg: String, - replyTos: List? = null, - mentions: List? = null, - zapReceiver: String?, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now(), - publishedRecipientPubKey: ByteArray? = null, - advertiseNip18: Boolean = true, - markAsSensitive: Boolean, - zapRaiserAmount: Long?, - geohash: String? = null - ): PrivateDmEvent { - val message = if (advertiseNip18) { nip18Advertisement } else { "" } + msg - val content = if (keyPair.privKey == null) message else CryptoUtils.encryptNIP04( - message, - keyPair.privKey, - recipientPubKey - ) - val tags = mutableListOf>() - publishedRecipientPubKey?.let { - tags.add(listOf("p", publishedRecipientPubKey.toHexKey())) - } - replyTos?.forEach { - tags.add(listOf("e", it)) - } - mentions?.forEach { - tags.add(listOf("p", it)) - } - zapReceiver?.let { - tags.add(listOf("zap", it)) - } - if (markAsSensitive) { - tags.add(listOf("content-warning", "")) - } - zapRaiserAmount?.let { - tags.add(listOf("zapraiser", "$it")) - } - geohash?.let { - tags.add(listOf("g", it)) - } - - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return PrivateDmEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create( - unsignedEvent: PrivateDmEvent, - signature: String, - ): PrivateDmEvent { - return PrivateDmEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ReactionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ReactionEvent.kt deleted file mode 100644 index fcf8a1a9..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ReactionEvent.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class ReactionEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - fun originalPost() = tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] } - fun originalAuthor() = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] } - - companion object { - const val kind = 7 - - fun createWarning(originalNote: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReactionEvent { - return create("\u26A0\uFE0F", originalNote, keyPair, createdAt) - } - - fun createLike(originalNote: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReactionEvent { - return create("+", originalNote, keyPair, createdAt) - } - - fun create(content: String, originalNote: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReactionEvent { - var tags = listOf(listOf("e", originalNote.id()), listOf("p", originalNote.pubKey())) - if (originalNote is AddressableEvent) { - tags = tags + listOf(listOf("a", originalNote.address().toTag())) - } - - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return ReactionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(emojiUrl: EmojiUrl, originalNote: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReactionEvent { - val content = ":${emojiUrl.code}:" - val pubKey = keyPair.pubKey.toHexKey() - - var tags = listOf( - listOf("e", originalNote.id()), - listOf("p", originalNote.pubKey()), - listOf("emoji", emojiUrl.code, emojiUrl.url) - ) - - if (originalNote is AddressableEvent) { - tags = tags + listOf(listOf("a", originalNote.address().toTag())) - } - - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return ReactionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(unsignedEvent: ReactionEvent, signature: String): ReactionEvent { - return ReactionEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/RecommendRelayEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/RecommendRelayEvent.kt deleted file mode 100644 index ec6dd23e..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/RecommendRelayEvent.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey -import java.net.URI - -@Immutable -class RecommendRelayEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - fun relay() = URI.create(content.trim()) - - companion object { - const val kind = 2 - - fun create(relay: URI, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): RecommendRelayEvent { - val content = relay.toString() - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val tags = listOf>() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return RecommendRelayEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/RelayAuthEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/RelayAuthEvent.kt deleted file mode 100644 index 6cb829ca..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/RelayAuthEvent.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class RelayAuthEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - fun relay() = tags.firstOrNull() { it.size > 1 && it[0] == "relay" }?.get(1) - fun challenge() = tags.firstOrNull() { it.size > 1 && it[0] == "challenge" }?.get(1) - - companion object { - const val kind = 22242 - - fun create(relay: String, challenge: String, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): RelayAuthEvent { - val content = "" - val tags = listOf( - listOf("relay", relay), - listOf("challenge", challenge) - ) - val localPubKey = if (pubKey.isBlank() && privateKey != null) CryptoUtils.pubkeyCreate(privateKey).toHexKey() else pubKey - val id = generateId(localPubKey, createdAt, kind, tags, content) - val sig = if (privateKey == null) null else CryptoUtils.sign(id, privateKey) - return RelayAuthEvent(id.toHexKey(), localPubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(unsignedEvent: RelayAuthEvent, signature: String): RelayAuthEvent { - return RelayAuthEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/RelaySetEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/RelaySetEvent.kt deleted file mode 100644 index cebff1e0..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/RelaySetEvent.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class RelaySetEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - fun relays() = tags.filter { it.size > 1 && it[0] == "r" }.map { it[1] } - fun description() = tags.firstOrNull() { it.size > 1 && it[0] == "description" }?.get(1) - - companion object { - const val kind = 30022 - - fun create( - relays: List, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): RelaySetEvent { - val tags = mutableListOf>() - relays.forEach { - tags.add(listOf("r", it)) - } - - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, "") - val sig = CryptoUtils.sign(id, privateKey) - return RelaySetEvent(id.toHexKey(), pubKey, createdAt, tags, "", sig.toHexKey()) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ReportEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ReportEvent.kt deleted file mode 100644 index d4436db6..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ReportEvent.kt +++ /dev/null @@ -1,100 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -data class ReportedKey(val key: String, val reportType: ReportEvent.ReportType) - -// NIP 56 event. -@Immutable -class ReportEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - private fun defaultReportType(): ReportType { - // Works with old and new structures for report. - var reportType = tags.filter { it.firstOrNull() == "report" }.mapNotNull { it.getOrNull(1) }.map { ReportType.valueOf(it.uppercase()) }.firstOrNull() - if (reportType == null) { - reportType = tags.mapNotNull { it.getOrNull(2) }.map { ReportType.valueOf(it.uppercase()) }.firstOrNull() - } - if (reportType == null) { - reportType = ReportType.SPAM - } - return reportType - } - - fun reportedPost() = tags - .filter { it.size > 1 && it[0] == "e" } - .map { - ReportedKey( - it[1], - it.getOrNull(2)?.uppercase()?.let { it1 -> ReportType.valueOf(it1) } ?: defaultReportType() - ) - } - - fun reportedAuthor() = tags - .filter { it.size > 1 && it[0] == "p" } - .map { - ReportedKey( - it[1], - it.getOrNull(2)?.uppercase()?.let { it1 -> ReportType.valueOf(it1) } ?: defaultReportType() - ) - } - - companion object { - const val kind = 1984 - - fun create( - reportedPost: EventInterface, - type: ReportType, - keyPair: KeyPair, - content: String = "", - createdAt: Long = TimeUtils.now() - ): ReportEvent { - val reportPostTag = listOf("e", reportedPost.id(), type.name.lowercase()) - val reportAuthorTag = listOf("p", reportedPost.pubKey(), type.name.lowercase()) - - val pubKey = keyPair.pubKey.toHexKey() - var tags: List> = listOf(reportPostTag, reportAuthorTag) - - if (reportedPost is AddressableEvent) { - tags = tags + listOf(listOf("a", reportedPost.address().toTag())) - } - - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return ReportEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(reportedUser: String, type: ReportType, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReportEvent { - val content = "" - - val reportAuthorTag = listOf("p", reportedUser, type.name.lowercase()) - - val pubKey = keyPair.pubKey.toHexKey() - val tags: List> = listOf(reportAuthorTag) - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return ReportEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - } - - enum class ReportType() { - EXPLICIT, // Not used anymore. - ILLEGAL, - SPAM, - IMPERSONATION, - NUDITY, - PROFANITY - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/RepostEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/RepostEvent.kt deleted file mode 100644 index 0a09b98e..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/RepostEvent.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class RepostEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : Event(id, pubKey, createdAt, kind, tags, content, sig) { - - fun boostedPost() = taggedEvents() - fun originalAuthor() = taggedUsers() - - fun containedPost() = try { - fromJson(content) - } catch (e: Exception) { - null - } - - companion object { - const val kind = 6 - - fun create(boostedPost: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): RepostEvent { - val content = boostedPost.toJson() - - val replyToPost = listOf("e", boostedPost.id()) - val replyToAuthor = listOf("p", boostedPost.pubKey()) - - val pubKey = keyPair.pubKey.toHexKey() - var tags: List> = listOf(replyToPost, replyToAuthor) - - if (boostedPost is AddressableEvent) { - tags = tags + listOf(listOf("a", boostedPost.address().toTag())) - } - - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return RepostEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") - } - - fun create(unsignedEvent: RepostEvent, signature: String): RepostEvent { - return RepostEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/SealedGossipEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/SealedGossipEvent.kt deleted file mode 100644 index 8a631427..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/SealedGossipEvent.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.vitorpamplona.quartz.events - -import android.util.Log -import androidx.compose.runtime.Immutable -import com.fasterxml.jackson.annotation.JsonProperty -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.hexToByteArray -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.Nip44Version -import com.vitorpamplona.quartz.crypto.decodeNIP44 -import com.vitorpamplona.quartz.crypto.encodeNIP44 -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class SealedGossipEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -): WrappedEvent(id, pubKey, createdAt, kind, tags, content, sig) { - @Transient - private var cachedInnerEvent: Map = mapOf() - - fun cachedGossip(privKey: ByteArray): Event? { - val hex = privKey.toHexKey() - if (cachedInnerEvent.contains(hex)) return cachedInnerEvent[hex] - - val gossip = unseal(privKey = privKey) - val event = gossip?.mergeWith(this) - if (event is WrappedEvent) { - event.host = host ?: this - } - - cachedInnerEvent = cachedInnerEvent + Pair(hex, event) - return event - } - - fun cachedGossip(pubKey: ByteArray, decryptedContent: String): Event? { - val hex = pubKey.toHexKey() - if (cachedInnerEvent.contains(hex)) return cachedInnerEvent[hex] - - val gossip = unseal(decryptedContent) - val event = gossip?.mergeWith(this) - if (event is WrappedEvent) { - event.host = host ?: this - } - - cachedInnerEvent = cachedInnerEvent + Pair(hex, event) - return event - } - - fun unseal(privKey: ByteArray): Gossip? = try { - plainContent(privKey)?.let { Gossip.fromJson(it) } - } catch (e: Exception) { - Log.w("GossipEvent", "Fail to decrypt or parse Gossip", e) - null - } - - fun unseal(decryptedContent: String): Gossip? = try { - plainContent(decryptedContent)?.let { Gossip.fromJson(it) } - } catch (e: Exception) { - Log.w("GossipEvent", "Fail to decrypt or parse Gossip", e) - null - } - - private fun plainContent(decryptedContent: String): String? { - if (decryptedContent.isEmpty()) return null - return decryptedContent - } - - private fun plainContent(privKey: ByteArray): String? { - if (content.isEmpty()) return null - - return try { - val toDecrypt = decodeNIP44(content) ?: return null - - return when (toDecrypt.v) { - Nip44Version.NIP04.versionCode -> CryptoUtils.decryptNIP04(toDecrypt, privKey, pubKey.hexToByteArray()) - Nip44Version.NIP44.versionCode -> CryptoUtils.decryptNIP44(toDecrypt, privKey, pubKey.hexToByteArray()) - else -> null - } - } catch (e: Exception) { - Log.w("GossipEvent", "Error decrypting the message ${e.message}") - null - } - } - - companion object { - const val kind = 13 - - fun create( - event: Event, - encryptTo: HexKey, - privateKey: ByteArray, - createdAt: Long = TimeUtils.now() - ): SealedGossipEvent { - val gossip = Gossip.create(event) - return create(gossip, encryptTo, privateKey, createdAt) - } - - fun create( - gossip: Gossip, - encryptTo: HexKey, - privateKey: ByteArray, - createdAt: Long = TimeUtils.randomWithinAWeek() - ): SealedGossipEvent { - val sharedSecret = CryptoUtils.getSharedSecretNIP44(privateKey, encryptTo.hexToByteArray()) - - val content = encodeNIP44( - CryptoUtils.encryptNIP44( - Gossip.toJson(gossip), - sharedSecret - ) - ) - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() - val tags = listOf>() - val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return SealedGossipEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) - } - } -} - -class Gossip( - val id: HexKey?, - @JsonProperty("pubkey") - val pubKey: HexKey?, - @JsonProperty("created_at") - val createdAt: Long?, - val kind: Int?, - val tags: List>?, - val content: String? -) { - fun mergeWith(event: SealedGossipEvent): Event { - val newPubKey = pubKey?.ifBlank { null } ?: event.pubKey - val newCreatedAt = if (createdAt != null && createdAt > 1000) createdAt else event.createdAt - val newKind = kind ?: -1 - val newTags = (tags ?: emptyList()).plus(event.tags) - val newContent = content ?: "" - val newID = id?.ifBlank { null } ?: Event.generateId(newPubKey, newCreatedAt, newKind, newTags, newContent).toHexKey() - val sig = "" - - return EventFactory.create(newID, newPubKey, newCreatedAt, newKind, newTags, newContent, sig) - } - - companion object { - fun fromJson(json: String): Gossip = Event.mapper.readValue(json, Gossip::class.java) - fun toJson(event: Gossip): String = Event.mapper.writeValueAsString(event) - - fun create(event: Event): Gossip { - return Gossip(event.id, event.pubKey, event.createdAt, event.kind, event.tags, event.content) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/StatusEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/StatusEvent.kt deleted file mode 100644 index d9b03f7a..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/StatusEvent.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class StatusEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - companion object { - const val kind = 30315 - - fun create( - msg: String, - type: String, - expiration: Long?, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): StatusEvent { - val tags = mutableListOf>() - - tags.add(listOf("d", type)) - expiration?.let { tags.add(listOf("expiration", it.toString())) } - - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return StatusEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig?.toHexKey() ?: "") - } - - fun update( - event: StatusEvent, - newStatus: String, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): StatusEvent { - val tags = event.tags - val pubKey = event.pubKey() - val id = generateId(pubKey, createdAt, kind, tags, newStatus) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return StatusEvent(id.toHexKey(), pubKey, createdAt, tags, newStatus, sig?.toHexKey() ?: "") - } - - fun clear( - event: StatusEvent, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): StatusEvent { - val msg = "" - val tags = event.tags.filter { it.size > 1 && it[0] == "d" } - val pubKey = event.pubKey() - val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return StatusEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig?.toHexKey() ?: "") - } - - fun create( - unsignedEvent: StatusEvent, - signature: String - ): StatusEvent { - return StatusEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/TextNoteEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/TextNoteEvent.kt deleted file mode 100644 index ebcd393c..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/TextNoteEvent.kt +++ /dev/null @@ -1,115 +0,0 @@ -package com.vitorpamplona.quartz.events - -import androidx.compose.runtime.Immutable -import com.linkedin.urls.detection.UrlDetector -import com.linkedin.urls.detection.UrlDetectorOptions -import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.encoders.toHexKey -import com.vitorpamplona.quartz.crypto.CryptoUtils -import com.vitorpamplona.quartz.crypto.KeyPair -import com.vitorpamplona.quartz.encoders.ATag -import com.vitorpamplona.quartz.encoders.HexKey - -@Immutable -class TextNoteEvent( - id: HexKey, - pubKey: HexKey, - createdAt: Long, - tags: List>, - content: String, - sig: HexKey -) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) { - - fun root() = tags.firstOrNull() { it.size > 3 && it[3] == "root" }?.get(1) - - companion object { - const val kind = 1 - - fun create( - msg: String, - replyTos: List?, - mentions: List?, - addresses: List?, - extraTags: List?, - zapReceiver: String?, - markAsSensitive: Boolean, - zapRaiserAmount: Long?, - replyingTo: String?, - root: String?, - directMentions: Set, - geohash: String? = null, - keyPair: KeyPair, - createdAt: Long = TimeUtils.now() - ): TextNoteEvent { - val tags = mutableListOf>() - replyTos?.forEach { - if (it == replyingTo) { - tags.add(listOf("e", it, "", "reply")) - } else if (it == root) { - tags.add(listOf("e", it, "", "root")) - } else if (it in directMentions) { - tags.add(listOf("e", it, "", "mention")) - } else { - tags.add(listOf("e", it)) - } - } - mentions?.forEach { - if (it in directMentions) { - tags.add(listOf("p", it, "", "mention")) - } else { - tags.add(listOf("p", it)) - } - } - addresses?.forEach { - val aTag = it.toTag() - if (aTag == replyingTo) { - tags.add(listOf("a", aTag, "", "reply")) - } else if (aTag == root) { - tags.add(listOf("a", aTag, "", "root")) - } else if (aTag in directMentions) { - tags.add(listOf("a", aTag, "", "mention")) - } else { - tags.add(listOf("a", aTag)) - } - } - findHashtags(msg).forEach { - tags.add(listOf("t", it)) - tags.add(listOf("t", it.lowercase())) - } - extraTags?.forEach { - tags.add(listOf("t", it)) - } - zapReceiver?.let { - tags.add(listOf("zap", it)) - } - findURLs(msg).forEach { - tags.add(listOf("r", it)) - } - if (markAsSensitive) { - tags.add(listOf("content-warning", "")) - } - zapRaiserAmount?.let { - tags.add(listOf("zapraiser", "$it")) - } - geohash?.let { - tags.add(listOf("g", it)) - } - - val pubKey = keyPair.pubKey.toHexKey() - val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey) - return TextNoteEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig?.toHexKey() ?: "") - } - - fun create( - unsignedEvent: TextNoteEvent, signature: String - ): TextNoteEvent { - - return TextNoteEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature) - } - } -} - -fun findURLs(text: String): List { - return UrlDetector(text, UrlDetectorOptions.Default).detect().map { it.originalUrl } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/TimeUtils.kt b/quartz/src/main/java/com/vitorpamplona/quartz/utils/TimeUtils.kt deleted file mode 100644 index e88af3ad..00000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/utils/TimeUtils.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vitorpamplona.quartz.utils - -import com.vitorpamplona.quartz.crypto.CryptoUtils - -object TimeUtils { - const val oneMinute = 60 - const val fiveMinutes = 5 * oneMinute - const val oneHour = 60 * oneMinute - const val eightHours = 8 * oneHour - const val oneDay = 24 * oneHour - const val oneWeek = 7 * oneDay - - fun now() = System.currentTimeMillis() / 1000 - fun fiveMinutesAgo() = now() - fiveMinutes - fun oneHourAgo() = now() - oneHour - fun oneHourAhead() = now() + oneHour - fun oneDayAgo() = now() - oneDay - fun eightHoursAgo() = now() - eightHours - fun oneWeekAgo() = now() - oneWeek - fun randomWithinAWeek() = System.currentTimeMillis() / 1000 - CryptoUtils.randomInt(oneWeek) -} diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/encoders/NIP19ParserTest.kt b/quartz/src/test/java/com/vitorpamplona/quartz/encoders/NIP19ParserTest.kt deleted file mode 100644 index b4578acd..00000000 --- a/quartz/src/test/java/com/vitorpamplona/quartz/encoders/NIP19ParserTest.kt +++ /dev/null @@ -1,173 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -import org.junit.Assert.assertEquals -import org.junit.Test - -class NIP19ParserTest { - @Test - fun nAddrParser() { - val result = Nip19.uriToRoute("nostr:naddr1qqqqygzxpsj7dqha57pjk5k37gkn6g4nzakewtmqmnwryyhd3jfwlpgxtspsgqqqw4rs3xyxus") - assertEquals("30023:460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:", result?.hex) - } - - @Test - fun nAddrParser2() { - val result = Nip19.uriToRoute("nostr:naddr1qq8kwatfv3jj6amfwfjkwatpwfjqygxsm6lelvfda7qlg0tud9pfhduysy4vrexj65azqtdk4tr75j6xdspsgqqqw4rsg32ag8") - assertEquals("30023:d0debf9fb12def81f43d7c69429bb784812ac1e4d2d53a202db6aac7ea4b466c:guide-wireguard", result?.hex) - } - - @Test - fun nAddrParse3() { - val result = Nip19.uriToRoute("naddr1qqyrswtyv5mnjv3sqy28wumn8ghj7un9d3shjtnyv9kh2uewd9hsygx3uczxts4hwue9ayfn7ggq62anzstde2qs749pm9tx2csuthhpjvpsgqqqw4rs8pmj38") - assertEquals(Nip19.Type.ADDRESS, result?.type) - assertEquals("30023:d1e60465c2b777325e9133f2100d2bb31416dca810f54a1d95665621c5dee193:89de7920", result?.hex) - assertEquals("wss://relay.damus.io", result?.relay) - } - - @Test - fun nAddrATagParse3() { - val address = ATag.parse("30023:d1e60465c2b777325e9133f2100d2bb31416dca810f54a1d95665621c5dee193:89de7920", "wss://relay.damus.io") - assertEquals(30023, address?.kind) - assertEquals("d1e60465c2b777325e9133f2100d2bb31416dca810f54a1d95665621c5dee193", address?.pubKeyHex) - assertEquals("89de7920", address?.dTag) - assertEquals("wss://relay.damus.io", address?.relay) - assertEquals("naddr1qqyrswtyv5mnjv3sqy28wumn8ghj7un9d3shjtnyv9kh2uewd9hsygx3uczxts4hwue9ayfn7ggq62anzstde2qs749pm9tx2csuthhpjvpsgqqqw4rs8pmj38", address?.toNAddr()) - } - - @Test - fun nAddrFormatter() { - val address = ATag( - 30023, - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - "", - null - ) - assertEquals("naddr1qqqqygzxpsj7dqha57pjk5k37gkn6g4nzakewtmqmnwryyhd3jfwlpgxtspsgqqqw4rs3xyxus", address.toNAddr()) - } - - @Test - fun nAddrFormatter2() { - val address = ATag( - 30023, - "d0debf9fb12def81f43d7c69429bb784812ac1e4d2d53a202db6aac7ea4b466c", - "guide-wireguard", - null - ) - assertEquals("naddr1qq8kwatfv3jj6amfwfjkwatpwfjqygxsm6lelvfda7qlg0tud9pfhduysy4vrexj65azqtdk4tr75j6xdspsgqqqw4rsg32ag8", address.toNAddr()) - } - - @Test - fun nAddrFormatter3() { - val address = ATag( - 30023, - "d1e60465c2b777325e9133f2100d2bb31416dca810f54a1d95665621c5dee193", - "89de7920", - "wss://relay.damus.io" - ) - assertEquals("naddr1qqyrswtyv5mnjv3sqy28wumn8ghj7un9d3shjtnyv9kh2uewd9hsygx3uczxts4hwue9ayfn7ggq62anzstde2qs749pm9tx2csuthhpjvpsgqqqw4rs8pmj38", address.toNAddr()) - } - - @Test - fun nAddrParserPablo() { - val result = Nip19.uriToRoute("naddr1qq2hs7p30p6kcunxxamkgcnyd33xxve3veshyq3qyujphdcz69z6jafxpnldae3xtymdekfeatkt3r4qusr3w5krqspqxpqqqpaxjlg805f") - assertEquals(Nip19.Type.ADDRESS, result?.type) - assertEquals("31337:27241bb702d145a975260cfedee6265936dcd939eaecb88ea0e4071752c30402:xx1xulrf7wdbdlbc31far", result?.hex) - assertEquals(null, result?.relay) - assertEquals("27241bb702d145a975260cfedee6265936dcd939eaecb88ea0e4071752c30402", result?.author) - assertEquals(31337, result?.kind) - } - - @Test - fun nAddrParserGizmo() { - val result = Nip19.uriToRoute("naddr1qpqrvvfnvccrzdryxgunzvtxvgukge34xfjnqdpcv9sk2desxgmrscesvserzd3h8ycrywphvg6nsvf58ycnqef3v5mnsvt98pjnqdfs8ypzq3huhccxt6h34eupz3jeynjgjgek8lel2f4adaea0svyk94a3njdqvzqqqr4gudhrkyk") - assertEquals(Nip19.Type.ADDRESS, result?.type) - assertEquals("30023:46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184b16bd8ce4d:613f014d2911fb9df52e048aae70268c0d216790287b5814910e1e781e8e0509", result?.hex) - assertEquals(null, result?.relay) - assertEquals("46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184b16bd8ce4d", result?.author) - assertEquals(30023, result?.kind) - } - - @Test - fun nAddrParserGizmo2() { - val result = Nip19.uriToRoute("naddr1qq9rzd3h8y6nqwf5xyuqygzxljlrqe027xh8sy2xtyjwfzfrxcll8afxh4hh847psjckhkxwf5psgqqqw4rsty50fx") - assertEquals(Nip19.Type.ADDRESS, result?.type) - assertEquals("30023:46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184b16bd8ce4d:1679509418", result?.hex) - assertEquals(null, result?.relay) - assertEquals("46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184b16bd8ce4d", result?.author) - assertEquals(30023, result?.kind) - } - - @Test - fun nEventParserTest() { - val result = Nip19.uriToRoute("nostr:nevent1qqs0tsw8hjacs4fppgdg7f5yhgwwfkyua4xcs3re9wwkpkk2qeu6mhql22rcy") - assertEquals(Nip19.Type.EVENT, result?.type) - assertEquals("f5c1c7bcbb8855210a1a8f2684ba1ce4d89ced4d8844792b9d60daca0679addc", result?.hex) - assertEquals(null, result?.relay) - assertEquals(null, result?.author) - assertEquals(null, result?.kind) - } - - @Test - fun nEventParser() { - val result = Nip19.uriToRoute("nostr:nevent1qqstvrl6wftd8ht4g0vrp6m30tjs6pdxcvk977g769dcvlptkzu4ftqppamhxue69uhkummnw3ezumt0d5pzp78lz8r60568sd2a8dx3wnj6gume02gxaf92vx4fk67qv5kpagt6qvzqqqqqqygqr86c") - assertEquals(Nip19.Type.EVENT, result?.type) - assertEquals("b60ffa7256d3dd7543d830eb717ae50d05a6c32c5f791ed15b867c2bb0b954ac", result?.hex) - assertEquals("wss://nostr.mom", result?.relay) - assertEquals("f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a", result?.author) - assertEquals(1, result?.kind) - } - - @Test - fun nEventParser2() { - val result = Nip19.uriToRoute("nostr:nevent1qqsplpuwsgrrmq85rfup6w3w777rxmcmadu590emfx6z4msj2844euqpz3mhxue69uhhyetvv9ujuerpd46hxtnfdupzq3svyhng9ld8sv44950j957j9vchdktj7cxumsep9mvvjthc2pjuqvzqqqqqqye3a70w") - - assertEquals(Nip19.Type.EVENT, result?.type) - assertEquals("1f878e82063d80f41a781d3a2ef7bc336f1beb7942bf3b49b42aee1251eb5cf0", result?.hex) - assertEquals("wss://relay.damus.io", result?.relay) - assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.author) - assertEquals(1, result?.kind) - } - - @Test - fun nEventParser3() { - val result = Nip19.uriToRoute("nostr:nevent1qqsg6gechd3dhzx38n4z8a2lylzgsmmgeamhmtzz72m9ummsnf0xjfspsdmhxue69uhkummn9ekx7mpvwaehxw309ahx7um5wghx77r5wghxgetk93mhxue69uhhyetvv9ujumn0wd68ytnzvuk8wumn8ghj7mn0wd68ytn9d9h82mny0fmkzmn6d9njuumsv93k2trhwden5te0wfjkccte9ehx7um5wghxyctwvsk8wumn8ghj7un9d3shjtnyv9kh2uewd9hs3kqsdn") - - assertEquals(Nip19.Type.EVENT, result?.type) - assertEquals("8d2338bb62db88d13cea23f55f27c4886f68cf777dac42f2b65e6f709a5e6926", result?.hex) - assertEquals("wss://nos.lol,wss://nostr.oxtr.dev,wss://relay.nostr.bg,wss://nostr.einundzwanzig.space,wss://relay.nostr.band,wss://relay.damus.io", result?.relay) - } - - @Test - fun nEventParserInvalidChecksum() { - val result = Nip19.uriToRoute("nostr:nevent1qqsyxq8v0730nz38dupnjzp5jegkyz4gu2ptwcps4v32hjnrap0q0espz3mhxue69uhhyetvv9ujuerpd46hxtnfdupzq3svyhng9ld8sv44950j957j9vchdktj7cxumsep9mvvjthc2pjuqvzqqqqqqyn3t9gj") - - assertEquals(Nip19.Type.EVENT, result?.type) - assertEquals("4300ec7fa2f98a276f033908349651620aa8e282b76030ab22abca63e85e07e6", result?.hex) - assertEquals("wss://relay.damus.io", result?.relay) - assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.author) - assertEquals(1, result?.kind) - } - - @Test - fun nEventFormatter() { - val nevent = Nip19.createNEvent("f5c1c7bcbb8855210a1a8f2684ba1ce4d89ced4d8844792b9d60daca0679addc", null, null, null) - assertEquals("nevent1qqs0tsw8hjacs4fppgdg7f5yhgwwfkyua4xcs3re9wwkpkk2qeu6mhql22rcy", nevent) - } - - @Test - fun nEventFormatterWithExtraInfo() { - val nevent = Nip19.createNEvent("f5c1c7bcbb8855210a1a8f2684ba1ce4d89ced4d8844792b9d60daca0679addc", "7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194", 40, null) - assertEquals("nevent1qqs0tsw8hjacs4fppgdg7f5yhgwwfkyua4xcs3re9wwkpkk2qeu6mhqzypl62m6ad932k83u6sjwwkxrqq4cve0hkrvdem5la83g34m4rtqegqcyqqqqq2qh26va4", nevent) - } - - @Test - fun nEventFormatterWithFullInfo() { - val nevent = Nip19.createNEvent( - "1f878e82063d80f41a781d3a2ef7bc336f1beb7942bf3b49b42aee1251eb5cf0", - "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", - 1, - "wss://relay.damus.io" - ) - assertEquals("nevent1qqsplpuwsgrrmq85rfup6w3w777rxmcmadu590emfx6z4msj2844euqpz3mhxue69uhhyetvv9ujuerpd46hxtnfdupzq3svyhng9ld8sv44950j957j9vchdktj7cxumsep9mvvjthc2pjuqvzqqqqqqye3a70w", nevent) - } -} diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/encoders/Nip19Test.kt b/quartz/src/test/java/com/vitorpamplona/quartz/encoders/Nip19Test.kt deleted file mode 100644 index 6e11ece4..00000000 --- a/quartz/src/test/java/com/vitorpamplona/quartz/encoders/Nip19Test.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -import org.junit.Assert -import org.junit.Ignore -import org.junit.Test - -class Nip19Test { - @Test() - fun uri_to_route_null() { - val actual = Nip19.uriToRoute(null) - - Assert.assertEquals(null, actual) - } - - @Test() - fun uri_to_route_unknown() { - val actual = Nip19.uriToRoute("nostr:unknown") - - Assert.assertEquals(null, actual) - } - - @Test() - fun uri_to_route_npub() { - val actual = - Nip19.uriToRoute("nostr:npub1hv7k2s755n697sptva8vkh9jz40lzfzklnwj6ekewfmxp5crwdjs27007y") - - Assert.assertEquals(Nip19.Type.USER, actual?.type) - Assert.assertEquals( - "bb3d6543d4a4f45f402b674ecb5cb2155ff12456fcdd2d66d9727660d3037365", - actual?.hex - ) - } - - @Test() - fun uri_to_route_note() { - val actual = - Nip19.uriToRoute("nostr:note1stqea6wmwezg9x6yyr6qkukw95ewtdukyaztycws65l8wppjmtpscawevv") - - Assert.assertEquals(Nip19.Type.NOTE, actual?.type) - Assert.assertEquals( - "82c19ee9db7644829b4420f40b72ce2d32e5b7962744b261d0d53e770432dac3", - actual?.hex - ) - } - - @Ignore("Test not implemented yet") - @Test() - fun uri_to_route_nprofile() { - val actual = Nip19.uriToRoute("nostr:nprofile") - - Assert.assertEquals(Nip19.Type.USER, actual?.type) - Assert.assertEquals("*", actual?.hex) - } - - @Ignore("Test not implemented yet") - @Test() - fun uri_to_route_nevent() { - val actual = Nip19.uriToRoute("nostr:nevent") - - Assert.assertEquals(Nip19.Type.USER, actual?.type) - Assert.assertEquals("*", actual?.hex) - } - - @Ignore("Test not implemented yet") - @Test() - fun uri_to_route_nrelay() { - val actual = Nip19.uriToRoute("nostr:nrelay") - - Assert.assertEquals(Nip19.Type.RELAY, actual?.type) - Assert.assertEquals("*", actual?.hex) - } - - @Ignore("Test not implemented yet") - @Test() - fun uri_to_route_naddr() { - val actual = Nip19.uriToRoute("nostr:naddr") - - Assert.assertEquals(Nip19.Type.ADDRESS, actual?.type) - Assert.assertEquals("*", actual?.hex) - } -} diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/encoders/TlvIntegerTest.kt b/quartz/src/test/java/com/vitorpamplona/quartz/encoders/TlvIntegerTest.kt deleted file mode 100644 index 83037aa8..00000000 --- a/quartz/src/test/java/com/vitorpamplona/quartz/encoders/TlvIntegerTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.vitorpamplona.quartz.encoders - -import org.junit.Assert -import org.junit.Assert.assertEquals -import org.junit.Test - -class TlvIntegerTest { - fun to_int_32_length_smaller_than_4() { - Assert.assertNull(byteArrayOfInts(1, 2, 3).toInt32()) - } - - fun to_int_32_length_bigger_than_4() { - Assert.assertNull(byteArrayOfInts(1, 2, 3, 4, 5).toInt32()) - } - - @Test() - fun to_int_32_length_4() { - val actual = byteArrayOfInts(1, 2, 3, 4).toInt32() - - assertEquals(16909060, actual) - } - - @Test() - fun backAndForth() { - assertEquals(234, 234.to32BitByteArray().toInt32()) - assertEquals(1, 1.to32BitByteArray().toInt32()) - assertEquals(0, 0.to32BitByteArray().toInt32()) - assertEquals(1000, 1000.to32BitByteArray().toInt32()) - - assertEquals(-234, (-234).to32BitByteArray().toInt32()) - assertEquals(-1, (-1).to32BitByteArray().toInt32()) - assertEquals(-0, (-0).to32BitByteArray().toInt32()) - assertEquals(-1000, (-1000).to32BitByteArray().toInt32()) - } - - private fun byteArrayOfInts(vararg ints: Int) = - ByteArray(ints.size) { pos -> ints[pos].toByte() } -} diff --git a/settings.gradle b/settings.gradle index 9773c3cc..6ecf5781 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,4 +16,3 @@ dependencyResolutionManagement { } rootProject.name = "Nostr Signer" include ':app' -include ':quartz'