From 21d230e4834080547b413c70de1eab5f47061a8c Mon Sep 17 00:00:00 2001 From: Gian <47775302+gpunto@users.noreply.github.com> Date: Thu, 9 Jul 2026 18:07:29 +0200 Subject: [PATCH] Migrate sendReaction request body to generated ReactionRequest and SendReactionRequest models --- .../chat/android/client/api2/MoshiChatApi.kt | 8 +-- .../client/api2/endpoint/MessageApi.kt | 4 +- .../android/client/api2/mapping/DtoMapping.kt | 18 +++---- .../client/api2/model/dto/ReactionDtos.kt | 25 ---------- .../api2/model/requests/ReactionRequest.kt | 34 ------------- .../adapters/CustomObjectDtoAdapter.kt | 47 ++++++++++-------- .../parser2/adapters/ReactionDtoAdapters.kt | 12 ++--- .../android/network/models/ReactionRequest.kt | 49 +++++++++++++++++++ .../network/models/SendReactionRequest.kt | 38 ++++++++++++++ .../client/api2/mapping/DtoMappingTest.kt | 18 +++---- .../parser2/testdata/ReactionDtoTestData.kt | 37 +++++--------- 11 files changed, 153 insertions(+), 137 deletions(-) delete mode 100644 stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/ReactionRequest.kt create mode 100644 stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ReactionRequest.kt create mode 100644 stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/SendReactionRequest.kt diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt index ce424316636..12fa8f7f48f 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt @@ -76,7 +76,6 @@ import io.getstream.chat.android.client.api2.model.requests.QueryGroupedChannels import io.getstream.chat.android.client.api2.model.requests.QueryPollVotesRequest import io.getstream.chat.android.client.api2.model.requests.QueryPollsRequest import io.getstream.chat.android.client.api2.model.requests.QueryRemindersRequest -import io.getstream.chat.android.client.api2.model.requests.ReactionRequest import io.getstream.chat.android.client.api2.model.requests.RejectInviteRequest import io.getstream.chat.android.client.api2.model.requests.ReminderRequest import io.getstream.chat.android.client.api2.model.requests.RemoveMembersRequest @@ -167,6 +166,7 @@ import io.getstream.chat.android.network.models.MarkReadRequest import io.getstream.chat.android.network.models.MarkUnreadRequest import io.getstream.chat.android.network.models.MuteChannelRequest import io.getstream.chat.android.network.models.QueryReactionsRequest +import io.getstream.chat.android.network.models.SendReactionRequest import io.getstream.chat.android.network.models.SortParamRequest import io.getstream.chat.android.network.models.UnblockUsersRequest import io.getstream.chat.android.network.models.UpdateChannelPartialRequest @@ -445,10 +445,10 @@ constructor( override fun sendReaction(reaction: Reaction, enforceUnique: Boolean, skipPush: Boolean): Call { return messageApi.sendReaction( messageId = reaction.messageId, - request = ReactionRequest( + request = SendReactionRequest( reaction = with(dtoMapping) { reaction.toDto() }, - enforce_unique = enforceUnique, - skip_push = skipPush, + enforceUnique = enforceUnique, + skipPush = skipPush, ), ).mapDomain { response -> response.reaction.toDomain() diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/MessageApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/MessageApi.kt index 3caeaec0e2e..c5d7ae6c1ed 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/MessageApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/MessageApi.kt @@ -20,7 +20,6 @@ import io.getstream.chat.android.client.api.AuthenticatedApi import io.getstream.chat.android.client.api2.model.requests.PartialUpdateMessageRequest import io.getstream.chat.android.client.api2.model.requests.QueryDraftMessagesRequest import io.getstream.chat.android.client.api2.model.requests.QueryDraftsRequest -import io.getstream.chat.android.client.api2.model.requests.ReactionRequest import io.getstream.chat.android.client.api2.model.requests.SendActionRequest import io.getstream.chat.android.client.api2.model.requests.SendMessageRequest import io.getstream.chat.android.client.api2.model.requests.UpdateMessageRequest @@ -35,6 +34,7 @@ import io.getstream.chat.android.client.api2.model.response.TranslateMessageRequ import io.getstream.chat.android.client.call.RetrofitCall import io.getstream.chat.android.network.models.QueryReactionsRequest import io.getstream.chat.android.network.models.Response +import io.getstream.chat.android.network.models.SendReactionRequest import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.GET @@ -119,7 +119,7 @@ internal interface MessageApi { @POST("/messages/{id}/reaction") fun sendReaction( @Path("id") messageId: String, - @Body request: ReactionRequest, + @Body request: SendReactionRequest, ): RetrofitCall @DELETE("/messages/{id}/reaction/{type}") diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt index ef2bd24df3b..afe9436f7ab 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt @@ -33,7 +33,6 @@ import io.getstream.chat.android.client.api2.model.dto.UpstreamMemberDataDto import io.getstream.chat.android.client.api2.model.dto.UpstreamMemberDto import io.getstream.chat.android.client.api2.model.dto.UpstreamMessageDto import io.getstream.chat.android.client.api2.model.dto.UpstreamMuteDto -import io.getstream.chat.android.client.api2.model.dto.UpstreamReactionDto import io.getstream.chat.android.client.api2.model.dto.UpstreamUserDto import io.getstream.chat.android.client.events.ConnectedEvent import io.getstream.chat.android.models.Attachment @@ -51,6 +50,7 @@ import io.getstream.chat.android.models.Reaction import io.getstream.chat.android.models.User import io.getstream.chat.android.models.UserGroup import io.getstream.chat.android.models.UserTransformer +import io.getstream.chat.android.network.models.ReactionRequest internal class DtoMapping( private val messageTransformer: MessageTransformer, @@ -202,18 +202,14 @@ internal class DtoMapping( ) /** - * Maps the domain [Reaction] model to a network [UpstreamReactionDto]. + * Maps the domain [Reaction] model to a network [ReactionRequest]. */ - internal fun Reaction.toDto(): UpstreamReactionDto = UpstreamReactionDto( - created_at = createdAt, - message_id = messageId, - score = score, + internal fun Reaction.toDto(): ReactionRequest = ReactionRequest( type = type, - updated_at = updatedAt, - user = user?.toDto(), - user_id = userId, - emoji_code = emojiCode, - extraData = extraData, + createdAt = createdAt, + score = score, + updatedAt = updatedAt, + custom = if (emojiCode != null) extraData + ("emoji_code" to emojiCode) else extraData, ) /** diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ReactionDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ReactionDtos.kt index 1ad58747311..a33d3f7cd50 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ReactionDtos.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ReactionDtos.kt @@ -20,31 +20,6 @@ import com.squareup.moshi.JsonClass import io.getstream.chat.android.core.internal.StreamHandsOff import java.util.Date -/** - * See [io.getstream.chat.android.client.parser2.adapters.UpstreamReactionDtoAdapter] for - * special [extraData] handling. - */ -@StreamHandsOff( - reason = "Field names can't be changed because [CustomObjectDtoAdapter] class uses reflections to add/remove " + - "content of [extraData] map", -) -@JsonClass(generateAdapter = true) -internal data class UpstreamReactionDto( - val created_at: Date?, - val message_id: String, - val score: Int, - val type: String, - val updated_at: Date?, - val user: UpstreamUserDto?, - val user_id: String, - // Note: This is not contextually a top-level field in the API, it should be inside `reaction.extraData`. - // But for convenience, we make it a top-level field here, because when serialized, it will be top-level in the - // JSON string. - val emoji_code: String?, - - val extraData: Map, -) : ExtraDataDto - /** * See [io.getstream.chat.android.client.parser2.adapters.DownstreamReactionDtoAdapter] for * special [extraData] handling. diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/ReactionRequest.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/ReactionRequest.kt deleted file mode 100644 index 6991b369759..00000000000 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/ReactionRequest.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2014-2026 Stream.io Inc. All rights reserved. - * - * Licensed under the Stream License; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.getstream.chat.android.client.api2.model.requests - -import com.squareup.moshi.JsonClass -import io.getstream.chat.android.client.api2.model.dto.UpstreamReactionDto - -/** - * Request for adding a reaction to a message. - * - * @property reaction The reaction to be added. - * @property enforce_unique If true, the reaction will be unique per user per message. - * @property skip_push If true, the reaction addition will not trigger a push notification. - */ -@JsonClass(generateAdapter = true) -internal data class ReactionRequest( - val reaction: UpstreamReactionDto, - val enforce_unique: Boolean, - val skip_push: Boolean, -) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/CustomObjectDtoAdapter.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/CustomObjectDtoAdapter.kt index 435e68db518..a81111034ba 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/CustomObjectDtoAdapter.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/CustomObjectDtoAdapter.kt @@ -16,28 +16,35 @@ package io.getstream.chat.android.client.parser2.adapters +import com.squareup.moshi.Json import com.squareup.moshi.JsonAdapter import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonWriter import kotlin.reflect.KClass +import kotlin.reflect.full.findAnnotation +import kotlin.reflect.full.primaryConstructor /** * Base class for implementing Moshi adapters that support our API's dynamic * JSON models. + * + * [extraDataPropertyName] names the property that holds the overflow map (`extraData` or `custom`). */ -internal open class CustomObjectDtoAdapter(private val kClass: KClass) { - - private companion object { - private const val EXTRA_DATA = "extraData" - } +internal open class CustomObjectDtoAdapter( + private val kClass: KClass, + private val extraDataPropertyName: String = "extraData", +) { /** - * Names of the declared properties that are inside the [Value] type being - * handled. These will not be copied into extraData when parsing with - * [parseWithExtraData]. + * Wire-format names of the declared properties on [Value]. These will not be copied into the + * overflow map when parsing with [parseWithExtraData]. Reads `@Json(name = ...)` first so + * camelCase properties map to their snake_case wire names, falling back to the Kotlin + * parameter name when `@Json` is absent. */ private val memberNames: List by lazy { - kClass.members.map { member -> member.name }.minus(EXTRA_DATA) + kClass.primaryConstructor?.parameters.orEmpty().mapNotNull { param -> + (param.findAnnotation()?.name ?: param.name)?.takeIf { it != extraDataPropertyName } + } } /** @@ -60,9 +67,9 @@ internal open class CustomObjectDtoAdapter(private val kClass: KCla val extraData = mutableMapOf() - // Save the value of the literal "extraData" field at the root of the object, if present - map[EXTRA_DATA]?.let { explicitExtraData -> - extraData[EXTRA_DATA] = explicitExtraData + // Save the value of the literal extraData field at the root of the object, if present + map[extraDataPropertyName]?.let { explicitExtraData -> + extraData[extraDataPropertyName] = explicitExtraData } // Save the values of non-member fields as extra data @@ -72,8 +79,8 @@ internal open class CustomObjectDtoAdapter(private val kClass: KCla } } - // Replace original "extraData" with the newly collected values - map[EXTRA_DATA] = extraData + // Replace original extraData with the newly collected values + map[extraDataPropertyName] = extraData // Parse output value object from the transformed Map return valueAdapter.fromJsonValue(map)!! @@ -99,14 +106,14 @@ internal open class CustomObjectDtoAdapter(private val kClass: KCla // Convert input value into a Map val map: MutableMap = valueAdapter.toJsonValue(value) as MutableMap - // Grab real "extraData" property's value - val extraData = map[EXTRA_DATA] as Map + // Grab real extraData property's value + val extraData = map[extraDataPropertyName] as? Map - // Remove literal "extraData" field from Map - map.remove(EXTRA_DATA) + // Remove literal extraData field from Map + map.remove(extraDataPropertyName) - // Merge all values from "extraData" property back into the Map as top level fields - map.putAll(extraData) + // Merge all values from the extraData property back into the Map as top level fields + extraData?.let(map::putAll) // Write Map to output mapAdapter.toJson(jsonWriter, map) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/ReactionDtoAdapters.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/ReactionDtoAdapters.kt index 4c0fbb6d478..9bb003fe99a 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/ReactionDtoAdapters.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/ReactionDtoAdapters.kt @@ -22,7 +22,7 @@ import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonWriter import com.squareup.moshi.ToJson import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto -import io.getstream.chat.android.client.api2.model.dto.UpstreamReactionDto +import io.getstream.chat.android.network.models.ReactionRequest internal object DownstreamReactionDtoAdapter : CustomObjectDtoAdapter(DownstreamReactionDto::class) { @@ -40,17 +40,17 @@ internal object DownstreamReactionDtoAdapter : } internal object UpstreamReactionDtoAdapter : - CustomObjectDtoAdapter(UpstreamReactionDto::class) { + CustomObjectDtoAdapter(ReactionRequest::class, extraDataPropertyName = "custom") { @FromJson @Suppress("UNUSED_PARAMETER") - fun fromJson(jsonReader: JsonReader): UpstreamReactionDto = error("Can't parse this from Json") + fun fromJson(jsonReader: JsonReader): ReactionRequest = error("Can't parse this from Json") @ToJson fun toJson( jsonWriter: JsonWriter, - message: UpstreamReactionDto?, + reaction: ReactionRequest?, mapAdapter: JsonAdapter>, - messageAdapter: JsonAdapter, - ) = serializeWithExtraData(jsonWriter, message, mapAdapter, messageAdapter) + reactionAdapter: JsonAdapter, + ) = serializeWithExtraData(jsonWriter, reaction, mapAdapter, reactionAdapter) } diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ReactionRequest.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ReactionRequest.kt new file mode 100644 index 00000000000..fad901f0ff5 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ReactionRequest.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014-2026 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport", +) + +package io.getstream.chat.android.network.models + +import com.squareup.moshi.Json +import kotlin.collections.Map + +/** + * Represents user reaction to a message + */ + +@com.squareup.moshi.JsonClass(generateAdapter = true) +internal data class ReactionRequest( + @Json(name = "type") + val type: kotlin.String, + + @Json(name = "created_at") + val createdAt: java.util.Date? = null, + + @Json(name = "score") + val score: kotlin.Int? = null, + + @Json(name = "updated_at") + val updatedAt: java.util.Date? = null, + + @Json(name = "custom") + val custom: kotlin.collections.Map? = emptyMap(), +) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/SendReactionRequest.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/SendReactionRequest.kt new file mode 100644 index 00000000000..fb5df4b66a7 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/SendReactionRequest.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2026 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport", +) + +package io.getstream.chat.android.network.models + +import com.squareup.moshi.Json + +@com.squareup.moshi.JsonClass(generateAdapter = true) +internal data class SendReactionRequest( + @Json(name = "reaction") + val reaction: ReactionRequest, + + @Json(name = "enforce_unique") + val enforceUnique: kotlin.Boolean? = null, + + @Json(name = "skip_push") + val skipPush: kotlin.Boolean? = null, +) diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DtoMappingTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DtoMappingTest.kt index 2236331c9e6..7390aa7e17f 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DtoMappingTest.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DtoMappingTest.kt @@ -31,7 +31,6 @@ import io.getstream.chat.android.client.api2.model.dto.UpstreamMemberDataDto import io.getstream.chat.android.client.api2.model.dto.UpstreamMemberDto import io.getstream.chat.android.client.api2.model.dto.UpstreamMessageDto import io.getstream.chat.android.client.api2.model.dto.UpstreamMuteDto -import io.getstream.chat.android.client.api2.model.dto.UpstreamReactionDto import io.getstream.chat.android.client.api2.model.dto.UpstreamUserDto import io.getstream.chat.android.client.test.randomConnectedEvent import io.getstream.chat.android.models.MessageTransformer @@ -40,6 +39,7 @@ import io.getstream.chat.android.models.NoOpMessageTransformer import io.getstream.chat.android.models.NoOpUserTransformer import io.getstream.chat.android.models.UserGroup import io.getstream.chat.android.models.UserTransformer +import io.getstream.chat.android.network.models.ReactionRequest import io.getstream.chat.android.randomAttachment import io.getstream.chat.android.randomDevice import io.getstream.chat.android.randomDraftMessage @@ -243,16 +243,14 @@ internal class DtoMappingTest { val reaction = randomReaction() val mapping = Fixture().get() val dto = with(mapping) { reaction.toDto() } - val expected = UpstreamReactionDto( - created_at = reaction.createdAt, - message_id = reaction.messageId, - score = reaction.score, + val expected = ReactionRequest( type = reaction.type, - updated_at = reaction.updatedAt, - user = reaction.user?.let { with(mapping) { it.toDto() } }, - user_id = reaction.userId, - extraData = reaction.extraData, - emoji_code = reaction.emojiCode, + createdAt = reaction.createdAt, + score = reaction.score, + updatedAt = reaction.updatedAt, + custom = reaction.emojiCode + ?.let { reaction.extraData + ("emoji_code" to it) } + ?: reaction.extraData, ) dto shouldBeEqualTo expected } diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ReactionDtoTestData.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ReactionDtoTestData.kt index 441eab6584d..2ee22328ffc 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ReactionDtoTestData.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ReactionDtoTestData.kt @@ -17,7 +17,7 @@ package io.getstream.chat.android.client.parser2.testdata import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto -import io.getstream.chat.android.client.api2.model.dto.UpstreamReactionDto +import io.getstream.chat.android.network.models.ReactionRequest import org.intellij.lang.annotations.Language import java.util.Date @@ -81,45 +81,32 @@ internal object ReactionDtoTestData { @Language("JSON") val upstreamJsonWithoutExtraData = """{ - "message_id": "messageId", "score": 0, - "type": "love", - "user_id": "userId" + "type": "love" }""".withoutWhitespace() - val upstreamReactionWithoutExtraData = UpstreamReactionDto( - created_at = null, - message_id = "messageId", - score = 0, + val upstreamReactionWithoutExtraData = ReactionRequest( type = "love", - updated_at = null, - user = null, - user_id = "userId", - emoji_code = null, - extraData = emptyMap(), + createdAt = null, + score = 0, + updatedAt = null, + custom = emptyMap(), ) @Language("JSON") val upstreamJson = """{ "created_at": "2020-06-10T11:04:31.000Z", - "message_id": "messageId", "score": 4, "type": "love", "updated_at": "2020-06-10T11:04:31.588Z", - "user": ${UserDtoTestData.upstreamJson}, - "user_id": "userId", "emoji_code": "👍", "other_score": 42 }""".withoutWhitespace() - val upstreamReaction = UpstreamReactionDto( - created_at = Date(1591787071000), - message_id = "messageId", - score = 4, + val upstreamReaction = ReactionRequest( type = "love", - updated_at = Date(1591787071588), - user = UserDtoTestData.upstreamUser, - user_id = "userId", - emoji_code = "👍", - extraData = mapOf("other_score" to 42), + createdAt = Date(1591787071000), + score = 4, + updatedAt = Date(1591787071588), + custom = mapOf("other_score" to 42, "emoji_code" to "👍"), ) }