Skip to content

Commit 3a55560

Browse files
authored
feat: Add MMS text/file/content messages (#27)
1 parent 6191d72 commit 3a55560

File tree

8 files changed

+118
-21
lines changed

8 files changed

+118
-21
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## [1.2.0] - 2025-03-05
8+
9+
### Added
10+
- Support for MMS text, file and multimedia content types in `Messages`
11+
12+
### Changed
13+
- Bumped Java SDK version to 8.18.0
14+
715
## [1.1.4] - 2025-02-28
816

917
### Added

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ See all of our SDKs and integrations on the [Vonage Developer portal](https://de
5353
## Installation
5454
Releases are published to [Maven Central](https://central.sonatype.com/artifact/com.vonage/server-sdk-kotlin).
5555
Instructions for your build system can be found in the snippets section.
56-
They're also available from [here](https://search.maven.org/artifact/com.vonage/server-sdk-kotlin/1.1.4/jar).
56+
They're also available from [here](https://search.maven.org/artifact/com.vonage/server-sdk-kotlin/1.2.0/jar).
5757
Release notes for each version can be found in the [changelog](CHANGELOG.md).
5858

5959
Here are the instructions for including the SDK in your project:
@@ -63,7 +63,7 @@ Add the following to your `build.gradle` or `build.gradle.kts` file:
6363

6464
```groovy
6565
dependencies {
66-
implementation("com.vonage:server-sdk-kotlin:1.1.4")
66+
implementation("com.vonage:server-sdk-kotlin:1.2.0")
6767
}
6868
```
6969

@@ -74,7 +74,7 @@ Add the following to the `<dependencies>` section of your `pom.xml` file:
7474
<dependency>
7575
<groupId>com.vonage</groupId>
7676
<artifactId>server-sdk-kotlin</artifactId>
77-
<version>1.1.4</version>
77+
<version>1.2.0</version>
7878
</dependency>
7979
```
8080

@@ -160,8 +160,8 @@ including [**a searchable list of snippets**](https://github.com/Vonage/vonage-k
160160

161161
The SDK is fully documented with [KDocs](https://kotlinlang.org/docs/kotlin-doc.html), so you should have complete
162162
documentation from your IDE. You may need to click "Download Sources" in IntelliJ to get the full documentation.
163-
Alternatively, you can browse the documentation using a service like [Javadoc.io](https://javadoc.io/doc/com.vonage/server-sdk-kotlin/1.1.4/index.html),
164-
which renders the documentation for you from [the artifacts on Maven Central](https://repo.maven.apache.org/maven2/com/vonage/server-sdk-kotlin/1.1.4/).
163+
Alternatively, you can browse the documentation using a service like [Javadoc.io](https://javadoc.io/doc/com.vonage/server-sdk-kotlin/1.2.0/index.html),
164+
which renders the documentation for you from [the artifacts on Maven Central](https://repo.maven.apache.org/maven2/com/vonage/server-sdk-kotlin/1.2.0/).
165165

166166
For help with any specific APIs, refer to the relevant documentation on our [developer portal](https://developer.vonage.com/en/documentation),
167167
using the links provided in the [Supported APIs](#supported-apis) section. For completeness, you can also consult the

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>com.vonage</groupId>
77
<artifactId>server-sdk-kotlin</artifactId>
8-
<version>1.1.4</version>
8+
<version>1.2.0</version>
99

1010
<name>Vonage Kotlin Server SDK</name>
1111
<description>Kotlin client for Vonage APIs</description>
@@ -55,7 +55,7 @@
5555
<dependency>
5656
<groupId>com.vonage</groupId>
5757
<artifactId>server-sdk</artifactId>
58-
<version>8.17.0</version>
58+
<version>8.18.0</version>
5959
</dependency>
6060
<dependency>
6161
<groupId>org.jetbrains.kotlin</groupId>
@@ -77,7 +77,7 @@
7777
<dependency>
7878
<groupId>org.wiremock</groupId>
7979
<artifactId>wiremock-standalone</artifactId>
80-
<version>3.12.0</version>
80+
<version>3.12.1</version>
8181
<scope>test</scope>
8282
</dependency>
8383
</dependencies>

src/main/kotlin/com/vonage/client/kt/Messages.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,18 @@ class Messages internal constructor(private val client: MessagesClient) {
113113
fun smsText(properties: SmsTextRequest.Builder.() -> Unit): SmsTextRequest =
114114
SmsTextRequest.builder().apply(properties).build()
115115

116+
/**
117+
* Create an MMS text message.
118+
*
119+
* @param properties A lambda function for setting the message's parameters.
120+
*
121+
* @return An [MmsTextRequest] object with the specified properties.
122+
*
123+
* @since 1.2.0
124+
*/
125+
fun mmsText(properties: MmsTextRequest.Builder.() -> Unit): MmsTextRequest =
126+
MmsTextRequest.builder().apply(properties).build()
127+
116128
/**
117129
* Creates an MMS vCard message.
118130
*
@@ -153,6 +165,30 @@ fun mmsAudio(properties: MmsAudioRequest.Builder.() -> Unit): MmsAudioRequest =
153165
fun mmsVideo(properties: MmsVideoRequest.Builder.() -> Unit): MmsVideoRequest =
154166
MmsVideoRequest.builder().apply(properties).build()
155167

168+
/**
169+
* Creates an MMS file message.
170+
*
171+
* @param properties A lambda function for setting the message's parameters.
172+
*
173+
* @return An [MmsFileRequest] object with the specified properties.
174+
*
175+
* @since 1.2.0
176+
*/
177+
fun mmsFile(properties: MmsFileRequest.Builder.() -> Unit): MmsFileRequest =
178+
MmsFileRequest.builder().apply(properties).build()
179+
180+
/**
181+
* Creates an MMS content message for sending multiple media files.
182+
*
183+
* @param properties A lambda function for setting the message's parameters.
184+
*
185+
* @return An [MmsContentRequest] object with the specified properties.
186+
*
187+
* @since 1.2.0
188+
*/
189+
fun mmsContent(properties: MmsContentRequest.Builder.() -> Unit): MmsContentRequest =
190+
MmsContentRequest.builder().apply(properties).build()
191+
156192
/**
157193
* Creates a WhatsApp text message.
158194
*

src/main/kotlin/com/vonage/client/kt/Vonage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import com.vonage.client.VonageClient
2121
/**
2222
* Denotes the version of the Vonage Kotlin SDK being used, in SemVer format.
2323
*/
24-
const val VONAGE_KOTLIN_SDK_VERSION = "1.1.4"
24+
const val VONAGE_KOTLIN_SDK_VERSION = "1.2.0"
2525

2626
/**
2727
* The non-overridable user agent string used by the SDK.

src/test/kotlin/com/vonage/client/kt/AbstractTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ abstract class AbstractTest {
105105
protected val audioUrl = "$exampleUrlBase/audio.mp3"
106106
protected val videoUrl = "$exampleUrlBase/video.mp4"
107107
protected val fileUrl = "$exampleUrlBase/file.pdf"
108+
protected val vcardUrl = "$exampleUrlBase/contact.vcf"
108109

109110
private val port = 8081
110111
protected val wmBaseUrl = "http://localhost:$port"

src/test/kotlin/com/vonage/client/kt/MessagesTest.kt

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import java.net.URI
2727
import java.util.*
2828
import kotlin.test.assertEquals
2929
import kotlin.test.assertNotNull
30+
import kotlin.test.assertNull
3031

3132
class MessagesTest : AbstractTest() {
3233
private val client = vonage.messages
@@ -117,6 +118,14 @@ class MessagesTest : AbstractTest() {
117118
})
118119
}
119120

121+
@Test
122+
fun `send MMS text with TTL`() {
123+
val ttl = 600
124+
testSend(textBody(mmsChannel) + mapOf("ttl" to ttl), mmsText {
125+
from(altNumber); to(toNumber); text(text); ttl(ttl)
126+
})
127+
}
128+
120129
@Test
121130
fun `send RCS text`() {
122131
testSend(textBody(rcsChannel), rcsText {
@@ -147,7 +156,6 @@ class MessagesTest : AbstractTest() {
147156

148157
@Test
149158
fun `send MMS vCard`() {
150-
val vcardUrl = "https://example.com/conatact.vcf"
151159
testSend(mediaBody(mmsChannel, "vcard", vcardUrl, captionMap), mmsVcard {
152160
from(altNumber); to(toNumber); url(vcardUrl); caption(caption)
153161
})
@@ -257,6 +265,13 @@ class MessagesTest : AbstractTest() {
257265
})
258266
}
259267

268+
@Test
269+
fun `send MMS file`() {
270+
testSend(fileBody(mmsChannel, captionMap), mmsFile {
271+
from(altNumber); to(toNumber); url(fileUrl); caption(caption)
272+
})
273+
}
274+
260275
@Test
261276
fun `send RCS file`() {
262277
testSend(fileBody(rcsChannel), rcsFile {
@@ -287,6 +302,28 @@ class MessagesTest : AbstractTest() {
287302
})
288303
}
289304

305+
@Test
306+
fun `send MMS content`() {
307+
testSend(baseBody("content", mmsChannel) + mapOf(
308+
"content" to listOf(
309+
mapOf("type" to "file", "url" to fileUrl, "caption" to caption),
310+
mapOf("type" to "image", "url" to imageUrl, "caption" to caption),
311+
mapOf("type" to "audio", "url" to audioUrl, "caption" to caption),
312+
mapOf("type" to "video", "url" to videoUrl, "caption" to caption),
313+
mapOf("type" to "vcard", "url" to vcardUrl, "caption" to caption)
314+
)
315+
),
316+
mmsContent {
317+
from(altNumber); to(toNumber)
318+
addFile(fileUrl, caption)
319+
addImage(imageUrl, caption)
320+
addAudio(audioUrl, caption)
321+
addVideo(videoUrl, caption)
322+
addVcard(vcardUrl, caption)
323+
}
324+
)
325+
}
326+
290327
@Test
291328
fun `send WhatsApp reaction`() {
292329
val emoji = "😍"
@@ -591,7 +628,14 @@ class MessagesTest : AbstractTest() {
591628
"url": "$imageUrl",
592629
"name": "image.jpg",
593630
"caption": "$caption"
594-
}
631+
},
632+
"content": [
633+
{
634+
"type": "image",
635+
"url": "$imageUrl",
636+
"caption": "$caption"
637+
}
638+
]
595639
}
596640
"""
597641
)
@@ -605,6 +649,13 @@ class MessagesTest : AbstractTest() {
605649
assertEquals(MessageType.IMAGE, parsed.messageType)
606650
assertEquals(URI.create(imageUrl), parsed.imageUrl)
607651
assertEquals(caption, parsed.imageCaption)
652+
val content = parsed.content
653+
assertNotNull(content)
654+
assertEquals(1, content.size)
655+
val contentImage = content[0]
656+
assertEquals(MessageType.IMAGE, contentImage.type)
657+
assertEquals(URI.create(imageUrl), contentImage.url)
658+
assertEquals(caption, contentImage.caption)
608659
}
609660

610661
@Test

src/test/kotlin/com/vonage/client/kt/VoiceTest.kt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.vonage.client.kt
1717

1818
import com.vonage.client.common.HttpMethod
19+
import com.vonage.client.common.SortOrder
1920
import com.vonage.client.voice.*
2021
import com.vonage.client.voice.ncco.*
2122
import org.junit.jupiter.api.Assertions.assertArrayEquals
@@ -244,7 +245,7 @@ class VoiceTest : AbstractTest() {
244245
)
245246

246247
testCreateCall(requestParams) {
247-
ncco(ncco); fromRandomNumber(true);
248+
ncco(ncco); fromRandomNumber(true)
248249
to(com.vonage.client.voice.WebSocketEndpoint(websocketUri, null, null))
249250
}
250251
}
@@ -415,7 +416,7 @@ class VoiceTest : AbstractTest() {
415416
status(CallStatus.UNANSWERED)
416417
dateStart(startTime); dateEnd(endTime)
417418
pageSize(pageSize); recordIndex(recordIndex)
418-
order(CallOrder.DESCENDING); conversationUuid(conversationId)
419+
order(SortOrder.DESCENDING); conversationUuid(conversationId)
419420
}
420421

421422
assertEqualsSampleCallsPage(callsPage)
@@ -579,7 +580,7 @@ class VoiceTest : AbstractTest() {
579580
"ringing_timer" to ringingTimer
580581
)) {
581582
answerUrl(answerUrl); answerMethod(answerMethod)
582-
from(fromPstn); fromRandomNumber(false);
583+
from(fromPstn); fromRandomNumber(false)
583584
eventUrl(eventUrl); eventMethod(eventMethod)
584585
lengthTimer(lengthTimer); ringingTimer(ringingTimer)
585586
advancedMachineDetection {
@@ -824,7 +825,7 @@ class VoiceTest : AbstractTest() {
824825
val premium = true
825826
val loop = 2
826827
val style = 1
827-
val level = -0.5f
828+
val level = -0.5
828829
val canHearId = UUID.randomUUID().toString()
829830
val canSpeakId = UUID.randomUUID().toString()
830831
val conversationEventMethod = EventMethod.POST
@@ -839,7 +840,7 @@ class VoiceTest : AbstractTest() {
839840
val record = true
840841
val endOnExit = true
841842
val startOnEnter = true
842-
val inputActionTypes = listOf("dtmf", "speech")
843+
val inputActionTypes = listOf("speech", "dtmf")
843844
val dtmfTimeout = 7
844845
val maxDigits = 16
845846
val submitOnHash = true
@@ -994,17 +995,17 @@ class VoiceTest : AbstractTest() {
994995
addCanHear(canHearId); addCanSpeak(canSpeakId)
995996
addCanHear(testUuidStr); addCanSpeak(testUuidStr)
996997
eventMethod(conversationEventMethod); eventUrl(eventUrl)
997-
musicOnHoldUrl(musicOnHoldUrl); record(record); mute(mute);
998+
musicOnHoldUrl(musicOnHoldUrl); record(record); mute(mute)
998999
startOnEnter(startOnEnter); endOnExit(endOnExit)
9991000
transcription {
10001001
eventMethod(transcriptionEventMethod); eventUrl(transcriptionEventUrl)
1001-
language(SpeechSettings.Language.SPANISH_DOMINICAN_REPUBLIC);
1002+
language(SpeechSettings.Language.SPANISH_DOMINICAN_REPUBLIC)
10021003
sentimentAnalysis(true)
10031004
}
10041005
},
10051006
inputAction {
10061007
eventUrl(eventUrl); eventMethod(inputEventMethod)
1007-
type(inputActionTypes); speech {
1008+
speech {
10081009
uuid(speechUuid); context(speechContext); saveAudio(saveAudio)
10091010
language(SpeechSettings.Language.UKRAINIAN)
10101011
endOnSilence(endOnSilenceSpeech); maxDuration(maxDuration)
@@ -1019,15 +1020,15 @@ class VoiceTest : AbstractTest() {
10191020
timeOut(recordingTimeout); channels(recordingChannels)
10201021
endOnKey(endOnKey); endOnSilence(endOnSilenceRecording)
10211022
eventUrl(recordEventUrl); eventMethod(recordEventMethod)
1022-
split(splitRecording); beepStart(beepStart); transcription {
1023+
beepStart(beepStart); transcription {
10231024
language(SpeechSettings.Language.ENGLISH_SOUTH_AFRICA)
10241025
eventUrl(eventUrl); eventMethod(transcriptionEventMethod)
10251026
sentimentAnalysis(false)
10261027
}
10271028
},
10281029
connectAction(com.vonage.client.voice.ncco.PhoneEndpoint.builder(altNumber).dtmfAnswer(dtmf).build()) {
10291030
eventUrl(eventUrl); eventMethod(connectEventMethod); limit(limit)
1030-
eventType(eventType); timeOut(connectTimeout); ringbackTone(ringbackTone);
1031+
eventType(eventType); timeOut(connectTimeout); ringbackTone(ringbackTone)
10311032
randomFromNumber(true); advancedMachineDetection {
10321033
beepTimeout(beepTimeout)
10331034
}

0 commit comments

Comments
 (0)