tgbotapi/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/boosts/ChatBoostSource.kt

176 lines
5.7 KiB
Kotlin

package dev.inmo.tgbotapi.types.boosts
import dev.inmo.tgbotapi.abstracts.WithMessageId
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.PreviewUser
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromJsonElement
@Serializable(ChatBoostSource.Companion::class)
@ClassCastsIncluded
sealed interface ChatBoostSource {
val sourceName: String
val user: PreviewUser?
sealed interface ByUser : ChatBoostSource {
override val user: PreviewUser
}
@Serializable(ChatBoostSource.Companion::class)
data class Premium(
@SerialName(userField)
override val user: PreviewUser
) : ByUser {
@Required
@EncodeDefault
@SerialName(sourceField)
override val sourceName: String = sourceCode
companion object {
const val sourceCode = "premium"
}
}
@Serializable(ChatBoostSource.Companion::class)
data class GiftCode(
@SerialName(userField)
override val user: PreviewUser
) : ByUser {
@Required
@EncodeDefault
@SerialName(sourceField)
override val sourceName: String = sourceCode
companion object {
const val sourceCode = "gift_code"
}
}
@Serializable(ChatBoostSource.Companion::class)
sealed interface Giveaway : ChatBoostSource, WithMessageId {
val unclaimed: Boolean
val claimed: Boolean
get() = !unclaimed
@Serializable(ChatBoostSource.Companion::class)
data class Claimed(
@SerialName(giveawayMessageIdField)
override val messageId: MessageId,
@SerialName(userField)
override val user: PreviewUser
) : Giveaway, ByUser {
@Required
@EncodeDefault
@SerialName(sourceField)
override val sourceName: String = Giveaway.sourceCode
@Required
@EncodeDefault
@SerialName(isUnclaimedField)
override val unclaimed: Boolean = false
}
@Serializable(ChatBoostSource.Companion::class)
data class Unclaimed(
@SerialName(giveawayMessageIdField)
override val messageId: MessageId
) : Giveaway {
@Required
@EncodeDefault
@SerialName(sourceField)
override val sourceName: String = Giveaway.sourceCode
@Required
@EncodeDefault
@SerialName(isUnclaimedField)
override val unclaimed: Boolean = true
@SerialName(userField)
override val user: PreviewUser? = null
}
companion object {
val sourceCode = "giveaway"
}
}
@Serializable(ChatBoostSource.Companion::class)
data class Unknown(
override val sourceName: String,
override val user: PreviewUser?,
val json: JsonElement?
) : ChatBoostSource
@Serializable
private data class Surrogate(
@Required
@EncodeDefault
@SerialName(sourceField)
val sourceName: String,
@SerialName(userField)
val user: PreviewUser? = null,
@SerialName(giveawayMessageIdField)
val messageId: MessageId? = null,
@SerialName(isUnclaimedField)
val unclaimed: Boolean? = null
)
companion object : KSerializer<ChatBoostSource> {
override val descriptor: SerialDescriptor
get() = Surrogate.serializer().descriptor
override fun deserialize(decoder: Decoder): ChatBoostSource {
val (surrogate, json) = when {
decoder is JsonDecoder -> {
val json = decoder.decodeJsonElement()
val surrogate = decoder.json.decodeFromJsonElement(Surrogate.serializer(), json)
surrogate to json
}
else -> Surrogate.serializer().deserialize(decoder) to null
}
return when {
surrogate.sourceName == Premium.sourceCode && surrogate.user != null -> {
Premium(surrogate.user)
}
surrogate.sourceName == GiftCode.sourceCode && surrogate.user != null -> {
GiftCode(surrogate.user)
}
surrogate.sourceName == Giveaway.sourceCode && surrogate.messageId != null -> {
when {
surrogate.user != null && surrogate.unclaimed == false -> Giveaway.Claimed(
surrogate.messageId,
surrogate.user
)
surrogate.unclaimed == true -> Giveaway.Unclaimed(
surrogate.messageId
)
else -> null
}
}
else -> null
} ?: Unknown(surrogate.sourceName, surrogate.user, json)
}
override fun serialize(encoder: Encoder, value: ChatBoostSource) {
if (value is Unknown && value.json != null) {
JsonElement.serializer().serialize(encoder, value.json)
return
}
val surrogate = Surrogate(
value.sourceName,
value.user,
(value as? Giveaway) ?.messageId,
(value as? Giveaway) ?.unclaimed,
)
Surrogate.serializer().serialize(encoder, surrogate)
}
}
}