mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2024-09-30 00:40:49 +00:00
Merge pull request #391 from believethehype/nostrbuild
Added example for Image upload on nostr.build
This commit is contained in:
commit
771bb3fc27
@ -1,14 +1,20 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.actions
|
package com.vitorpamplona.amethyst.ui.actions
|
||||||
|
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.provider.OpenableColumns
|
||||||
|
import android.util.Log
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
import com.vitorpamplona.amethyst.BuildConfig
|
import com.vitorpamplona.amethyst.BuildConfig
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
import okio.BufferedSink
|
import okio.BufferedSink
|
||||||
import okio.source
|
import okio.source
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
@ -21,46 +27,68 @@ object ImageUploader {
|
|||||||
fun uploadImage(
|
fun uploadImage(
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
server: ServersAvailable,
|
server: ServersAvailable,
|
||||||
|
context: Context,
|
||||||
contentResolver: ContentResolver,
|
contentResolver: ContentResolver,
|
||||||
onSuccess: (String, String?) -> Unit,
|
onSuccess: (String, String?) -> Unit,
|
||||||
onError: (Throwable) -> Unit
|
onError: (Throwable) -> Unit
|
||||||
) {
|
) {
|
||||||
val contentType = contentResolver.getType(uri)
|
val contentType = contentResolver.getType(uri)
|
||||||
val imageInputStream = contentResolver.openInputStream(uri)
|
val imageInputStream = contentResolver.openInputStream(uri)
|
||||||
|
|
||||||
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 = if (server == ServersAvailable.IMGUR) {
|
||||||
ImgurServer()
|
ImgurServer()
|
||||||
} else if (server == ServersAvailable.NOSTRIMG) {
|
} else if (server == ServersAvailable.NOSTRIMG) {
|
||||||
NostrImgServer()
|
NostrImgServer()
|
||||||
|
} else if (server == ServersAvailable.NOSTR_BUILD) {
|
||||||
|
NostrBuildServer()
|
||||||
} else {
|
} else {
|
||||||
ImgurServer()
|
ImgurServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadImage(imageInputStream, contentType, myServer, 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(
|
fun uploadImage(
|
||||||
|
file: File,
|
||||||
inputStream: InputStream,
|
inputStream: InputStream,
|
||||||
contentType: String?,
|
contentType: String?,
|
||||||
server: FileServer,
|
server: FileServer,
|
||||||
|
serverType: ServersAvailable,
|
||||||
onSuccess: (String, String?) -> Unit,
|
onSuccess: (String, String?) -> Unit,
|
||||||
onError: (Throwable) -> Unit
|
onError: (Throwable) -> Unit
|
||||||
) {
|
) {
|
||||||
val category = contentType?.toMediaType()?.toString()?.split("/")?.get(0) ?: "image"
|
val category = contentType?.toMediaType()?.toString()?.split("/")?.get(0) ?: "image"
|
||||||
|
|
||||||
val fileName = randomChars()
|
val fileName = randomChars()
|
||||||
val extension = contentType?.let { MimeTypeMap.getSingleton().getExtensionFromMimeType(it) } ?: ""
|
val extension = contentType?.let { MimeTypeMap.getSingleton().getExtensionFromMimeType(it) } ?: ""
|
||||||
|
|
||||||
val client = OkHttpClient.Builder().build()
|
val client = OkHttpClient.Builder().build()
|
||||||
|
val requestBody: RequestBody
|
||||||
|
val requestBuilder = Request.Builder()
|
||||||
|
|
||||||
val requestBody: RequestBody = MultipartBody.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())
|
||||||
|
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
} else {
|
||||||
|
requestBody = MultipartBody.Builder()
|
||||||
.setType(MultipartBody.FORM)
|
.setType(MultipartBody.FORM)
|
||||||
.addFormDataPart(
|
.addFormDataPart(
|
||||||
category,
|
category,
|
||||||
"$fileName.$extension",
|
"$fileName.$extension",
|
||||||
|
|
||||||
object : RequestBody() {
|
object : RequestBody() {
|
||||||
override fun contentType(): MediaType? =
|
override fun contentType(): MediaType? =
|
||||||
contentType?.toMediaType()
|
contentType?.toMediaType()
|
||||||
@ -71,18 +99,16 @@ object ImageUploader {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
|
}
|
||||||
val requestBuilder = Request.Builder()
|
|
||||||
|
|
||||||
server.clientID()?.let {
|
server.clientID()?.let {
|
||||||
requestBuilder.header("Authorization", it)
|
requestBuilder.addHeader("Authorization", it)
|
||||||
}
|
}
|
||||||
|
|
||||||
requestBuilder
|
requestBuilder
|
||||||
.header("User-Agent", "Amethyst/${BuildConfig.VERSION_NAME}")
|
.addHeader("User-Agent", "Amethyst/${BuildConfig.VERSION_NAME}")
|
||||||
.url(server.postUrl(contentType))
|
.url(server.postUrl(contentType))
|
||||||
.post(requestBody)
|
.post(requestBody)
|
||||||
|
|
||||||
val request = requestBuilder.build()
|
val request = requestBuilder.build()
|
||||||
|
|
||||||
client.newCall(request).enqueue(object : Callback {
|
client.newCall(request).enqueue(object : Callback {
|
||||||
@ -111,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 class FileServer {
|
||||||
abstract fun postUrl(contentType: String?): String
|
abstract fun postUrl(contentType: String?): String
|
||||||
abstract fun parseUrlFromSucess(body: String): String?
|
abstract fun parseUrlFromSucess(body: String): String?
|
||||||
@ -146,12 +204,10 @@ class ImgurServer : FileServer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class NostrBuildServer : FileServer() {
|
class NostrBuildServer : FileServer() {
|
||||||
override fun postUrl(contentType: String?) = "https://nostr.build/api/upload/amethyst.php"
|
override fun postUrl(contentType: String?) = "https://nostr.build/api/upload/android.php"
|
||||||
|
|
||||||
override fun parseUrlFromSucess(body: String): String? {
|
override fun parseUrlFromSucess(body: String): String? {
|
||||||
val tree = jacksonObjectMapper().readTree(body)
|
val url = jacksonObjectMapper().readTree(body) // return url.toString()
|
||||||
val url = tree?.get("data")?.get("link")?.asText()
|
return url.toString().replace("\"", "")
|
||||||
return url
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clientID() = null
|
override fun clientID() = null
|
||||||
|
@ -44,6 +44,8 @@ open class NewMediaModel : ViewModel() {
|
|||||||
selectedServer = ServersAvailable.IMGUR_NIP_94
|
selectedServer = ServersAvailable.IMGUR_NIP_94
|
||||||
} else if (selectedServer == ServersAvailable.NOSTRIMG) {
|
} else if (selectedServer == ServersAvailable.NOSTRIMG) {
|
||||||
selectedServer = ServersAvailable.NOSTRIMG_NIP_94
|
selectedServer = ServersAvailable.NOSTRIMG_NIP_94
|
||||||
|
} else if (selectedServer == ServersAvailable.NOSTR_BUILD) {
|
||||||
|
selectedServer = ServersAvailable.NOSTR_BUILD_NIP_94
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +77,7 @@ open class NewMediaModel : ViewModel() {
|
|||||||
ImageUploader.uploadImage(
|
ImageUploader.uploadImage(
|
||||||
uri = uri,
|
uri = uri,
|
||||||
server = serverToUse,
|
server = serverToUse,
|
||||||
|
context = context,
|
||||||
contentResolver = contentResolver,
|
contentResolver = contentResolver,
|
||||||
onSuccess = { imageUrl, mimeType ->
|
onSuccess = { imageUrl, mimeType ->
|
||||||
createNIP94Record(imageUrl, mimeType, description)
|
createNIP94Record(imageUrl, mimeType, description)
|
||||||
|
@ -116,6 +116,7 @@ fun ImageVideoPost(postViewModel: NewMediaModel, acc: Account) {
|
|||||||
val fileServers = listOf(
|
val fileServers = listOf(
|
||||||
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.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))
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -192,6 +193,7 @@ fun ImageVideoPost(postViewModel: NewMediaModel, acc: Account) {
|
|||||||
|
|
||||||
if (postViewModel.selectedServer == ServersAvailable.NOSTRIMG_NIP_94 ||
|
if (postViewModel.selectedServer == ServersAvailable.NOSTRIMG_NIP_94 ||
|
||||||
postViewModel.selectedServer == ServersAvailable.IMGUR_NIP_94 ||
|
postViewModel.selectedServer == ServersAvailable.IMGUR_NIP_94 ||
|
||||||
|
postViewModel.selectedServer == ServersAvailable.NOSTR_BUILD_NIP_94 ||
|
||||||
postViewModel.selectedServer == ServersAvailable.NIP95
|
postViewModel.selectedServer == ServersAvailable.NIP95
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
@ -590,6 +590,7 @@ enum class ServersAvailable {
|
|||||||
NOSTRIMG,
|
NOSTRIMG,
|
||||||
IMGUR_NIP_94,
|
IMGUR_NIP_94,
|
||||||
NOSTRIMG_NIP_94,
|
NOSTRIMG_NIP_94,
|
||||||
|
NOSTR_BUILD_NIP_94,
|
||||||
NIP95
|
NIP95
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,8 +611,10 @@ fun ImageVideoDescription(
|
|||||||
val fileServers = listOf(
|
val fileServers = listOf(
|
||||||
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.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.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))
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -741,6 +744,7 @@ fun ImageVideoDescription(
|
|||||||
|
|
||||||
if (selectedServer == ServersAvailable.NOSTRIMG_NIP_94 ||
|
if (selectedServer == ServersAvailable.NOSTRIMG_NIP_94 ||
|
||||||
selectedServer == ServersAvailable.IMGUR_NIP_94 ||
|
selectedServer == ServersAvailable.IMGUR_NIP_94 ||
|
||||||
|
selectedServer == ServersAvailable.NOSTR_BUILD_NIP_94 ||
|
||||||
selectedServer == ServersAvailable.NIP95
|
selectedServer == ServersAvailable.NIP95
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
@ -145,9 +145,10 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
ImageUploader.uploadImage(
|
ImageUploader.uploadImage(
|
||||||
uri = it,
|
uri = it,
|
||||||
server = server,
|
server = server,
|
||||||
|
context = context,
|
||||||
contentResolver = contentResolver,
|
contentResolver = contentResolver,
|
||||||
onSuccess = { imageUrl, mimeType ->
|
onSuccess = { imageUrl, mimeType ->
|
||||||
if (server == ServersAvailable.IMGUR_NIP_94 || server == ServersAvailable.NOSTRIMG_NIP_94) {
|
if (server == ServersAvailable.IMGUR_NIP_94 || server == ServersAvailable.NOSTRIMG_NIP_94 || server == ServersAvailable.NOSTR_BUILD_NIP_94) {
|
||||||
createNIP94Record(imageUrl, mimeType, description)
|
createNIP94Record(imageUrl, mimeType, description)
|
||||||
} else {
|
} else {
|
||||||
isUploadingImage = false
|
isUploadingImage = false
|
||||||
|
@ -171,6 +171,7 @@ class NewUserMetadataViewModel : ViewModel() {
|
|||||||
ImageUploader.uploadImage(
|
ImageUploader.uploadImage(
|
||||||
uri = it,
|
uri = it,
|
||||||
server = account.defaultFileServer,
|
server = account.defaultFileServer,
|
||||||
|
context = context,
|
||||||
contentResolver = context.contentResolver,
|
contentResolver = context.contentResolver,
|
||||||
onSuccess = { imageUrl, mimeType ->
|
onSuccess = { imageUrl, mimeType ->
|
||||||
onUploading(false)
|
onUploading(false)
|
||||||
|
@ -333,12 +333,18 @@
|
|||||||
<string name="upload_server_nostrimg">nostrimg.com - less secure</string>
|
<string name="upload_server_nostrimg">nostrimg.com - less secure</string>
|
||||||
<string name="upload_server_nostrimg_explainer">Uploads to NostrImg. NostrImg can change your image at any time</string>
|
<string name="upload_server_nostrimg_explainer">Uploads to NostrImg. NostrImg can change your image at any time</string>
|
||||||
|
|
||||||
|
<string name="upload_server_nostrbuild">nostr.build- less secure</string>
|
||||||
|
<string name="upload_server_nostrbuild_explainer">Uploads to nostr.build. Nostr.build can change your image at any time</string>
|
||||||
|
|
||||||
<string name="upload_server_imgur_nip94">Verifiable Imgur (NIP-94)</string>
|
<string name="upload_server_imgur_nip94">Verifiable Imgur (NIP-94)</string>
|
||||||
<string name="upload_server_imgur_nip94_explainer">Protects from Imgur modifying the content afterwards. This is a new NIP: other clients might not see the image</string>
|
<string name="upload_server_imgur_nip94_explainer">Protects from Imgur modifying the content afterwards. This is a new NIP: other clients might not see the image</string>
|
||||||
|
|
||||||
<string name="upload_server_nostrimg_nip94">Verifiable NostrImg (NIP-94)</string>
|
<string name="upload_server_nostrimg_nip94">Verifiable NostrImg (NIP-94)</string>
|
||||||
<string name="upload_server_nostrimg_nip94_explainer">Protects from NostrImg modifying the content afterwards. This is a new NIP: other clients might not see the image</string>
|
<string name="upload_server_nostrimg_nip94_explainer">Protects from NostrImg modifying the content afterwards. This is a new NIP: other clients might not see the image</string>
|
||||||
|
|
||||||
|
<string name="upload_server_nostrbuild_nip94">Verifiable Nostr.build (NIP-94)</string>
|
||||||
|
<string name="upload_server_nostrbuild_nip94_explainer">Protects from Nostr.build modifying the content afterwards. This is a new NIP: other clients might not see the image</string>
|
||||||
|
|
||||||
<string name="upload_server_relays_nip95">Your relays (NIP-95)</string>
|
<string name="upload_server_relays_nip95">Your relays (NIP-95)</string>
|
||||||
<string name="upload_server_relays_nip95_explainer">Files are uploaded to and hosted by relays. They are free from a fixed url (third-party dependency). Make sure to have a NIP-95 relay in your relay list</string>
|
<string name="upload_server_relays_nip95_explainer">Files are uploaded to and hosted by relays. They are free from a fixed url (third-party dependency). Make sure to have a NIP-95 relay in your relay list</string>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user