From 7224ad4b05fc3dd79bae51bd8b1d1a0a7d31052e Mon Sep 17 00:00:00 2001 From: Believethehype Date: Wed, 3 May 2023 00:48:01 +0200 Subject: [PATCH] image upload works to nostr.build --- .../amethyst/ui/actions/ImageUploader.kt | 106 +++++++++++++----- .../amethyst/ui/actions/NewMediaModel.kt | 1 + .../amethyst/ui/actions/NewPostViewModel.kt | 1 + .../ui/actions/NewUserMetadataViewModel.kt | 1 + 4 files changed, 81 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageUploader.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageUploader.kt index be6095797..766056a87 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageUploader.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageUploader.kt @@ -1,14 +1,20 @@ package com.vitorpamplona.amethyst.ui.actions import android.content.ContentResolver +import android.content.Context import android.net.Uri +import android.provider.OpenableColumns +import android.util.Log import android.webkit.MimeTypeMap 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 +import java.io.FileOutputStream import java.io.IOException import java.io.InputStream @@ -21,13 +27,13 @@ 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) - checkNotNull(imageInputStream) { "Can't open the image input stream" } @@ -41,10 +47,14 @@ object ImageUploader { ImgurServer() } - uploadImage(imageInputStream, contentType, myServer, server, onSuccess, onError) + val file = getRealPathFromURI(uri, context)?.let { File(it) } // create path from uri + if (file != null) { + uploadImage(file, imageInputStream, contentType, myServer, server, onSuccess, onError) + } } fun uploadImage( + file: File, inputStream: InputStream, contentType: String?, server: FileServer, @@ -52,38 +62,47 @@ object ImageUploader { onSuccess: (String, String?) -> Unit, onError: (Throwable) -> Unit ) { - var category = "fileToUpload" - if (serverType != ServersAvailable.NOSTR_BUILD) { - category = contentType?.toMediaType()?.toString()?.split("/")?.get(0) ?: "image" - } + val category = contentType?.toMediaType()?.toString()?.split("/")?.get(0) ?: "image" + val fileName = randomChars() val extension = contentType?.let { MimeTypeMap.getSingleton().getExtensionFromMimeType(it) } ?: "" val client = OkHttpClient.Builder().build() - - val requestBody: RequestBody = MultipartBody.Builder() - .setType(MultipartBody.FORM) - .addFormDataPart( - category, - "$fileName.$extension", - object : RequestBody() { - override fun contentType(): MediaType? = - contentType?.toMediaType() - - override fun writeTo(sink: BufferedSink) { - inputStream.source().use(sink::writeAll) - } - } - ) - .build() - + val requestBody: RequestBody val requestBuilder = Request.Builder() - server.clientID()?.let { - requestBuilder.addHeader("Authorization", it) - } 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()) + + ) + .build() + } else { + requestBody = MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart( + category, + "$fileName.$extension", + + object : RequestBody() { + override fun contentType(): MediaType? = + contentType?.toMediaType() + + override fun writeTo(sink: BufferedSink) { + inputStream.source().use(sink::writeAll) + } + } + ) + .build() + } + + server.clientID()?.let { + requestBuilder.addHeader("Authorization", it) } requestBuilder @@ -118,6 +137,38 @@ object ImageUploader { } } +fun getRealPathFromURI(uri: Uri, context: Context): String? { + val returnCursor = context.contentResolver.query(uri, null, null, null, null) + val nameIndex = returnCursor!!.getColumnIndex(OpenableColumns.DISPLAY_NAME) + returnCursor.moveToFirst() + val name = returnCursor.getString(nameIndex) + val file = File(context.filesDir, name) + try { + val inputStream: InputStream? = context.contentResolver.openInputStream(uri) + val outputStream = FileOutputStream(file) + var read = 0 + val maxBufferSize = 1 * 1024 * 1024 + val bytesAvailable: Int = inputStream?.available() ?: 0 + val bufferSize = Math.min(bytesAvailable, maxBufferSize) + val buffers = ByteArray(bufferSize) + while (inputStream?.read(buffers).also { + if (it != null) { + read = it + } + } != -1 + ) { + outputStream.write(buffers, 0, read) + } + Log.e("File Size", "Size " + file.length()) + inputStream?.close() + outputStream.close() + Log.e("File Path", "Path " + file.path) + } catch (e: java.lang.Exception) { + Log.e("Exception", e.message!!) + } + return file.path +} + abstract class FileServer { abstract fun postUrl(contentType: String?): String abstract fun parseUrlFromSucess(body: String): String? @@ -154,9 +205,8 @@ class ImgurServer : FileServer() { class NostrBuildServer : FileServer() { override fun postUrl(contentType: String?) = "https://nostr.build/api/upload/android.php" - override fun parseUrlFromSucess(body: String): String? { - val url = jacksonObjectMapper().readTree(body) + val url = jacksonObjectMapper().readTree(body) // return url.toString() return url.toString().replace("\"", "") } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt index 880192257..b21629737 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt @@ -75,6 +75,7 @@ open class NewMediaModel : ViewModel() { ImageUploader.uploadImage( uri = uri, server = serverToUse, + context = context, contentResolver = contentResolver, onSuccess = { imageUrl, mimeType -> createNIP94Record(imageUrl, mimeType, description) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt index fd38e3031..c5353035c 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt @@ -145,6 +145,7 @@ 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) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt index 269f22871..80abdf2cf 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt @@ -171,6 +171,7 @@ class NewUserMetadataViewModel : ViewModel() { ImageUploader.uploadImage( uri = it, server = account.defaultFileServer, + context = context, contentResolver = context.contentResolver, onSuccess = { imageUrl, mimeType -> onUploading(false)