From ddc5c235b3c100603e203534405db41dc8ce1d40 Mon Sep 17 00:00:00 2001 From: Sina Madani Date: Thu, 27 Jun 2024 17:18:28 +0100 Subject: [PATCH] feat: Audio stream endpoints in Voice --- src/main/kotlin/com/vonage/client/kt/Voice.kt | 7 +++ .../com/vonage/client/kt/AbstractTest.kt | 6 ++- .../kotlin/com/vonage/client/kt/VoiceTest.kt | 48 +++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/vonage/client/kt/Voice.kt b/src/main/kotlin/com/vonage/client/kt/Voice.kt index eaa86b1..b71d06b 100644 --- a/src/main/kotlin/com/vonage/client/kt/Voice.kt +++ b/src/main/kotlin/com/vonage/client/kt/Voice.kt @@ -33,6 +33,13 @@ class Voice(private val voiceClient: VoiceClient) { fun transfer(nccoUrl: URI) = transfer(nccoUrl.toString()) fun sendDtmf(digits: String): DtmfResponse = voiceClient.sendDtmf(callId, digits) + + fun streamAudio(streamUrl: String, loop: Int? = null, level: Double? = null): StreamResponse = + if (loop != null && level != null) voiceClient.startStream(callId, streamUrl, loop, level) + else if (loop != null) voiceClient.startStream(callId, streamUrl, loop) + else voiceClient.startStream(callId, streamUrl) + + fun stopStream(): StreamResponse = voiceClient.stopStream(callId) } fun listCalls(filter: (CallsFilter.Builder.() -> Unit)? = null): CallInfoPage = diff --git a/src/test/kotlin/com/vonage/client/kt/AbstractTest.kt b/src/test/kotlin/com/vonage/client/kt/AbstractTest.kt index 9f55bbc..14e0233 100644 --- a/src/test/kotlin/com/vonage/client/kt/AbstractTest.kt +++ b/src/test/kotlin/com/vonage/client/kt/AbstractTest.kt @@ -151,8 +151,10 @@ abstract class AbstractTest { expectedResponseParams: Map? = null) = mockP(HttpMethod.PUT, expectedUrl, expectedRequestParams, status, authType, expectedResponseParams) - protected fun mockDelete(expectedUrl: String, authType: AuthType? = null) = - mockRequest(HttpMethod.DELETE, expectedUrl, authType = authType).mockReturn(204) + protected fun mockDelete(expectedUrl: String, authType: AuthType? = null, + expectedResponseParams: Map? = null) = + mockRequest(HttpMethod.DELETE, expectedUrl, authType = authType) + .mockReturn(if (expectedResponseParams == null) 204 else 200, expectedResponseParams) protected fun mockGet(expectedUrl: String, expectedQueryParams: Map? = null, diff --git a/src/test/kotlin/com/vonage/client/kt/VoiceTest.kt b/src/test/kotlin/com/vonage/client/kt/VoiceTest.kt index c7dc60c..1d8ae7b 100644 --- a/src/test/kotlin/com/vonage/client/kt/VoiceTest.kt +++ b/src/test/kotlin/com/vonage/client/kt/VoiceTest.kt @@ -25,6 +25,7 @@ class VoiceTest : AbstractTest() { private val pageSize = 25 private val recordIndex = 14 private val dtmf = "p*123#" + private val streamUrl = "https://example.com/waiting.mp3" private val callResponseMap = mapOf( "_links" to mapOf( "self" to mapOf( @@ -113,6 +114,30 @@ class VoiceTest : AbstractTest() { invocation.invoke() } + private fun testStream(loop: Int = 1, level: Double = 0.0, invocation: (() -> StreamResponse)? = null) { + + val message = "Stream ${if (invocation == null) "stopped" else "started"}" + val expectedResponseParams = mapOf("message" to message, "uuid" to callIdStr) + val expectedUrl = "$callUrl/stream" + val response = if (invocation == null) { + mockDelete(expectedUrl, expectedResponseParams = expectedResponseParams) + callObj.stopStream() + } + else { + mockPut(expectedUrl, status = 200, + expectedRequestParams = mapOf( + "stream_url" to listOf(streamUrl), + "loop" to loop, "level" to level + ), + expectedResponseParams = expectedResponseParams + ) + invocation.invoke() + } + assertNotNull(response) + assertEquals(message, response.message) + assertEquals(callIdStr, response.uuid) + } + @Test fun `terminate call`() { testModifyCall("hangup", callObj::hangup) @@ -173,6 +198,29 @@ class VoiceTest : AbstractTest() { assertEquals(callIdStr, response.uuid) } + @Test + fun `stream audio into call`() { + val loop = 3 + val level = 0.45 + testStream { + callObj.streamAudio(streamUrl) + } + testStream(loop = loop) { + callObj.streamAudio(streamUrl, loop) + } + testStream(level = level) { + callObj.streamAudio(streamUrl, level = level) + } + testStream(loop = loop, level = level) { + callObj.streamAudio(streamUrl, loop = loop, level = level) + } + } + + @Test + fun `stop audio stream`() { + testStream() + } + @Test fun `list calls all filter parameters`() { mockGet(callsBaseUrl, expectedQueryParams = mapOf(