Skip to content

Commit

Permalink
feat: Messages API Q3 2024 updates (#542)
Browse files Browse the repository at this point in the history
* Bump versions

* Factor out Text & TTL

* Add RCS text

* MessagePayload in base class

* Factor out custom messages

* Additional WhatsApp Referral properties

* Fix viber_service deserialisation

* MMS content test

* Add remaining RCS outbound tests

* Add WhatsApp Reaction

* Add WhatsApp Button

* Move Button up to accomodate RCS

* Add vCard name

* Add update message endpoint

* Require context for Reaction

* Update tests
  • Loading branch information
SMadani authored Sep 23, 2024
1 parent 0ef4ed8 commit f1c9252
Show file tree
Hide file tree
Showing 67 changed files with 2,005 additions and 406 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

# [8.11.0] - 2024-09-2?
- Added RCS channel to Messages API
- Added `ackInboundMessage` and `revokeOutboundMessage` methods to `MessagesClient`
- Fixed `viber_service` deserialization in `com.vonage.client.messages.Channel`
- Added `thumbnail_url`, `video_url`, `image_url`, `ctwa_clid` and `media_type` to WhatsApp `Referral`
- Added `_self.href` property to `com.vonage.client.messages.InboundMessage`
- Added `reaction` and `button` types to WhatsApp messages
- Added `content` property to `InboundMessage` for MMS messages
- Removed `com.vonage.client.messages.internal.Text`
- Factored out common properties & validation for text, media and custom messages into `MessageRequest`

# [8.10.0] - 2024-08-02
- Added `targetApiKey` for buy & cancel number endpoints
- Added Builder for `UpdateNumberRequest` and deprecated setters
Expand Down
14 changes: 7 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>com.vonage</groupId>
<artifactId>server-sdk</artifactId>
<version>8.10.0</version>
<version>8.11.0</version>

<name>Vonage Java Server SDK</name>
<description>Java client for Vonage APIs</description>
Expand Down Expand Up @@ -74,7 +74,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.16.0</version>
<version>3.17.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
Expand All @@ -86,13 +86,13 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.3</version>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.12.0</version>
<version>5.13.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -190,7 +190,7 @@

<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.1</version>
<version>3.5.0</version>
</plugin>

<plugin>
Expand Down Expand Up @@ -228,7 +228,7 @@

<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.8.0</version>
<version>3.10.0</version>
<configuration>
<linksource>true</linksource>
</configuration>
Expand Down Expand Up @@ -291,7 +291,7 @@
<plugins>
<plugin>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.2.4</version>
<version>3.2.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/com/vonage/client/ApiRegion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2024 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* Enum representing the different regions that the Vonage API can be accessed from.
*
* @since 8.11.0
*/
public enum ApiRegion {
/**
* The region for the Vonage API in Europe.
*/
API_EU,

/**
* The region for the Vonage API in the US.
*/
API_US,

/**
* The region for the Vonage API in Asia Pacific.
*/
API_AP;

@JsonValue
@Override
public String toString() {
return name().toLowerCase().replace("_", "-");
}

/**
* Converts a string representation of a region to the corresponding enum value.
*
* @param region The region as a string.
* @return The region enum, or {@code null} if the input is {@code null}.
*/
@JsonCreator
public static ApiRegion fromString(String region) {
if (region == null) return null;
return valueOf(region.toUpperCase().replace("-", "_"));
}
}
33 changes: 33 additions & 0 deletions src/main/java/com/vonage/client/HttpConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.vonage.client;

import java.net.URI;
import java.util.Objects;
import java.util.function.Function;

public class HttpConfig {
private static final String
Expand All @@ -26,6 +28,7 @@ public class HttpConfig {

private final int timeoutMillis;
private final String apiBaseUri, restBaseUri, apiEuBaseUri, videoBaseUri;
private final Function<ApiRegion, String> regionalUriGetter;

private HttpConfig(Builder builder) {
if ((timeoutMillis = builder.timeoutMillis) < 10) {
Expand All @@ -35,6 +38,7 @@ private HttpConfig(Builder builder) {
restBaseUri = builder.restBaseUri;
videoBaseUri = builder.videoBaseUri;
apiEuBaseUri = builder.apiEuBaseUri;
regionalUriGetter = builder.regionalUriGetter;
}

/**
Expand Down Expand Up @@ -63,18 +67,33 @@ public String getApiEuBaseUri() {
return apiEuBaseUri;
}

/**
* Returns the base URI for the specified region.
*
* @param region The region as an enum.
* @return The base URI for the given region.
* @since 8.11.0
*/
public URI getRegionalBaseUri(ApiRegion region) {
return URI.create(regionalUriGetter.apply(region));
}

@Deprecated
public boolean isDefaultApiBaseUri() {
return DEFAULT_API_BASE_URI.equals(apiBaseUri);
}

@Deprecated
public boolean isDefaultRestBaseUri() {
return DEFAULT_REST_BASE_URI.equals(restBaseUri);
}

@Deprecated
public boolean isDefaultApiEuBaseUri() {
return DEFAULT_API_EU_BASE_URI.equals(apiEuBaseUri);
}

@Deprecated
public boolean isDefaultVideoBaseUri() {
return DEFAULT_VIDEO_BASE_URI.equals(videoBaseUri);
}
Expand Down Expand Up @@ -121,6 +140,7 @@ public static Builder builder() {
*/
public static class Builder {
private int timeoutMillis = 60_000;
private Function<ApiRegion, String> regionalUriGetter = region -> "https://"+region+".vonage.com";
private String
apiBaseUri = DEFAULT_API_BASE_URI,
restBaseUri = DEFAULT_REST_BASE_URI,
Expand Down Expand Up @@ -198,6 +218,7 @@ public Builder videoBaseUri(String videoBaseUri) {
*/
public Builder baseUri(String baseUri) {
String sanitizedUri = sanitizeUri(baseUri);
regionalUriGetter(region -> sanitizedUri.replace("://", "://" + region + '.'));
apiBaseUri = sanitizedUri;
restBaseUri = sanitizedUri;
apiEuBaseUri = sanitizedUri;
Expand All @@ -216,6 +237,18 @@ public Builder baseUri(URI baseUri) {
return baseUri(baseUri.toString());
}

/**
* Sets a function to get the base URI for a given region.
*
* @param uriGetter The function which takes as input a region and returns a base URI as a string.
* @return This builder.
* @since 8.11.0
*/
public Builder regionalUriGetter(Function<ApiRegion, String> uriGetter) {
this.regionalUriGetter = Objects.requireNonNull(uriGetter);
return this;
}

/**
* Builds the HttpConfig.
*
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/HttpWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
public class HttpWrapper {
private static final String
CLIENT_NAME = "vonage-java-sdk",
CLIENT_VERSION = "8.10.0",
CLIENT_VERSION = "8.11.0",
JAVA_VERSION = System.getProperty("java.version"),
USER_AGENT = String.format("%s/%s java/%s", CLIENT_NAME, CLIENT_VERSION, JAVA_VERSION);

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/vonage/client/common/MessageType.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
* @since 8.4.0
*/
public enum MessageType {
TEXT, IMAGE, AUDIO, VIDEO, FILE, VCARD, TEMPLATE, CUSTOM,
LOCATION, STICKER, UNSUPPORTED, REPLY, ORDER, RANDOM;
TEXT, IMAGE, AUDIO, VIDEO, FILE, VCARD, TEMPLATE, CUSTOM, LOCATION,
STICKER, UNSUPPORTED, REPLY, ORDER, RANDOM, BUTTON, REACTION, CONTACT;

@JsonCreator
public static MessageType fromString(String value) {
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/com/vonage/client/common/UrlContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@

/**
* Represents a link under the {@code _links} section of a HAL response.
*
* @deprecated This class will be made package-private in the next major release.
*/
@Deprecated
public class UrlContainer extends JsonableBaseObject {
protected URI href;

Expand Down
63 changes: 63 additions & 0 deletions src/main/java/com/vonage/client/messages/Button.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2024 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client.messages;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.vonage.client.JsonableBaseObject;
import java.util.Map;

/**
* Used for inbound Button messages.
*
* @since 8.11.0
*/
public final class Button extends JsonableBaseObject {
private Object payload;
private String text, subtype;

Button() {}

/**
* Payload for the button. Contents can be varied depending on the type of button.
* For WhatsApp messages, this will be a Map. For RCS, this will be a String.
*
* @return The button payload, or {@code null} if absent.
*/
@JsonProperty("payload")
public Object getPayload() {
return payload;
}

/**
* Additional context for the button.
*
* @return The button text, or {@code null} if absent.
*/
@JsonProperty("text")
public String getText() {
return text;
}

/**
* Subtype of button being received. This only applies to WhatsApp messages.
*
* @return The button subtype, or {@code null} if absent / not applicable.
*/
@JsonProperty("subtype")
public String getSubtype() {
return subtype;
}
}
13 changes: 10 additions & 3 deletions src/main/java/com/vonage/client/messages/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
public enum Channel {
SMS (TEXT),
MMS (TEXT, IMAGE, VCARD, AUDIO, VIDEO),
WHATSAPP (TEXT, IMAGE, AUDIO, VIDEO, FILE, TEMPLATE, CUSTOM, LOCATION, STICKER, ORDER, REPLY, UNSUPPORTED),
RCS (TEXT, IMAGE, VIDEO, FILE, CUSTOM, AUDIO, LOCATION, VCARD, REPLY, BUTTON),
WHATSAPP (TEXT, IMAGE, AUDIO, VIDEO, FILE, TEMPLATE, CUSTOM, LOCATION,
STICKER, ORDER, REPLY, REACTION, CONTACT, BUTTON, UNSUPPORTED),
MESSENGER (TEXT, IMAGE, AUDIO, VIDEO, FILE, UNSUPPORTED),
VIBER (TEXT, IMAGE, VIDEO, FILE);

Expand Down Expand Up @@ -56,14 +58,19 @@ public Set<MessageType> getSupportedMessageTypes() {
public Set<MessageType> getSupportedOutboundMessageTypes() {
return getSupportedMessageTypes().stream().filter(mt -> mt != MessageType.UNSUPPORTED &&
mt != MessageType.REPLY && mt != MessageType.ORDER &&
(this != Channel.MMS || mt != MessageType.TEXT)
mt != MessageType.CONTACT && mt != MessageType.BUTTON &&
(this != Channel.MMS || mt != MessageType.TEXT) &&
(this != Channel.RCS || (
mt != AUDIO && mt != LOCATION && mt != BUTTON && mt != VCARD
))
).collect(Collectors.toSet());
}

@JsonCreator
public static Channel fromString(String value) {
if (value == null) return null;
return Channel.valueOf(value.toUpperCase());
String upper = value.toUpperCase();
return upper.equals("VIBER_SERVICE") ? VIBER : Channel.valueOf(upper);
}

@JsonValue
Expand Down
Loading

0 comments on commit f1c9252

Please sign in to comment.