Refactoring the nostr.build uploader

This commit is contained in:
Vitor Pamplona 2023-05-07 18:37:33 -04:00
parent eba14cf9f1
commit cb09a26ef5
5 changed files with 59 additions and 58 deletions

View File

@ -9,7 +9,6 @@ import junit.framework.TestCase.assertNotNull
import junit.framework.TestCase.fail
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import java.util.Base64
@ -21,12 +20,12 @@ class ImageUploadTesting {
@Test()
fun testImgurUpload() = runBlocking {
val inputStream = Base64.getDecoder().decode(image).inputStream()
println("Uploading")
val bytes = Base64.getDecoder().decode(image)
val inputStream = bytes.inputStream()
ImageUploader.uploadImage(
inputStream,
bytes.size.toLong(),
"image/gif",
ImgurServer(),
onSuccess = { url, contentType ->
@ -43,14 +42,13 @@ class ImageUploadTesting {
}
@Test()
@Ignore
fun testNostrBuildUpload() = runBlocking {
val inputStream = Base64.getDecoder().decode(image).inputStream()
println("Uploading")
val bytes = Base64.getDecoder().decode(image)
val inputStream = bytes.inputStream()
ImageUploader.uploadImage(
inputStream,
bytes.size.toLong(),
"image/gif",
NostrBuildServer(),
onSuccess = { url, contentType ->
@ -68,12 +66,12 @@ class ImageUploadTesting {
@Test()
fun testNostrImgUpload() = runBlocking {
val inputStream = Base64.getDecoder().decode(image).inputStream()
println("Uploading")
val bytes = Base64.getDecoder().decode(image)
val inputStream = bytes.inputStream()
ImageUploader.uploadImage(
inputStream,
bytes.size.toLong(),
"image/gif",
NostrImgServer(),
onSuccess = { url, contentType ->

View File

@ -10,7 +10,6 @@ import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.amethyst.BuildConfig
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.asRequestBody
import okio.BufferedSink
import okio.source
import java.io.File
@ -27,13 +26,19 @@ object ImageUploader {
fun uploadImage(
uri: Uri,
server: ServersAvailable,
context: Context,
contentResolver: ContentResolver,
onSuccess: (String, String?) -> Unit,
onError: (Throwable) -> Unit
) {
val contentType = contentResolver.getType(uri)
val imageInputStream = contentResolver.openInputStream(uri)
val length = contentResolver.query(uri, null, null, null, null)?.use {
it.moveToFirst()
val sizeIndex = it.getColumnIndex(OpenableColumns.SIZE)
it.getLong(sizeIndex)
} ?: 0
checkNotNull(imageInputStream) {
"Can't open the image input stream"
}
@ -47,23 +52,17 @@ object ImageUploader {
ImgurServer()
}
val file = getRealPathFromURI(uri, context)?.let { File(it) } // create path from uri
if (file != null) {
uploadImage(file, imageInputStream, contentType, myServer, server, onSuccess, onError)
}
uploadImage(imageInputStream, length, contentType, myServer, onSuccess, onError)
}
fun uploadImage(
file: File,
inputStream: InputStream,
length: Long,
contentType: String?,
server: FileServer,
serverType: ServersAvailable,
onSuccess: (String, String?) -> Unit,
onError: (Throwable) -> Unit
) {
val category = contentType?.toMediaType()?.toString()?.split("/")?.get(0) ?: "image"
val fileName = randomChars()
val extension = contentType?.let { MimeTypeMap.getSingleton().getExtensionFromMimeType(it) } ?: ""
@ -71,35 +70,23 @@ object ImageUploader {
val requestBody: RequestBody
val requestBuilder = Request.Builder()
if (serverType == ServersAvailable.NOSTR_BUILD) {
requestBuilder.addHeader("Content-Type", "multipart/form-data")
requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(
"fileToUpload",
"$fileName.$extension",
file.asRequestBody(contentType?.toMediaType())
requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(
server.inputParameterName(contentType),
"$fileName.$extension",
)
.build()
} else {
requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(
category,
"$fileName.$extension",
object : RequestBody() {
override fun contentType() = contentType?.toMediaType()
object : RequestBody() {
override fun contentType(): MediaType? =
contentType?.toMediaType()
override fun contentLength() = length
override fun writeTo(sink: BufferedSink) {
inputStream.source().use(sink::writeAll)
}
override fun writeTo(sink: BufferedSink) {
inputStream.source().use(sink::writeAll)
}
)
.build()
}
}
)
.build()
server.clientID()?.let {
requestBuilder.addHeader("Authorization", it)
@ -172,6 +159,7 @@ fun getRealPathFromURI(uri: Uri, context: Context): String? {
abstract class FileServer {
abstract fun postUrl(contentType: String?): String
abstract fun parseUrlFromSucess(body: String): String?
abstract fun inputParameterName(contentType: String?): String
open fun clientID(): String? = null
}
@ -185,6 +173,10 @@ class NostrImgServer : FileServer() {
return url
}
override fun inputParameterName(contentType: String?): String {
return contentType?.toMediaType()?.toString()?.split("/")?.get(0) ?: "image"
}
override fun clientID() = null
}
@ -200,6 +192,10 @@ class ImgurServer : FileServer() {
return url
}
override fun inputParameterName(contentType: String?): String {
return contentType?.toMediaType()?.toString()?.split("/")?.get(0) ?: "image"
}
override fun clientID() = "Client-ID e6aea87296f3f96"
}
@ -210,5 +206,9 @@ class NostrBuildServer : FileServer() {
return url.toString().replace("\"", "")
}
override fun inputParameterName(contentType: String?): String {
return "fileToUpload"
}
override fun clientID() = null
}

View File

@ -77,7 +77,6 @@ open class NewMediaModel : ViewModel() {
ImageUploader.uploadImage(
uri = uri,
server = serverToUse,
context = context,
contentResolver = contentResolver,
onSuccess = { imageUrl, mimeType ->
createNIP94Record(imageUrl, mimeType, description)
@ -115,18 +114,24 @@ open class NewMediaModel : ViewModel() {
uploadingDescription.value = "Server Processing"
// Images don't seem to be ready immediately after upload
if (mimeType?.startsWith("image/") == true) {
delay(2000)
} else {
delay(15000)
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
}
}
uploadingDescription.value = "Downloading"
uploadingPercentage.value = 0.60f
try {
val imageData = URL(imageUrl).readBytes()
if (imageData != null) {
uploadingPercentage.value = 0.80f
uploadingDescription.value = "Hashing"
@ -154,8 +159,8 @@ open class NewMediaModel : ViewModel() {
}
}
)
} catch (e: Exception) {
Log.e("ImageDownload", "Couldn't download image from server: ${e.message}")
} else {
Log.e("ImageDownload", "Couldn't download image from server")
cancel()
uploadingPercentage.value = 0.00f
uploadingDescription.value = null

View File

@ -145,7 +145,6 @@ open class NewPostViewModel : ViewModel() {
ImageUploader.uploadImage(
uri = it,
server = server,
context = context,
contentResolver = contentResolver,
onSuccess = { imageUrl, mimeType ->
if (server == ServersAvailable.IMGUR_NIP_94 || server == ServersAvailable.NOSTRIMG_NIP_94 || server == ServersAvailable.NOSTR_BUILD_NIP_94) {

View File

@ -171,7 +171,6 @@ class NewUserMetadataViewModel : ViewModel() {
ImageUploader.uploadImage(
uri = it,
server = account.defaultFileServer,
context = context,
contentResolver = context.contentResolver,
onSuccess = { imageUrl, mimeType ->
onUploading(false)