From c9585d48d8dd95bf9585254660cf78ad4dd02cfd Mon Sep 17 00:00:00 2001 From: Jimmy Pettersson Date: Fri, 20 Feb 2026 08:53:10 +0100 Subject: [PATCH 1/7] WIP --- src/main/java/io/getstream/client/Client.java | 41 +++++++--- src/main/java/io/getstream/client/Feed.java | 23 ++++-- .../io/getstream/client/ReactionsClient.java | 19 ++++- .../java/io/getstream/cloud/CloudClient.java | 12 ++- .../java/io/getstream/cloud/CloudFeed.java | 23 ++++-- .../getstream/cloud/CloudReactionsClient.java | 17 +++- src/main/java/io/getstream/core/Stream.java | 36 ++++++--- .../io/getstream/core/StreamReactions.java | 12 ++- .../io/getstream/client/BatchClientTest.java | 78 +++++++++++++++++++ .../java/io/getstream/client/FeedTest.java | 20 +++++ .../getstream/client/ReactionsClientTest.java | 36 +++++++++ 11 files changed, 267 insertions(+), 50 deletions(-) diff --git a/src/main/java/io/getstream/client/Client.java b/src/main/java/io/getstream/client/Client.java index 49fba80c..6beee690 100644 --- a/src/main/java/io/getstream/client/Client.java +++ b/src/main/java/io/getstream/client/Client.java @@ -47,9 +47,10 @@ public CompletableFuture updateActivityByID(ActivityUpdate update) } public CompletableFuture updateActivityByID( - String id, Map set, String[] unset) throws StreamException { + String id, Map set, String[] unset, RequestOption... options) + throws StreamException { final Token token = buildActivityToken(secret, TokenAction.WRITE); - return stream.updateActivityByID(token, id, set, unset); + return stream.updateActivityByID(token, id, set, unset, options); } public CompletableFuture updateActivityByForeignID( @@ -82,10 +83,10 @@ public CompletableFuture updateActivityByForeignID(ActivityUpdate upda } public CompletableFuture updateActivityByForeignID( - String foreignID, Date timestamp, Map set, String[] unset) - throws StreamException { + String foreignID, Date timestamp, Map set, String[] unset, + RequestOption... options) throws StreamException { final Token token = buildActivityToken(secret, TokenAction.WRITE); - return stream.updateActivityByForeignID(token, foreignID, timestamp, set, unset); + return stream.updateActivityByForeignID(token, foreignID, timestamp, set, unset, options); } public CompletableFuture openGraph(URL url) throws StreamException { @@ -95,24 +96,34 @@ public CompletableFuture openGraph(URL url) throws StreamException { public CompletableFuture> updateActivitiesByID(Iterable updates) throws StreamException { - return updateActivitiesByID(Iterables.toArray(updates, ActivityUpdate.class)); + return updateActivitiesByID(Iterables.toArray(updates, ActivityUpdate.class), new RequestOption[0]); } public CompletableFuture> updateActivitiesByID(ActivityUpdate... updates) throws StreamException { + return updateActivitiesByID(updates, new RequestOption[0]); + } + + public CompletableFuture> updateActivitiesByID( + ActivityUpdate[] updates, RequestOption... options) throws StreamException { final Token token = buildActivityToken(secret, TokenAction.WRITE); - return stream.updateActivitiesByID(token, updates); + return stream.updateActivitiesByID(token, updates, options); } public CompletableFuture> updateActivitiesByForeignID( Iterable updates) throws StreamException { - return updateActivitiesByForeignID(Iterables.toArray(updates, ActivityUpdate.class)); + return updateActivitiesByForeignID(Iterables.toArray(updates, ActivityUpdate.class), new RequestOption[0]); } public CompletableFuture> updateActivitiesByForeignID(ActivityUpdate... updates) throws StreamException { + return updateActivitiesByForeignID(updates, new RequestOption[0]); + } + + public CompletableFuture> updateActivitiesByForeignID( + ActivityUpdate[] updates, RequestOption... options) throws StreamException { final Token token = buildActivityToken(secret, TokenAction.WRITE); - return stream.updateActivitiesByForeignID(token, updates); + return stream.updateActivitiesByForeignID(token, updates, options); } public static final class Builder { @@ -280,15 +291,21 @@ CompletableFuture getEnrichedActivities(FeedID feed, RequestOption... return stream.getEnrichedActivities(token, feed, options); } - CompletableFuture addActivity(FeedID feed, Activity activity) throws StreamException { + CompletableFuture addActivity(FeedID feed, Activity activity, RequestOption... options) + throws StreamException { final Token token = buildFeedToken(secret, feed, TokenAction.WRITE); - return stream.addActivity(token, feed, activity); + return stream.addActivity(token, feed, activity, options); } CompletableFuture addActivities(FeedID feed, Activity... activities) throws StreamException { + return addActivities(feed, activities, new RequestOption[0]); + } + + CompletableFuture addActivities( + FeedID feed, Activity[] activities, RequestOption... options) throws StreamException { final Token token = buildFeedToken(secret, feed, TokenAction.WRITE); - return stream.addActivities(token, feed, activities); + return stream.addActivities(token, feed, activities, options); } CompletableFuture removeActivityByID(FeedID feed, String id) throws StreamException { diff --git a/src/main/java/io/getstream/client/Feed.java b/src/main/java/io/getstream/client/Feed.java index 26cede4d..3fc1d45a 100644 --- a/src/main/java/io/getstream/client/Feed.java +++ b/src/main/java/io/getstream/client/Feed.java @@ -50,9 +50,10 @@ public final String getUserID() { return id.getUserID(); } - public final CompletableFuture addActivity(Activity activity) throws StreamException { + public final CompletableFuture addActivity(Activity activity, RequestOption... options) + throws StreamException { return getClient() - .addActivity(id, activity) + .addActivity(id, activity, options) .thenApply( response -> { try { @@ -63,9 +64,10 @@ public final CompletableFuture addActivity(Activity activity) throws S }); } - public final CompletableFuture addCustomActivity(T activity) throws StreamException { + public final CompletableFuture addCustomActivity(T activity, RequestOption... options) + throws StreamException { return getClient() - .addActivity(id, Activity.builder().fromCustomActivity(activity).build()) + .addActivity(id, Activity.builder().fromCustomActivity(activity).build(), options) .thenApply( response -> { try { @@ -78,7 +80,7 @@ public final CompletableFuture addCustomActivity(T activity) throws Strea public final CompletableFuture> addActivities(Iterable activities) throws StreamException { - return addActivities(Iterables.toArray(activities, Activity.class)); + return addActivities(Iterables.toArray(activities, Activity.class), new RequestOption[0]); } public final CompletableFuture> addCustomActivities(Iterable activities) @@ -88,7 +90,7 @@ public final CompletableFuture> addCustomActivities(Iterable acti .map(activity -> Activity.builder().fromCustomActivity(activity).build()) .toArray(Activity[]::new); return getClient() - .addActivities(id, custom) + .addActivities(id, custom, new RequestOption[0]) .thenApply( response -> { try { @@ -105,8 +107,13 @@ public final CompletableFuture> addCustomActivities(Iterable acti public final CompletableFuture> addActivities(Activity... activities) throws StreamException { + return addActivities(activities, new RequestOption[0]); + } + + public final CompletableFuture> addActivities( + Activity[] activities, RequestOption... options) throws StreamException { return getClient() - .addActivities(id, activities) + .addActivities(id, activities, options) .thenApply( response -> { try { @@ -124,7 +131,7 @@ public final CompletableFuture> addCustomActivities(T... activities) .map(activity -> Activity.builder().fromCustomActivity(activity).build()) .toArray(Activity[]::new); return getClient() - .addActivities(id, custom) + .addActivities(id, custom, new RequestOption[0]) .thenApply( response -> { try { diff --git a/src/main/java/io/getstream/client/ReactionsClient.java b/src/main/java/io/getstream/client/ReactionsClient.java index c2658163..179284fc 100644 --- a/src/main/java/io/getstream/client/ReactionsClient.java +++ b/src/main/java/io/getstream/client/ReactionsClient.java @@ -15,6 +15,7 @@ import io.getstream.core.models.ReactionBatch; import io.getstream.core.options.Filter; import io.getstream.core.options.Limit; +import io.getstream.core.options.RequestOption; import io.getstream.core.utils.Auth.TokenAction; import io.getstream.core.utils.DefaultOptions; import java.util.List; @@ -168,10 +169,18 @@ public CompletableFuture add(String userID, Reaction reaction, FeedID. return reactions.add(token, userID, reaction, targetFeeds); } - public CompletableFuture add(String userID, Reaction reaction, FeedID[] targetFeeds, Map targetFeedsExtraData) + public CompletableFuture add( + String userID, Reaction reaction, FeedID[] targetFeeds, RequestOption... options) throws StreamException { final Token token = buildReactionsToken(secret, TokenAction.WRITE); - return reactions.add(token, userID, reaction, targetFeeds, targetFeedsExtraData); + return reactions.add(token, userID, reaction, targetFeeds, null, options); + } + + public CompletableFuture add( + String userID, Reaction reaction, FeedID[] targetFeeds, + Map targetFeedsExtraData, RequestOption... options) throws StreamException { + final Token token = buildReactionsToken(secret, TokenAction.WRITE); + return reactions.add(token, userID, reaction, targetFeeds, targetFeedsExtraData, options); } public CompletableFuture addChild( @@ -237,6 +246,12 @@ public CompletableFuture update(Reaction reaction, FeedID... targetFeeds) return reactions.update(token, reaction, targetFeeds); } + public CompletableFuture update( + Reaction reaction, FeedID[] targetFeeds, RequestOption... options) throws StreamException { + final Token token = buildReactionsToken(secret, TokenAction.WRITE); + return reactions.update(token, reaction, targetFeeds, options); + } + public CompletableFuture delete(String id) throws StreamException { final Token token = buildReactionsToken(secret, TokenAction.DELETE); return reactions.delete(token, id, false); diff --git a/src/main/java/io/getstream/cloud/CloudClient.java b/src/main/java/io/getstream/cloud/CloudClient.java index e2417ec4..328cb8a4 100644 --- a/src/main/java/io/getstream/cloud/CloudClient.java +++ b/src/main/java/io/getstream/cloud/CloudClient.java @@ -337,13 +337,19 @@ CompletableFuture getEnrichedActivities(FeedID feed, RequestOption... return stream.getEnrichedActivities(token, feed, options); } - CompletableFuture addActivity(FeedID feed, Activity activity) throws StreamException { - return stream.addActivity(token, feed, activity); + CompletableFuture addActivity(FeedID feed, Activity activity, RequestOption... options) + throws StreamException { + return stream.addActivity(token, feed, activity, options); } CompletableFuture addActivities(FeedID feed, Activity... activities) throws StreamException { - return stream.addActivities(token, feed, activities); + return addActivities(feed, activities, new RequestOption[0]); + } + + CompletableFuture addActivities( + FeedID feed, Activity[] activities, RequestOption... options) throws StreamException { + return stream.addActivities(token, feed, activities, options); } CompletableFuture removeActivityByID(FeedID feed, String id) throws StreamException { diff --git a/src/main/java/io/getstream/cloud/CloudFeed.java b/src/main/java/io/getstream/cloud/CloudFeed.java index 07673c01..04506392 100644 --- a/src/main/java/io/getstream/cloud/CloudFeed.java +++ b/src/main/java/io/getstream/cloud/CloudFeed.java @@ -69,9 +69,10 @@ public final String getUserID() { return id.getUserID(); } - public final CompletableFuture addActivity(Activity activity) throws StreamException { + public final CompletableFuture addActivity(Activity activity, RequestOption... options) + throws StreamException { return getClient() - .addActivity(id, activity) + .addActivity(id, activity, options) .thenApply( response -> { try { @@ -82,9 +83,10 @@ public final CompletableFuture addActivity(Activity activity) throws S }); } - public final CompletableFuture addCustomActivity(T activity) throws StreamException { + public final CompletableFuture addCustomActivity(T activity, RequestOption... options) + throws StreamException { return getClient() - .addActivity(id, Activity.builder().fromCustomActivity(activity).build()) + .addActivity(id, Activity.builder().fromCustomActivity(activity).build(), options) .thenApply( response -> { try { @@ -97,7 +99,7 @@ public final CompletableFuture addCustomActivity(T activity) throws Strea public final CompletableFuture> addActivities(Iterable activities) throws StreamException { - return addActivities(Iterables.toArray(activities, Activity.class)); + return addActivities(Iterables.toArray(activities, Activity.class), new RequestOption[0]); } public final CompletableFuture> addCustomActivities(Iterable activities) @@ -107,7 +109,7 @@ public final CompletableFuture> addCustomActivities(Iterable acti .map(activity -> Activity.builder().fromCustomActivity(activity).build()) .toArray(Activity[]::new); return getClient() - .addActivities(id, custom) + .addActivities(id, custom, new RequestOption[0]) .thenApply( (Response response) -> { try { @@ -124,8 +126,13 @@ public final CompletableFuture> addCustomActivities(Iterable acti public final CompletableFuture> addActivities(Activity... activities) throws StreamException { + return addActivities(activities, new RequestOption[0]); + } + + public final CompletableFuture> addActivities( + Activity[] activities, RequestOption... options) throws StreamException { return getClient() - .addActivities(id, activities) + .addActivities(id, activities, options) .thenApply( (Response response) -> { try { @@ -143,7 +150,7 @@ public final CompletableFuture> addCustomActivities(T... activities) .map(activity -> Activity.builder().fromCustomActivity(activity).build()) .toArray(Activity[]::new); return getClient() - .addActivities(id, custom) + .addActivities(id, custom, new RequestOption[0]) .thenApply( (Response response) -> { try { diff --git a/src/main/java/io/getstream/cloud/CloudReactionsClient.java b/src/main/java/io/getstream/cloud/CloudReactionsClient.java index ab04d5a4..099c5187 100644 --- a/src/main/java/io/getstream/cloud/CloudReactionsClient.java +++ b/src/main/java/io/getstream/cloud/CloudReactionsClient.java @@ -12,6 +12,7 @@ import io.getstream.core.models.Reaction; import io.getstream.core.options.Filter; import io.getstream.core.options.Limit; +import io.getstream.core.options.RequestOption; import io.getstream.core.utils.DefaultOptions; import java.util.List; import java.util.Map; @@ -151,9 +152,16 @@ public CompletableFuture add(String userID, Reaction reaction, FeedID. return reactions.add(token, userID, reaction, targetFeeds); } - public CompletableFuture add(String userID, Reaction reaction, FeedID[] targetFeeds, Map targetFeedsExtraData) + public CompletableFuture add( + String userID, Reaction reaction, FeedID[] targetFeeds, RequestOption... options) throws StreamException { - return reactions.add(token, userID, reaction, targetFeeds, targetFeedsExtraData); + return reactions.add(token, userID, reaction, targetFeeds, null, options); + } + + public CompletableFuture add( + String userID, Reaction reaction, FeedID[] targetFeeds, + Map targetFeedsExtraData, RequestOption... options) throws StreamException { + return reactions.add(token, userID, reaction, targetFeeds, targetFeedsExtraData, options); } public CompletableFuture addChild( @@ -218,6 +226,11 @@ public CompletableFuture update(Reaction reaction, FeedID... targetFeeds) return reactions.update(token, reaction, targetFeeds); } + public CompletableFuture update( + Reaction reaction, FeedID[] targetFeeds, RequestOption... options) throws StreamException { + return reactions.update(token, reaction, targetFeeds, options); + } + public CompletableFuture delete(String id) throws StreamException { return reactions.delete(token, id, false); } diff --git a/src/main/java/io/getstream/core/Stream.java b/src/main/java/io/getstream/core/Stream.java index 897817c9..895f5254 100644 --- a/src/main/java/io/getstream/core/Stream.java +++ b/src/main/java/io/getstream/core/Stream.java @@ -72,7 +72,7 @@ public StreamImages images() { } public CompletableFuture> updateActivitiesByID( - Token token, ActivityUpdate[] updates) throws StreamException { + Token token, ActivityUpdate[] updates, RequestOption... options) throws StreamException { checkNotNull(updates, "No updates"); checkArgument(updates.length > 0, "No updates"); for (ActivityUpdate update : updates) { @@ -89,7 +89,7 @@ public CompletableFuture> updateActivitiesByID( }); final URL url = buildActivityUpdateURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -104,7 +104,8 @@ public CompletableFuture> updateActivitiesByID( } public CompletableFuture updateActivityByID( - Token token, String id, Map set, String[] unset) throws StreamException { + Token token, String id, Map set, String[] unset, RequestOption... options) + throws StreamException { checkNotNull(id, "No activity to update"); checkNotNull(set, "No activity properties to set"); checkNotNull(unset, "No activity properties to unset"); @@ -123,7 +124,7 @@ public CompletableFuture updateActivityByID( }); final URL url = buildActivityUpdateURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -138,7 +139,7 @@ public CompletableFuture updateActivityByID( } public CompletableFuture> updateActivitiesByForeignID( - Token token, ActivityUpdate[] updates) throws StreamException { + Token token, ActivityUpdate[] updates, RequestOption... options) throws StreamException { checkNotNull(updates, "No updates"); checkArgument(updates.length > 0, "No updates"); for (ActivityUpdate update : updates) { @@ -156,7 +157,7 @@ public CompletableFuture> updateActivitiesByForeignID( }); final URL url = buildActivityUpdateURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -171,7 +172,12 @@ public CompletableFuture> updateActivitiesByForeignID( } public CompletableFuture updateActivityByForeignID( - Token token, String foreignID, Date timestamp, Map set, String[] unset) + Token token, + String foreignID, + Date timestamp, + Map set, + String[] unset, + RequestOption... options) throws StreamException { checkNotNull(foreignID, "No activity to update"); checkNotNull(timestamp, "Missing timestamp"); @@ -199,7 +205,7 @@ public CompletableFuture updateActivityByForeignID( }); final URL url = buildActivityUpdateURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -263,14 +269,14 @@ public CompletableFuture getEnrichedActivities( } } - public CompletableFuture addActivity(Token token, FeedID feed, Activity activity) - throws StreamException { + public CompletableFuture addActivity( + Token token, FeedID feed, Activity activity, RequestOption... options) throws StreamException { checkNotNull(activity, "No activity to add"); try { final byte[] payload = toJSON(activity); final URL url = buildFeedURL(baseURL, feed, "/"); - return httpClient.execute(buildPost(url, key, token, payload)); + return httpClient.execute(buildPost(url, key, token, payload, options)); } catch (JsonProcessingException | MalformedURLException | URISyntaxException e) { throw new StreamException(e); } @@ -278,6 +284,12 @@ public CompletableFuture addActivity(Token token, FeedID feed, Activit public CompletableFuture addActivities( Token token, FeedID feed, Activity... activityObjects) throws StreamException { + return addActivities(token, feed, activityObjects, new RequestOption[0]); + } + + public CompletableFuture addActivities( + Token token, FeedID feed, Activity[] activityObjects, RequestOption... options) + throws StreamException { checkNotNull(activityObjects, "No activities to add"); try { @@ -287,7 +299,7 @@ public CompletableFuture addActivities( public final Activity[] activities = activityObjects; }); final URL url = buildFeedURL(baseURL, feed, "/"); - return httpClient.execute(buildPost(url, key, token, payload)); + return httpClient.execute(buildPost(url, key, token, payload, options)); } catch (JsonProcessingException | MalformedURLException | URISyntaxException e) { throw new StreamException(e); } diff --git a/src/main/java/io/getstream/core/StreamReactions.java b/src/main/java/io/getstream/core/StreamReactions.java index 1bbba031..cb9c7357 100644 --- a/src/main/java/io/getstream/core/StreamReactions.java +++ b/src/main/java/io/getstream/core/StreamReactions.java @@ -208,7 +208,7 @@ public CompletableFuture add( } public CompletableFuture add( - Token token, String userID, Reaction reaction, FeedID[] targetFeeds, Map targetFeedsExtraData) throws StreamException { + Token token, String userID, Reaction reaction, FeedID[] targetFeeds, Map targetFeedsExtraData, RequestOption... options) throws StreamException { checkNotNull(reaction, "Reaction can't be null"); checkArgument( reaction.getActivityID() != null || reaction.getParent() != null, @@ -256,7 +256,7 @@ public CompletableFuture add( final byte[] payload = toJSON(payloadBuilder.build()); final URL url = buildReactionsURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -272,6 +272,12 @@ public CompletableFuture add( public CompletableFuture update(Token token, Reaction reaction, FeedID... targetFeeds) throws StreamException { + return update(token, reaction, targetFeeds, new RequestOption[0]); + } + + public CompletableFuture update( + Token token, Reaction reaction, FeedID[] targetFeeds, RequestOption... options) + throws StreamException { checkNotNull(reaction, "Reaction can't be null"); checkNotNull(reaction.getId(), "Reaction id can't be null"); checkArgument(!reaction.getId().isEmpty(), "Reaction id can't be empty"); @@ -291,7 +297,7 @@ public CompletableFuture update(Token token, Reaction reaction, FeedID... final byte[] payload = toJSON(payloadBuilder.build()); final URL url = buildReactionsURL(baseURL, reaction.getId() + '/'); return httpClient - .execute(buildPut(url, key, token, payload)) + .execute(buildPut(url, key, token, payload, options)) .thenApply( response -> { try { diff --git a/src/test/java/io/getstream/client/BatchClientTest.java b/src/test/java/io/getstream/client/BatchClientTest.java index 7a88f8ed..3bf27f89 100644 --- a/src/test/java/io/getstream/client/BatchClientTest.java +++ b/src/test/java/io/getstream/client/BatchClientTest.java @@ -3,6 +3,7 @@ import com.google.common.collect.ImmutableMap; import io.getstream.core.KeepHistory; import io.getstream.core.models.*; +import io.getstream.core.options.CustomQueryParameter; import java.text.SimpleDateFormat; import java.util.*; import org.junit.Test; @@ -161,6 +162,83 @@ public void partiallyUpdateActivitiesByForeignID() throws Exception { List result = client.updateActivitiesByForeignID(update).join(); } + @Test + public void partiallyUpdateActivityByIDWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + Map set = ImmutableMap.of("value", "message"); + Iterable unset = Collections.emptyList(); + Activity result = + client + .updateActivityByID( + "1657b300-a648-11d5-8080-800020fde6c3", + set, + new String[0], + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + + @Test + public void partiallyUpdateActivitiesByIDWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + ActivityUpdate update = + ActivityUpdate.builder() + .id("1657b300-a648-11d5-8080-800020fde6c3") + .set(ImmutableMap.of("value", "message")) + .unset(Collections.emptyList()) + .build(); + + List result = + client + .updateActivitiesByID( + new ActivityUpdate[] {update}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + + @Test + public void partiallyUpdateActivityByForeignIDWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"); + isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + Date time = isoFormat.parse("2001-09-11T00:01:02.000000"); + + Activity result = + client + .updateActivityByForeignID( + "foreignID", + time, + ImmutableMap.of("value", "message"), + new String[0], + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + + @Test + public void partiallyUpdateActivitiesByForeignIDWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"); + isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + ActivityUpdate update = + ActivityUpdate.builder() + .foreignID("foreignID") + .time(isoFormat.parse("2001-09-11T00:01:02.000000")) + .set(ImmutableMap.of("value", "message")) + .unset(Collections.emptyList()) + .build(); + + List result = + client + .updateActivitiesByForeignID( + new ActivityUpdate[] {update}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + @Test public void getActivitiesByID() throws Exception { BatchClient client = Client.builder(apiKey, secret).build().batch(); diff --git a/src/test/java/io/getstream/client/FeedTest.java b/src/test/java/io/getstream/client/FeedTest.java index c38dd1d7..5705651d 100644 --- a/src/test/java/io/getstream/client/FeedTest.java +++ b/src/test/java/io/getstream/client/FeedTest.java @@ -10,6 +10,7 @@ import io.getstream.core.models.Activity; import io.getstream.core.models.FeedID; import io.getstream.core.models.FollowStats; +import io.getstream.core.options.CustomQueryParameter; import java.net.MalformedURLException; import java.util.Collections; import java.util.Date; @@ -50,6 +51,25 @@ public void addActivity() throws Exception { Activity result = feed.addActivity(activity).join(); } + @Test + public void addActivityWithRequestOptions() throws Exception { + Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); + FlatFeed feed = client.flatFeed("flat", "1"); + Activity result = + feed.addActivity(activity, new CustomQueryParameter("skip_moderation", "true")).join(); + } + + @Test + public void addActivitiesWithRequestOptions() throws Exception { + Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); + FlatFeed feed = client.flatFeed("flat", "1"); + List result = + feed.addActivities( + new Activity[] {activity}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + @Test public void addActivities() throws Exception { Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); diff --git a/src/test/java/io/getstream/client/ReactionsClientTest.java b/src/test/java/io/getstream/client/ReactionsClientTest.java index da11c692..48f204d3 100644 --- a/src/test/java/io/getstream/client/ReactionsClientTest.java +++ b/src/test/java/io/getstream/client/ReactionsClientTest.java @@ -8,6 +8,7 @@ import java.util.function.Function; import java.util.stream.Collectors; +import io.getstream.core.options.CustomQueryParameter; import io.getstream.core.options.Filter; import io.getstream.core.options.Limit; import org.junit.Test; @@ -188,6 +189,41 @@ public void update() throws Exception { client.reactions().update(data, new FeedID("flat", "1")).join(); } + @Test + public void addWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + Reaction data = + Reaction.builder().activityID("ed2837a6-0a3b-4679-adc1-778a1704852d").kind("like").build(); + client + .reactions() + .add( + "user-id", + data, + new FeedID[] {new FeedID("flat", "1")}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + + @Test + public void updateWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + Reaction data = + Reaction.builder() + .id("b5c46f9b-0839-4207-86aa-6a7f388b7748") + .kind("like") + .extraField("key", "value") + .build(); + client + .reactions() + .update( + data, + new FeedID[] {new FeedID("flat", "1")}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + @Test public void delete() throws Exception { Client client = Client.builder(apiKey, secret).build(); From b7738e25c2553b4fc55edae0b05f1333fba1fc48 Mon Sep 17 00:00:00 2001 From: Jimmy Pettersson Date: Fri, 20 Feb 2026 08:53:10 +0100 Subject: [PATCH 2/7] feat(moderation): skip moderation --- src/main/java/io/getstream/client/Client.java | 41 +++++++--- src/main/java/io/getstream/client/Feed.java | 23 ++++-- .../io/getstream/client/ReactionsClient.java | 19 ++++- .../java/io/getstream/cloud/CloudClient.java | 12 ++- .../java/io/getstream/cloud/CloudFeed.java | 23 ++++-- .../getstream/cloud/CloudReactionsClient.java | 17 +++- src/main/java/io/getstream/core/Stream.java | 36 ++++++--- .../io/getstream/core/StreamReactions.java | 12 ++- .../io/getstream/client/BatchClientTest.java | 78 +++++++++++++++++++ .../java/io/getstream/client/FeedTest.java | 20 +++++ .../getstream/client/ReactionsClientTest.java | 36 +++++++++ 11 files changed, 267 insertions(+), 50 deletions(-) diff --git a/src/main/java/io/getstream/client/Client.java b/src/main/java/io/getstream/client/Client.java index 49fba80c..6beee690 100644 --- a/src/main/java/io/getstream/client/Client.java +++ b/src/main/java/io/getstream/client/Client.java @@ -47,9 +47,10 @@ public CompletableFuture updateActivityByID(ActivityUpdate update) } public CompletableFuture updateActivityByID( - String id, Map set, String[] unset) throws StreamException { + String id, Map set, String[] unset, RequestOption... options) + throws StreamException { final Token token = buildActivityToken(secret, TokenAction.WRITE); - return stream.updateActivityByID(token, id, set, unset); + return stream.updateActivityByID(token, id, set, unset, options); } public CompletableFuture updateActivityByForeignID( @@ -82,10 +83,10 @@ public CompletableFuture updateActivityByForeignID(ActivityUpdate upda } public CompletableFuture updateActivityByForeignID( - String foreignID, Date timestamp, Map set, String[] unset) - throws StreamException { + String foreignID, Date timestamp, Map set, String[] unset, + RequestOption... options) throws StreamException { final Token token = buildActivityToken(secret, TokenAction.WRITE); - return stream.updateActivityByForeignID(token, foreignID, timestamp, set, unset); + return stream.updateActivityByForeignID(token, foreignID, timestamp, set, unset, options); } public CompletableFuture openGraph(URL url) throws StreamException { @@ -95,24 +96,34 @@ public CompletableFuture openGraph(URL url) throws StreamException { public CompletableFuture> updateActivitiesByID(Iterable updates) throws StreamException { - return updateActivitiesByID(Iterables.toArray(updates, ActivityUpdate.class)); + return updateActivitiesByID(Iterables.toArray(updates, ActivityUpdate.class), new RequestOption[0]); } public CompletableFuture> updateActivitiesByID(ActivityUpdate... updates) throws StreamException { + return updateActivitiesByID(updates, new RequestOption[0]); + } + + public CompletableFuture> updateActivitiesByID( + ActivityUpdate[] updates, RequestOption... options) throws StreamException { final Token token = buildActivityToken(secret, TokenAction.WRITE); - return stream.updateActivitiesByID(token, updates); + return stream.updateActivitiesByID(token, updates, options); } public CompletableFuture> updateActivitiesByForeignID( Iterable updates) throws StreamException { - return updateActivitiesByForeignID(Iterables.toArray(updates, ActivityUpdate.class)); + return updateActivitiesByForeignID(Iterables.toArray(updates, ActivityUpdate.class), new RequestOption[0]); } public CompletableFuture> updateActivitiesByForeignID(ActivityUpdate... updates) throws StreamException { + return updateActivitiesByForeignID(updates, new RequestOption[0]); + } + + public CompletableFuture> updateActivitiesByForeignID( + ActivityUpdate[] updates, RequestOption... options) throws StreamException { final Token token = buildActivityToken(secret, TokenAction.WRITE); - return stream.updateActivitiesByForeignID(token, updates); + return stream.updateActivitiesByForeignID(token, updates, options); } public static final class Builder { @@ -280,15 +291,21 @@ CompletableFuture getEnrichedActivities(FeedID feed, RequestOption... return stream.getEnrichedActivities(token, feed, options); } - CompletableFuture addActivity(FeedID feed, Activity activity) throws StreamException { + CompletableFuture addActivity(FeedID feed, Activity activity, RequestOption... options) + throws StreamException { final Token token = buildFeedToken(secret, feed, TokenAction.WRITE); - return stream.addActivity(token, feed, activity); + return stream.addActivity(token, feed, activity, options); } CompletableFuture addActivities(FeedID feed, Activity... activities) throws StreamException { + return addActivities(feed, activities, new RequestOption[0]); + } + + CompletableFuture addActivities( + FeedID feed, Activity[] activities, RequestOption... options) throws StreamException { final Token token = buildFeedToken(secret, feed, TokenAction.WRITE); - return stream.addActivities(token, feed, activities); + return stream.addActivities(token, feed, activities, options); } CompletableFuture removeActivityByID(FeedID feed, String id) throws StreamException { diff --git a/src/main/java/io/getstream/client/Feed.java b/src/main/java/io/getstream/client/Feed.java index 26cede4d..3fc1d45a 100644 --- a/src/main/java/io/getstream/client/Feed.java +++ b/src/main/java/io/getstream/client/Feed.java @@ -50,9 +50,10 @@ public final String getUserID() { return id.getUserID(); } - public final CompletableFuture addActivity(Activity activity) throws StreamException { + public final CompletableFuture addActivity(Activity activity, RequestOption... options) + throws StreamException { return getClient() - .addActivity(id, activity) + .addActivity(id, activity, options) .thenApply( response -> { try { @@ -63,9 +64,10 @@ public final CompletableFuture addActivity(Activity activity) throws S }); } - public final CompletableFuture addCustomActivity(T activity) throws StreamException { + public final CompletableFuture addCustomActivity(T activity, RequestOption... options) + throws StreamException { return getClient() - .addActivity(id, Activity.builder().fromCustomActivity(activity).build()) + .addActivity(id, Activity.builder().fromCustomActivity(activity).build(), options) .thenApply( response -> { try { @@ -78,7 +80,7 @@ public final CompletableFuture addCustomActivity(T activity) throws Strea public final CompletableFuture> addActivities(Iterable activities) throws StreamException { - return addActivities(Iterables.toArray(activities, Activity.class)); + return addActivities(Iterables.toArray(activities, Activity.class), new RequestOption[0]); } public final CompletableFuture> addCustomActivities(Iterable activities) @@ -88,7 +90,7 @@ public final CompletableFuture> addCustomActivities(Iterable acti .map(activity -> Activity.builder().fromCustomActivity(activity).build()) .toArray(Activity[]::new); return getClient() - .addActivities(id, custom) + .addActivities(id, custom, new RequestOption[0]) .thenApply( response -> { try { @@ -105,8 +107,13 @@ public final CompletableFuture> addCustomActivities(Iterable acti public final CompletableFuture> addActivities(Activity... activities) throws StreamException { + return addActivities(activities, new RequestOption[0]); + } + + public final CompletableFuture> addActivities( + Activity[] activities, RequestOption... options) throws StreamException { return getClient() - .addActivities(id, activities) + .addActivities(id, activities, options) .thenApply( response -> { try { @@ -124,7 +131,7 @@ public final CompletableFuture> addCustomActivities(T... activities) .map(activity -> Activity.builder().fromCustomActivity(activity).build()) .toArray(Activity[]::new); return getClient() - .addActivities(id, custom) + .addActivities(id, custom, new RequestOption[0]) .thenApply( response -> { try { diff --git a/src/main/java/io/getstream/client/ReactionsClient.java b/src/main/java/io/getstream/client/ReactionsClient.java index c2658163..179284fc 100644 --- a/src/main/java/io/getstream/client/ReactionsClient.java +++ b/src/main/java/io/getstream/client/ReactionsClient.java @@ -15,6 +15,7 @@ import io.getstream.core.models.ReactionBatch; import io.getstream.core.options.Filter; import io.getstream.core.options.Limit; +import io.getstream.core.options.RequestOption; import io.getstream.core.utils.Auth.TokenAction; import io.getstream.core.utils.DefaultOptions; import java.util.List; @@ -168,10 +169,18 @@ public CompletableFuture add(String userID, Reaction reaction, FeedID. return reactions.add(token, userID, reaction, targetFeeds); } - public CompletableFuture add(String userID, Reaction reaction, FeedID[] targetFeeds, Map targetFeedsExtraData) + public CompletableFuture add( + String userID, Reaction reaction, FeedID[] targetFeeds, RequestOption... options) throws StreamException { final Token token = buildReactionsToken(secret, TokenAction.WRITE); - return reactions.add(token, userID, reaction, targetFeeds, targetFeedsExtraData); + return reactions.add(token, userID, reaction, targetFeeds, null, options); + } + + public CompletableFuture add( + String userID, Reaction reaction, FeedID[] targetFeeds, + Map targetFeedsExtraData, RequestOption... options) throws StreamException { + final Token token = buildReactionsToken(secret, TokenAction.WRITE); + return reactions.add(token, userID, reaction, targetFeeds, targetFeedsExtraData, options); } public CompletableFuture addChild( @@ -237,6 +246,12 @@ public CompletableFuture update(Reaction reaction, FeedID... targetFeeds) return reactions.update(token, reaction, targetFeeds); } + public CompletableFuture update( + Reaction reaction, FeedID[] targetFeeds, RequestOption... options) throws StreamException { + final Token token = buildReactionsToken(secret, TokenAction.WRITE); + return reactions.update(token, reaction, targetFeeds, options); + } + public CompletableFuture delete(String id) throws StreamException { final Token token = buildReactionsToken(secret, TokenAction.DELETE); return reactions.delete(token, id, false); diff --git a/src/main/java/io/getstream/cloud/CloudClient.java b/src/main/java/io/getstream/cloud/CloudClient.java index e2417ec4..328cb8a4 100644 --- a/src/main/java/io/getstream/cloud/CloudClient.java +++ b/src/main/java/io/getstream/cloud/CloudClient.java @@ -337,13 +337,19 @@ CompletableFuture getEnrichedActivities(FeedID feed, RequestOption... return stream.getEnrichedActivities(token, feed, options); } - CompletableFuture addActivity(FeedID feed, Activity activity) throws StreamException { - return stream.addActivity(token, feed, activity); + CompletableFuture addActivity(FeedID feed, Activity activity, RequestOption... options) + throws StreamException { + return stream.addActivity(token, feed, activity, options); } CompletableFuture addActivities(FeedID feed, Activity... activities) throws StreamException { - return stream.addActivities(token, feed, activities); + return addActivities(feed, activities, new RequestOption[0]); + } + + CompletableFuture addActivities( + FeedID feed, Activity[] activities, RequestOption... options) throws StreamException { + return stream.addActivities(token, feed, activities, options); } CompletableFuture removeActivityByID(FeedID feed, String id) throws StreamException { diff --git a/src/main/java/io/getstream/cloud/CloudFeed.java b/src/main/java/io/getstream/cloud/CloudFeed.java index 07673c01..04506392 100644 --- a/src/main/java/io/getstream/cloud/CloudFeed.java +++ b/src/main/java/io/getstream/cloud/CloudFeed.java @@ -69,9 +69,10 @@ public final String getUserID() { return id.getUserID(); } - public final CompletableFuture addActivity(Activity activity) throws StreamException { + public final CompletableFuture addActivity(Activity activity, RequestOption... options) + throws StreamException { return getClient() - .addActivity(id, activity) + .addActivity(id, activity, options) .thenApply( response -> { try { @@ -82,9 +83,10 @@ public final CompletableFuture addActivity(Activity activity) throws S }); } - public final CompletableFuture addCustomActivity(T activity) throws StreamException { + public final CompletableFuture addCustomActivity(T activity, RequestOption... options) + throws StreamException { return getClient() - .addActivity(id, Activity.builder().fromCustomActivity(activity).build()) + .addActivity(id, Activity.builder().fromCustomActivity(activity).build(), options) .thenApply( response -> { try { @@ -97,7 +99,7 @@ public final CompletableFuture addCustomActivity(T activity) throws Strea public final CompletableFuture> addActivities(Iterable activities) throws StreamException { - return addActivities(Iterables.toArray(activities, Activity.class)); + return addActivities(Iterables.toArray(activities, Activity.class), new RequestOption[0]); } public final CompletableFuture> addCustomActivities(Iterable activities) @@ -107,7 +109,7 @@ public final CompletableFuture> addCustomActivities(Iterable acti .map(activity -> Activity.builder().fromCustomActivity(activity).build()) .toArray(Activity[]::new); return getClient() - .addActivities(id, custom) + .addActivities(id, custom, new RequestOption[0]) .thenApply( (Response response) -> { try { @@ -124,8 +126,13 @@ public final CompletableFuture> addCustomActivities(Iterable acti public final CompletableFuture> addActivities(Activity... activities) throws StreamException { + return addActivities(activities, new RequestOption[0]); + } + + public final CompletableFuture> addActivities( + Activity[] activities, RequestOption... options) throws StreamException { return getClient() - .addActivities(id, activities) + .addActivities(id, activities, options) .thenApply( (Response response) -> { try { @@ -143,7 +150,7 @@ public final CompletableFuture> addCustomActivities(T... activities) .map(activity -> Activity.builder().fromCustomActivity(activity).build()) .toArray(Activity[]::new); return getClient() - .addActivities(id, custom) + .addActivities(id, custom, new RequestOption[0]) .thenApply( (Response response) -> { try { diff --git a/src/main/java/io/getstream/cloud/CloudReactionsClient.java b/src/main/java/io/getstream/cloud/CloudReactionsClient.java index ab04d5a4..099c5187 100644 --- a/src/main/java/io/getstream/cloud/CloudReactionsClient.java +++ b/src/main/java/io/getstream/cloud/CloudReactionsClient.java @@ -12,6 +12,7 @@ import io.getstream.core.models.Reaction; import io.getstream.core.options.Filter; import io.getstream.core.options.Limit; +import io.getstream.core.options.RequestOption; import io.getstream.core.utils.DefaultOptions; import java.util.List; import java.util.Map; @@ -151,9 +152,16 @@ public CompletableFuture add(String userID, Reaction reaction, FeedID. return reactions.add(token, userID, reaction, targetFeeds); } - public CompletableFuture add(String userID, Reaction reaction, FeedID[] targetFeeds, Map targetFeedsExtraData) + public CompletableFuture add( + String userID, Reaction reaction, FeedID[] targetFeeds, RequestOption... options) throws StreamException { - return reactions.add(token, userID, reaction, targetFeeds, targetFeedsExtraData); + return reactions.add(token, userID, reaction, targetFeeds, null, options); + } + + public CompletableFuture add( + String userID, Reaction reaction, FeedID[] targetFeeds, + Map targetFeedsExtraData, RequestOption... options) throws StreamException { + return reactions.add(token, userID, reaction, targetFeeds, targetFeedsExtraData, options); } public CompletableFuture addChild( @@ -218,6 +226,11 @@ public CompletableFuture update(Reaction reaction, FeedID... targetFeeds) return reactions.update(token, reaction, targetFeeds); } + public CompletableFuture update( + Reaction reaction, FeedID[] targetFeeds, RequestOption... options) throws StreamException { + return reactions.update(token, reaction, targetFeeds, options); + } + public CompletableFuture delete(String id) throws StreamException { return reactions.delete(token, id, false); } diff --git a/src/main/java/io/getstream/core/Stream.java b/src/main/java/io/getstream/core/Stream.java index 897817c9..895f5254 100644 --- a/src/main/java/io/getstream/core/Stream.java +++ b/src/main/java/io/getstream/core/Stream.java @@ -72,7 +72,7 @@ public StreamImages images() { } public CompletableFuture> updateActivitiesByID( - Token token, ActivityUpdate[] updates) throws StreamException { + Token token, ActivityUpdate[] updates, RequestOption... options) throws StreamException { checkNotNull(updates, "No updates"); checkArgument(updates.length > 0, "No updates"); for (ActivityUpdate update : updates) { @@ -89,7 +89,7 @@ public CompletableFuture> updateActivitiesByID( }); final URL url = buildActivityUpdateURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -104,7 +104,8 @@ public CompletableFuture> updateActivitiesByID( } public CompletableFuture updateActivityByID( - Token token, String id, Map set, String[] unset) throws StreamException { + Token token, String id, Map set, String[] unset, RequestOption... options) + throws StreamException { checkNotNull(id, "No activity to update"); checkNotNull(set, "No activity properties to set"); checkNotNull(unset, "No activity properties to unset"); @@ -123,7 +124,7 @@ public CompletableFuture updateActivityByID( }); final URL url = buildActivityUpdateURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -138,7 +139,7 @@ public CompletableFuture updateActivityByID( } public CompletableFuture> updateActivitiesByForeignID( - Token token, ActivityUpdate[] updates) throws StreamException { + Token token, ActivityUpdate[] updates, RequestOption... options) throws StreamException { checkNotNull(updates, "No updates"); checkArgument(updates.length > 0, "No updates"); for (ActivityUpdate update : updates) { @@ -156,7 +157,7 @@ public CompletableFuture> updateActivitiesByForeignID( }); final URL url = buildActivityUpdateURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -171,7 +172,12 @@ public CompletableFuture> updateActivitiesByForeignID( } public CompletableFuture updateActivityByForeignID( - Token token, String foreignID, Date timestamp, Map set, String[] unset) + Token token, + String foreignID, + Date timestamp, + Map set, + String[] unset, + RequestOption... options) throws StreamException { checkNotNull(foreignID, "No activity to update"); checkNotNull(timestamp, "Missing timestamp"); @@ -199,7 +205,7 @@ public CompletableFuture updateActivityByForeignID( }); final URL url = buildActivityUpdateURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -263,14 +269,14 @@ public CompletableFuture getEnrichedActivities( } } - public CompletableFuture addActivity(Token token, FeedID feed, Activity activity) - throws StreamException { + public CompletableFuture addActivity( + Token token, FeedID feed, Activity activity, RequestOption... options) throws StreamException { checkNotNull(activity, "No activity to add"); try { final byte[] payload = toJSON(activity); final URL url = buildFeedURL(baseURL, feed, "/"); - return httpClient.execute(buildPost(url, key, token, payload)); + return httpClient.execute(buildPost(url, key, token, payload, options)); } catch (JsonProcessingException | MalformedURLException | URISyntaxException e) { throw new StreamException(e); } @@ -278,6 +284,12 @@ public CompletableFuture addActivity(Token token, FeedID feed, Activit public CompletableFuture addActivities( Token token, FeedID feed, Activity... activityObjects) throws StreamException { + return addActivities(token, feed, activityObjects, new RequestOption[0]); + } + + public CompletableFuture addActivities( + Token token, FeedID feed, Activity[] activityObjects, RequestOption... options) + throws StreamException { checkNotNull(activityObjects, "No activities to add"); try { @@ -287,7 +299,7 @@ public CompletableFuture addActivities( public final Activity[] activities = activityObjects; }); final URL url = buildFeedURL(baseURL, feed, "/"); - return httpClient.execute(buildPost(url, key, token, payload)); + return httpClient.execute(buildPost(url, key, token, payload, options)); } catch (JsonProcessingException | MalformedURLException | URISyntaxException e) { throw new StreamException(e); } diff --git a/src/main/java/io/getstream/core/StreamReactions.java b/src/main/java/io/getstream/core/StreamReactions.java index 1bbba031..cb9c7357 100644 --- a/src/main/java/io/getstream/core/StreamReactions.java +++ b/src/main/java/io/getstream/core/StreamReactions.java @@ -208,7 +208,7 @@ public CompletableFuture add( } public CompletableFuture add( - Token token, String userID, Reaction reaction, FeedID[] targetFeeds, Map targetFeedsExtraData) throws StreamException { + Token token, String userID, Reaction reaction, FeedID[] targetFeeds, Map targetFeedsExtraData, RequestOption... options) throws StreamException { checkNotNull(reaction, "Reaction can't be null"); checkArgument( reaction.getActivityID() != null || reaction.getParent() != null, @@ -256,7 +256,7 @@ public CompletableFuture add( final byte[] payload = toJSON(payloadBuilder.build()); final URL url = buildReactionsURL(baseURL); return httpClient - .execute(buildPost(url, key, token, payload)) + .execute(buildPost(url, key, token, payload, options)) .thenApply( response -> { try { @@ -272,6 +272,12 @@ public CompletableFuture add( public CompletableFuture update(Token token, Reaction reaction, FeedID... targetFeeds) throws StreamException { + return update(token, reaction, targetFeeds, new RequestOption[0]); + } + + public CompletableFuture update( + Token token, Reaction reaction, FeedID[] targetFeeds, RequestOption... options) + throws StreamException { checkNotNull(reaction, "Reaction can't be null"); checkNotNull(reaction.getId(), "Reaction id can't be null"); checkArgument(!reaction.getId().isEmpty(), "Reaction id can't be empty"); @@ -291,7 +297,7 @@ public CompletableFuture update(Token token, Reaction reaction, FeedID... final byte[] payload = toJSON(payloadBuilder.build()); final URL url = buildReactionsURL(baseURL, reaction.getId() + '/'); return httpClient - .execute(buildPut(url, key, token, payload)) + .execute(buildPut(url, key, token, payload, options)) .thenApply( response -> { try { diff --git a/src/test/java/io/getstream/client/BatchClientTest.java b/src/test/java/io/getstream/client/BatchClientTest.java index 7a88f8ed..3bf27f89 100644 --- a/src/test/java/io/getstream/client/BatchClientTest.java +++ b/src/test/java/io/getstream/client/BatchClientTest.java @@ -3,6 +3,7 @@ import com.google.common.collect.ImmutableMap; import io.getstream.core.KeepHistory; import io.getstream.core.models.*; +import io.getstream.core.options.CustomQueryParameter; import java.text.SimpleDateFormat; import java.util.*; import org.junit.Test; @@ -161,6 +162,83 @@ public void partiallyUpdateActivitiesByForeignID() throws Exception { List result = client.updateActivitiesByForeignID(update).join(); } + @Test + public void partiallyUpdateActivityByIDWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + Map set = ImmutableMap.of("value", "message"); + Iterable unset = Collections.emptyList(); + Activity result = + client + .updateActivityByID( + "1657b300-a648-11d5-8080-800020fde6c3", + set, + new String[0], + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + + @Test + public void partiallyUpdateActivitiesByIDWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + ActivityUpdate update = + ActivityUpdate.builder() + .id("1657b300-a648-11d5-8080-800020fde6c3") + .set(ImmutableMap.of("value", "message")) + .unset(Collections.emptyList()) + .build(); + + List result = + client + .updateActivitiesByID( + new ActivityUpdate[] {update}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + + @Test + public void partiallyUpdateActivityByForeignIDWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"); + isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + Date time = isoFormat.parse("2001-09-11T00:01:02.000000"); + + Activity result = + client + .updateActivityByForeignID( + "foreignID", + time, + ImmutableMap.of("value", "message"), + new String[0], + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + + @Test + public void partiallyUpdateActivitiesByForeignIDWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"); + isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + ActivityUpdate update = + ActivityUpdate.builder() + .foreignID("foreignID") + .time(isoFormat.parse("2001-09-11T00:01:02.000000")) + .set(ImmutableMap.of("value", "message")) + .unset(Collections.emptyList()) + .build(); + + List result = + client + .updateActivitiesByForeignID( + new ActivityUpdate[] {update}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + @Test public void getActivitiesByID() throws Exception { BatchClient client = Client.builder(apiKey, secret).build().batch(); diff --git a/src/test/java/io/getstream/client/FeedTest.java b/src/test/java/io/getstream/client/FeedTest.java index c38dd1d7..5705651d 100644 --- a/src/test/java/io/getstream/client/FeedTest.java +++ b/src/test/java/io/getstream/client/FeedTest.java @@ -10,6 +10,7 @@ import io.getstream.core.models.Activity; import io.getstream.core.models.FeedID; import io.getstream.core.models.FollowStats; +import io.getstream.core.options.CustomQueryParameter; import java.net.MalformedURLException; import java.util.Collections; import java.util.Date; @@ -50,6 +51,25 @@ public void addActivity() throws Exception { Activity result = feed.addActivity(activity).join(); } + @Test + public void addActivityWithRequestOptions() throws Exception { + Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); + FlatFeed feed = client.flatFeed("flat", "1"); + Activity result = + feed.addActivity(activity, new CustomQueryParameter("skip_moderation", "true")).join(); + } + + @Test + public void addActivitiesWithRequestOptions() throws Exception { + Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); + FlatFeed feed = client.flatFeed("flat", "1"); + List result = + feed.addActivities( + new Activity[] {activity}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + @Test public void addActivities() throws Exception { Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); diff --git a/src/test/java/io/getstream/client/ReactionsClientTest.java b/src/test/java/io/getstream/client/ReactionsClientTest.java index da11c692..48f204d3 100644 --- a/src/test/java/io/getstream/client/ReactionsClientTest.java +++ b/src/test/java/io/getstream/client/ReactionsClientTest.java @@ -8,6 +8,7 @@ import java.util.function.Function; import java.util.stream.Collectors; +import io.getstream.core.options.CustomQueryParameter; import io.getstream.core.options.Filter; import io.getstream.core.options.Limit; import org.junit.Test; @@ -188,6 +189,41 @@ public void update() throws Exception { client.reactions().update(data, new FeedID("flat", "1")).join(); } + @Test + public void addWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + Reaction data = + Reaction.builder().activityID("ed2837a6-0a3b-4679-adc1-778a1704852d").kind("like").build(); + client + .reactions() + .add( + "user-id", + data, + new FeedID[] {new FeedID("flat", "1")}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + + @Test + public void updateWithRequestOptions() throws Exception { + Client client = Client.builder(apiKey, secret).build(); + + Reaction data = + Reaction.builder() + .id("b5c46f9b-0839-4207-86aa-6a7f388b7748") + .kind("like") + .extraField("key", "value") + .build(); + client + .reactions() + .update( + data, + new FeedID[] {new FeedID("flat", "1")}, + new CustomQueryParameter("skip_moderation", "true")) + .join(); + } + @Test public void delete() throws Exception { Client client = Client.builder(apiKey, secret).build(); From dd096cb97d8451f702f2cf7246beffab197301b3 Mon Sep 17 00:00:00 2001 From: Jimmy Pettersson Date: Fri, 20 Feb 2026 09:07:07 +0100 Subject: [PATCH 3/7] tests --- .../io/getstream/client/BatchClientTest.java | 103 ++++++++++++++---- .../java/io/getstream/client/FeedTest.java | 52 +++++++-- .../getstream/client/ReactionsClientTest.java | 82 +++++++++++--- 3 files changed, 187 insertions(+), 50 deletions(-) diff --git a/src/test/java/io/getstream/client/BatchClientTest.java b/src/test/java/io/getstream/client/BatchClientTest.java index 3bf27f89..8252503b 100644 --- a/src/test/java/io/getstream/client/BatchClientTest.java +++ b/src/test/java/io/getstream/client/BatchClientTest.java @@ -1,5 +1,9 @@ package io.getstream.client; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + import com.google.common.collect.ImmutableMap; import io.getstream.core.KeepHistory; import io.getstream.core.models.*; @@ -163,29 +167,54 @@ public void partiallyUpdateActivitiesByForeignID() throws Exception { } @Test - public void partiallyUpdateActivityByIDWithRequestOptions() throws Exception { + public void partiallyUpdateActivityByIDSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - Map set = ImmutableMap.of("value", "message"); - Iterable unset = Collections.emptyList(); - Activity result = + Activity activity = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "safe text") + .foreignID(UUID.randomUUID().toString()) + .time(new Date()) + .build(); + Activity created = client.flatFeed("user", "1").addActivity(activity).join(); + assertNotNull(created.getModerationResponse()); + assertEquals("keep", created.getModerationResponse().getRecommendedAction()); + + Activity updated = client .updateActivityByID( - "1657b300-a648-11d5-8080-800020fde6c3", - set, + created.getID(), + ImmutableMap.of("text", "pissoar"), new String[0], new CustomQueryParameter("skip_moderation", "true")) .join(); + assertNull(updated.getModerationResponse()); } @Test - public void partiallyUpdateActivitiesByIDWithRequestOptions() throws Exception { + public void partiallyUpdateActivitiesByIDSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); + Activity activity = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "safe text") + .foreignID(UUID.randomUUID().toString()) + .time(new Date()) + .build(); + Activity created = client.flatFeed("user", "1").addActivity(activity).join(); + ActivityUpdate update = ActivityUpdate.builder() - .id("1657b300-a648-11d5-8080-800020fde6c3") - .set(ImmutableMap.of("value", "message")) + .id(created.getID()) + .set(ImmutableMap.of("text", "pissoar")) .unset(Collections.emptyList()) .build(); @@ -195,39 +224,67 @@ public void partiallyUpdateActivitiesByIDWithRequestOptions() throws Exception { new ActivityUpdate[] {update}, new CustomQueryParameter("skip_moderation", "true")) .join(); + assertEquals(1, result.size()); + assertNull(result.get(0).getModerationResponse()); } @Test - public void partiallyUpdateActivityByForeignIDWithRequestOptions() throws Exception { + public void partiallyUpdateActivityByForeignIDSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"); - isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - Date time = isoFormat.parse("2001-09-11T00:01:02.000000"); + String foreignID = UUID.randomUUID().toString(); + Date time = new Date(); - Activity result = + Activity activity = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "safe text") + .foreignID(foreignID) + .time(time) + .build(); + Activity created = client.flatFeed("user", "1").addActivity(activity).join(); + assertNotNull(created.getModerationResponse()); + assertEquals("keep", created.getModerationResponse().getRecommendedAction()); + + Activity updated = client .updateActivityByForeignID( - "foreignID", + foreignID, time, - ImmutableMap.of("value", "message"), + ImmutableMap.of("text", "pissoar"), new String[0], new CustomQueryParameter("skip_moderation", "true")) .join(); + assertNull(updated.getModerationResponse()); } @Test - public void partiallyUpdateActivitiesByForeignIDWithRequestOptions() throws Exception { + public void partiallyUpdateActivitiesByForeignIDSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"); - isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + String foreignID = UUID.randomUUID().toString(); + Date time = new Date(); + + Activity activity = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "safe text") + .foreignID(foreignID) + .time(time) + .build(); + client.flatFeed("user", "1").addActivity(activity).join(); ActivityUpdate update = ActivityUpdate.builder() - .foreignID("foreignID") - .time(isoFormat.parse("2001-09-11T00:01:02.000000")) - .set(ImmutableMap.of("value", "message")) + .foreignID(foreignID) + .time(time) + .set(ImmutableMap.of("text", "pissoar")) .unset(Collections.emptyList()) .build(); @@ -237,6 +294,8 @@ public void partiallyUpdateActivitiesByForeignIDWithRequestOptions() throws Exce new ActivityUpdate[] {update}, new CustomQueryParameter("skip_moderation", "true")) .join(); + assertEquals(1, result.size()); + assertNull(result.get(0).getModerationResponse()); } @Test diff --git a/src/test/java/io/getstream/client/FeedTest.java b/src/test/java/io/getstream/client/FeedTest.java index 5705651d..4506327e 100644 --- a/src/test/java/io/getstream/client/FeedTest.java +++ b/src/test/java/io/getstream/client/FeedTest.java @@ -1,6 +1,8 @@ package io.getstream.client; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import com.google.common.collect.Lists; import io.getstream.client.entities.FootballMatch; @@ -10,6 +12,7 @@ import io.getstream.core.models.Activity; import io.getstream.core.models.FeedID; import io.getstream.core.models.FollowStats; +import io.getstream.core.models.ModerationResponse; import io.getstream.core.options.CustomQueryParameter; import java.net.MalformedURLException; import java.util.Collections; @@ -52,22 +55,51 @@ public void addActivity() throws Exception { } @Test - public void addActivityWithRequestOptions() throws Exception { - Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); - FlatFeed feed = client.flatFeed("flat", "1"); - Activity result = - feed.addActivity(activity, new CustomQueryParameter("skip_moderation", "true")).join(); + public void addActivitySkipModeration() throws Exception { + FlatFeed feed = client.flatFeed("user", "1"); + + Activity blocked = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "pissoar") + .foreignID(UUID.randomUUID().toString()) + .time(new Date()) + .build(); + + Activity withModeration = feed.addActivity(blocked).join(); + assertNotNull(withModeration.getModerationResponse()); + assertEquals("remove", withModeration.getModerationResponse().getRecommendedAction()); + + Activity withoutModeration = + feed.addActivity(blocked, new CustomQueryParameter("skip_moderation", "true")).join(); + assertNull(withoutModeration.getModerationResponse()); } @Test - public void addActivitiesWithRequestOptions() throws Exception { - Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); - FlatFeed feed = client.flatFeed("flat", "1"); - List result = + public void addActivitiesSkipModeration() throws Exception { + FlatFeed feed = client.flatFeed("user", "1"); + + Activity blocked = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "pissoar") + .foreignID(UUID.randomUUID().toString()) + .time(new Date()) + .build(); + + List withoutModeration = feed.addActivities( - new Activity[] {activity}, + new Activity[] {blocked}, new CustomQueryParameter("skip_moderation", "true")) .join(); + assertEquals(1, withoutModeration.size()); + assertNull(withoutModeration.get(0).getModerationResponse()); } @Test diff --git a/src/test/java/io/getstream/client/ReactionsClientTest.java b/src/test/java/io/getstream/client/ReactionsClientTest.java index 48f204d3..55afcaab 100644 --- a/src/test/java/io/getstream/client/ReactionsClientTest.java +++ b/src/test/java/io/getstream/client/ReactionsClientTest.java @@ -14,6 +14,8 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; public class ReactionsClientTest { private static final String apiKey = @@ -190,38 +192,82 @@ public void update() throws Exception { } @Test - public void addWithRequestOptions() throws Exception { + public void addReactionSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - Reaction data = - Reaction.builder().activityID("ed2837a6-0a3b-4679-adc1-778a1704852d").kind("like").build(); - client - .reactions() - .add( - "user-id", - data, - new FeedID[] {new FeedID("flat", "1")}, - new CustomQueryParameter("skip_moderation", "true")) - .join(); + Activity activity = + client + .flatFeed("user", "reactor") + .addActivity( + Activity.builder().actor("test").verb("post").object("test").build()) + .join(); + + Reaction blocked = + Reaction.builder() + .activityID(activity.getID()) + .kind("comment") + .userID("test-user") + .extraField("text", "pissoar") + .moderationTemplate("moderation_template_reaction") + .build(); + + Reaction withModeration = client.reactions().add("test-user", blocked).join(); + assertNotNull(withModeration.getModerationResponse()); + assertEquals("remove", withModeration.getModerationResponse().getRecommendedAction()); + + Reaction withoutModeration = + client + .reactions() + .add( + "test-user", + blocked, + new FeedID[0], + new CustomQueryParameter("skip_moderation", "true")) + .join(); + assertNull(withoutModeration.getModerationResponse()); } @Test - public void updateWithRequestOptions() throws Exception { + public void updateReactionSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - Reaction data = + Activity activity = + client + .flatFeed("user", "reactor") + .addActivity( + Activity.builder().actor("test").verb("post").object("test").build()) + .join(); + + Reaction safe = Reaction.builder() - .id("b5c46f9b-0839-4207-86aa-6a7f388b7748") - .kind("like") - .extraField("key", "value") + .activityID(activity.getID()) + .kind("comment") + .userID("test-user") + .extraField("text", "safe text") + .moderationTemplate("moderation_template_reaction") + .build(); + Reaction created = client.reactions().add("test-user", safe).join(); + assertNotNull(created.getModerationResponse()); + assertEquals("keep", created.getModerationResponse().getRecommendedAction()); + + Reaction blockedUpdate = + Reaction.builder() + .id(created.getId()) + .kind("comment") + .extraField("text", "pissoar") + .moderationTemplate("moderation_template_reaction") .build(); client .reactions() .update( - data, - new FeedID[] {new FeedID("flat", "1")}, + blockedUpdate, + new FeedID[0], new CustomQueryParameter("skip_moderation", "true")) .join(); + + Reaction fetched = client.reactions().get(created.getId()).join(); + ModerationResponse m = fetched.getModerationResponse(); + assertEquals("keep", m.getRecommendedAction()); } @Test From 54563d767a55b9b81ff69e499fda275b7ef24295 Mon Sep 17 00:00:00 2001 From: Jimmy Pettersson Date: Fri, 20 Feb 2026 09:07:07 +0100 Subject: [PATCH 4/7] chore: tests --- .../io/getstream/client/BatchClientTest.java | 103 ++++++++++++++---- .../java/io/getstream/client/FeedTest.java | 52 +++++++-- .../getstream/client/ReactionsClientTest.java | 82 +++++++++++--- 3 files changed, 187 insertions(+), 50 deletions(-) diff --git a/src/test/java/io/getstream/client/BatchClientTest.java b/src/test/java/io/getstream/client/BatchClientTest.java index 3bf27f89..8252503b 100644 --- a/src/test/java/io/getstream/client/BatchClientTest.java +++ b/src/test/java/io/getstream/client/BatchClientTest.java @@ -1,5 +1,9 @@ package io.getstream.client; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + import com.google.common.collect.ImmutableMap; import io.getstream.core.KeepHistory; import io.getstream.core.models.*; @@ -163,29 +167,54 @@ public void partiallyUpdateActivitiesByForeignID() throws Exception { } @Test - public void partiallyUpdateActivityByIDWithRequestOptions() throws Exception { + public void partiallyUpdateActivityByIDSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - Map set = ImmutableMap.of("value", "message"); - Iterable unset = Collections.emptyList(); - Activity result = + Activity activity = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "safe text") + .foreignID(UUID.randomUUID().toString()) + .time(new Date()) + .build(); + Activity created = client.flatFeed("user", "1").addActivity(activity).join(); + assertNotNull(created.getModerationResponse()); + assertEquals("keep", created.getModerationResponse().getRecommendedAction()); + + Activity updated = client .updateActivityByID( - "1657b300-a648-11d5-8080-800020fde6c3", - set, + created.getID(), + ImmutableMap.of("text", "pissoar"), new String[0], new CustomQueryParameter("skip_moderation", "true")) .join(); + assertNull(updated.getModerationResponse()); } @Test - public void partiallyUpdateActivitiesByIDWithRequestOptions() throws Exception { + public void partiallyUpdateActivitiesByIDSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); + Activity activity = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "safe text") + .foreignID(UUID.randomUUID().toString()) + .time(new Date()) + .build(); + Activity created = client.flatFeed("user", "1").addActivity(activity).join(); + ActivityUpdate update = ActivityUpdate.builder() - .id("1657b300-a648-11d5-8080-800020fde6c3") - .set(ImmutableMap.of("value", "message")) + .id(created.getID()) + .set(ImmutableMap.of("text", "pissoar")) .unset(Collections.emptyList()) .build(); @@ -195,39 +224,67 @@ public void partiallyUpdateActivitiesByIDWithRequestOptions() throws Exception { new ActivityUpdate[] {update}, new CustomQueryParameter("skip_moderation", "true")) .join(); + assertEquals(1, result.size()); + assertNull(result.get(0).getModerationResponse()); } @Test - public void partiallyUpdateActivityByForeignIDWithRequestOptions() throws Exception { + public void partiallyUpdateActivityByForeignIDSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"); - isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - Date time = isoFormat.parse("2001-09-11T00:01:02.000000"); + String foreignID = UUID.randomUUID().toString(); + Date time = new Date(); - Activity result = + Activity activity = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "safe text") + .foreignID(foreignID) + .time(time) + .build(); + Activity created = client.flatFeed("user", "1").addActivity(activity).join(); + assertNotNull(created.getModerationResponse()); + assertEquals("keep", created.getModerationResponse().getRecommendedAction()); + + Activity updated = client .updateActivityByForeignID( - "foreignID", + foreignID, time, - ImmutableMap.of("value", "message"), + ImmutableMap.of("text", "pissoar"), new String[0], new CustomQueryParameter("skip_moderation", "true")) .join(); + assertNull(updated.getModerationResponse()); } @Test - public void partiallyUpdateActivitiesByForeignIDWithRequestOptions() throws Exception { + public void partiallyUpdateActivitiesByForeignIDSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"); - isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + String foreignID = UUID.randomUUID().toString(); + Date time = new Date(); + + Activity activity = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "safe text") + .foreignID(foreignID) + .time(time) + .build(); + client.flatFeed("user", "1").addActivity(activity).join(); ActivityUpdate update = ActivityUpdate.builder() - .foreignID("foreignID") - .time(isoFormat.parse("2001-09-11T00:01:02.000000")) - .set(ImmutableMap.of("value", "message")) + .foreignID(foreignID) + .time(time) + .set(ImmutableMap.of("text", "pissoar")) .unset(Collections.emptyList()) .build(); @@ -237,6 +294,8 @@ public void partiallyUpdateActivitiesByForeignIDWithRequestOptions() throws Exce new ActivityUpdate[] {update}, new CustomQueryParameter("skip_moderation", "true")) .join(); + assertEquals(1, result.size()); + assertNull(result.get(0).getModerationResponse()); } @Test diff --git a/src/test/java/io/getstream/client/FeedTest.java b/src/test/java/io/getstream/client/FeedTest.java index 5705651d..4506327e 100644 --- a/src/test/java/io/getstream/client/FeedTest.java +++ b/src/test/java/io/getstream/client/FeedTest.java @@ -1,6 +1,8 @@ package io.getstream.client; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import com.google.common.collect.Lists; import io.getstream.client.entities.FootballMatch; @@ -10,6 +12,7 @@ import io.getstream.core.models.Activity; import io.getstream.core.models.FeedID; import io.getstream.core.models.FollowStats; +import io.getstream.core.models.ModerationResponse; import io.getstream.core.options.CustomQueryParameter; import java.net.MalformedURLException; import java.util.Collections; @@ -52,22 +55,51 @@ public void addActivity() throws Exception { } @Test - public void addActivityWithRequestOptions() throws Exception { - Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); - FlatFeed feed = client.flatFeed("flat", "1"); - Activity result = - feed.addActivity(activity, new CustomQueryParameter("skip_moderation", "true")).join(); + public void addActivitySkipModeration() throws Exception { + FlatFeed feed = client.flatFeed("user", "1"); + + Activity blocked = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "pissoar") + .foreignID(UUID.randomUUID().toString()) + .time(new Date()) + .build(); + + Activity withModeration = feed.addActivity(blocked).join(); + assertNotNull(withModeration.getModerationResponse()); + assertEquals("remove", withModeration.getModerationResponse().getRecommendedAction()); + + Activity withoutModeration = + feed.addActivity(blocked, new CustomQueryParameter("skip_moderation", "true")).join(); + assertNull(withoutModeration.getModerationResponse()); } @Test - public void addActivitiesWithRequestOptions() throws Exception { - Activity activity = Activity.builder().actor("test").verb("test").object("test").build(); - FlatFeed feed = client.flatFeed("flat", "1"); - List result = + public void addActivitiesSkipModeration() throws Exception { + FlatFeed feed = client.flatFeed("user", "1"); + + Activity blocked = + Activity.builder() + .actor("test") + .verb("test") + .object("test") + .moderationTemplate("moderation_template_activity") + .extraField("text", "pissoar") + .foreignID(UUID.randomUUID().toString()) + .time(new Date()) + .build(); + + List withoutModeration = feed.addActivities( - new Activity[] {activity}, + new Activity[] {blocked}, new CustomQueryParameter("skip_moderation", "true")) .join(); + assertEquals(1, withoutModeration.size()); + assertNull(withoutModeration.get(0).getModerationResponse()); } @Test diff --git a/src/test/java/io/getstream/client/ReactionsClientTest.java b/src/test/java/io/getstream/client/ReactionsClientTest.java index 48f204d3..55afcaab 100644 --- a/src/test/java/io/getstream/client/ReactionsClientTest.java +++ b/src/test/java/io/getstream/client/ReactionsClientTest.java @@ -14,6 +14,8 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; public class ReactionsClientTest { private static final String apiKey = @@ -190,38 +192,82 @@ public void update() throws Exception { } @Test - public void addWithRequestOptions() throws Exception { + public void addReactionSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - Reaction data = - Reaction.builder().activityID("ed2837a6-0a3b-4679-adc1-778a1704852d").kind("like").build(); - client - .reactions() - .add( - "user-id", - data, - new FeedID[] {new FeedID("flat", "1")}, - new CustomQueryParameter("skip_moderation", "true")) - .join(); + Activity activity = + client + .flatFeed("user", "reactor") + .addActivity( + Activity.builder().actor("test").verb("post").object("test").build()) + .join(); + + Reaction blocked = + Reaction.builder() + .activityID(activity.getID()) + .kind("comment") + .userID("test-user") + .extraField("text", "pissoar") + .moderationTemplate("moderation_template_reaction") + .build(); + + Reaction withModeration = client.reactions().add("test-user", blocked).join(); + assertNotNull(withModeration.getModerationResponse()); + assertEquals("remove", withModeration.getModerationResponse().getRecommendedAction()); + + Reaction withoutModeration = + client + .reactions() + .add( + "test-user", + blocked, + new FeedID[0], + new CustomQueryParameter("skip_moderation", "true")) + .join(); + assertNull(withoutModeration.getModerationResponse()); } @Test - public void updateWithRequestOptions() throws Exception { + public void updateReactionSkipModeration() throws Exception { Client client = Client.builder(apiKey, secret).build(); - Reaction data = + Activity activity = + client + .flatFeed("user", "reactor") + .addActivity( + Activity.builder().actor("test").verb("post").object("test").build()) + .join(); + + Reaction safe = Reaction.builder() - .id("b5c46f9b-0839-4207-86aa-6a7f388b7748") - .kind("like") - .extraField("key", "value") + .activityID(activity.getID()) + .kind("comment") + .userID("test-user") + .extraField("text", "safe text") + .moderationTemplate("moderation_template_reaction") + .build(); + Reaction created = client.reactions().add("test-user", safe).join(); + assertNotNull(created.getModerationResponse()); + assertEquals("keep", created.getModerationResponse().getRecommendedAction()); + + Reaction blockedUpdate = + Reaction.builder() + .id(created.getId()) + .kind("comment") + .extraField("text", "pissoar") + .moderationTemplate("moderation_template_reaction") .build(); client .reactions() .update( - data, - new FeedID[] {new FeedID("flat", "1")}, + blockedUpdate, + new FeedID[0], new CustomQueryParameter("skip_moderation", "true")) .join(); + + Reaction fetched = client.reactions().get(created.getId()).join(); + ModerationResponse m = fetched.getModerationResponse(); + assertEquals("keep", m.getRecommendedAction()); } @Test From b9a06d4ac7ec62304fba2f0f201c93a8a57bdbba Mon Sep 17 00:00:00 2001 From: Jimmy Pettersson Date: Fri, 20 Feb 2026 09:37:46 +0100 Subject: [PATCH 5/7] chore: fix test --- src/test/java/io/getstream/client/BatchClientTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/io/getstream/client/BatchClientTest.java b/src/test/java/io/getstream/client/BatchClientTest.java index 8252503b..55606d70 100644 --- a/src/test/java/io/getstream/client/BatchClientTest.java +++ b/src/test/java/io/getstream/client/BatchClientTest.java @@ -192,7 +192,7 @@ public void partiallyUpdateActivityByIDSkipModeration() throws Exception { new String[0], new CustomQueryParameter("skip_moderation", "true")) .join(); - assertNull(updated.getModerationResponse()); + assertEquals("keep", updated.getModerationResponse().getRecommendedAction()); } @Test @@ -225,7 +225,7 @@ public void partiallyUpdateActivitiesByIDSkipModeration() throws Exception { new CustomQueryParameter("skip_moderation", "true")) .join(); assertEquals(1, result.size()); - assertNull(result.get(0).getModerationResponse()); + assertEquals("keep", result.get(0).getModerationResponse().getRecommendedAction()); } @Test @@ -258,7 +258,7 @@ public void partiallyUpdateActivityByForeignIDSkipModeration() throws Exception new String[0], new CustomQueryParameter("skip_moderation", "true")) .join(); - assertNull(updated.getModerationResponse()); + assertEquals("keep", updated.getModerationResponse().getRecommendedAction()); } @Test @@ -295,7 +295,7 @@ public void partiallyUpdateActivitiesByForeignIDSkipModeration() throws Exceptio new CustomQueryParameter("skip_moderation", "true")) .join(); assertEquals(1, result.size()); - assertNull(result.get(0).getModerationResponse()); + assertEquals("keep", result.get(0).getModerationResponse().getRecommendedAction()); } @Test From 4800efb7b8eec72440f88330085fa5826dfedf8b Mon Sep 17 00:00:00 2001 From: Jimmy Pettersson Date: Fri, 20 Feb 2026 09:53:37 +0100 Subject: [PATCH 6/7] chore: fix test --- .../getstream/client/ReactionsClientTest.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/test/java/io/getstream/client/ReactionsClientTest.java b/src/test/java/io/getstream/client/ReactionsClientTest.java index 55afcaab..fa975464 100644 --- a/src/test/java/io/getstream/client/ReactionsClientTest.java +++ b/src/test/java/io/getstream/client/ReactionsClientTest.java @@ -197,30 +197,38 @@ public void addReactionSkipModeration() throws Exception { Activity activity = client - .flatFeed("user", "reactor") + .flatFeed("user", "1") .addActivity( - Activity.builder().actor("test").verb("post").object("test").build()) + Activity.builder().actor("test").verb("test").object("test").build()) .join(); Reaction blocked = Reaction.builder() .activityID(activity.getID()) - .kind("comment") - .userID("test-user") + .kind("like") + .userID("user123") .extraField("text", "pissoar") .moderationTemplate("moderation_template_reaction") .build(); - Reaction withModeration = client.reactions().add("test-user", blocked).join(); + Reaction withModeration = client.reactions().add("user", blocked).join(); assertNotNull(withModeration.getModerationResponse()); assertEquals("remove", withModeration.getModerationResponse().getRecommendedAction()); + Reaction skipped = + Reaction.builder() + .activityID(activity.getID()) + .kind("like") + .userID("user123") + .extraField("text", "pissoar") + .moderationTemplate("moderation_template_reaction") + .build(); Reaction withoutModeration = client .reactions() .add( - "test-user", - blocked, + "user", + skipped, new FeedID[0], new CustomQueryParameter("skip_moderation", "true")) .join(); @@ -233,27 +241,27 @@ public void updateReactionSkipModeration() throws Exception { Activity activity = client - .flatFeed("user", "reactor") + .flatFeed("user", "1") .addActivity( - Activity.builder().actor("test").verb("post").object("test").build()) + Activity.builder().actor("test").verb("test").object("test").build()) .join(); Reaction safe = Reaction.builder() .activityID(activity.getID()) - .kind("comment") - .userID("test-user") + .kind("like") + .userID("user123") .extraField("text", "safe text") .moderationTemplate("moderation_template_reaction") .build(); - Reaction created = client.reactions().add("test-user", safe).join(); + Reaction created = client.reactions().add("user", safe).join(); assertNotNull(created.getModerationResponse()); assertEquals("keep", created.getModerationResponse().getRecommendedAction()); Reaction blockedUpdate = Reaction.builder() .id(created.getId()) - .kind("comment") + .kind("like") .extraField("text", "pissoar") .moderationTemplate("moderation_template_reaction") .build(); From 217db6451e1fd7c9a5d4eca397f990533d2624e7 Mon Sep 17 00:00:00 2001 From: Jimmy Pettersson Date: Fri, 20 Feb 2026 10:10:33 +0100 Subject: [PATCH 7/7] chore: fix test --- src/test/java/io/getstream/client/ReactionsClientTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/io/getstream/client/ReactionsClientTest.java b/src/test/java/io/getstream/client/ReactionsClientTest.java index fa975464..a0d32a19 100644 --- a/src/test/java/io/getstream/client/ReactionsClientTest.java +++ b/src/test/java/io/getstream/client/ReactionsClientTest.java @@ -232,7 +232,10 @@ public void addReactionSkipModeration() throws Exception { new FeedID[0], new CustomQueryParameter("skip_moderation", "true")) .join(); - assertNull(withoutModeration.getModerationResponse()); + Map moderation = withoutModeration.getModeration(); + if (moderation != null) { + assertNull(moderation.get("response")); + } } @Test