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
10 changes: 10 additions & 0 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,16 @@ Channel.getChannel("messaging", "travel")
.request();
```

Message pagination. The cursors are `messagesIdLt`, `messagesIdLte`, `messagesIdGt`, `messagesIdGte` and `messagesIdAround`. They need `state(true)`, and a message ID the channel does not hold yields a 400.

```java
Channel.getChannel("messaging", "travel")
.state(true)
.messagesLimit(20)
.messagesIdLt(oldestLoadedMessageId)
.request();
```

**Get or create channel (type,id)**

Standard
Expand Down
23 changes: 22 additions & 1 deletion src/main/java/io/getstream/chat/java/models/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,26 @@ public static class GetChannelRequestData {
@JsonProperty("watchers_limit")
private Integer watchersLimit;

@Nullable
@JsonProperty("messages_id_lt")
private String messagesIdLt;

@Nullable
@JsonProperty("messages_id_lte")
private String messagesIdLte;

@Nullable
@JsonProperty("messages_id_gt")
private String messagesIdGt;

@Nullable
@JsonProperty("messages_id_gte")
private String messagesIdGte;

@Nullable
@JsonProperty("messages_id_around")
private String messagesIdAround;

public static class GetChannelRequest extends StreamRequest<ChannelGetResponse> {
@NotNull private String channelType;

Expand Down Expand Up @@ -1688,7 +1708,8 @@ public static ChannelGetRequest getOrCreate(@NotNull String type) {

/**
* Creates a get channel request. The channel is never created: a missing, deleted or disabled
* channel yields a 404, so this request doubles as an existence check.
* channel yields a 404, so this request doubles as an existence check. The messages of the
* channel are paged with the messagesId* parameters, which need state to be true.
*
* @param type the channel type
* @param id the channel id
Expand Down
71 changes: 71 additions & 0 deletions src/test/java/io/getstream/chat/java/ChannelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.getstream.chat.java.models.Channel;
import io.getstream.chat.java.models.Channel.*;
import io.getstream.chat.java.models.DeleteStrategy;
import io.getstream.chat.java.models.Message;
import io.getstream.chat.java.models.Message.MessageRequestObject;
import io.getstream.chat.java.models.Sort;
import io.getstream.chat.java.models.Sort.Direction;
Expand Down Expand Up @@ -51,6 +52,76 @@ void whenGettingExistingChannel_thenReturnsChannel() {
Assertions.assertEquals(testChannel.getId(), response.getChannel().getId());
}

@DisplayName("Can page the messages of a channel by message ID")
@Test
void whenGettingChannelWithMessageCursor_thenPagesMessages() {
var channelId = RandomStringUtils.randomAlphabetic(12);
Assertions.assertDoesNotThrow(
() ->
Channel.getOrCreate(testChannel.getType(), channelId)
.data(
ChannelRequestObject.builder()
.createdBy(testUserRequestObject)
.members(buildChannelMembersList())
.build())
.request());

var first = sendMessageToChannel(channelId, "first");
var second = sendMessageToChannel(channelId, "second");
var third = sendMessageToChannel(channelId, "third");

var older =
Assertions.assertDoesNotThrow(
() ->
Channel.getChannel(testChannel.getType(), channelId)
.state(true)
.messagesIdLt(third)
.request());
Assertions.assertEquals(Arrays.asList(first, second), messageIds(older));

var newer =
Assertions.assertDoesNotThrow(
() ->
Channel.getChannel(testChannel.getType(), channelId)
.state(true)
.messagesIdGt(first)
.request());
Assertions.assertEquals(Arrays.asList(second, third), messageIds(newer));
}

@DisplayName("Get channel rejects a message cursor the channel does not hold")
@Test
void whenGettingChannelWithUnknownMessageCursor_thenBadRequest() {
var exception =
Assertions.assertThrows(
StreamException.class,
() ->
Channel.getChannel(testChannel.getType(), testChannel.getId())
.state(true)
.messagesIdLt(RandomStringUtils.randomAlphabetic(12))
.request());
Assertions.assertEquals(400, exception.getResponseData().getStatusCode());
}

private String sendMessageToChannel(String channelId, String text) {
var message =
Assertions.assertDoesNotThrow(
() ->
Message.send(testChannel.getType(), channelId)
.message(
MessageRequestObject.builder()
.text(text)
.userId(testUserRequestObject.getId())
.build())
.request()
.getMessage());
return message.getId();
}

private List<String> messageIds(ChannelGetResponse response) {
return response.getMessages().stream().map(Message::getId).collect(Collectors.toList());
}

@DisplayName("Get channel does not create a missing channel")
@Test
void whenGettingMissingChannel_thenNotFound() {
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/io/getstream/chat/java/GetChannelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ void whenBuildingGetChannelRequest_thenOptionsGoIntoPayloadQueryParameter() {
Assertions.assertTrue(payload.contains("\"messages_limit\":5"), payload);
}

@Test
@DisplayName("Get channel sends its message cursors in the payload query parameter")
void whenBuildingGetChannelRequestWithCursors_thenCursorsGoIntoPayloadQueryParameter() {
var data =
Channel.getChannel("messaging", "abc")
.state(true)
.messagesLimit(20)
.messagesIdLt("message-1")
.messagesIdGte("message-2")
.messagesIdAround("message-3")
.internalBuild();

var request =
client().create(ChannelService.class).getChannel("messaging", "abc", data).request();

var payload = request.url().queryParameter("payload");
Assertions.assertNotNull(payload);
Assertions.assertTrue(payload.contains("\"messages_id_lt\":\"message-1\""), payload);
Assertions.assertTrue(payload.contains("\"messages_id_gte\":\"message-2\""), payload);
Assertions.assertTrue(payload.contains("\"messages_id_around\":\"message-3\""), payload);
}

@Test
@DisplayName("Get channel sends a payload query parameter even without options")
void whenBuildingGetChannelRequestWithoutOptions_thenPayloadQueryParameterIsStillSent() {
Expand Down
Loading