com.pubnub.api.endpoints.FetchMessages.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pubnub-kotlin Show documentation
Show all versions of pubnub-kotlin Show documentation
PubNub is a cross-platform client-to-client (1:1 and 1:many) push service in the cloud, capable of
broadcasting real-time messages to millions of web and mobile clients simultaneously, in less than a quarter
second!
package com.pubnub.api.endpoints
import com.pubnub.api.Endpoint
import com.pubnub.api.PubNub
import com.pubnub.api.PubNubError
import com.pubnub.api.PubNubException
import com.pubnub.api.enums.PNOperationType
import com.pubnub.api.models.consumer.PNBoundedPage
import com.pubnub.api.models.consumer.history.HistoryMessageType
import com.pubnub.api.models.consumer.history.PNFetchMessageItem
import com.pubnub.api.models.consumer.history.PNFetchMessagesResult
import com.pubnub.api.models.server.FetchMessagesEnvelope
import com.pubnub.api.toCsv
import com.pubnub.extension.limit
import com.pubnub.extension.nonPositiveToNull
import com.pubnub.extension.processHistoryMessage
import retrofit2.Call
import retrofit2.Response
import java.util.Locale
/**
* @see [PubNub.fetchMessages]
*/
class FetchMessages internal constructor(
pubnub: PubNub,
val channels: List,
val page: PNBoundedPage,
val includeUUID: Boolean,
val includeMeta: Boolean,
val includeMessageActions: Boolean,
val includeMessageType: Boolean
) : Endpoint(pubnub) {
internal companion object {
private const val SINGLE_CHANNEL_DEFAULT_MESSAGES = 100
private const val SINGLE_CHANNEL_MAX_MESSAGES = 100
private const val MULTIPLE_CHANNEL_DEFAULT_MESSAGES = 25
private const val MULTIPLE_CHANNEL_MAX_MESSAGES = 25
private const val DEFAULT_MESSAGES_WITH_ACTIONS = 25
private const val MAX_MESSAGES_WITH_ACTIONS = 25
internal const val INCLUDE_MESSAGE_TYPE_QUERY_PARAM = "include_message_type"
internal fun effectiveMax(
maximumPerChannel: Int?,
includeMessageActions: Boolean,
numberOfChannels: Int
): Int = when {
includeMessageActions -> maximumPerChannel?.limit(MAX_MESSAGES_WITH_ACTIONS)?.nonPositiveToNull()
?: DEFAULT_MESSAGES_WITH_ACTIONS
numberOfChannels == 1 -> maximumPerChannel?.limit(SINGLE_CHANNEL_MAX_MESSAGES)?.nonPositiveToNull()
?: SINGLE_CHANNEL_DEFAULT_MESSAGES
else -> maximumPerChannel?.limit(MULTIPLE_CHANNEL_MAX_MESSAGES)?.nonPositiveToNull()
?: MULTIPLE_CHANNEL_DEFAULT_MESSAGES
}
}
override fun validateParams() {
super.validateParams()
if (channels.isEmpty()) throw PubNubException(PubNubError.CHANNEL_MISSING)
if (includeMessageActions && channels.size > 1) throw PubNubException(PubNubError.HISTORY_MESSAGE_ACTIONS_MULTIPLE_CHANNELS)
}
override fun getAffectedChannels() = channels
override fun doWork(queryParams: HashMap): Call {
addQueryParams(queryParams)
return if (!includeMessageActions) {
pubnub.retrofitManager.historyService.fetchMessages(
subKey = pubnub.configuration.subscribeKey, channels = channels.toCsv(), options = queryParams
)
} else {
pubnub.retrofitManager.historyService.fetchMessagesWithActions(
subKey = pubnub.configuration.subscribeKey, channel = channels.first(), options = queryParams
)
}
}
override fun createResponse(input: Response): PNFetchMessagesResult {
val body = input.body()!!
val channelsMap = body.channels.mapValues { (_, value) ->
value.map { serverMessageItem ->
val (newMessage, error) = serverMessageItem.message.processHistoryMessage(
pubnub.cryptoModule,
pubnub.mapper
)
val newActions =
if (includeMessageActions) serverMessageItem.actions ?: mapOf() else serverMessageItem.actions
PNFetchMessageItem(
uuid = serverMessageItem.uuid,
message = newMessage,
meta = serverMessageItem.meta,
timetoken = serverMessageItem.timetoken,
actions = newActions,
messageType = if (includeMessageType) HistoryMessageType.of(serverMessageItem.messageType) else null,
error = error
)
}
}.toMap()
val page = body.more?.let {
PNBoundedPage(start = it.start, end = it.end, limit = it.max)
}
return PNFetchMessagesResult(channels = channelsMap, page = page)
}
override fun operationType() = PNOperationType.PNFetchMessagesOperation
private fun addQueryParams(queryParams: MutableMap) {
queryParams["max"] = effectiveMax(page.limit, includeMessageActions, channels.size).toString()
queryParams["include_uuid"] = includeUUID.toString()
page.start?.run { queryParams["start"] = this.toString().lowercase(Locale.US) }
page.end?.run { queryParams["end"] = this.toString().lowercase(Locale.US) }
queryParams[INCLUDE_MESSAGE_TYPE_QUERY_PARAM] = includeMessageType.toString()
if (includeMeta) queryParams["include_meta"] = "true"
}
}