diff --git a/src/main/java/io/getstream/core/StreamReactions.java b/src/main/java/io/getstream/core/StreamReactions.java index ab8702ff..87bab7f5 100644 --- a/src/main/java/io/getstream/core/StreamReactions.java +++ b/src/main/java/io/getstream/core/StreamReactions.java @@ -272,12 +272,15 @@ public CompletableFuture update(Token token, Reaction reaction, FeedID... J8Arrays.stream(targetFeeds).map(feed -> feed.toString()).toArray(String[]::new); try { - final byte[] payload = - toJSON( - new Object() { - public final Map data = reaction.getExtra(); - public final String[] target_feeds = targetFeedIDs; - }); + ImmutableMap.Builder payloadBuilder = ImmutableMap.builder(); + payloadBuilder.put("data", reaction.getExtra()); + payloadBuilder.put("target_feeds", targetFeedIDs); + + if (reaction.getModerationTemplate() != null) { + payloadBuilder.put("moderation_template", reaction.getModerationTemplate()); + } + + final byte[] payload = toJSON(payloadBuilder.build()); final URL url = buildReactionsURL(baseURL, reaction.getId() + '/'); return httpClient .execute(buildPut(url, key, token, payload)) diff --git a/src/test/java/io/getstream/client/ModerationClientTest.java b/src/test/java/io/getstream/client/ModerationClientTest.java index 0a2aeec0..4f6f19a5 100644 --- a/src/test/java/io/getstream/client/ModerationClientTest.java +++ b/src/test/java/io/getstream/client/ModerationClientTest.java @@ -136,4 +136,55 @@ public void testActivityModeratedReactions() throws Exception { assertEquals(m.getStatus(), "complete"); assertEquals(m.getRecommendedAction(), "remove"); } + + @Test + public void testReactionModerationDuringUpdate() throws Exception { + // Create a test activity first + Activity activity = Activity.builder() + .actor("test-user") + .verb("post") + .object("test-object") + .build(); + + // Add the activity to a test feed + Activity createdActivity = client.flatFeed("user", "test-user").addActivity(activity).join(); + String activityId = createdActivity.getID(); + + // Create initial reaction with safe text + Reaction initialReaction = Reaction.builder() + .activityID(activityId) + .kind("comment") + .userID("test-user") + .extraField("text", "This is a perfectly fine comment") + .moderationTemplate("moderation_template_reaction") + .build(); + + // Add reaction and verify it passes moderation + Reaction createdReaction = client.reactions().add("test-user", initialReaction).join(); + ModerationResponse initialModeration = createdReaction.getModerationResponse(); + assertEquals("keep", initialModeration.getRecommendedAction()); + + // Now update the reaction with text that should trigger moderation + Reaction updateData = Reaction.builder() + .id(createdReaction.getId()) + .kind("comment") + .extraField("text", "pissoar") // Using same blocked word as in testActivityModeratedReactions + .moderationTemplate("moderation_template_reaction") + .build(); + + // Update the reaction + client.reactions().update(updateData).join(); + + // Fetch the updated reaction and verify moderation was applied + Reaction updatedReaction = client.reactions().get(createdReaction.getId()).join(); + ModerationResponse updatedModeration = updatedReaction.getModerationResponse(); + + // With our fix to include moderation_template in updates, this should now be "remove" + assertEquals("complete", updatedModeration.getStatus()); + assertEquals("remove", updatedModeration.getRecommendedAction()); + + // Clean up + client.reactions().delete(createdReaction.getId(), false).join(); + client.flatFeed("user", "test-user").removeActivityByID(activityId).join(); + } }