Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 213 additions & 0 deletions src/main/java/io/getstream/chat/java/models/Moderation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package io.getstream.chat.java.models;

import com.fasterxml.jackson.annotation.*;
import io.getstream.chat.java.models.Moderation.UpsertConfigRequestData.UpsertConfigRequest;
import io.getstream.chat.java.models.framework.StreamRequest;
import io.getstream.chat.java.models.framework.StreamResponseObject;
import io.getstream.chat.java.services.ModerationService;
import io.getstream.chat.java.services.framework.Client;
import java.util.Date;
import java.util.List;
import lombok.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import retrofit2.Call;

@Data
@NoArgsConstructor
public class Moderation {

@Builder(
builderClassName = "ConfigGetRequest",
builderMethodName = "",
buildMethodName = "internalBuild")
public static class ConfigGetRequestData {
public static class ConfigGetRequest extends StreamRequest<ConfigGetResponse> {
@NotNull private String key;

private ConfigGetRequest(@NotNull String key) {
this.key = key;
}

@Override
protected Call<ConfigGetResponse> generateCall(Client client) {
return client.create(ModerationService.class).getConfig(this.key);
}
}
}

@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public static class ConfigGetResponse extends StreamResponseObject {
@Nullable
@JsonProperty("config")
private Config config;
}

@Data
@NoArgsConstructor
public static class Config {
@Nullable
@JsonProperty("key")
private String key;

@Nullable
@JsonProperty("async")
private Boolean async;

@Nullable
@JsonProperty("block_list_config")
private BlockListConfig blockListConfig;

@Nullable
@JsonProperty("created_at")
private Date createdAt;

@Nullable
@JsonProperty("updated_at")
private Date updatedAt;
}

@Data
@NoArgsConstructor
public static class BlockListConfig {
@Nullable
@JsonProperty("async")
private Boolean async;

@NotNull
@JsonProperty("enabled")
private Boolean enabled;

@NotNull
@JsonProperty("rules")
private List<BlockListRule> rules;
}

public enum Action {
@JsonProperty("flag")
FLAG,
@JsonProperty("shadow")
SHADOW,
@JsonProperty("remove")
REMOVE,
@JsonProperty("bounce")
BOUNCE,
@JsonProperty("bounce_flag")
BOUNCE_FLAG,
@JsonProperty("bounce_remove")
BOUNCE_REMOVE,
@JsonEnumDefaultValue
UNKNOWN
}

@Data
@NoArgsConstructor
@Builder
@AllArgsConstructor
public static class BlockListRule {
@NotNull
@JsonProperty("name")
private String name;

@NotNull
@JsonProperty("action")
private Action action;
}

@Builder
public static class BlockListConfigRequestObject {
@Nullable
@JsonProperty("async")
private Boolean async;

@NotNull
@JsonProperty("rules")
private List<BlockListRule> rules;
}

@Builder(
builderClassName = "UpsertConfigRequest",
builderMethodName = "",
buildMethodName = "internalBuild")
public static class UpsertConfigRequestData {
@Nullable
@JsonProperty("key")
private String key;

@Nullable
@JsonProperty("async")
private Boolean async;

@Nullable
@JsonProperty("block_list_config")
private BlockListConfigRequestObject blockListConfig;

public static class UpsertConfigRequest extends StreamRequest<UpsertConfigResponse> {
@NotNull private String key;

private UpsertConfigRequest(@NotNull String key) {
this.key = key;
}

@Override
protected Call<UpsertConfigResponse> generateCall(Client client) {
return client
.create(ModerationService.class)
.upsertConfig(this.key(this.key).internalBuild());
}
}
}

@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public static class UpsertConfigResponse extends StreamResponseObject {
@Nullable
@JsonProperty("config")
private Config config;
}

@RequiredArgsConstructor
public static class DeleteConfigRequest extends StreamRequest<StreamResponseObject> {
@NotNull private String key;

@Override
protected Call<StreamResponseObject> generateCall(Client client) {
return client.create(ModerationService.class).deleteConfig(this.key);
}
}

@RequiredArgsConstructor
public static class ConfigGetRequest extends StreamRequest<ConfigGetResponse> {
@NotNull private String key;

@Override
protected Call<ConfigGetResponse> generateCall(Client client) {
return client.create(ModerationService.class).getConfig(this.key);
}
}

/**
* Creates a get or create request
*
* @param type the channel type
* @param id the channel id
* @return the created request
*/
@NotNull
public static UpsertConfigRequest upsertConfig(@NotNull String key) {
return new UpsertConfigRequest(key);
}

@NotNull
public static DeleteConfigRequest deleteConfig(@NotNull String key) {
return new DeleteConfigRequest(key);
}

@NotNull
public static ConfigGetRequest getConfig(@NotNull String key) {
return new ConfigGetRequest(key);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.getstream.chat.java.services;

import io.getstream.chat.java.models.Moderation.*;
import io.getstream.chat.java.models.framework.StreamResponseObject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import retrofit2.Call;
import retrofit2.http.*;

public interface ModerationService {
@GET("api/v2/moderation/config/{key}")
Call<ConfigGetResponse> getConfig(@NotNull @Path("key") String key);

@DELETE("api/v2/moderation/config/{key}")
Call<StreamResponseObject> deleteConfig(@NotNull @Path("key") String key);

@POST("api/v2/moderation/config")
Call<UpsertConfigResponse> upsertConfig(@Nullable @Body UpsertConfigRequestData upsertConfig);
}
6 changes: 4 additions & 2 deletions src/test/java/io/getstream/chat/java/MessageHistoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ void whenMessageUpdated_thenGetHistory() {
initialCustomFieldValue, firstUpdate.getAdditionalFields().get(customField));
var secondUpdate = history.get(0);
Assertions.assertEquals(updatedText1, secondUpdate.getText());
Assertions.assertEquals(secondUser.getId(), secondUpdate.getMessageUpdatedById());
Assertions.assertEquals(
testUserRequestObject.getId(), secondUpdate.getMessageUpdatedById());
Assertions.assertEquals(
updatedCustomFieldValue, secondUpdate.getAdditionalFields().get(customField));

Expand All @@ -106,7 +107,8 @@ void whenMessageUpdated_thenGetHistory() {

secondUpdate = sortedHistory.get(1);
Assertions.assertEquals(updatedText1, secondUpdate.getText());
Assertions.assertEquals(secondUser.getId(), secondUpdate.getMessageUpdatedById());
Assertions.assertEquals(
testUserRequestObject.getId(), secondUpdate.getMessageUpdatedById());
});
}
}
34 changes: 21 additions & 13 deletions src/test/java/io/getstream/chat/java/MessageTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import io.getstream.chat.java.models.App;
import io.getstream.chat.java.models.App.FileUploadConfigRequestObject;
import io.getstream.chat.java.models.Blocklist;
import io.getstream.chat.java.models.ChannelType;
import io.getstream.chat.java.models.Language;
import io.getstream.chat.java.models.Message;
import io.getstream.chat.java.models.Message.*;
import io.getstream.chat.java.models.Moderation;
import io.getstream.chat.java.models.Moderation.*;
import io.getstream.chat.java.models.Sort;
import io.getstream.chat.java.models.framework.DefaultFileHandler;
import io.getstream.chat.java.services.framework.DefaultClient;
Expand Down Expand Up @@ -699,11 +700,14 @@ void whenForcingModerationOnAMessage_thenIsForced() {
Assertions.assertDoesNotThrow(() -> Thread.sleep(5000));

Assertions.assertDoesNotThrow(
() ->
ChannelType.update(testChannel.getType())
.blocklist(blocklistName)
.blocklistBehavior(ChannelType.BlocklistBehavior.BLOCK)
.request());
() -> {
String key = String.format("chat:%s:%s", testChannel.getType(), testChannel.getId());
BlockListRule rule =
BlockListRule.builder().name(blocklistName).action(Moderation.Action.REMOVE).build();
Moderation.upsertConfig(key)
.blockListConfig(BlockListConfigRequestObject.builder().rules(List.of(rule)).build())
.request();
});

Assertions.assertDoesNotThrow(() -> Thread.sleep(5000));

Expand All @@ -718,7 +722,7 @@ void whenForcingModerationOnAMessage_thenIsForced() {
.request())
.getMessage();

Assertions.assertTrue(msg1.getText().equals("Message was blocked by moderation policies"));
Assertions.assertEquals("Message was blocked by moderation policies", msg1.getText());

MessageRequestObject messageRequest2 =
MessageRequestObject.builder().text(text).userId(testUserRequestObject.getId()).build();
Expand All @@ -731,13 +735,14 @@ void whenForcingModerationOnAMessage_thenIsForced() {
.request())
.getMessage();

Assertions.assertTrue(msg2.getText().equals(text));
Assertions.assertEquals(text, msg2.getText());

Assertions.assertDoesNotThrow(() -> Blocklist.delete(blocklistName).request());
}

@DisplayName("Can unblock a message")
@Test
@Disabled("Need to implement unblock with moderation v2")
void whenUnblockingAMessage_thenIsUnblocked() {
final String swearText = "This is a hate message";
final String blocklistName = RandomStringUtils.randomAlphabetic(5);
Expand All @@ -747,11 +752,14 @@ void whenUnblockingAMessage_thenIsUnblocked() {
Assertions.assertDoesNotThrow(() -> Thread.sleep(5000));

Assertions.assertDoesNotThrow(
() ->
ChannelType.update(testChannel.getType())
.blocklist(blocklistName)
.blocklistBehavior(ChannelType.BlocklistBehavior.BLOCK)
.request());
() -> {
String key = String.format("chat:%s:%s", testChannel.getType(), testChannel.getId());
BlockListRule rule =
BlockListRule.builder().name(blocklistName).action(Moderation.Action.REMOVE).build();
Moderation.upsertConfig(key)
.blockListConfig(BlockListConfigRequestObject.builder().rules(List.of(rule)).build())
.request();
});

Assertions.assertDoesNotThrow(() -> Thread.sleep(5000));

Expand Down
36 changes: 36 additions & 0 deletions src/test/java/io/getstream/chat/java/ModerationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.getstream.chat.java;

import io.getstream.chat.java.exceptions.StreamException;
import io.getstream.chat.java.models.Moderation;
import io.getstream.chat.java.models.Moderation.*;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class ModerationTest extends BasicTest {
@DisplayName("Can upsert, get and delete moderation config")
@Test
void whenUpsertingGetttingDeletingModerationConfig_thenNoException() {
BlockListRule rule =
BlockListRule.builder().name("test").action(Moderation.Action.REMOVE).build();

String key = "chat:messaging:1234";
Assertions.assertDoesNotThrow(
() ->
Moderation.upsertConfig(key)
.blockListConfig(
BlockListConfigRequestObject.builder().rules(List.of(rule)).build())
.request());

ConfigGetResponse response =
Assertions.assertDoesNotThrow(() -> Moderation.getConfig(key).request());

Assertions.assertEquals(
response.getConfig().getBlockListConfig().getRules().get(0).getName(), "test");

Assertions.assertDoesNotThrow(() -> Moderation.deleteConfig(key).request());

Assertions.assertThrows(StreamException.class, () -> Moderation.getConfig(key).request());
}
}
Loading