diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/MessageOrigin.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/MessageOrigin.kt index 57e162a3b6..1ab6d6e542 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/MessageOrigin.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/MessageOrigin.kt @@ -2,11 +2,18 @@ package dev.inmo.tgbotapi.types.message import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.chat.* +import kotlinx.serialization.KSerializer import kotlinx.serialization.Required import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +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 +@Serializable(MessageOrigin.Companion::class) sealed interface MessageOrigin { val type: String val date: TelegramDate @@ -14,7 +21,7 @@ sealed interface MessageOrigin { @Serializable data class User( @SerialName(senderUserField) - val user: dev.inmo.tgbotapi.types.chat.User, + val user: PreviewUser, @SerialName(dateField) override val date: TelegramDate ) : MessageOrigin { @@ -43,7 +50,7 @@ sealed interface MessageOrigin { } } - @Serializable + @Serializable(MessageOrigin.Companion::class) sealed interface Public : MessageOrigin { val chat: PublicChat val authorSignature: AuthorSignature? @@ -86,4 +93,87 @@ sealed interface MessageOrigin { } } } + + @Serializable + data class Unknown internal constructor( + override val type: String, + override val date: TelegramDate, + val source: JsonElement? + ) : MessageOrigin + + @Serializable + private data class Surrogate( + @SerialName(typeField) + @Required + val type: String, + @SerialName(senderChatField) + val senderChat: PreviewChat? = null, + @SerialName(chatField) + val chat: PreviewChat? = null, + @SerialName(dateField) + val date: TelegramDate, + @SerialName(authorSignatureField) + val authorSignature: AuthorSignature? = null, + @SerialName(messageIdField) + val messageId: MessageId? = null, + @SerialName(senderUserNameField) + val name: String? = null, + @SerialName(senderUserField) + val user: PreviewUser? = null + ) + + companion object : KSerializer { + override val descriptor: SerialDescriptor + get() = Surrogate.serializer().descriptor + + override fun deserialize(decoder: Decoder): MessageOrigin { + val (surrogate, json) = if (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 let { + when (surrogate.type) { + HiddenUser.type -> HiddenUser( + surrogate.name ?: return@let null, + surrogate.date + ) + Public.Channel.type -> Public.Channel( + surrogate.chat as? ChannelChat ?: return@let null, + surrogate.messageId ?: return@let null, + surrogate.date, + surrogate.authorSignature + ) + Public.Sender.type -> Public.Sender( + surrogate.senderChat as? ChannelChat ?: return@let null, + surrogate.date, + surrogate.authorSignature + ) + User.type -> User( + surrogate.user ?: return@let null, + surrogate.date + ) + else -> null + } + } ?: Unknown( + surrogate.type, + surrogate.date, + json + ) + } + + override fun serialize(encoder: Encoder, value: MessageOrigin) { + when (value) { + is HiddenUser -> HiddenUser.serializer().serialize(encoder, value) + is Public.Channel -> Public.Channel.serializer().serialize(encoder, value) + is Public.Sender -> Public.Sender.serializer().serialize(encoder, value) + is Unknown -> value.source ?.let { JsonElement.serializer().serialize(encoder, it) } ?: Unknown.serializer().serialize(encoder, value) + is User -> User.serializer().serialize(encoder, value) + } + } + + } } \ No newline at end of file