From 656efc5e7e3242917adbc3fc894808ba1ba99df5 Mon Sep 17 00:00:00 2001 From: camilo cantillo Date: Fri, 20 Feb 2026 12:13:49 -0500 Subject: [PATCH] Using md5 as file key and checks if the file exist --- .gitignore | 3 ++ .../com/cloudcontactai/sdk/mms/MMSModels.kt | 4 ++ .../com/cloudcontactai/sdk/mms/MMSService.kt | 41 ++++++++++++++++++- .../cloudcontactai/sdk/mms/MMSServiceTest.kt | 18 ++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 933d8bc..098621a 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,6 @@ logs npm-debug.log* yarn-debug.log* yarn-error.log* + +# Test files +test-image.jpg diff --git a/src/main/kotlin/com/cloudcontactai/sdk/mms/MMSModels.kt b/src/main/kotlin/com/cloudcontactai/sdk/mms/MMSModels.kt index 35d2164..0767289 100644 --- a/src/main/kotlin/com/cloudcontactai/sdk/mms/MMSModels.kt +++ b/src/main/kotlin/com/cloudcontactai/sdk/mms/MMSModels.kt @@ -41,3 +41,7 @@ data class SignedUploadUrlResponse( val signedS3Url: String, val fileKey: String? = null ) + +data class StoredUrlResponse( + val storedUrl: String +) diff --git a/src/main/kotlin/com/cloudcontactai/sdk/mms/MMSService.kt b/src/main/kotlin/com/cloudcontactai/sdk/mms/MMSService.kt index 3a84849..3d5856e 100644 --- a/src/main/kotlin/com/cloudcontactai/sdk/mms/MMSService.kt +++ b/src/main/kotlin/com/cloudcontactai/sdk/mms/MMSService.kt @@ -9,6 +9,8 @@ import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import java.io.File +import java.io.FileInputStream +import java.security.MessageDigest class MMSService(private val config: CCAIConfig, private val apiClient: ApiClient) { private val httpClient = OkHttpClient() @@ -113,22 +115,57 @@ class MMSService(private val config: CCAIConfig, private val apiClient: ApiClien imageFile: File, senderPhone: String? = null ): MMSResponse { + val md5Image = md5(imageFile) val extension = imageFile.extension.lowercase() + val fileName = "${md5Image}.${extension}" + val fileKey = "${config.clientId}/campaign/${fileName}" + + //Check if the same image has already been uploaded + val storedUrlResponse = checkFileUploaded(fileKey) + if(storedUrlResponse.storedUrl.isNotEmpty()){ + return send(accounts, message, title, fileKey, senderPhone) + } + val contentType = when (extension) { "jpg", "jpeg" -> "image/jpeg" "png" -> "image/png" "gif" -> "image/gif" else -> "image/jpeg" } - val fileName = "${System.currentTimeMillis()}_${imageFile.name}" val uploadRequest = SignedUploadUrlRequest( fileName = fileName, fileType = contentType, publicFile = true ) - val fileKey = "${config.clientId}/campaign/${fileName}" val uploadResponse = getSignedUploadUrl(uploadRequest) uploadImageToSignedUrl(uploadResponse.signedS3Url, imageFile, contentType) return send(accounts, message, title, fileKey, senderPhone) } + + private fun md5(file: File): String { + val digest = MessageDigest.getInstance("MD5") + FileInputStream(file).use { fis -> + val buffer = ByteArray(8192) + var bytesRead: Int + + while (fis.read(buffer).also { bytesRead = it } != -1) { + digest.update(buffer, 0, bytesRead) + } + } + + return digest.digest().joinToString("") { "%02x".format(it) } + } + + fun checkFileUploaded(fileKey: String):StoredUrlResponse{ + return try { + apiClient.request( + method = "GET", + endpoint = "/clients/${config.clientId}/storedUrl?fileKey=${fileKey}", + responseClass = StoredUrlResponse::class.java + ) + } catch (e: Exception) { + e.printStackTrace() + StoredUrlResponse("") + } + } } diff --git a/src/test/kotlin/com/cloudcontactai/sdk/mms/MMSServiceTest.kt b/src/test/kotlin/com/cloudcontactai/sdk/mms/MMSServiceTest.kt index 5e8d3d8..aa33fcc 100644 --- a/src/test/kotlin/com/cloudcontactai/sdk/mms/MMSServiceTest.kt +++ b/src/test/kotlin/com/cloudcontactai/sdk/mms/MMSServiceTest.kt @@ -134,4 +134,22 @@ class MMSServiceTest { assertEquals("mms-single-123", response.campaignId) assertTrue(response.success == true) } + + @Test + fun `should check if file is uploaded and return stored URL`() { + val responseJson = """ + { + "storedUrl": "https://s3.amazonaws.com/bucket/test-client/campaign/image.jpg" + } + """.trimIndent() + + mockServer.enqueue(MockResponse() + .setResponseCode(200) + .setBody(responseJson) + .addHeader("Content-Type", "application/json")) + + val response = client.mms.checkFileUploaded("test-client/campaign/image.jpg") + + assertEquals("https://s3.amazonaws.com/bucket/test-client/campaign/image.jpg", response.storedUrl) + } }