Skip to content
Closed
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
61 changes: 61 additions & 0 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1860,4 +1860,65 @@ Import.createImport(createUrlResponse.getPath(), Import.ImportMode.Upsert);
```java
// signature comes from the HTTP header x-signature
boolean valid = App.verifyWebhook(body, signature)
```

## Live Location Features

Stream Chat supports sharing and updating a user's live location within a channel. There are a few ways to work with live locations:

### Sending a Message with Live Location

The simplest way to share a location is to send a message containing live location data:

```java
Date endTime = new Date(System.currentTimeMillis() + 3600 * 1000); // 1 hour from now

// Send a message with live location
Message message = Message.sendWithLiveLocation(
"messaging", // channel type
"my-channel-id", // channel id
"Sharing my location", // message text
"user-id", // user id
40.7128, // latitude (New York City)
-74.0060, // longitude
endTime, // when the live location sharing ends
"ios-device-123" // device ID that's sharing the location
)
.request()
.getMessage();
```

### Updating a Live Location

Once a live location has been created, you can update it with new coordinates:

```java
// Update existing live location
LiveLocationUpdateRequestData requestData = LiveLocationUpdateRequestData.builder()
.locationId("existing-location-id")
.userId("user-id")
.latitude(34.0522) // new latitude (Los Angeles)
.longitude(-118.2437) // new longitude
.build();

Channel.updateLiveLocation("messaging", "my-channel-id")
.liveLocation(requestData)
.request();
```

### Getting a User's Active Live Locations

To retrieve all active live locations for a user:

```java
UserGetActiveLiveLocationsResponse response = User.getActiveLiveLocations("user-id")
.request();

List<LiveLocation> liveLocations = response.getLiveLocations();
for (LiveLocation location : liveLocations) {
System.out.println("Location ID: " + location.getId());
System.out.println("Latitude: " + location.getLatitude());
System.out.println("Longitude: " + location.getLongitude());
System.out.println("End time: " + location.getEndAt());
}
```
58 changes: 58 additions & 0 deletions src/main/java/io/getstream/chat/java/models/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -1725,4 +1725,62 @@ public static ChannelMemberPartialUpdateRequest unarchive(
@NotNull String type, @NotNull String id, @NotNull String userId) {
return new ChannelMemberPartialUpdateRequest(type, id, userId).setValue("archived", false);
}

@Builder(
builderClassName = "LiveLocationUpdateRequest",
builderMethodName = "",
buildMethodName = "internalBuild")
public static class LiveLocationUpdateRequestData {
@Nullable
@JsonProperty("location_id")
private String locationId;

@Nullable
@JsonProperty("user_id")
private String userId;

@Nullable
@JsonProperty("latitude")
private Double latitude;

@Nullable
@JsonProperty("longitude")
private Double longitude;

@Nullable
@JsonProperty("end_at")
private Date endAt;

@Nullable
@JsonProperty("created_by_device_id")
private String createdByDeviceId;

public static class LiveLocationUpdateRequest extends StreamRequest<StreamResponseObject> {
@NotNull private String channelType;
@NotNull private String channelId;
@NotNull private LiveLocationUpdateRequestData liveLocationData;

private LiveLocationUpdateRequest(@NotNull String channelType, @NotNull String channelId) {
this.channelType = channelType;
this.channelId = channelId;
}

public LiveLocationUpdateRequest liveLocation(@NotNull LiveLocationUpdateRequestData data) {
this.liveLocationData = data;
return this;
}

@Override
protected Call<StreamResponseObject> generateCall(Client client) {
return client
.create(ChannelService.class)
.updateLiveLocation(this.channelType, this.channelId, this.liveLocationData);
}
}
}

public static LiveLocationUpdateRequestData.LiveLocationUpdateRequest updateLiveLocation(
@NotNull String channelType, @NotNull String channelId) {
return new LiveLocationUpdateRequestData.LiveLocationUpdateRequest(channelType, channelId);
}
}
35 changes: 35 additions & 0 deletions src/main/java/io/getstream/chat/java/models/ChannelType.java
Original file line number Diff line number Diff line change
Expand Up @@ -673,4 +673,39 @@ public static ChannelTypeDeleteRequest delete(String name) {
public static ChannelTypeListRequest list() throws StreamException {
return new ChannelTypeListRequest();
}

/**
* Represents a live location shared in a channel
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class LiveLocation {
private String id;

@JsonProperty("user_id")
private String userId;

@JsonProperty("channel_cid")
private String channelCid;

@JsonProperty("message_id")
private String messageId;

private Double latitude;
private Double longitude;

@JsonProperty("end_at")
private Date endAt;

@JsonProperty("created_by_device_id")
private String createdByDeviceId;

@JsonProperty("created_at")
private Date createdAt;

@JsonProperty("updated_at")
private Date updatedAt;
}
}
92 changes: 92 additions & 0 deletions src/main/java/io/getstream/chat/java/models/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import retrofit2.Call;
import java.util.UUID;

@Data
@NoArgsConstructor
Expand Down Expand Up @@ -168,6 +169,10 @@ public class Message {
@JsonProperty("pinned_at")
private Date pinnedAt;

@Nullable
@JsonProperty("live_location")
private LiveLocationRequestObject liveLocation;

@NotNull @JsonIgnore private Map<String, Object> additionalFields = new HashMap<>();

@JsonAnyGetter
Expand Down Expand Up @@ -491,6 +496,10 @@ public static class MessageRequestObject {
@JsonProperty("pinned_at")
private Date pinnedAt;

@Nullable
@JsonProperty("live_location")
private LiveLocationRequestObject liveLocation;

@Singular @Nullable @JsonIgnore private Map<String, Object> additionalFields;

@JsonAnyGetter
Expand Down Expand Up @@ -654,6 +663,43 @@ public static FieldRequestObject buildFrom(@Nullable Field field) {
}
}

@Builder
@Setter
public static class LiveLocationRequestObject {
@Nullable
@JsonProperty("id")
private String id;

@Nullable
@JsonProperty("user_id")
private String userId;

@Nullable
@JsonProperty("channel_cid")
private String channelCid;

@Nullable
@JsonProperty("latitude")
private Double latitude;

@Nullable
@JsonProperty("longitude")
private Double longitude;

@Nullable
@JsonProperty("end_at")
private Date endAt;

@Nullable
@JsonProperty("created_by_device_id")
private String createdByDeviceId;

@Nullable
public static LiveLocationRequestObject buildFrom(@Nullable ChannelType.LiveLocation liveLocation) {
return RequestObjectBuilder.build(LiveLocationRequestObject.class, liveLocation);
}
}

@Builder
@Setter
public static class ImageSizeRequestObject {
Expand Down Expand Up @@ -1692,4 +1738,50 @@ public static MessagePartialUpdateRequest unpinMessage(
public static MessageUnblockRequest unblock(@NotNull String messageId) {
return new MessageUnblockRequest().targetMessageId(messageId);
}

/**
* Helper method to create a message with a live location
*
* @param channelType the channel type
* @param channelId the channel id
* @param text the message text
* @param userId the user id
* @param latitude the location latitude
* @param longitude the location longitude
* @param endAt the end time for the live location
* @param deviceId the device id that created the location
* @return the message send request
*/
@NotNull
public static MessageSendRequest sendWithLiveLocation(
@NotNull String channelType,
@NotNull String channelId,
@Nullable String text,
@NotNull String userId,
@NotNull Double latitude,
@NotNull Double longitude,
@NotNull Date endAt,
@NotNull String deviceId) {

String locationId = UUID.randomUUID().toString();
String channelCid = channelType + ":" + channelId;

LiveLocationRequestObject liveLocation = LiveLocationRequestObject.builder()
.id(locationId)
.userId(userId)
.channelCid(channelCid)
.latitude(latitude)
.longitude(longitude)
.endAt(endAt)
.createdByDeviceId(deviceId)
.build();

MessageRequestObject message = MessageRequestObject.builder()
.text(text)
.userId(userId)
.liveLocation(liveLocation)
.build();

return send(channelType, channelId).message(message);
}
}
28 changes: 28 additions & 0 deletions src/main/java/io/getstream/chat/java/models/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -1447,4 +1447,32 @@ public static String createToken(
.signWith(signingKey, SignatureAlgorithm.HS256)
.compact();
}

@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public static class UserGetActiveLiveLocationsResponse extends StreamResponseObject {
@Nullable
@JsonProperty("live_locations")
private List<ChannelType.LiveLocation> liveLocations;
}

public static class UserGetActiveLiveLocationsRequest extends StreamRequest<UserGetActiveLiveLocationsResponse> {
@NotNull private String userId;

private UserGetActiveLiveLocationsRequest(@NotNull String userId) {
this.userId = userId;
}

@Override
protected Call<UserGetActiveLiveLocationsResponse> generateCall(Client client) {
return client
.create(UserService.class)
.getUserActiveLiveLocations(this.userId, this.userId);
}
}

public static UserGetActiveLiveLocationsRequest getActiveLiveLocations(@NotNull String userId) {
return new UserGetActiveLiveLocationsRequest(userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,10 @@ Call<ChannelMemberResponse> updateMemberPartial(
@NotNull @Path("id") String channelId,
@NotNull @Path("user_id") String userId,
@NotNull @Body ChannelMemberPartialUpdateRequestData updateMemberPartialRequestData);

@PUT("channels/{type}/{id}/live_location")
Call<StreamResponseObject> updateLiveLocation(
@NotNull @Path("type") String channelType,
@NotNull @Path("id") String channelId,
@NotNull @Body Channel.LiveLocationUpdateRequestData liveLocationUpdateRequestData);
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,9 @@ Call<StreamResponseObject> unban(
@Nullable @Query("type") String channelType,
@Nullable @Query("id") String channelId,
@Nullable @Query("shadow") Boolean shadow);

@GET("users/{user_id}/live_locations")
Call<User.UserGetActiveLiveLocationsResponse> getUserActiveLiveLocations(
@NotNull @Path("user_id") String userId,
@NotNull @Query("user_id") String queryUserId);
}
Loading
Loading