Fixing NostrFiles dev downloader
This commit is contained in:
@@ -4,6 +4,7 @@ import android.graphics.Bitmap
|
|||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.vitorpamplona.amethyst.model.toHexKey
|
import com.vitorpamplona.amethyst.model.toHexKey
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.ImageDownloader
|
||||||
import io.trbl.blurhash.BlurHash
|
import io.trbl.blurhash.BlurHash
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
@@ -19,11 +20,15 @@ class FileHeader(
|
|||||||
val description: String? = null
|
val description: String? = null
|
||||||
) {
|
) {
|
||||||
companion object {
|
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 {
|
try {
|
||||||
val imageData = URL(fileUrl).readBytes()
|
val imageData: ByteArray? = ImageDownloader().waitAndGetImage(fileUrl)
|
||||||
|
|
||||||
|
if (imageData != null)
|
||||||
prepare(imageData, fileUrl, mimeType, description, onReady, onError)
|
prepare(imageData, fileUrl, mimeType, description, onReady, onError)
|
||||||
|
else {
|
||||||
|
onError()
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("ImageDownload", "Couldn't download image from server: ${e.message}")
|
Log.e("ImageDownload", "Couldn't download image from server: ${e.message}")
|
||||||
onError()
|
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,17 +38,23 @@ object ImageUploader {
|
|||||||
checkNotNull(imageInputStream) {
|
checkNotNull(imageInputStream) {
|
||||||
"Can't open the image input stream"
|
"Can't open the image input stream"
|
||||||
}
|
}
|
||||||
val myServer = if (server == ServersAvailable.IMGUR) {
|
val myServer = when (server) {
|
||||||
|
ServersAvailable.IMGUR, ServersAvailable.IMGUR_NIP_94 -> {
|
||||||
ImgurServer()
|
ImgurServer()
|
||||||
} else if (server == ServersAvailable.NOSTRIMG) {
|
}
|
||||||
|
ServersAvailable.NOSTRIMG, ServersAvailable.NOSTRIMG_NIP_94 -> {
|
||||||
NostrImgServer()
|
NostrImgServer()
|
||||||
} else if (server == ServersAvailable.NOSTR_BUILD) {
|
}
|
||||||
|
ServersAvailable.NOSTR_BUILD, ServersAvailable.NOSTR_BUILD_NIP_94 -> {
|
||||||
NostrBuildServer()
|
NostrBuildServer()
|
||||||
} else if (server == ServersAvailable.NOSTRFILES_DEV) {
|
}
|
||||||
|
ServersAvailable.NOSTRFILES_DEV, ServersAvailable.NOSTRFILES_DEV_NIP_94 -> {
|
||||||
NostrFilesDevServer()
|
NostrFilesDevServer()
|
||||||
} else {
|
}
|
||||||
|
else -> {
|
||||||
ImgurServer()
|
ImgurServer()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uploadImage(imageInputStream, length, contentType, myServer, onSuccess, onError)
|
uploadImage(imageInputStream, length, contentType, myServer, onSuccess, onError)
|
||||||
}
|
}
|
||||||
@@ -101,7 +107,7 @@ object ImageUploader {
|
|||||||
try {
|
try {
|
||||||
check(response.isSuccessful)
|
check(response.isSuccessful)
|
||||||
response.body.use { body ->
|
response.body.use { body ->
|
||||||
val url = server.parseUrlFromSucess(body.string())
|
val url = server.parseUrlFromSuccess(body.string())
|
||||||
checkNotNull(url) {
|
checkNotNull(url) {
|
||||||
"There must be an uploaded image URL in the response"
|
"There must be an uploaded image URL in the response"
|
||||||
}
|
}
|
||||||
@@ -124,7 +130,7 @@ object ImageUploader {
|
|||||||
|
|
||||||
abstract class FileServer {
|
abstract class FileServer {
|
||||||
abstract fun postUrl(contentType: String?): String
|
abstract fun postUrl(contentType: String?): String
|
||||||
abstract fun parseUrlFromSucess(body: String): String?
|
abstract fun parseUrlFromSuccess(body: String): String?
|
||||||
abstract fun inputParameterName(contentType: String?): String
|
abstract fun inputParameterName(contentType: String?): String
|
||||||
|
|
||||||
open fun clientID(): String? = null
|
open fun clientID(): String? = null
|
||||||
@@ -133,7 +139,7 @@ abstract class FileServer {
|
|||||||
class NostrImgServer : FileServer() {
|
class NostrImgServer : FileServer() {
|
||||||
override fun postUrl(contentType: String?) = "https://nostrimg.com/api/upload"
|
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 tree = jacksonObjectMapper().readTree(body)
|
||||||
val url = tree?.get("data")?.get("link")?.asText()
|
val url = tree?.get("data")?.get("link")?.asText()
|
||||||
return url
|
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"
|
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 tree = jacksonObjectMapper().readTree(body)
|
||||||
val url = tree?.get("data")?.get("link")?.asText()
|
val url = tree?.get("data")?.get("link")?.asText()
|
||||||
return url
|
return url
|
||||||
@@ -167,7 +173,7 @@ class ImgurServer : FileServer() {
|
|||||||
|
|
||||||
class NostrBuildServer : FileServer() {
|
class NostrBuildServer : FileServer() {
|
||||||
override fun postUrl(contentType: String?) = "https://nostr.build/api/upload/android.php"
|
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()
|
val url = jacksonObjectMapper().readTree(body) // return url.toString()
|
||||||
return url.toString().replace("\"", "")
|
return url.toString().replace("\"", "")
|
||||||
}
|
}
|
||||||
@@ -181,10 +187,9 @@ class NostrBuildServer : FileServer() {
|
|||||||
|
|
||||||
class NostrFilesDevServer : FileServer() {
|
class NostrFilesDevServer : FileServer() {
|
||||||
override fun postUrl(contentType: String?) = "https://nostrfiles.dev/upload_image"
|
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 tree = jacksonObjectMapper().readTree(body)
|
||||||
val url = tree?.get("url")?.asText()
|
return tree?.get("url")?.asText()
|
||||||
return url
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inputParameterName(contentType: String?): String {
|
override fun inputParameterName(contentType: String?): String {
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
|
|
||||||
open class NewMediaModel : ViewModel() {
|
open class NewMediaModel : ViewModel() {
|
||||||
var account: Account? = null
|
var account: Account? = null
|
||||||
|
|
||||||
@@ -116,19 +118,7 @@ open class NewMediaModel : ViewModel() {
|
|||||||
uploadingDescription.value = "Server Processing"
|
uploadingDescription.value = "Server Processing"
|
||||||
// Images don't seem to be ready immediately after upload
|
// Images don't seem to be ready immediately after upload
|
||||||
|
|
||||||
var imageData: ByteArray? = null
|
val imageData: ByteArray? = ImageDownloader().waitAndGetImage(imageUrl)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadingDescription.value = "Downloading"
|
uploadingDescription.value = "Downloading"
|
||||||
uploadingPercentage.value = 0.60f
|
uploadingPercentage.value = 0.60f
|
||||||
|
|||||||
@@ -110,7 +110,10 @@ fun NewMediaView(uri: Uri, onClose: () -> Unit, postViewModel: NewMediaModel, ac
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isNIP94Server(selectedServer: ServersAvailable?): Boolean {
|
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
|
@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.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.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.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.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.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.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))
|
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) {
|
fun createNIP94Record(imageUrl: String, mimeType: String?, description: String) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
// Images don't seem to be ready immediately after upload
|
// Images don't seem to be ready immediately after upload
|
||||||
|
|
||||||
if (mimeType?.startsWith("image/") == true) {
|
|
||||||
delay(2000)
|
|
||||||
} else {
|
|
||||||
delay(5000)
|
|
||||||
}
|
|
||||||
|
|
||||||
FileHeader.prepare(
|
FileHeader.prepare(
|
||||||
imageUrl,
|
imageUrl,
|
||||||
mimeType,
|
mimeType,
|
||||||
|
|||||||
@@ -259,7 +259,6 @@ private fun UrlImageView(
|
|||||||
content: ZoomableUrlImage,
|
content: ZoomableUrlImage,
|
||||||
mainImageModifier: Modifier
|
mainImageModifier: Modifier
|
||||||
) {
|
) {
|
||||||
println("UrlImageView")
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user