diff --git a/README.md b/README.md index 4e806e4..eb13aff 100644 --- a/README.md +++ b/README.md @@ -307,7 +307,23 @@ suspend fun downloadAttachment(attachmentId: String, filename: String): Result +``` +* `attachmentId` + * The ID of the attachment. + * Type: `String` +* Return result type: `URL` + * This return URL points to the S3 download URL of the attachment. + -------------------- ### ChatSession Events diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/ChatSession.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/ChatSession.kt index 53eca6d..438247d 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/ChatSession.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/ChatSession.kt @@ -74,6 +74,13 @@ interface ChatSession { */ suspend fun downloadAttachment(attachmentId: String, filename: String): Result + /** + * Returns the S3 download URL for an attachment. + * @param attachmentId The ID of the attachment. + * @return A Result containing the download URL for the attachment. + */ + suspend fun getAttachmentDownloadUrl(attachmentId: String): Result + /** * Gets the transcript. * @param scanDirection The direction of the scan. @@ -220,6 +227,14 @@ class ChatSessionImpl @Inject constructor(private val chatService: ChatService) } } + override suspend fun getAttachmentDownloadUrl(attachmentId: String): Result { + return withContext(Dispatchers.IO) { + runCatching { + chatService.getAttachmentDownloadUrl(attachmentId).getOrThrow() + } + } + } + override suspend fun getTranscript( scanDirection: ScanDirection?, sortKey: SortKey?, diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/network/AttachmentsManager.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/network/AttachmentsManager.kt index 4e4318b..80608ee 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/network/AttachmentsManager.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/network/AttachmentsManager.kt @@ -68,6 +68,7 @@ class AttachmentsManager @Inject constructor( } suspend fun completeAttachmentUpload(connectionToken: String, attachmentId: String) { + print("HIT!!") val request = CompleteAttachmentUploadRequest().apply { this.connectionToken = connectionToken this.setAttachmentIds(listOf(attachmentId)) @@ -110,9 +111,9 @@ class AttachmentsManager @Inject constructor( } suspend fun downloadAttachment( + connectionToken: String, attachmentId: String, fileName: String, - connectionToken: String ): Result { return getAttachmentDownloadUrl(connectionToken, attachmentId).mapCatching { url -> downloadFile(url, fileName).getOrThrow() @@ -121,7 +122,7 @@ class AttachmentsManager @Inject constructor( } } - private suspend fun getAttachmentDownloadUrl(connectionToken: String, attachmentId: String): Result { + suspend fun getAttachmentDownloadUrl(connectionToken: String, attachmentId: String): Result { return runCatching { val response = awsClient.getAttachment(connectionToken, attachmentId) URL(response.getOrNull()?.url ?: throw IOException("Invalid URL")) @@ -130,7 +131,7 @@ class AttachmentsManager @Inject constructor( } } - private suspend fun downloadFile(url: URL, fileName: String): Result = withContext(Dispatchers.IO) { + suspend fun downloadFile(url: URL, fileName: String): Result = withContext(Dispatchers.IO) { runCatching { val connection = url.openConnection() as HttpURLConnection connection.requestMethod = "GET" diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/repository/ChatService.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/repository/ChatService.kt index ffeaaaa..94a3d37 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/repository/ChatService.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/repository/ChatService.kt @@ -98,6 +98,14 @@ interface ChatService { */ suspend fun downloadAttachment(attachmentId: String, fileName: String): Result + + /** + * Returns the S3 download URL for an attachment. + * @param attachmentId The ID of the attachment. + * @return A Result containing the download URL for the attachment. + */ + suspend fun getAttachmentDownloadUrl(attachmentId: String): Result + /** * Gets the transcript. * @param scanDirection The direction of the scan. @@ -590,9 +598,19 @@ class ChatServiceImpl @Inject constructor( return runCatching { val connectionDetails = connectionDetailsProvider.getConnectionDetails() ?: throw Exception("No connection details available") - attachmentsManager.downloadAttachment(attachmentId, fileName, connectionDetails.connectionToken).getOrThrow() + attachmentsManager.downloadAttachment(connectionDetails.connectionToken, attachmentId, fileName).getOrThrow() + }.onFailure { exception -> + SDKLogger.logger.logError { "Failed to download attachment for attachmentId $attachmentId. Error: ${exception.message}" } + } + } + + override suspend fun getAttachmentDownloadUrl(attachmentId: String): Result { + return runCatching { + val connectionDetails = connectionDetailsProvider.getConnectionDetails() + ?: throw Exception("No connection details available") + attachmentsManager.getAttachmentDownloadUrl(attachmentId, connectionDetails.connectionToken).getOrThrow() }.onFailure { exception -> - SDKLogger.logger.logError { "Failed to download attachment: ${exception.message}" } + SDKLogger.logger.logError { "Failed to retrieve attachment download URL for attachment $attachmentId. Error: ${exception.message}" } } } diff --git a/chat-sdk/src/test/java/com/amazon/connect/chat/sdk/network/AttachmentsManagerTest.kt b/chat-sdk/src/test/java/com/amazon/connect/chat/sdk/network/AttachmentsManagerTest.kt index c7e8f05..2328e32 100644 --- a/chat-sdk/src/test/java/com/amazon/connect/chat/sdk/network/AttachmentsManagerTest.kt +++ b/chat-sdk/src/test/java/com/amazon/connect/chat/sdk/network/AttachmentsManagerTest.kt @@ -7,6 +7,7 @@ import com.amazon.connect.chat.sdk.utils.Constants import com.amazonaws.services.connectparticipant.AmazonConnectParticipantClient import com.amazonaws.services.connectparticipant.model.CompleteAttachmentUploadRequest import com.amazonaws.services.connectparticipant.model.CompleteAttachmentUploadResult +import com.amazonaws.services.connectparticipant.model.GetAttachmentResult import com.amazonaws.services.connectparticipant.model.StartAttachmentUploadRequest import com.amazonaws.services.connectparticipant.model.StartAttachmentUploadResult import com.amazonaws.services.connectparticipant.model.UploadMetadata @@ -33,6 +34,7 @@ import org.robolectric.RobolectricTestRunner import java.io.File import java.io.FileInputStream import java.io.InputStream +import java.net.URL import retrofit2.Response as RetrofitResponse @ExperimentalCoroutinesApi @@ -56,6 +58,7 @@ class AttachmentsManagerTest { private val contentResolver = mock(ContentResolver::class.java) private val mockStartAttachmentUploadRequest = StartAttachmentUploadRequest() private val mockStartAttachmentUploadResult = StartAttachmentUploadResult() + private val mockGetAttachmentResult = GetAttachmentResult() private val mockUri: Uri = Uri.parse("https://example.com/dummy") private val mockAttachmentId = "12345" @@ -63,6 +66,7 @@ class AttachmentsManagerTest { private val mockUrl = "https://example.com/" private val mockHeadersToInclude = mapOf("key1" to "value1", "key2" to "value2", "key3" to "value3") private val mockConnectionToken = "connectionToken" + private val mockFilename = "example.txt" @Before fun setUp() { @@ -178,6 +182,19 @@ class AttachmentsManagerTest { File("test").deleteRecursively() } + @Test + fun test_downloadAttachment() = runTest { + mockGetAttachmentResult.url = mockUrl + doReturn(mockGetAttachmentResult) + .`when`(awsClient) + .getAttachment(mockConnectionToken, mockAttachmentId) + + attachmentsManager.downloadAttachment(mockConnectionToken, mockAttachmentId, mockFilename) + verify(awsClient).getAttachment(mockConnectionToken, mockAttachmentId) + verify(attachmentsManager).getAttachmentDownloadUrl(mockConnectionToken, mockAttachmentId) + verify(attachmentsManager).downloadFile(URL(mockUrl), mockFilename) + } + @Test fun test_getFileExtension() = runTest { for (extension in Constants.attachmentTypeMap.keys) { diff --git a/chat-sdk/src/test/java/com/amazon/connect/chat/sdk/repository/ChatServiceImplTest.kt b/chat-sdk/src/test/java/com/amazon/connect/chat/sdk/repository/ChatServiceImplTest.kt index 0cf5360..ba05967 100644 --- a/chat-sdk/src/test/java/com/amazon/connect/chat/sdk/repository/ChatServiceImplTest.kt +++ b/chat-sdk/src/test/java/com/amazon/connect/chat/sdk/repository/ChatServiceImplTest.kt @@ -326,13 +326,13 @@ class ChatServiceImplTest { val mockConnectionDetails = createMockConnectionDetails("valid_token") `when`(connectionDetailsProvider.getConnectionDetails()).thenReturn(mockConnectionDetails) - `when`(attachmentsManager.downloadAttachment(attachmentId, fileName, mockConnectionDetails.connectionToken)).thenReturn(Result.success(mockUrl)) + `when`(attachmentsManager.downloadAttachment(mockConnectionDetails.connectionToken, attachmentId, fileName)).thenReturn(Result.success(mockUrl)) val result = chatService.downloadAttachment(attachmentId, fileName) assertTrue(result.isSuccess) assertEquals(mockUrl, result.getOrNull()) - verify(attachmentsManager).downloadAttachment(attachmentId, fileName, mockConnectionDetails.connectionToken) + verify(attachmentsManager).downloadAttachment(mockConnectionDetails.connectionToken, attachmentId, fileName) } @Test @@ -342,12 +342,12 @@ class ChatServiceImplTest { val mockConnectionDetails = createMockConnectionDetails("valid_token") `when`(connectionDetailsProvider.getConnectionDetails()).thenReturn(mockConnectionDetails) - `when`(attachmentsManager.downloadAttachment(attachmentId, fileName, mockConnectionDetails.connectionToken)).thenThrow(RuntimeException("Download error")) + `when`(attachmentsManager.downloadAttachment(mockConnectionDetails.connectionToken, attachmentId, fileName)).thenThrow(RuntimeException("Download error")) val result = chatService.downloadAttachment(attachmentId, fileName) assertTrue(result.isFailure) - verify(attachmentsManager).downloadAttachment(attachmentId, fileName, mockConnectionDetails.connectionToken) + verify(attachmentsManager).downloadAttachment(mockConnectionDetails.connectionToken, attachmentId, fileName) } @Test