Fixing NostrFiles dev downloader

This commit is contained in:
Vitor Pamplona
2023-05-08 09:39:44 -04:00
parent d6d273e34c
commit ae268cc197
8 changed files with 87 additions and 45 deletions
@@ -4,6 +4,7 @@ import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Log
import com.vitorpamplona.amethyst.model.toHexKey
import com.vitorpamplona.amethyst.ui.actions.ImageDownloader
import io.trbl.blurhash.BlurHash
import java.net.URL
import java.security.MessageDigest
@@ -19,11 +20,15 @@ class FileHeader(
val description: String? = null
) {
companion object {
fun prepare(fileUrl: String, mimeType: String?, description: String?, onReady: (FileHeader) -> Unit, onError: () -> Unit) {
suspend fun prepare(fileUrl: String, mimeType: String?, description: String?, onReady: (FileHeader) -> Unit, onError: () -> Unit) {
try {
val imageData = URL(fileUrl).readBytes()
val imageData: ByteArray? = ImageDownloader().waitAndGetImage(fileUrl)
prepare(imageData, fileUrl, mimeType, description, onReady, onError)
if (imageData != null)
prepare(imageData, fileUrl, mimeType, description, onReady, onError)
else {
onError()
}
} catch (e: Exception) {
Log.e("ImageDownload", "Couldn't download image from server: ${e.message}")
onError()
@@ -0,0 +1,47 @@
package com.vitorpamplona.amethyst.ui.actions
import kotlinx.coroutines.delay
import java.net.HttpURLConnection
import java.net.URL
class ImageDownloader {
suspend fun waitAndGetImage(imageUrl: String): ByteArray? {
var imageData: ByteArray? = null
var tentatives = 0
// Servers are usually not ready.. so tries to download it for 15 times/seconds.
while (imageData == null && tentatives < 15) {
imageData = try {
HttpURLConnection.setFollowRedirects(true)
var url = URL(imageUrl)
var huc = url.openConnection() as HttpURLConnection
huc.instanceFollowRedirects = true
var responseCode = huc.responseCode
if (responseCode in 300..400) {
val newUrl: String = huc.getHeaderField("Location")
// open the new connnection again
url = URL(newUrl)
huc = url.openConnection() as HttpURLConnection
responseCode = huc.responseCode
}
if (responseCode in 200..300) {
huc.inputStream.use { it.readBytes() }
} else {
tentatives++
delay(1000)
null
}
} catch (e: Exception) {
tentatives++
delay(1000)
null
}
}
return imageData
}
}
@@ -38,16 +38,22 @@ object ImageUploader {
checkNotNull(imageInputStream) {
"Can't open the image input stream"
}
val myServer = if (server == ServersAvailable.IMGUR) {
ImgurServer()
} else if (server == ServersAvailable.NOSTRIMG) {
NostrImgServer()
} else if (server == ServersAvailable.NOSTR_BUILD) {
NostrBuildServer()
} else if (server == ServersAvailable.NOSTRFILES_DEV) {
NostrFilesDevServer()
} else {
ImgurServer()
val myServer = when (server) {
ServersAvailable.IMGUR, ServersAvailable.IMGUR_NIP_94 -> {
ImgurServer()
}
ServersAvailable.NOSTRIMG, ServersAvailable.NOSTRIMG_NIP_94 -> {
NostrImgServer()
}
ServersAvailable.NOSTR_BUILD, ServersAvailable.NOSTR_BUILD_NIP_94 -> {
NostrBuildServer()
}
ServersAvailable.NOSTRFILES_DEV, ServersAvailable.NOSTRFILES_DEV_NIP_94 -> {
NostrFilesDevServer()
}
else -> {
ImgurServer()
}
}
uploadImage(imageInputStream, length, contentType, myServer, onSuccess, onError)
@@ -101,7 +107,7 @@ object ImageUploader {
try {
check(response.isSuccessful)
response.body.use { body ->
val url = server.parseUrlFromSucess(body.string())
val url = server.parseUrlFromSuccess(body.string())
checkNotNull(url) {
"There must be an uploaded image URL in the response"
}
@@ -124,7 +130,7 @@ object ImageUploader {
abstract class FileServer {
abstract fun postUrl(contentType: String?): String
abstract fun parseUrlFromSucess(body: String): String?
abstract fun parseUrlFromSuccess(body: String): String?
abstract fun inputParameterName(contentType: String?): String
open fun clientID(): String? = null
@@ -133,7 +139,7 @@ abstract class FileServer {
class NostrImgServer : FileServer() {
override fun postUrl(contentType: String?) = "https://nostrimg.com/api/upload"
override fun parseUrlFromSucess(body: String): String? {
override fun parseUrlFromSuccess(body: String): String? {
val tree = jacksonObjectMapper().readTree(body)
val url = tree?.get("data")?.get("link")?.asText()
return url
@@ -152,7 +158,7 @@ class ImgurServer : FileServer() {
return if (category == "image") "https://api.imgur.com/3/image" else "https://api.imgur.com/3/upload"
}
override fun parseUrlFromSucess(body: String): String? {
override fun parseUrlFromSuccess(body: String): String? {
val tree = jacksonObjectMapper().readTree(body)
val url = tree?.get("data")?.get("link")?.asText()
return url
@@ -167,7 +173,7 @@ class ImgurServer : FileServer() {
class NostrBuildServer : FileServer() {
override fun postUrl(contentType: String?) = "https://nostr.build/api/upload/android.php"
override fun parseUrlFromSucess(body: String): String? {
override fun parseUrlFromSuccess(body: String): String? {
val url = jacksonObjectMapper().readTree(body) // return url.toString()
return url.toString().replace("\"", "")
}
@@ -181,10 +187,9 @@ class NostrBuildServer : FileServer() {
class NostrFilesDevServer : FileServer() {
override fun postUrl(contentType: String?) = "https://nostrfiles.dev/upload_image"
override fun parseUrlFromSucess(body: String): String? {
override fun parseUrlFromSuccess(body: String): String? {
val tree = jacksonObjectMapper().readTree(body)
val url = tree?.get("url")?.asText()
return url
return tree?.get("url")?.asText()
}
override fun inputParameterName(contentType: String?): String {
@@ -14,8 +14,10 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import java.net.HttpURLConnection
import java.net.URL
open class NewMediaModel : ViewModel() {
var account: Account? = null
@@ -116,19 +118,7 @@ open class NewMediaModel : ViewModel() {
uploadingDescription.value = "Server Processing"
// Images don't seem to be ready immediately after upload
var imageData: ByteArray? = null
var tentatives = 0
// Servers are usually not ready.. so tries to download it for 15 times/seconds.
while (imageData == null && tentatives < 15) {
imageData = try {
URL(imageUrl).readBytes()
} catch (e: Exception) {
tentatives++
delay(1000)
null
}
}
val imageData: ByteArray? = ImageDownloader().waitAndGetImage(imageUrl)
uploadingDescription.value = "Downloading"
uploadingPercentage.value = 0.60f
@@ -110,7 +110,10 @@ fun NewMediaView(uri: Uri, onClose: () -> Unit, postViewModel: NewMediaModel, ac
}
fun isNIP94Server(selectedServer: ServersAvailable?): Boolean {
return selectedServer == ServersAvailable.NOSTRIMG_NIP_94 || selectedServer == ServersAvailable.IMGUR_NIP_94 || selectedServer == ServersAvailable.NOSTR_BUILD_NIP_94 || selectedServer == ServersAvailable.NOSTRFILES_DEV_NIP_94
return selectedServer == ServersAvailable.NOSTRIMG_NIP_94
|| selectedServer == ServersAvailable.IMGUR_NIP_94
|| selectedServer == ServersAvailable.NOSTR_BUILD_NIP_94
|| selectedServer == ServersAvailable.NOSTRFILES_DEV_NIP_94
}
@Composable
@@ -614,11 +614,11 @@ fun ImageVideoDescription(
Triple(ServersAvailable.IMGUR, stringResource(id = R.string.upload_server_imgur), stringResource(id = R.string.upload_server_imgur_explainer)),
Triple(ServersAvailable.NOSTRIMG, stringResource(id = R.string.upload_server_nostrimg), stringResource(id = R.string.upload_server_nostrimg_explainer)),
Triple(ServersAvailable.NOSTR_BUILD, stringResource(id = R.string.upload_server_nostrbuild), stringResource(id = R.string.upload_server_nostrbuild_explainer)),
// Triple(ServersAvailable.NOSTRFILES_DEV, stringResource(id = R.string.upload_server_nostrfilesdev), stringResource(id = R.string.upload_server_nostrfilesdev_explainer)),
Triple(ServersAvailable.NOSTRFILES_DEV, stringResource(id = R.string.upload_server_nostrfilesdev), stringResource(id = R.string.upload_server_nostrfilesdev_explainer)),
Triple(ServersAvailable.IMGUR_NIP_94, stringResource(id = R.string.upload_server_imgur_nip94), stringResource(id = R.string.upload_server_imgur_nip94_explainer)),
Triple(ServersAvailable.NOSTRIMG_NIP_94, stringResource(id = R.string.upload_server_nostrimg_nip94), stringResource(id = R.string.upload_server_nostrimg_nip94_explainer)),
Triple(ServersAvailable.NOSTR_BUILD_NIP_94, stringResource(id = R.string.upload_server_nostrbuild_nip94), stringResource(id = R.string.upload_server_nostrbuild_nip94_explainer)),
// Triple(ServersAvailable.NOSTRFILES_DEV_NIP_94, stringResource(id = R.string.upload_server_nostrfilesdev_nip94), stringResource(id = R.string.upload_server_nostrfilesdev_nip94_explainer)),
Triple(ServersAvailable.NOSTRFILES_DEV_NIP_94, stringResource(id = R.string.upload_server_nostrfilesdev_nip94), stringResource(id = R.string.upload_server_nostrfilesdev_nip94_explainer)),
Triple(ServersAvailable.NIP95, stringResource(id = R.string.upload_server_relays_nip95), stringResource(id = R.string.upload_server_relays_nip95_explainer))
)
@@ -287,13 +287,6 @@ open class NewPostViewModel : ViewModel() {
fun createNIP94Record(imageUrl: String, mimeType: String?, description: String) {
viewModelScope.launch(Dispatchers.IO) {
// Images don't seem to be ready immediately after upload
if (mimeType?.startsWith("image/") == true) {
delay(2000)
} else {
delay(5000)
}
FileHeader.prepare(
imageUrl,
mimeType,
@@ -259,7 +259,6 @@ private fun UrlImageView(
content: ZoomableUrlImage,
mainImageModifier: Modifier
) {
println("UrlImageView")
val scope = rememberCoroutineScope()
val context = LocalContext.current